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) {...@@ -114,6 +114,9 @@ static void begin_token(CTokenize *ctok, CTokId id) {
114 case CTokIdCharLit:114 case CTokIdCharLit:
115 case CTokIdNumLitFloat:115 case CTokIdNumLitFloat:
116 case CTokIdMinus:116 case CTokIdMinus:
117 case CTokIdLParen:
118 case CTokIdRParen:
119 case CTokIdEOF:
117 break;120 break;
118 }121 }
119}122}
...@@ -214,6 +217,18 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {...@@ -214,6 +217,18 @@ void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {
214 ctok->state = CTokStateFloat;217 ctok->state = CTokStateFloat;
215 buf_init_from_str(&ctok->buf, "0.");218 buf_init_from_str(&ctok->buf, "0.");
216 break;219 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;
217 default:232 default:
218 return mark_error(ctok);233 return mark_error(ctok);
219 }234 }
...@@ -738,4 +753,7 @@ found_end_of_macro:...@@ -738,4 +753,7 @@ found_end_of_macro:
738 }753 }
739754
740 assert(ctok->cur_tok == nullptr);755 assert(ctok->cur_tok == nullptr);
756
757 begin_token(ctok, CTokIdEOF);
758 end_token(ctok);
741}759}
src/c_tokenizer.hpp+3
...@@ -18,6 +18,9 @@ enum CTokId {...@@ -18,6 +18,9 @@ enum CTokId {
18 CTokIdNumLitFloat,18 CTokIdNumLitFloat,
19 CTokIdSymbol,19 CTokIdSymbol,
20 CTokIdMinus,20 CTokIdMinus,
21 CTokIdLParen,
22 CTokIdRParen,
23 CTokIdEOF,
21};24};
2225
23enum CNumLitSuffix {26enum CNumLitSuffix {
src/parsec.cpp+92-76
...@@ -2469,6 +2469,74 @@ static void render_macros(Context *c) {...@@ -2469,6 +2469,74 @@ static void render_macros(Context *c) {
2469 }2469 }
2470}2470}
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
2472static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *char_ptr) {2540static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *char_ptr) {
2473 tokenize_c_macro(ctok, (const uint8_t *)char_ptr);2541 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...@@ -2476,81 +2544,29 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch
2476 return;2544 return;
2477 }2545 }
24782546
2479 bool negate = false;2547 size_t tok_i = 0;
2480 for (size_t i = 0; i < ctok->tokens.length; i += 1) {2548 CTok *name_tok = &ctok->tokens.at(tok_i);
2481 bool is_first = (i == 0);2549 assert(name_tok->id == CTokIdSymbol && buf_eql_buf(&name_tok->data.symbol, name));
2482 bool is_last = (i == ctok->tokens.length - 1);2550 tok_i += 1;
2483 CTok *tok = &ctok->tokens.at(i);2551
2484 switch (tok->id) {2552 AstNode *result_node = parse_ctok(c, ctok, &tok_i);
2485 case CTokIdCharLit:2553 if (result_node == nullptr) {
2486 if (is_last && is_first) {2554 return;
2487 AstNode *node = trans_create_node_unsigned(c, tok->data.char_lit);2555 }
2488 c->macro_table.put(name, node);2556 CTok *eof_tok = &ctok->tokens.at(tok_i);
2489 }2557 if (eof_tok->id != CTokIdEOF) {
2490 return;2558 return;
2491 case CTokIdStrLit:2559 }
2492 if (is_last && is_first) {2560 if (result_node->type == NodeTypeSymbol) {
2493 AstNode *node = trans_create_node_str_lit_c(c, buf_create_from_buf(&tok->data.str_lit));2561 // if it equals itself, ignore. for example, from stdio.h:
2494 c->macro_table.put(name, node);2562 // #define stdin stdin
2495 }2563 Buf *symbol_name = result_node->data.symbol_expr.symbol;
2496 return;2564 if (buf_eql_buf(name, symbol_name)) {
2497 case CTokIdNumLitInt:2565 return;
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 }
2553 }2566 }
2567 c->macro_symbols.append({name, symbol_name});
2568 } else {
2569 c->macro_table.put(name, result_node);
2554 }2570 }
2555}2571}
25562572
...@@ -2613,8 +2629,8 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) {...@@ -2613,8 +2629,8 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) {
2613 continue;2629 continue;
2614 }2630 }
26152631
2616 const char *end_c = c->source_manager->getCharacterData(end_loc);2632 const char *begin_c = c->source_manager->getCharacterData(begin_loc);
2617 process_macro(c, &ctok, name, end_c);2633 process_macro(c, &ctok, name, begin_c);
2618 }2634 }
2619 }2635 }
2620 }2636 }
test/parsec.zig+6
...@@ -296,4 +296,10 @@ pub fn addCases(cases: &tests.ParseCContext) {...@@ -296,4 +296,10 @@ pub fn addCases(cases: &tests.ParseCContext) {
296 ,296 ,
297 \\pub const FOO_CHAR = 63;297 \\pub const FOO_CHAR = 63;
298 );298 );
299
300 cases.add("macro with parens around negative number",
301 \\#define LUA_GLOBALSINDEX (-10002)
302 ,
303 \\pub const LUA_GLOBALSINDEX = -10002;
304 );
299}305}