authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-28 11:03:44-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-28 11:03:44-07:00
log474340a0031c9b3c8ce0d97c2cc36d5327c4e304
treecbf4236fc3caa716feab12cdd21dabd8cbb3fbdc
parent137bb51e200517c40e4863d9d45dd31c5bf90967

parseh recognizes C enums


5 files changed, 216 insertions(+), 61 deletions(-)

src/ast_render.cpp+27-8
......@@ -73,13 +73,20 @@ static const char *visib_mod_string(VisibMod mod) {
7373}
7474
7575static const char *extern_string(bool is_extern) {
76 return is_extern ? "export " : "";
76 return is_extern ? "extern " : "";
7777}
7878
7979static const char *const_or_var_string(bool is_const) {
8080 return is_const ? "const" : "var";
8181}
8282
83static const char *container_string(ContainerKind kind) {
84 switch (kind) {
85 case ContainerKindEnum: return "enum";
86 case ContainerKindStruct: return "struct";
87 }
88}
89
8390static const char *node_type_str(NodeType node_type) {
8491 switch (node_type) {
8592 case NodeTypeRoot:
......@@ -486,6 +493,10 @@ static void print_indent(AstRender *ar) {
486493 }
487494}
488495
496static bool is_node_void(AstNode *node) {
497 return node->type == NodeTypeSymbol && buf_eql_str(&node->data.symbol_expr.symbol, "void");
498}
499
489500static void render_node(AstRender *ar, AstNode *node) {
490501 assert(node->type == NodeTypeRoot || *node->parent_field == node);
491502
......@@ -533,9 +544,7 @@ static void render_node(AstRender *ar, AstNode *node) {
533544 fprintf(ar->f, ")");
534545
535546 AstNode *return_type_node = node->data.fn_proto.return_type;
536 bool is_void = return_type_node->type != NodeTypeSymbol &&
537 buf_eql_str(&return_type_node->data.symbol_expr.symbol, "void");
538 if (!is_void) {
547 if (!is_node_void(return_type_node)) {
539548 fprintf(ar->f, " -> ");
540549 render_node(ar, return_type_node);
541550 }
......@@ -601,7 +610,13 @@ static void render_node(AstRender *ar, AstNode *node) {
601610 case NodeTypeSliceExpr:
602611 zig_panic("TODO");
603612 case NodeTypeFieldAccessExpr:
604 zig_panic("TODO");
613 {
614 AstNode *lhs = node->data.field_access_expr.struct_expr;
615 Buf *rhs = &node->data.field_access_expr.field_name;
616 render_node(ar, lhs);
617 fprintf(ar->f, ".%s", buf_ptr(rhs));
618 break;
619 }
605620 case NodeTypeImport:
606621 zig_panic("TODO");
607622 case NodeTypeCImport:
......@@ -640,15 +655,19 @@ static void render_node(AstRender *ar, AstNode *node) {
640655 {
641656 const char *struct_name = buf_ptr(&node->data.struct_decl.name);
642657 const char *pub_str = visib_mod_string(node->data.struct_decl.visib_mod);
643 fprintf(ar->f, "%sstruct %s {\n", pub_str, struct_name);
658 const char *container_str = container_string(node->data.struct_decl.kind);
659 fprintf(ar->f, "%s%s %s {\n", pub_str, container_str, struct_name);
644660 ar->indent += ar->indent_size;
645661 for (int field_i = 0; field_i < node->data.struct_decl.fields.length; field_i += 1) {
646662 AstNode *field_node = node->data.struct_decl.fields.at(field_i);
647663 assert(field_node->type == NodeTypeStructField);
648664 const char *field_name = buf_ptr(&field_node->data.struct_field.name);
649665 print_indent(ar);
650 fprintf(ar->f, "%s: ", field_name);
651 render_node(ar, field_node->data.struct_field.type);
666 fprintf(ar->f, "%s", field_name);
667 if (!is_node_void(field_node->data.struct_field.type)) {
668 fprintf(ar->f, ": ");
669 render_node(ar, field_node->data.struct_field.type);
670 }
652671 fprintf(ar->f, ",\n");
653672 }
654673
src/buffer.hpp+7
......@@ -140,6 +140,13 @@ static inline bool buf_eql_str(Buf *buf, const char *str) {
140140 return buf_eql_mem(buf, str, strlen(str));
141141}
142142
143static inline bool buf_starts_with_buf(Buf *buf, Buf *sub) {
144 if (buf_len(buf) < buf_len(sub)) {
145 return false;
146 }
147 return buf_eql_mem(sub, buf_ptr(buf), buf_len(sub));
148}
149
143150bool buf_eql_buf(Buf *buf, Buf *other);
144151uint32_t buf_hash(Buf *buf);
145152
src/parseh.cpp+169-53
......@@ -11,6 +11,7 @@
1111#include "error.hpp"
1212#include "parser.hpp"
1313#include "all_types.hpp"
14#include "tokenizer.hpp"
1415
1516#include <clang/Frontend/ASTUnit.h>
1617#include <clang/Frontend/CompilerInstance.h>
......@@ -24,11 +25,12 @@ struct Context {
2425 ZigList<ErrorMsg *> *errors;
2526 bool warnings_on;
2627 VisibMod visib_mod;
27 AstNode *c_void_decl_node;
28 bool have_c_void_decl_node;
2829 AstNode *root;
2930 HashMap<Buf *, bool, buf_hash, buf_eql_buf> type_table;
3031 HashMap<Buf *, bool, buf_hash, buf_eql_buf> fn_table;
3132 SourceManager *source_manager;
33 ZigList<AstNode *> aliases;
3234};
3335
3436__attribute__ ((format (printf, 3, 4)))
......@@ -57,7 +59,7 @@ static void emit_warning(Context *c, const Decl *decl, const char *format, ...)
5759 fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg));
5860}
5961
60static AstNode *make_qual_type_node(Context *c, QualType qt, Decl *decl);
62static AstNode *make_qual_type_node(Context *c, QualType qt, const Decl *decl);
6163
6264static AstNode *create_node(Context *c, NodeType type) {
6365 AstNode *node = allocate<AstNode>(1);
......@@ -66,33 +68,48 @@ static AstNode *create_node(Context *c, NodeType type) {
6668 return node;
6769}
6870
69static AstNode *simple_type_node(Context *c, const char *type_name) {
71static AstNode *create_symbol_node(Context *c, const char *type_name) {
7072 AstNode *node = create_node(c, NodeTypeSymbol);
7173 buf_init_from_str(&node->data.symbol_expr.symbol, type_name);
7274 return node;
7375}
7476
75static const char *decl_name(const Decl *decl) {
76 const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl);
77 return (const char *)named_decl->getName().bytes_begin();
77static AstNode *create_field_access_node(Context *c, const char *lhs, const char *rhs) {
78 AstNode *node = create_node(c, NodeTypeFieldAccessExpr);
79 node->data.field_access_expr.struct_expr = create_symbol_node(c, lhs);
80 buf_init_from_str(&node->data.field_access_expr.field_name, rhs);
81 normalize_parent_ptrs(node);
82 return node;
7883}
7984
8085static ZigList<AstNode *> *create_empty_directives(Context *c) {
8186 return allocate<ZigList<AstNode*>>(1);
8287}
8388
84static AstNode *create_typedef_node(Context *c, Buf *new_name, AstNode *target_node) {
85 if (!target_node) {
86 return nullptr;
87 }
89static AstNode *create_var_decl_node(Context *c, const char *var_name, AstNode *expr_node) {
8890 AstNode *node = create_node(c, NodeTypeVariableDeclaration);
89 buf_init_from_buf(&node->data.variable_declaration.symbol, new_name);
91 buf_init_from_str(&node->data.variable_declaration.symbol, var_name);
9092 node->data.variable_declaration.is_const = true;
9193 node->data.variable_declaration.visib_mod = c->visib_mod;
92 node->data.variable_declaration.expr = target_node;
94 node->data.variable_declaration.expr = expr_node;
9395 node->data.variable_declaration.directives = create_empty_directives(c);
9496 normalize_parent_ptrs(node);
97 return node;
98}
99
100static const char *decl_name(const Decl *decl) {
101 const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl);
102 return (const char *)named_decl->getName().bytes_begin();
103}
104
95105
106static AstNode *add_typedef_node(Context *c, Buf *new_name, AstNode *target_node) {
107 if (!target_node) {
108 return nullptr;
109 }
110 AstNode *node = create_var_decl_node(c, buf_ptr(new_name), target_node);
111
112 c->type_table.put(new_name, true);
96113 c->root->data.root.top_level_decls.append(node);
97114 return node;
98115}
......@@ -101,12 +118,11 @@ static AstNode *convert_to_c_void(Context *c, AstNode *type_node) {
101118 if (type_node->type == NodeTypeSymbol &&
102119 buf_eql_str(&type_node->data.symbol_expr.symbol, "void"))
103120 {
104 if (!c->c_void_decl_node) {
105 c->c_void_decl_node = create_typedef_node(c, buf_create_from_str("c_void"),
106 simple_type_node(c, "u8"));
107 assert(c->c_void_decl_node);
121 if (!c->have_c_void_decl_node) {
122 add_typedef_node(c, buf_create_from_str("c_void"), create_symbol_node(c, "u8"));
123 c->have_c_void_decl_node = true;
108124 }
109 return simple_type_node(c, "c_void");
125 return create_symbol_node(c, "c_void");
110126 } else {
111127 return type_node;
112128 }
......@@ -123,42 +139,42 @@ static AstNode *pointer_to_type(Context *c, AstNode *type_node, bool is_const) {
123139 return node;
124140}
125141
126static AstNode *make_type_node(Context *c, const Type *ty, Decl *decl) {
142static AstNode *make_type_node(Context *c, const Type *ty, const Decl *decl) {
127143 switch (ty->getTypeClass()) {
128144 case Type::Builtin:
129145 {
130146 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
131147 switch (builtin_ty->getKind()) {
132148 case BuiltinType::Void:
133 return simple_type_node(c, "void");
149 return create_symbol_node(c, "void");
134150 case BuiltinType::Bool:
135 return simple_type_node(c, "bool");
151 return create_symbol_node(c, "bool");
136152 case BuiltinType::Char_U:
137153 case BuiltinType::UChar:
138154 case BuiltinType::Char_S:
139 return simple_type_node(c, "u8");
155 return create_symbol_node(c, "u8");
140156 case BuiltinType::SChar:
141 return simple_type_node(c, "i8");
157 return create_symbol_node(c, "i8");
142158 case BuiltinType::UShort:
143 return simple_type_node(c, "c_ushort");
159 return create_symbol_node(c, "c_ushort");
144160 case BuiltinType::UInt:
145 return simple_type_node(c, "c_uint");
161 return create_symbol_node(c, "c_uint");
146162 case BuiltinType::ULong:
147 return simple_type_node(c, "c_ulong");
163 return create_symbol_node(c, "c_ulong");
148164 case BuiltinType::ULongLong:
149 return simple_type_node(c, "c_ulonglong");
165 return create_symbol_node(c, "c_ulonglong");
150166 case BuiltinType::Short:
151 return simple_type_node(c, "c_short");
167 return create_symbol_node(c, "c_short");
152168 case BuiltinType::Int:
153 return simple_type_node(c, "c_int");
169 return create_symbol_node(c, "c_int");
154170 case BuiltinType::Long:
155 return simple_type_node(c, "c_long");
171 return create_symbol_node(c, "c_long");
156172 case BuiltinType::LongLong:
157 return simple_type_node(c, "c_longlong");
173 return create_symbol_node(c, "c_longlong");
158174 case BuiltinType::Float:
159 return simple_type_node(c, "f32");
175 return create_symbol_node(c, "f32");
160176 case BuiltinType::Double:
161 return simple_type_node(c, "f64");
177 return create_symbol_node(c, "f64");
162178 case BuiltinType::LongDouble:
163179 case BuiltinType::WChar_U:
164180 case BuiltinType::Char16:
......@@ -204,29 +220,29 @@ static AstNode *make_type_node(Context *c, const Type *ty, Decl *decl) {
204220 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
205221 Buf *type_name = buf_create_from_str(decl_name(typedef_decl));
206222 if (buf_eql_str(type_name, "uint8_t")) {
207 return simple_type_node(c, "u8");
223 return create_symbol_node(c, "u8");
208224 } else if (buf_eql_str(type_name, "int8_t")) {
209 return simple_type_node(c, "i8");
225 return create_symbol_node(c, "i8");
210226 } else if (buf_eql_str(type_name, "uint16_t")) {
211 return simple_type_node(c, "u16");
227 return create_symbol_node(c, "u16");
212228 } else if (buf_eql_str(type_name, "int16_t")) {
213 return simple_type_node(c, "i16");
229 return create_symbol_node(c, "i16");
214230 } else if (buf_eql_str(type_name, "uint32_t")) {
215 return simple_type_node(c, "u32");
231 return create_symbol_node(c, "u32");
216232 } else if (buf_eql_str(type_name, "int32_t")) {
217 return simple_type_node(c, "i32");
233 return create_symbol_node(c, "i32");
218234 } else if (buf_eql_str(type_name, "uint64_t")) {
219 return simple_type_node(c, "u64");
235 return create_symbol_node(c, "u64");
220236 } else if (buf_eql_str(type_name, "int64_t")) {
221 return simple_type_node(c, "i64");
237 return create_symbol_node(c, "i64");
222238 } else if (buf_eql_str(type_name, "intptr_t")) {
223 return simple_type_node(c, "isize");
239 return create_symbol_node(c, "isize");
224240 } else if (buf_eql_str(type_name, "uintptr_t")) {
225 return simple_type_node(c, "usize");
241 return create_symbol_node(c, "usize");
226242 } else {
227243 auto entry = c->type_table.maybe_get(type_name);
228244 if (entry) {
229 return simple_type_node(c, buf_ptr(type_name));
245 return create_symbol_node(c, buf_ptr(type_name));
230246 } else {
231247 return nullptr;
232248 }
......@@ -280,7 +296,7 @@ static AstNode *make_type_node(Context *c, const Type *ty, Decl *decl) {
280296 }
281297}
282298
283static AstNode *make_qual_type_node(Context *c, QualType qt, Decl *decl) {
299static AstNode *make_qual_type_node(Context *c, QualType qt, const Decl *decl) {
284300 return make_type_node(c, qt.getTypePtr(), decl);
285301}
286302
......@@ -311,7 +327,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
311327 buf_init_from_str(&param_decl_node->data.param_decl.name, name);
312328 QualType qt = param->getOriginalType();
313329 param_decl_node->data.param_decl.is_noalias = qt.isRestrictQualified();
314 param_decl_node->data.param_decl.type = make_qual_type_node(c, qt, (Decl*)fn_decl);
330 param_decl_node->data.param_decl.type = make_qual_type_node(c, qt, fn_decl);
315331 if (!param_decl_node->data.param_decl.type) {
316332 all_ok = false;
317333 break;
......@@ -322,9 +338,9 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
322338 }
323339
324340 if (fn_decl->isNoReturn()) {
325 node->data.fn_proto.return_type = simple_type_node(c, "unreachable");
341 node->data.fn_proto.return_type = create_symbol_node(c, "unreachable");
326342 } else {
327 node->data.fn_proto.return_type = make_qual_type_node(c, fn_decl->getReturnType(), (Decl*)fn_decl);
343 node->data.fn_proto.return_type = make_qual_type_node(c, fn_decl->getReturnType(), fn_decl);
328344 }
329345
330346 if (!node->data.fn_proto.return_type) {
......@@ -332,7 +348,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
332348 }
333349 if (!all_ok) {
334350 // not all the types could be resolved, so we give up on the function decl
335 emit_warning(c, (Decl*)fn_decl, "skipping function %s\n", buf_ptr(&node->data.fn_proto.name));
351 emit_warning(c, fn_decl, "skipping function %s\n", buf_ptr(&node->data.fn_proto.name));
336352 return;
337353 }
338354
......@@ -361,12 +377,92 @@ static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl)
361377 return;
362378 }
363379
364 AstNode *node = create_typedef_node(c, type_name, make_qual_type_node(c, child_qt, (Decl*)typedef_decl));
380 add_typedef_node(c, type_name, make_qual_type_node(c, child_qt, typedef_decl));
381}
382
383static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
384 Buf bare_name = BUF_INIT;
385 buf_init_from_str(&bare_name, decl_name(enum_decl));
386
387 Buf *type_name = buf_alloc();
388 buf_appendf(type_name, "enum_%s", buf_ptr(&bare_name));
389
390 if (c->type_table.maybe_get(type_name)) {
391 // we've already seen it
392 return;
393 }
394
395 const EnumDecl *enum_def = enum_decl->getDefinition();
396
397 if (!enum_def) {
398 // this is a type that we can point to but that's it, same as `struct Foo;`.
399 add_typedef_node(c, type_name, create_symbol_node(c, "u8"));
400 return;
401 }
402
403 AstNode *node = create_node(c, NodeTypeStructDecl);
404 buf_init_from_buf(&node->data.struct_decl.name, type_name);
405
406 node->data.struct_decl.kind = ContainerKindEnum;
407 node->data.struct_decl.visib_mod = c->visib_mod;
408 node->data.struct_decl.directives = create_empty_directives(c);
409
410 ZigList<AstNode *> var_decls = {0};
411 int i = 0;
412 for (auto it = enum_def->enumerator_begin(),
413 it_end = enum_def->enumerator_end();
414 it != it_end; ++it, i += 1)
415 {
416 const EnumConstantDecl *enum_const = *it;
417 if (enum_const->getInitExpr()) {
418 emit_warning(c, enum_const, "skipping enum %s - has init expression\n", buf_ptr(type_name));
419 return;
420 }
421 AstNode *field_node = create_node(c, NodeTypeStructField);
422 Buf enum_val_name = BUF_INIT;
423 buf_init_from_str(&enum_val_name, decl_name(enum_const));
424
425 if (buf_starts_with_buf(&enum_val_name, &bare_name)) {
426 Buf *slice = buf_slice(&enum_val_name, buf_len(&bare_name), buf_len(&enum_val_name));
427 if (valid_symbol_starter(buf_ptr(slice)[0])) {
428 buf_init_from_buf(&field_node->data.struct_field.name, slice);
429 } else {
430 buf_resize(&field_node->data.struct_field.name, 0);
431 buf_appendf(&field_node->data.struct_field.name, "_%s", buf_ptr(slice));
432 }
433 } else {
434 buf_init_from_buf(&field_node->data.struct_field.name, &enum_val_name);
435 }
436
437 field_node->data.struct_field.directives = create_empty_directives(c);
438 field_node->data.struct_field.visib_mod = VisibModPub;
439 field_node->data.struct_field.type = create_symbol_node(c, "void");
440
441 normalize_parent_ptrs(field_node);
442 node->data.struct_decl.fields.append(field_node);
443
444 // in C each enum value is in the global namespace. so we put them there too.
445 AstNode *field_access_node = create_field_access_node(c, buf_ptr(type_name),
446 buf_ptr(&field_node->data.struct_field.name));
447 AstNode *var_node = create_var_decl_node(c, buf_ptr(&enum_val_name), field_access_node);
448 var_decls.append(var_node);
449 }
450
451 c->type_table.put(type_name, true);
365452
366 if (node) {
367 normalize_parent_ptrs(node);
368 c->type_table.put(type_name, true);
453 normalize_parent_ptrs(node);
454 c->root->data.root.top_level_decls.append(node);
455
456 for (int i = 0; i < var_decls.length; i += 1) {
457 AstNode *var_node = var_decls.at(i);
458 c->root->data.root.top_level_decls.append(var_node);
369459 }
460
461 // make an alias without the "enum_" prefix. this will get emitted at the
462 // end if it doesn't conflict with anything else
463 AstNode *alias_node = create_var_decl_node(c, buf_ptr(&bare_name), create_symbol_node(c, buf_ptr(type_name)));
464 c->aliases.append(alias_node);
465
370466}
371467
372468static bool decl_visitor(void *context, const Decl *decl) {
......@@ -379,6 +475,9 @@ static bool decl_visitor(void *context, const Decl *decl) {
379475 case Decl::Typedef:
380476 visit_typedef_decl(c, static_cast<const TypedefNameDecl *>(decl));
381477 break;
478 case Decl::Enum:
479 visit_enum_decl(c, static_cast<const EnumDecl *>(decl));
480 break;
382481 default:
383482 emit_warning(c, decl, "ignoring %s decl\n", decl->getDeclKindName());
384483 }
......@@ -386,6 +485,21 @@ static bool decl_visitor(void *context, const Decl *decl) {
386485 return true;
387486}
388487
488static void render_aliases(Context *c) {
489 for (int i = 0; i < c->aliases.length; i += 1) {
490 AstNode *alias_node = c->aliases.at(i);
491 assert(alias_node->type == NodeTypeVariableDeclaration);
492 Buf *name = &alias_node->data.variable_declaration.symbol;
493 if (c->type_table.maybe_get(name)) {
494 continue;
495 }
496 if (c->fn_table.maybe_get(name)) {
497 continue;
498 }
499 c->root->data.root.top_level_decls.append(alias_node);
500 }
501}
502
389503int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source,
390504 const char **args, int args_len, const char *libc_include_path, bool warnings_on)
391505{
......@@ -514,8 +628,10 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors,
514628
515629 c->root = create_node(c, NodeTypeRoot);
516630 ast_unit->visitLocalTopLevelDecls(c, decl_visitor);
517 normalize_parent_ptrs(c->root);
518631
632 render_aliases(c);
633
634 normalize_parent_ptrs(c->root);
519635 import->root = c->root;
520636
521637 return 0;
src/tokenizer.cpp+11
......@@ -93,6 +93,10 @@
9393 case DIGIT: \
9494 case '_'
9595
96#define SYMBOL_START \
97 ALPHA: \
98 case '_'
99
96100enum TokenizeState {
97101 TokenizeStateStart,
98102 TokenizeStateSymbol,
......@@ -1170,3 +1174,10 @@ bool is_printable(uint8_t c) {
11701174 }
11711175}
11721176
1177bool valid_symbol_starter(uint8_t c) {
1178 switch (c) {
1179 case SYMBOL_START:
1180 return true;
1181 }
1182 return false;
1183}
src/tokenizer.hpp+2
......@@ -131,4 +131,6 @@ int get_digit_value(uint8_t c);
131131
132132const char * token_name(TokenId id);
133133
134bool valid_symbol_starter(uint8_t c);
135
134136#endif