diff options
| -rw-r--r-- | src/main.c | 27 | ||||
| -rw-r--r-- | src/parser/ast.h | 15 | ||||
| -rw-r--r-- | src/parser/parser.c | 27 | ||||
| -rw-r--r-- | tests/parser_test.c | 22 |
4 files changed, 82 insertions, 9 deletions
@@ -62,14 +62,27 @@ int main(int argc, char** argv) for (size_t s = 0; s < proc.body_count; s += 1) { struct Statement statement = proc.body[s]; - if (statement.kind == STATEMENT_ASSIGN) + switch (statement.kind) { - struct AssignStatement assign = statement.assign; - printf(" %s%.*s %.*s %.*s\n", - assign.target_deref ? "^" : "", - (int)assign.target.length, assign.target.start, - (int)assign.op.length, assign.op.start, - (int)assign.value.length, assign.value.start); + case STATEMENT_ASSIGN: + { + struct AssignStatement assign = statement.assign; + printf(" %s%.*s %.*s %.*s\n", + assign.target_deref ? "^" : "", + (int)assign.target.length, assign.target.start, + (int)assign.op.length, assign.op.start, + (int)assign.value.length, assign.value.start); + break; + } + case STATEMENT_LABEL: + printf(" %.*s:\n", (int)statement.label.name.length, statement.label.name.start); + break; + case STATEMENT_GOTO: + printf(" goto %.*s\n", (int)statement.jump.label.length, statement.jump.label.start); + break; + case STATEMENT_SYSCALL: + printf(" syscall\n"); + break; } } } diff --git a/src/parser/ast.h b/src/parser/ast.h index 83483e9..4604e1a 100644 --- a/src/parser/ast.h +++ b/src/parser/ast.h @@ -26,6 +26,9 @@ struct Param enum StatementKind { STATEMENT_ASSIGN, + STATEMENT_LABEL, + STATEMENT_GOTO, + STATEMENT_SYSCALL, }; struct AssignStatement @@ -36,12 +39,24 @@ struct AssignStatement struct Token value; }; +struct LabelStatement +{ + struct Token name; +}; + +struct GotoStatement +{ + struct Token label; +}; + struct Statement { enum StatementKind kind; union { struct AssignStatement assign; + struct LabelStatement label; + struct GotoStatement jump; }; }; diff --git a/src/parser/parser.c b/src/parser/parser.c index d86502f..a125b7d 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -138,11 +138,34 @@ static bool parse_value(struct Parser* parser, struct Token* out) static bool parse_statement(struct Parser* parser, struct Statement* out) { + if (match_token(parser, TOKEN_SYSCALL)) + { + out->kind = STATEMENT_SYSCALL; + return true; + } + + if (match_token(parser, TOKEN_GOTO)) + { + if (!consume(parser, TOKEN_IDENTIFIER, "expected label after 'goto'")) + return false; + + out->kind = STATEMENT_GOTO; + out->jump.label = parser->previous; + return true; + } + bool deref = match_token(parser, TOKEN_CARET); if (!consume(parser, TOKEN_IDENTIFIER, "expected a statement")) return false; - struct Token target = parser->previous; + struct Token name = parser->previous; + + if (!deref && match_token(parser, TOKEN_COLON)) + { + out->kind = STATEMENT_LABEL; + out->label.name = name; + return true; + } if (!is_assign_op(parser->current.type)) { @@ -152,7 +175,7 @@ static bool parse_statement(struct Parser* parser, struct Statement* out) struct AssignStatement assign; assign.target_deref = deref; - assign.target = target; + assign.target = name; advance_parser(parser); assign.op = parser->previous; diff --git a/tests/parser_test.c b/tests/parser_test.c index 85626a0..ea18add 100644 --- a/tests/parser_test.c +++ b/tests/parser_test.c @@ -83,6 +83,27 @@ static void test_parse_proc_body(struct TestContext* context) free_program(&program); } +static void test_parse_simple_statements(struct TestContext* context) +{ + struct Lexer lexer = create_lexer("proc main\n{\nloop:\nsyscall\ngoto loop\n}\n"); + struct Program program; + + check(context, parse_program(&lexer, &program)); + check(context, program.procs[0].body_count == 3); + + struct Statement label = program.procs[0].body[0]; + check(context, label.kind == STATEMENT_LABEL); + check(context, text_is(label.label.name, "loop")); + + check(context, program.procs[0].body[1].kind == STATEMENT_SYSCALL); + + struct Statement jump = program.procs[0].body[2]; + check(context, jump.kind == STATEMENT_GOTO); + check(context, text_is(jump.jump.label, "loop")); + + free_program(&program); +} + static void test_parse_errors(struct TestContext* context) { struct Program program; @@ -106,5 +127,6 @@ void run_parser_tests(struct TestContext* context) test_parse_data(context); test_parse_proc_params(context); test_parse_proc_body(context); + test_parse_simple_statements(context); test_parse_errors(context); } |
