aboutsummaryrefslogtreecommitdiff
path: root/src/parser.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2015-12-12 00:10:37 -0700
committerAndrew Kelley <superjoe30@gmail.com>2015-12-12 00:10:37 -0700
commita10277bd949d47370e427d4457d93e907de9a6f7 (patch)
tree4f5ca4247559c679a5a04ea0816c2c78f90211ed /src/parser.cpp
parent4c16eaa6401786e6c2de84d7c9f231107d6f2cb7 (diff)
downloadzig-a10277bd949d47370e427d4457d93e907de9a6f7.tar.gz
zig-a10277bd949d47370e427d4457d93e907de9a6f7.zip
prepare codebase for struct and string support
parsing code for structs, strings, and c string literals partial semantic analyzing code for structs, strings, and c string literals
Diffstat (limited to 'src/parser.cpp')
-rw-r--r--src/parser.cpp156
1 files changed, 126 insertions, 30 deletions
diff --git a/src/parser.cpp b/src/parser.cpp
index 29bc069429..9497224fbb 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -106,6 +106,12 @@ const char *node_type_str(NodeType node_type) {
return "Label";
case NodeTypeAsmExpr:
return "AsmExpr";
+ case NodeTypeFieldAccessExpr:
+ return "FieldAccessExpr";
+ case NodeTypeStructDecl:
+ return "StructDecl";
+ case NodeTypeStructField:
+ return "StructField";
}
zig_unreachable();
}
@@ -259,9 +265,12 @@ void ast_print(AstNode *node, int indent) {
buf_ptr(&node->data.number));
break;
case NodeTypeStringLiteral:
- fprintf(stderr, "StringLiteral '%s'\n",
- buf_ptr(&node->data.string));
- break;
+ {
+ const char *c = node->data.string_literal.c ? "c" : "";
+ fprintf(stderr, "StringLiteral %s'%s'\n", c,
+ buf_ptr(&node->data.string_literal.buf));
+ break;
+ }
case NodeTypeUnreachable:
fprintf(stderr, "Unreachable\n");
break;
@@ -295,6 +304,19 @@ void ast_print(AstNode *node, int indent) {
case NodeTypeAsmExpr:
fprintf(stderr, "%s\n", node_type_str(node->type));
break;
+ case NodeTypeFieldAccessExpr:
+ fprintf(stderr, "%s '%s'\n", node_type_str(node->type),
+ buf_ptr(&node->data.field_access_expr.field_name));
+ ast_print(node->data.field_access_expr.struct_expr, indent + 2);
+ break;
+ case NodeTypeStructDecl:
+ fprintf(stderr, "%s '%s'\n",
+ node_type_str(node->type), buf_ptr(&node->data.struct_decl.name));
+ break;
+ case NodeTypeStructField:
+ fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_field.name));
+ ast_print(node->data.struct_field.type, indent + 2);
+ break;
}
}
@@ -475,18 +497,28 @@ static void parse_asm_template(ParseContext *pc, AstNode *node) {
}
}
-static void parse_string_literal(ParseContext *pc, Token *token, Buf *buf, ZigList<SrcPos> *offset_map) {
+static void parse_string_literal(ParseContext *pc, Token *token, Buf *buf, bool *out_c_str,
+ ZigList<SrcPos> *offset_map)
+{
// skip the double quotes at beginning and end
// convert escape sequences
+ // detect c string literal
buf_resize(buf, 0);
bool escape = false;
- bool first = true;
+ bool skip_quote;
SrcPos pos = {token->start_line, token->start_column};
for (int i = token->start_pos; i < token->end_pos - 1; i += 1) {
uint8_t c = *((uint8_t*)buf_ptr(pc->buf) + i);
- if (first) {
- first = false;
+ if (i == token->start_pos) {
+ skip_quote = (c == 'c');
+ if (out_c_str) {
+ *out_c_str = skip_quote;
+ } else if (skip_quote) {
+ ast_error(pc, token, "C string literal not allowed here");
+ }
+ } else if (skip_quote) {
+ skip_quote = false;
} else {
if (escape) {
switch (c) {
@@ -541,13 +573,20 @@ static AstNode *ast_parse_expression(ParseContext *pc, int *token_index, bool ma
static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandatory);
static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool mandatory);
-
static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) {
if (token->id != token_id) {
ast_invalid_token_error(pc, token);
}
}
+static Token *ast_eat_token(ParseContext *pc, int *token_index, TokenId token_id) {
+ Token *token = &pc->tokens->at(*token_index);
+ ast_expect_token(pc, token, token_id);
+ *token_index += 1;
+ return token;
+}
+
+
static AstNode *ast_parse_directive(ParseContext *pc, int token_index, int *new_token_index) {
Token *number_sign = &pc->tokens->at(token_index);
token_index += 1;
@@ -569,7 +608,7 @@ static AstNode *ast_parse_directive(ParseContext *pc, int token_index, int *new_
token_index += 1;
ast_expect_token(pc, param_str, TokenIdStringLiteral);
- parse_string_literal(pc, param_str, &node->data.directive.param, nullptr);
+ parse_string_literal(pc, param_str, &node->data.directive.param, nullptr, nullptr);
Token *r_paren = &pc->tokens->at(token_index);
token_index += 1;
@@ -782,7 +821,7 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
return node;
} else if (token->id == TokenIdStringLiteral) {
AstNode *node = ast_create_node(pc, NodeTypeStringLiteral, token);
- parse_string_literal(pc, token, &node->data.string, nullptr);
+ parse_string_literal(pc, token, &node->data.string_literal.buf, &node->data.string_literal.c, nullptr);
*token_index += 1;
return node;
} else if (token->id == TokenIdKeywordUnreachable) {
@@ -832,9 +871,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
}
/*
-SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression)
+SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression)
FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)
ArrayAccessExpression : token(LBracket) Expression token(RBracket)
+FieldAccessExpression : token(Dot) token(Symbol)
*/
static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, bool mandatory) {
AstNode *primary_expr = ast_parse_primary_expr(pc, token_index, mandatory);
@@ -862,6 +902,16 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, boo
ast_expect_token(pc, r_bracket, TokenIdRBracket);
return node;
+ } else if (token->id == TokenIdDot) {
+ *token_index += 1;
+
+ Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);
+
+ AstNode *node = ast_create_node(pc, NodeTypeFieldAccessExpr, token);
+ node->data.field_access_expr.struct_expr = primary_expr;
+ ast_buf_from_token(pc, name_token, &node->data.field_access_expr.field_name);
+
+ return node;
} else {
return primary_expr;
}
@@ -1397,14 +1447,6 @@ static AstNode *ast_parse_ass_expr(ParseContext *pc, int *token_index, bool mand
return node;
}
-static Token *ast_eat_token(ParseContext *pc, int *token_index, TokenId token_id) {
- Token *token = &pc->tokens->at(*token_index);
- ast_expect_token(pc, token, token_id);
- *token_index += 1;
- return token;
-}
-
-
/*
AsmInputItem : token(LBracket) token(Symbol) token(RBracket) token(String) token(LParen) Expression token(RParen)
*/
@@ -1421,7 +1463,7 @@ static void ast_parse_asm_input_item(ParseContext *pc, int *token_index, AstNode
AsmInput *asm_input = allocate<AsmInput>(1);
ast_buf_from_token(pc, alias, &asm_input->asm_symbolic_name);
- parse_string_literal(pc, constraint, &asm_input->constraint, nullptr);
+ parse_string_literal(pc, constraint, &asm_input->constraint, nullptr, nullptr);
asm_input->expr = expr_node;
node->data.asm_expr.input_list.append(asm_input);
}
@@ -1442,7 +1484,7 @@ static void ast_parse_asm_output_item(ParseContext *pc, int *token_index, AstNod
AsmOutput *asm_output = allocate<AsmOutput>(1);
ast_buf_from_token(pc, alias, &asm_output->asm_symbolic_name);
- parse_string_literal(pc, constraint, &asm_output->constraint, nullptr);
+ parse_string_literal(pc, constraint, &asm_output->constraint, nullptr, nullptr);
ast_buf_from_token(pc, out_symbol, &asm_output->variable_name);
node->data.asm_expr.output_list.append(asm_output);
}
@@ -1464,7 +1506,7 @@ static void ast_parse_asm_clobbers(ParseContext *pc, int *token_index, AstNode *
*token_index += 1;
Buf *clobber_buf = buf_alloc();
- parse_string_literal(pc, string_tok, clobber_buf, nullptr);
+ parse_string_literal(pc, string_tok, clobber_buf, nullptr, nullptr);
node->data.asm_expr.clobber_list.append(clobber_buf);
Token *comma = &pc->tokens->at(*token_index);
@@ -1565,7 +1607,7 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc, int *token_index, bool mand
ast_expect_token(pc, template_tok, TokenIdStringLiteral);
*token_index += 1;
- parse_string_literal(pc, template_tok, &node->data.asm_expr.asm_template,
+ parse_string_literal(pc, template_tok, &node->data.asm_expr.asm_template, nullptr,
&node->data.asm_expr.offset_map);
parse_asm_template(pc, node);
@@ -1877,7 +1919,7 @@ static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index, b
*token_index += 1;
ast_expect_token(pc, export_name, TokenIdStringLiteral);
- parse_string_literal(pc, export_name, &node->data.root_export_decl.name, nullptr);
+ parse_string_literal(pc, export_name, &node->data.root_export_decl.name, nullptr, nullptr);
Token *semicolon = &pc->tokens->at(*token_index);
*token_index += 1;
@@ -1889,9 +1931,7 @@ static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index, b
/*
Use : many(Directive) token(Use) token(String) token(Semicolon)
*/
-static AstNode *ast_parse_use(ParseContext *pc, int *token_index, bool mandatory) {
- assert(mandatory == false);
-
+static AstNode *ast_parse_use(ParseContext *pc, int *token_index) {
Token *use_kw = &pc->tokens->at(*token_index);
if (use_kw->id != TokenIdKeywordUse)
return nullptr;
@@ -1907,7 +1947,7 @@ static AstNode *ast_parse_use(ParseContext *pc, int *token_index, bool mandatory
AstNode *node = ast_create_node(pc, NodeTypeUse, use_kw);
- parse_string_literal(pc, use_name, &node->data.use.path, nullptr);
+ parse_string_literal(pc, use_name, &node->data.use.path, nullptr, nullptr);
node->data.use.directives = pc->directive_list;
pc->directive_list = nullptr;
@@ -1916,7 +1956,57 @@ static AstNode *ast_parse_use(ParseContext *pc, int *token_index, bool mandatory
}
/*
-TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use
+StructDecl : many(Directive) token(Struct) token(Symbol) token(LBrace) many(StructField) token(RBrace)
+StructField : token(Symbol) token(Colon) Type token(Comma)
+*/
+static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {
+ Token *struct_kw = &pc->tokens->at(*token_index);
+ if (struct_kw->id != TokenIdKeywordStruct)
+ return nullptr;
+ *token_index += 1;
+
+ Token *struct_name = &pc->tokens->at(*token_index);
+ *token_index += 1;
+ ast_expect_token(pc, struct_name, TokenIdSymbol);
+
+ AstNode *node = ast_create_node(pc, NodeTypeStructDecl, struct_kw);
+ ast_buf_from_token(pc, struct_name, &node->data.struct_decl.name);
+
+ ast_eat_token(pc, token_index, TokenIdLBrace);
+
+ for (;;) {
+ Token *token = &pc->tokens->at(*token_index);
+
+ if (token->id == TokenIdRBrace) {
+ *token_index += 1;
+ break;
+ } else if (token->id == TokenIdSymbol) {
+ AstNode *field_node = ast_create_node(pc, NodeTypeStructField, token);
+ *token_index += 1;
+
+ ast_buf_from_token(pc, token, &field_node->data.struct_field.name);
+
+ ast_eat_token(pc, token_index, TokenIdColon);
+
+ field_node->data.struct_field.type = ast_parse_type(pc, *token_index, token_index);
+
+ ast_eat_token(pc, token_index, TokenIdComma);
+
+ node->data.struct_decl.fields.append(field_node);
+ } else {
+ ast_invalid_token_error(pc, token);
+ }
+ }
+
+
+ node->data.struct_decl.directives = pc->directive_list;
+ pc->directive_list = nullptr;
+
+ return node;
+}
+
+/*
+TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl
*/
static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) {
for (;;) {
@@ -1943,12 +2033,18 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis
continue;
}
- AstNode *use_node = ast_parse_use(pc, token_index, false);
+ AstNode *use_node = ast_parse_use(pc, token_index);
if (use_node) {
top_level_decls->append(use_node);
continue;
}
+ AstNode *struct_node = ast_parse_struct_decl(pc, token_index);
+ if (struct_node) {
+ top_level_decls->append(struct_node);
+ continue;
+ }
+
if (pc->directive_list->length > 0) {
ast_error(pc, directive_token, "invalid directive");
}