implemented labels and goto parsing
This commit is contained in:
parent
1be3bf0659
commit
1ca6f024ee
7 changed files with 71 additions and 17 deletions
21
examples/for.l
Normal file
21
examples/for.l
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import std::io;
|
||||||
|
|
||||||
|
i32 main()
|
||||||
|
{
|
||||||
|
[u32] list = [1, 2, 3, 4, 5];
|
||||||
|
|
||||||
|
// iterative loop
|
||||||
|
loop (0.., list) |i, v| {
|
||||||
|
printf("%d\n", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// conditional loop
|
||||||
|
loop a == 3 {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// infinite loop
|
||||||
|
loop {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
12
lc.c
12
lc.c
|
|
@ -76,6 +76,12 @@ void print_ast(ast_node *node, int depth) {
|
||||||
printf("Access: %.*s\n", (int)node->expr.access.member_len, node->expr.access.member);
|
printf("Access: %.*s\n", (int)node->expr.access.member_len, node->expr.access.member);
|
||||||
print_ast(node->expr.access.expr, depth + 1);
|
print_ast(node->expr.access.expr, depth + 1);
|
||||||
break;
|
break;
|
||||||
|
case NODE_LABEL:
|
||||||
|
printf("Label: %.*s\n", (int)node->expr.label.name_len, node->expr.label.name);
|
||||||
|
break;
|
||||||
|
case NODE_GOTO:
|
||||||
|
printf("Goto: %.*s\n", (int)node->expr.label.name_len, node->expr.label.name);
|
||||||
|
break;
|
||||||
case NODE_BINARY:
|
case NODE_BINARY:
|
||||||
printf("BinaryOp (%s)\n", get_op_str(node->expr.binary.operator));
|
printf("BinaryOp (%s)\n", get_op_str(node->expr.binary.operator));
|
||||||
print_ast(node->expr.binary.left, depth + 1);
|
print_ast(node->expr.binary.left, depth + 1);
|
||||||
|
|
@ -126,9 +132,6 @@ void print_ast(ast_node *node, int depth) {
|
||||||
case NODE_IF:
|
case NODE_IF:
|
||||||
printf("IfStmt (Fields missing in struct)\n");
|
printf("IfStmt (Fields missing in struct)\n");
|
||||||
break;
|
break;
|
||||||
case NODE_WHILE:
|
|
||||||
printf("WhileStmt (Fields missing in struct)\n");
|
|
||||||
break;
|
|
||||||
case NODE_VAR_DECL:
|
case NODE_VAR_DECL:
|
||||||
printf("VarDecl (Fields missing in struct)\n");
|
printf("VarDecl (Fields missing in struct)\n");
|
||||||
break;
|
break;
|
||||||
|
|
@ -136,7 +139,8 @@ void print_ast(ast_node *node, int depth) {
|
||||||
printf("FunctionDef (Fields missing in struct)\n");
|
printf("FunctionDef (Fields missing in struct)\n");
|
||||||
break;
|
break;
|
||||||
case NODE_RETURN:
|
case NODE_RETURN:
|
||||||
printf("Return (Fields missing in struct)\n");
|
printf("Return:\n");
|
||||||
|
print_ast(node->expr.ret.value, depth + 1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Unknown Node Type: %d\n", node->type);
|
printf("Unknown Node Type: %d\n", node->type);
|
||||||
|
|
|
||||||
3
lexer.c
3
lexer.c
|
|
@ -394,8 +394,7 @@ lexer *lexer_init(char *source, usize size, arena *arena)
|
||||||
trie_insert(keywords, lex->allocator, "struct", TOKEN_STRUCT);
|
trie_insert(keywords, lex->allocator, "struct", TOKEN_STRUCT);
|
||||||
trie_insert(keywords, lex->allocator, "enum", TOKEN_ENUM);
|
trie_insert(keywords, lex->allocator, "enum", TOKEN_ENUM);
|
||||||
trie_insert(keywords, lex->allocator, "union", TOKEN_UNION);
|
trie_insert(keywords, lex->allocator, "union", TOKEN_UNION);
|
||||||
trie_insert(keywords, lex->allocator, "while", TOKEN_WHILE);
|
trie_insert(keywords, lex->allocator, "loop", TOKEN_LOOP);
|
||||||
trie_insert(keywords, lex->allocator, "for", TOKEN_FOR);
|
|
||||||
trie_insert(keywords, lex->allocator, "goto", TOKEN_GOTO);
|
trie_insert(keywords, lex->allocator, "goto", TOKEN_GOTO);
|
||||||
trie_insert(keywords, lex->allocator, "if", TOKEN_IF);
|
trie_insert(keywords, lex->allocator, "if", TOKEN_IF);
|
||||||
trie_insert(keywords, lex->allocator, "else", TOKEN_ELSE);
|
trie_insert(keywords, lex->allocator, "else", TOKEN_ELSE);
|
||||||
|
|
|
||||||
3
lexer.h
3
lexer.h
|
|
@ -57,9 +57,8 @@ typedef enum {
|
||||||
TOKEN_STRING,
|
TOKEN_STRING,
|
||||||
TOKEN_CHAR,
|
TOKEN_CHAR,
|
||||||
|
|
||||||
TOKEN_WHILE,
|
|
||||||
TOKEN_FOR,
|
|
||||||
TOKEN_GOTO,
|
TOKEN_GOTO,
|
||||||
|
TOKEN_LOOP,
|
||||||
TOKEN_IF,
|
TOKEN_IF,
|
||||||
TOKEN_ELSE,
|
TOKEN_ELSE,
|
||||||
TOKEN_SWITCH,
|
TOKEN_SWITCH,
|
||||||
|
|
|
||||||
34
parser.c
34
parser.c
|
|
@ -66,8 +66,7 @@ static void parser_sync(parser *p)
|
||||||
case TOKEN_STRUCT:
|
case TOKEN_STRUCT:
|
||||||
case TOKEN_ENUM:
|
case TOKEN_ENUM:
|
||||||
case TOKEN_IF:
|
case TOKEN_IF:
|
||||||
case TOKEN_WHILE:
|
case TOKEN_LOOP:
|
||||||
case TOKEN_FOR:
|
|
||||||
case TOKEN_DO:
|
case TOKEN_DO:
|
||||||
case TOKEN_RETURN:
|
case TOKEN_RETURN:
|
||||||
case TOKEN_SWITCH:
|
case TOKEN_SWITCH:
|
||||||
|
|
@ -380,7 +379,7 @@ static ast_node *parse_statement(parser *p)
|
||||||
{
|
{
|
||||||
if (match(p, TOKEN_BREAK)) {
|
if (match(p, TOKEN_BREAK)) {
|
||||||
if (!match(p, TOKEN_SEMICOLON)) {
|
if (!match(p, TOKEN_SEMICOLON)) {
|
||||||
error(p, "expected `;`.");
|
error(p, "expected `;` after `break`.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
|
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
|
|
@ -390,7 +389,7 @@ static ast_node *parse_statement(parser *p)
|
||||||
ast_node *expr = parse_expression(p);
|
ast_node *expr = parse_expression(p);
|
||||||
|
|
||||||
if (!expr) {
|
if (!expr) {
|
||||||
error(p, "expected expression.");
|
error(p, "expected expression after `return`.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!match(p, TOKEN_SEMICOLON)) {
|
if (!match(p, TOKEN_SEMICOLON)) {
|
||||||
|
|
@ -402,13 +401,38 @@ static ast_node *parse_statement(parser *p)
|
||||||
node->type = NODE_RETURN;
|
node->type = NODE_RETURN;
|
||||||
node->expr.ret.value = expr;
|
node->expr.ret.value = expr;
|
||||||
return node;
|
return node;
|
||||||
|
} else if (match_peek(p, TOKEN_IDENTIFIER) && p->tokens->next && p->tokens->next->type == TOKEN_COLON) {
|
||||||
|
/* In this case, this is a label. */
|
||||||
|
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
|
node->type = NODE_LABEL;
|
||||||
|
node->expr.label.name = p->tokens->lexeme;
|
||||||
|
node->expr.label.name_len = p->tokens->lexeme_len;
|
||||||
|
advance(p);
|
||||||
|
/* Consume `:` */
|
||||||
|
advance(p);
|
||||||
|
return node;
|
||||||
|
} else if (match(p, TOKEN_GOTO)) {
|
||||||
|
if (!match_peek(p, TOKEN_IDENTIFIER)) {
|
||||||
|
error(p, "expected label identifier after `goto`.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
|
node->type = NODE_GOTO;
|
||||||
|
node->expr.label.name = p->tokens->lexeme;
|
||||||
|
node->expr.label.name_len = p->tokens->lexeme_len;
|
||||||
|
advance(p);
|
||||||
|
if (!match(p, TOKEN_SEMICOLON)) {
|
||||||
|
error(p, "expected `;` after `goto`.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return node;
|
||||||
} else {
|
} else {
|
||||||
ast_node *expr = parse_expression(p);
|
ast_node *expr = parse_expression(p);
|
||||||
if (!expr) {
|
if (!expr) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!match(p, TOKEN_SEMICOLON)) {
|
if (!match(p, TOKEN_SEMICOLON)) {
|
||||||
error(p, "expected `;`.");
|
error(p, "expected `;` after expression.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return expr;
|
return expr;
|
||||||
|
|
|
||||||
11
parser.h
11
parser.h
|
|
@ -75,9 +75,10 @@ typedef enum {
|
||||||
NODE_POSTFIX,
|
NODE_POSTFIX,
|
||||||
NODE_BREAK,
|
NODE_BREAK,
|
||||||
NODE_RETURN,
|
NODE_RETURN,
|
||||||
NODE_SWITCH,
|
NODE_LABEL,
|
||||||
NODE_FOR,
|
NODE_GOTO,
|
||||||
NODE_DO,
|
NODE_DO,
|
||||||
|
NODE_FOR,
|
||||||
NODE_WHILE,
|
NODE_WHILE,
|
||||||
NODE_IF,
|
NODE_IF,
|
||||||
NODE_COMPOUND,
|
NODE_COMPOUND,
|
||||||
|
|
@ -87,13 +88,17 @@ typedef enum {
|
||||||
NODE_VAR_DECL,
|
NODE_VAR_DECL,
|
||||||
NODE_FUNCTION,
|
NODE_FUNCTION,
|
||||||
NODE_TERNARY,
|
NODE_TERNARY,
|
||||||
NODE_GOTO,
|
NODE_SWITCH,
|
||||||
NODE_UNIT,
|
NODE_UNIT,
|
||||||
} node_type;
|
} node_type;
|
||||||
|
|
||||||
typedef struct _ast_node {
|
typedef struct _ast_node {
|
||||||
node_type type;
|
node_type type;
|
||||||
union {
|
union {
|
||||||
|
struct {
|
||||||
|
char *name;
|
||||||
|
usize name_len;
|
||||||
|
} label; // both label and goto
|
||||||
struct {
|
struct {
|
||||||
struct _ast_node *left;
|
struct _ast_node *left;
|
||||||
struct _ast_node *right;
|
struct _ast_node *right;
|
||||||
|
|
|
||||||
4
test.c
4
test.c
|
|
@ -1 +1,3 @@
|
||||||
x[3];
|
test:
|
||||||
|
goto test;
|
||||||
|
return 5;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue