diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2015-12-10 15:34:38 -0700 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2015-12-10 15:34:38 -0700 |
| commit | 0dbee2300ed28c18ecccaf71f10f68eb2da71266 (patch) | |
| tree | ac804032eccb2f07258b45023739b694ee937d8c /src/parser.cpp | |
| parent | 3e8a98fa619516d0617a827a79601264a554d88b (diff) | |
| download | zig-0dbee2300ed28c18ecccaf71f10f68eb2da71266.tar.gz zig-0dbee2300ed28c18ecccaf71f10f68eb2da71266.zip | |
add inline assembly support
Diffstat (limited to 'src/parser.cpp')
| -rw-r--r-- | src/parser.cpp | 119 |
1 files changed, 118 insertions, 1 deletions
diff --git a/src/parser.cpp b/src/parser.cpp index 6c8a54ad9e..6740a065a2 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -104,6 +104,8 @@ const char *node_type_str(NodeType node_type) { return "Label"; case NodeTypeGoto: return "Label"; + case NodeTypeAsmExpr: + return "AsmExpr"; } zig_unreachable(); } @@ -290,6 +292,9 @@ void ast_print(AstNode *node, int indent) { case NodeTypeGoto: fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.go_to.name)); break; + case NodeTypeAsmExpr: + fprintf(stderr, "%s\n", node_type_str(node->type)); + break; } } @@ -360,6 +365,71 @@ static void ast_buf_from_token(ParseContext *pc, Token *token, Buf *buf) { buf_init_from_mem(buf, buf_ptr(pc->buf) + token->start_pos, token->end_pos - token->start_pos); } +static void parse_asm_template(ParseContext *pc, AstNode *node) { + Buf *asm_template = &node->data.asm_expr.asm_template; + + enum State { + StateStart, + StatePercent, + StateTemplate, + }; + + ZigList<AsmToken> *tok_list = &node->data.asm_expr.token_list; + assert(tok_list->length == 0); + + AsmToken *cur_tok = nullptr; + + enum State state = StateStart; + + for (int i = 0; i < buf_len(asm_template); i += 1) { + uint8_t c = *((uint8_t*)buf_ptr(asm_template) + i); + switch (state) { + case StateStart: + if (c == '%') { + tok_list->add_one(); + cur_tok = &tok_list->last(); + cur_tok->id = AsmTokenIdPercent; + cur_tok->start = i; + state = StatePercent; + } else { + tok_list->add_one(); + cur_tok = &tok_list->last(); + cur_tok->id = AsmTokenIdTemplate; + cur_tok->start = i; + state = StateTemplate; + } + break; + case StatePercent: + if (c == '%') { + cur_tok->end = i; + state = StateStart; + } else { + zig_panic("TODO handle assembly tokenize error"); + } + break; + case StateTemplate: + if (c == '%') { + cur_tok->end = i; + i -= 1; + cur_tok = nullptr; + state = StateStart; + } + break; + } + } + + switch (state) { + case StateStart: + break; + case StatePercent: + zig_panic("TODO handle assembly tokenize error eof"); + break; + case StateTemplate: + cur_tok->end = buf_len(asm_template); + break; + } +} + static void parse_string_literal(ParseContext *pc, Token *token, Buf *buf) { // skip the double quotes at beginning and end // convert escape sequences @@ -1264,7 +1334,50 @@ static AstNode *ast_parse_ass_expr(ParseContext *pc, int *token_index, bool mand } /* -NonBlockExpression : ReturnExpression | AssignmentExpression +AsmExpression : token(Asm) option(token(Volatile)) token(LParen) token(String) option(AsmOutput) token(RParen) +*/ +static AstNode *ast_parse_asm_expr(ParseContext *pc, int *token_index, bool mandatory) { + Token *asm_token = &pc->tokens->at(*token_index); + + if (asm_token->id != TokenIdKeywordAsm) { + if (mandatory) { + ast_invalid_token_error(pc, asm_token); + } else { + return nullptr; + } + } + + AstNode *node = ast_create_node(pc, NodeTypeAsmExpr, asm_token); + + *token_index += 1; + Token *lparen_tok = &pc->tokens->at(*token_index); + + if (lparen_tok->id == TokenIdKeywordVolatile) { + node->data.asm_expr.is_volatile = true; + + *token_index += 1; + lparen_tok = &pc->tokens->at(*token_index); + } + + ast_expect_token(pc, lparen_tok, TokenIdLParen); + *token_index += 1; + + Token *template_tok = &pc->tokens->at(*token_index); + ast_expect_token(pc, template_tok, TokenIdStringLiteral); + *token_index += 1; + + parse_string_literal(pc, template_tok, &node->data.asm_expr.asm_template); + parse_asm_template(pc, node); + + Token *rparen_tok = &pc->tokens->at(*token_index); + ast_expect_token(pc, rparen_tok, TokenIdRParen); + *token_index += 1; + + return node; +} + +/* +NonBlockExpression : ReturnExpression | AssignmentExpression | AsmExpression */ static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, bool mandatory) { Token *token = &pc->tokens->at(*token_index); @@ -1277,6 +1390,10 @@ static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, boo if (ass_expr) return ass_expr; + AstNode *asm_expr = ast_parse_asm_expr(pc, token_index, false); + if (asm_expr) + return asm_expr; + if (mandatory) ast_invalid_token_error(pc, token); |
