authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-29 00:28:52-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-29 00:28:52-07:00
log9b2ed1fac53319cbddb2752409e166334bb339bf
treefe546d1f1e6ad720bd9f1b999f7b08d88b05a8ec
parent923e78785d8505d16026f1c2b78079b79adac8fa

parseh understands simple character literal macro


5 files changed, 111 insertions(+), 46 deletions(-)

src/ast_render.cpp+15-1
......@@ -497,6 +497,12 @@ static bool is_node_void(AstNode *node) {
497497 return node->type == NodeTypeSymbol && buf_eql_str(&node->data.symbol_expr.symbol, "void");
498498}
499499
500static bool is_printable(uint8_t c) {
501 return (c >= 'a' && c <= 'z') ||
502 (c >= 'A' && c <= 'A') ||
503 (c >= '0' && c <= '9');
504}
505
500506static void render_node(AstRender *ar, AstNode *node) {
501507 assert(node->type == NodeTypeRoot || *node->parent_field == node);
502508
......@@ -601,7 +607,15 @@ static void render_node(AstRender *ar, AstNode *node) {
601607 case NodeTypeStringLiteral:
602608 zig_panic("TODO");
603609 case NodeTypeCharLiteral:
604 zig_panic("TODO");
610 {
611 uint8_t c = node->data.char_literal.value;
612 if (is_printable(c)) {
613 fprintf(ar->f, "'%c'", c);
614 } else {
615 fprintf(ar->f, "'\\x%x'", (int)c);
616 }
617 break;
618 }
605619 case NodeTypeSymbol:
606620 fprintf(ar->f, "%s", buf_ptr(&node->data.symbol_expr.symbol));
607621 break;
src/parseh.cpp+91-8
......@@ -31,6 +31,7 @@ struct Context {
3131 HashMap<Buf *, bool, buf_hash, buf_eql_buf> struct_type_table;
3232 HashMap<Buf *, bool, buf_hash, buf_eql_buf> enum_type_table;
3333 HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table;
34 HashMap<Buf *, bool, buf_hash, buf_eql_buf> macro_table;
3435 SourceManager *source_manager;
3536 ZigList<AstNode *> aliases;
3637};
......@@ -132,12 +133,17 @@ static AstNode *create_param_decl_node(Context *c, const char *name, AstNode *ty
132133 return node;
133134}
134135
136static AstNode *create_char_lit_node(Context *c, uint8_t value) {
137 AstNode *node = create_node(c, NodeTypeCharLiteral);
138 node->data.char_literal.value = value;
139 return node;
140}
141
135142static AstNode *create_num_lit_unsigned(Context *c, uint64_t x) {
136143 AstNode *node = create_node(c, NodeTypeNumberLiteral);
137144 node->data.number_literal.kind = NumLitUInt;
138145 node->data.number_literal.data.x_uint = x;
139146
140 normalize_parent_ptrs(node);
141147 return node;
142148}
143149
......@@ -713,6 +719,69 @@ static void render_aliases(Context *c) {
713719 }
714720}
715721
722static int parse_c_char_lit(Buf *value, uint8_t *out_c) {
723 enum State {
724 StateExpectStartQuot,
725 StateExpectChar,
726 StateExpectEndQuot,
727 StateExpectEnd,
728 };
729 State state = StateExpectStartQuot;
730 for (int i = 0; i < buf_len(value); i += 1) {
731 uint8_t c = buf_ptr(value)[i];
732 switch (state) {
733 case StateExpectStartQuot:
734 switch (c) {
735 case '\'':
736 state = StateExpectChar;
737 break;
738 default:
739 return -1;
740 }
741 break;
742 case StateExpectChar:
743 switch (c) {
744 case '\\':
745 case '\'':
746 return -1;
747 default:
748 *out_c = c;
749 state = StateExpectEndQuot;
750 }
751 break;
752 case StateExpectEndQuot:
753 switch (c) {
754 case '\'':
755 state = StateExpectEnd;
756 break;
757 default:
758 return -1;
759 }
760 break;
761 case StateExpectEnd:
762 return -1;
763 }
764 }
765 return (state == StateExpectEnd) ? 0 : -1;
766}
767
768static void process_macro(Context *c, Buf *name, Buf *value) {
769 // maybe it's a character literal
770 uint8_t ch;
771 if (!parse_c_char_lit(value, &ch)) {
772 c->macro_table.put(name, true);
773 AstNode *var_node = create_var_decl_node(c, buf_ptr(name), create_char_lit_node(c, ch));
774 c->root->data.root.top_level_decls.append(var_node);
775 return;
776 }
777 // maybe it's a string literal
778 // TODO
779 // maybe it's a number literal
780 // TODO
781 // maybe it's a symbol
782 // TODO
783}
784
716785static void process_preprocessor_entities(Context *c, ASTUnit &unit) {
717786 for (PreprocessedEntity *entity : unit.getLocalPreprocessingEntities()) {
718787 switch (entity->getKind()) {
......@@ -724,14 +793,27 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) {
724793 {
725794 MacroDefinitionRecord *macro = static_cast<MacroDefinitionRecord *>(entity);
726795 const char *name = macro->getName()->getNameStart();
727 fprintf(stderr, "definition macro: %s\n", name);
728796 SourceRange range = macro->getSourceRange();
729797 SourceLocation begin_loc = range.getBegin();
730798 SourceLocation end_loc = range.getEnd();
731799
732 const char *start_c = c->source_manager->getCharacterData(begin_loc);
800 if (begin_loc == end_loc) {
801 // this means it is a macro without a value
802 // we don't care about such things
803 continue;
804 }
805
733806 const char *end_c = c->source_manager->getCharacterData(end_loc);
734 fprintf(stderr, "source: '%.*s'\n", (int)(end_c - start_c), start_c);
807 Buf *value = buf_alloc();
808 while (*end_c && *end_c != '\n') {
809 buf_append_char(value, *end_c);
810 if (end_c[0] == '\\' && end_c[1] == '\n') {
811 end_c += 2;
812 } else {
813 end_c += 1;
814 }
815 }
816 process_macro(c, buf_create_from_str(name), value);
735817 }
736818 }
737819 }
......@@ -771,10 +853,11 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors,
771853 c->import = import;
772854 c->errors = errors;
773855 c->visib_mod = VisibModPub;
774 c->root_type_table.init(16);
775 c->enum_type_table.init(16);
776 c->struct_type_table.init(16);
777 c->fn_table.init(16);
856 c->root_type_table.init(8);
857 c->enum_type_table.init(8);
858 c->struct_type_table.init(8);
859 c->fn_table.init(8);
860 c->macro_table.init(8);
778861
779862 char *ZIG_PARSEH_CFLAGS = getenv("ZIG_PARSEH_CFLAGS");
780863 if (ZIG_PARSEH_CFLAGS) {
src/tokenizer.cpp-36
......@@ -1140,42 +1140,6 @@ void print_tokens(Buf *buf, ZigList<Token> *tokens) {
11401140 }
11411141}
11421142
1143bool is_printable(uint8_t c) {
1144 switch (c) {
1145 default:
1146 return false;
1147 case DIGIT:
1148 case ALPHA:
1149 case '!':
1150 case '#':
1151 case '$':
1152 case '%':
1153 case '&':
1154 case '\'':
1155 case '(':
1156 case ')':
1157 case '*':
1158 case '+':
1159 case ',':
1160 case '-':
1161 case '.':
1162 case '/':
1163 case ':':
1164 case ';':
1165 case '<':
1166 case '=':
1167 case '>':
1168 case '?':
1169 case '@':
1170 case '^':
1171 case '_':
1172 case '`':
1173 case '~':
1174 case ' ':
1175 return true;
1176 }
1177}
1178
11791143bool valid_symbol_starter(uint8_t c) {
11801144 switch (c) {
11811145 case SYMBOL_START:
src/tokenizer.hpp-1
......@@ -126,7 +126,6 @@ void tokenize(Buf *buf, Tokenization *out_tokenization);
126126
127127void print_tokens(Buf *buf, ZigList<Token> *tokens);
128128
129bool is_printable(uint8_t c);
130129int get_digit_value(uint8_t c);
131130
132131const char * token_name(TokenId id);
test/run_tests.cpp+5
......@@ -1979,6 +1979,11 @@ struct Foo *some_func(struct Foo *foo, int x);
19791979 )SOURCE", R"OUTPUT(pub const struct_Foo = u8;
19801980pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;
19811981pub const Foo = struct_Foo;)OUTPUT");
1982
1983
1984 add_parseh_case("#define a char literal", R"SOURCE(
1985#define A_CHAR 'a'
1986 )SOURCE", R"OUTPUT(pub const A_CHAR = 'a';)OUTPUT");
19821987}
19831988
19841989static void print_compiler_invocation(TestCase *test_case) {