aboutsummaryrefslogtreecommitdiff
path: root/src/parser.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2015-12-03 00:47:35 -0700
committerAndrew Kelley <superjoe30@gmail.com>2015-12-03 00:47:35 -0700
commitf8ca6c70c74db6e6f0d4462aa763adb6f1f41c7e (patch)
tree99bc3d06bb37abb267a2a59f3ba04523c2c430eb /src/parser.cpp
parentc89f77dd8e5005e60e8fb223c6c68b50566ac1ed (diff)
downloadzig-f8ca6c70c74db6e6f0d4462aa763adb6f1f41c7e.tar.gz
zig-f8ca6c70c74db6e6f0d4462aa763adb6f1f41c7e.zip
add labels and goto
Diffstat (limited to 'src/parser.cpp')
-rw-r--r--src/parser.cpp69
1 files changed, 62 insertions, 7 deletions
diff --git a/src/parser.cpp b/src/parser.cpp
index bd4c959608..24b7cc7790 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -95,6 +95,10 @@ const char *node_type_str(NodeType node_type) {
return "Void";
case NodeTypeIfExpr:
return "IfExpr";
+ case NodeTypeLabel:
+ return "Label";
+ case NodeTypeGoto:
+ return "Label";
}
zig_unreachable();
}
@@ -260,6 +264,12 @@ void ast_print(AstNode *node, int indent) {
if (node->data.if_expr.else_node)
ast_print(node->data.if_expr.else_node, indent + 2);
break;
+ case NodeTypeLabel:
+ fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.label.name));
+ break;
+ case NodeTypeGoto:
+ fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.go_to.name));
+ break;
}
}
@@ -581,7 +591,7 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, int *token_index, bool
}
/*
-PrimaryExpression : token(Number) | token(String) | token(Unreachable) | GroupedExpression | token(Symbol)
+PrimaryExpression : token(Number) | token(String) | token(Unreachable) | GroupedExpression | token(Symbol) | Goto
*/
static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {
Token *token = &pc->tokens->at(*token_index);
@@ -609,6 +619,16 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
ast_buf_from_token(pc, token, &node->data.symbol);
*token_index += 1;
return node;
+ } else if (token->id == TokenIdKeywordGoto) {
+ AstNode *node = ast_create_node(pc, NodeTypeGoto, token);
+ *token_index += 1;
+
+ Token *dest_symbol = &pc->tokens->at(*token_index);
+ *token_index += 1;
+ ast_expect_token(pc, dest_symbol, TokenIdSymbol);
+
+ ast_buf_from_token(pc, dest_symbol, &node->data.go_to.name);
+ return node;
}
AstNode *grouped_expr_node = ast_parse_grouped_expr(pc, token_index, false);
@@ -1181,7 +1201,36 @@ static AstNode *ast_parse_expression(ParseContext *pc, int *token_index, bool ma
}
/*
-Statement : NonBlockExpression token(Semicolon) | BlockExpression
+Label: token(Symbol) token(Colon)
+*/
+static AstNode *ast_parse_label(ParseContext *pc, int *token_index, bool mandatory) {
+ Token *symbol_token = &pc->tokens->at(*token_index);
+ if (symbol_token->id != TokenIdSymbol) {
+ if (mandatory) {
+ ast_invalid_token_error(pc, symbol_token);
+ } else {
+ return nullptr;
+ }
+ }
+
+ Token *colon_token = &pc->tokens->at(*token_index + 1);
+ if (colon_token->id != TokenIdColon) {
+ if (mandatory) {
+ ast_invalid_token_error(pc, colon_token);
+ } else {
+ return nullptr;
+ }
+ }
+
+ *token_index += 2;
+
+ AstNode *node = ast_create_node(pc, NodeTypeLabel, symbol_token);
+ ast_buf_from_token(pc, symbol_token, &node->data.label.name);
+ return node;
+}
+
+/*
+Statement : Label | NonBlockExpression token(Semicolon) | BlockExpression
Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)
*/
static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandatory) {
@@ -1204,12 +1253,18 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato
// {2;} -> {2;void}
// {;2} -> {void;2}
for (;;) {
- AstNode *statement_node = ast_parse_block_expr(pc, token_index, false);
- bool semicolon_expected = !statement_node;
- if (!statement_node) {
- statement_node = ast_parse_non_block_expr(pc, token_index, false);
+ AstNode *statement_node = ast_parse_label(pc, token_index, false);
+ bool semicolon_expected;
+ if (statement_node) {
+ semicolon_expected = false;
+ } else {
+ statement_node = ast_parse_block_expr(pc, token_index, false);
+ semicolon_expected = !statement_node;
if (!statement_node) {
- statement_node = ast_create_node(pc, NodeTypeVoid, last_token);
+ statement_node = ast_parse_non_block_expr(pc, token_index, false);
+ if (!statement_node) {
+ statement_node = ast_create_node(pc, NodeTypeVoid, last_token);
+ }
}
}
node->data.block.statements.append(statement_node);