authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-09-10 00:20:09-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-09-10 00:20:09-04:00
logb5d9584e6fc9e113435e0d555c2df62379cdcb8b
tree24714d2331b009607a7acd83c5c4dde031c70891
parent9dfbdeace6fd6fbeaea38bd48757f0ca0aee09a9

support parens in C macros

closes #454

4 files changed, 119 insertions(+), 76 deletions(-)

src/c_tokenizer.cpp+18
......@@ -114,6 +114,9 @@ static void begin_token(CTokenize *ctok, CTokId id) {
114114 case CTokIdCharLit:
115115 case CTokIdNumLitFloat:
116116 case CTokIdMinus:
117 case CTokIdLParen:
118 case CTokIdRParen:
119 case CTokIdEOF:
117120 break;
118121 }
119122}
......@@ -214,6 +217,18 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {
214217 ctok->state = CTokStateFloat;
215218 buf_init_from_str(&ctok->buf, "0.");
216219 break;
220 case '(':
221 begin_token(ctok, CTokIdLParen);
222 end_token(ctok);
223 break;
224 case ')':
225 begin_token(ctok, CTokIdRParen);
226 end_token(ctok);
227 break;
228 case '-':
229 begin_token(ctok, CTokIdMinus);
230 end_token(ctok);
231 break;
217232 default:
218233 return mark_error(ctok);
219234 }
......@@ -738,4 +753,7 @@ found_end_of_macro:
738753 }
739754
740755 assert(ctok->cur_tok == nullptr);
756
757 begin_token(ctok, CTokIdEOF);
758 end_token(ctok);
741759}
src/c_tokenizer.hpp+3
......@@ -18,6 +18,9 @@ enum CTokId {
1818 CTokIdNumLitFloat,
1919 CTokIdSymbol,
2020 CTokIdMinus,
21 CTokIdLParen,
22 CTokIdRParen,
23 CTokIdEOF,
2124};
2225
2326enum CNumLitSuffix {
src/parsec.cpp+92-76
......@@ -2469,6 +2469,74 @@ static void render_macros(Context *c) {
24692469 }
24702470}
24712471
2472static AstNode *parse_ctok_num_lit(Context *c, CTokenize *ctok, size_t *tok_i, bool negate) {
2473 CTok *tok = &ctok->tokens.at(*tok_i);
2474 if (tok->id == CTokIdNumLitInt) {
2475 *tok_i += 1;
2476 switch (tok->data.num_lit_int.suffix) {
2477 case CNumLitSuffixNone:
2478 return trans_create_node_unsigned_negative(c, tok->data.num_lit_int.x, negate);
2479 case CNumLitSuffixL:
2480 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_long");
2481 case CNumLitSuffixU:
2482 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_uint");
2483 case CNumLitSuffixLU:
2484 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_ulong");
2485 case CNumLitSuffixLL:
2486 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_longlong");
2487 case CNumLitSuffixLLU:
2488 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_ulonglong");
2489 }
2490 zig_unreachable();
2491 } else if (tok->id == CTokIdNumLitFloat) {
2492 *tok_i += 1;
2493 double value = negate ? -tok->data.num_lit_float : tok->data.num_lit_float;
2494 return trans_create_node_float_lit(c, value);
2495 }
2496 return nullptr;
2497}
2498
2499static AstNode *parse_ctok(Context *c, CTokenize *ctok, size_t *tok_i) {
2500 CTok *tok = &ctok->tokens.at(*tok_i);
2501 switch (tok->id) {
2502 case CTokIdCharLit:
2503 *tok_i += 1;
2504 return trans_create_node_unsigned(c, tok->data.char_lit);
2505 case CTokIdStrLit:
2506 *tok_i += 1;
2507 return trans_create_node_str_lit_c(c, buf_create_from_buf(&tok->data.str_lit));
2508 case CTokIdMinus:
2509 *tok_i += 1;
2510 return parse_ctok_num_lit(c, ctok, tok_i, true);
2511 case CTokIdNumLitInt:
2512 case CTokIdNumLitFloat:
2513 return parse_ctok_num_lit(c, ctok, tok_i, false);
2514 case CTokIdSymbol:
2515 {
2516 *tok_i += 1;
2517 Buf *symbol_name = buf_create_from_buf(&tok->data.symbol);
2518 return trans_create_node_symbol(c, symbol_name);
2519 }
2520 case CTokIdLParen:
2521 {
2522 *tok_i += 1;
2523 AstNode *inner_node = parse_ctok(c, ctok, tok_i);
2524
2525 CTok *next_tok = &ctok->tokens.at(*tok_i);
2526 if (next_tok->id != CTokIdRParen) {
2527 return nullptr;
2528 }
2529 *tok_i += 1;
2530 return inner_node;
2531 }
2532 case CTokIdEOF:
2533 case CTokIdRParen:
2534 // not able to make sense of this
2535 return nullptr;
2536 }
2537 zig_unreachable();
2538}
2539
24722540static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *char_ptr) {
24732541 tokenize_c_macro(ctok, (const uint8_t *)char_ptr);
24742542
......@@ -2476,81 +2544,29 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch
24762544 return;
24772545 }
24782546
2479 bool negate = false;
2480 for (size_t i = 0; i < ctok->tokens.length; i += 1) {
2481 bool is_first = (i == 0);
2482 bool is_last = (i == ctok->tokens.length - 1);
2483 CTok *tok = &ctok->tokens.at(i);
2484 switch (tok->id) {
2485 case CTokIdCharLit:
2486 if (is_last && is_first) {
2487 AstNode *node = trans_create_node_unsigned(c, tok->data.char_lit);
2488 c->macro_table.put(name, node);
2489 }
2490 return;
2491 case CTokIdStrLit:
2492 if (is_last && is_first) {
2493 AstNode *node = trans_create_node_str_lit_c(c, buf_create_from_buf(&tok->data.str_lit));
2494 c->macro_table.put(name, node);
2495 }
2496 return;
2497 case CTokIdNumLitInt:
2498 if (is_last) {
2499 AstNode *node;
2500 switch (tok->data.num_lit_int.suffix) {
2501 case CNumLitSuffixNone:
2502 node = trans_create_node_unsigned_negative(c, tok->data.num_lit_int.x, negate);
2503 break;
2504 case CNumLitSuffixL:
2505 node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate,
2506 "c_long");
2507 break;
2508 case CNumLitSuffixU:
2509 node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate,
2510 "c_uint");
2511 break;
2512 case CNumLitSuffixLU:
2513 node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate,
2514 "c_ulong");
2515 break;
2516 case CNumLitSuffixLL:
2517 node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate,
2518 "c_longlong");
2519 break;
2520 case CNumLitSuffixLLU:
2521 node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate,
2522 "c_ulonglong");
2523 break;
2524 }
2525 c->macro_table.put(name, node);
2526 }
2527 return;
2528 case CTokIdNumLitFloat:
2529 if (is_last) {
2530 double value = negate ? -tok->data.num_lit_float : tok->data.num_lit_float;
2531 AstNode *node = trans_create_node_float_lit(c, value);
2532 c->macro_table.put(name, node);
2533 }
2534 return;
2535 case CTokIdSymbol:
2536 if (is_last && is_first) {
2537 // if it equals itself, ignore. for example, from stdio.h:
2538 // #define stdin stdin
2539 Buf *symbol_name = buf_create_from_buf(&tok->data.symbol);
2540 if (buf_eql_buf(name, symbol_name)) {
2541 return;
2542 }
2543 c->macro_symbols.append({name, symbol_name});
2544 return;
2545 }
2546 case CTokIdMinus:
2547 if (is_first) {
2548 negate = true;
2549 break;
2550 } else {
2551 return;
2552 }
2547 size_t tok_i = 0;
2548 CTok *name_tok = &ctok->tokens.at(tok_i);
2549 assert(name_tok->id == CTokIdSymbol && buf_eql_buf(&name_tok->data.symbol, name));
2550 tok_i += 1;
2551
2552 AstNode *result_node = parse_ctok(c, ctok, &tok_i);
2553 if (result_node == nullptr) {
2554 return;
2555 }
2556 CTok *eof_tok = &ctok->tokens.at(tok_i);
2557 if (eof_tok->id != CTokIdEOF) {
2558 return;
2559 }
2560 if (result_node->type == NodeTypeSymbol) {
2561 // if it equals itself, ignore. for example, from stdio.h:
2562 // #define stdin stdin
2563 Buf *symbol_name = result_node->data.symbol_expr.symbol;
2564 if (buf_eql_buf(name, symbol_name)) {
2565 return;
25532566 }
2567 c->macro_symbols.append({name, symbol_name});
2568 } else {
2569 c->macro_table.put(name, result_node);
25542570 }
25552571}
25562572
......@@ -2613,8 +2629,8 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) {
26132629 continue;
26142630 }
26152631
2616 const char *end_c = c->source_manager->getCharacterData(end_loc);
2617 process_macro(c, &ctok, name, end_c);
2632 const char *begin_c = c->source_manager->getCharacterData(begin_loc);
2633 process_macro(c, &ctok, name, begin_c);
26182634 }
26192635 }
26202636 }
test/parsec.zig+6
......@@ -296,4 +296,10 @@ pub fn addCases(cases: &tests.ParseCContext) {
296296 ,
297297 \\pub const FOO_CHAR = 63;
298298 );
299
300 cases.add("macro with parens around negative number",
301 \\#define LUA_GLOBALSINDEX (-10002)
302 ,
303 \\pub const LUA_GLOBALSINDEX = -10002;
304 );
299305}