diff options
-rw-r--r-- | ast.c | 29 | ||||
-rw-r--r-- | ast.h | 5 | ||||
-rw-r--r-- | com.c | 44 | ||||
-rw-r--r-- | g.peg | 7 |
4 files changed, 65 insertions, 20 deletions
@@ -3,6 +3,7 @@ #include <stddef.h> #include <stdio.h> #include <assert.h> +#include <string.h> AstVec astvec_new() { AstNode *vals = malloc(2 * sizeof(AstNode)); @@ -48,24 +49,44 @@ AstNode astnode_new_list() { }; } -AstNode astnode_new_ident(char *s) { +AstNode astnode_new_ident(const char *s) { return (AstNode){ .ty =AST_IDENT, .as = { - .str = s + .str = strdup(s) } }; } -AstNode astnode_new_string(char *s) { +AstNode astnode_new_string(const char *s) { return (AstNode){ .ty =AST_STRING, .as = { - .str = s + .str = strdup(s) } }; } +void astnode_free(AstNode *a) { + switch (a->ty) { + case AST_NUM: break; + case AST_IDENT: + case AST_STRING: + free(a->as.str); + break; + case AST_LIST:; + AstVec *v = &a->as.list; + for (int i = 0; i < v->len; i++) { + astnode_free(&v->vals[i]); + } + free(v->vals); + v->vals = NULL; + v->len = 0; + v->cap = 0; + break; + } +} + void astnode_disp(AstNode *a) { switch (a->ty) { case AST_NUM: @@ -36,10 +36,11 @@ void astnode_append(AstNode *l, AstNode val); AstNode astnode_new_num(int n); AstNode astnode_new_list(); -AstNode astnode_new_ident(char *s); -AstNode astnode_new_string(char *s); +AstNode astnode_new_ident(const char *s); +AstNode astnode_new_string(const char *s); void astnode_disp(AstNode *a); +void astnode_free(AstNode *a); const char *ast_ty_to_str(AstTy ty); @@ -458,8 +458,14 @@ int main(int argc, char **argv) { S->do_disasm = false; S->do_trace = false; + char *infile_names[16]; + int infile_name_n = 0; for (int i = 1; i < argc; i++) { - if (argv[i][0] != '-') break; + if (argv[i][0] != '-') { + infile_names[infile_name_n++] = argv[i]; + CHECK(infile_name_n < 16, "input file count exceeded"); + continue; + } switch (argv[i][1]) { case 'D': CHECK(strlen(argv[i]) > 1, "unknown option a"); @@ -473,21 +479,37 @@ int main(int argc, char **argv) { } } - Compiler com = (Compiler){ 0 }; com.S = S; com.ch = &ch; + if (infile_name_n == 0) infile_names[infile_name_n++] = "-"; + + for (int i = 0; i < infile_name_n; i++) { + char *fname = infile_names[i]; + FILE *infile = NULL; + if (0 == strcmp(fname, "-")) + infile = stdin; + else + infile = fopen(fname, "r"); + + if (infile == NULL) { + perror("fopen"); + exit(1); + } + + AstNode an; + memset(&an, 0, sizeof an); + pcc_context_t *parser = pcc_create(infile); + int rv; + do { + astnode_free(&an); + rv = pcc_parse(parser, &an); + compile_node(&com, an); + } while (rv != 0); + pcc_destroy(parser); + } - AstNode an; - memset(&an, 0, sizeof an); - pcc_context_t *parser = pcc_create(NULL); - int rv; - do { - rv = pcc_parse(parser, &an); - compile_node(&com, an); - } while (rv != 0); - pcc_destroy(parser); compile_opcode(&com, OP_PUTS); compile_opcode(&com, OP_HALT); @@ -10,7 +10,7 @@ static const char *dbg_str[] = { "Evaluating rule", "Matched rule", "Abandoning fprintf(stderr, "%*s%s %s @%zu [%.*s]\n", (int)((level) * 2), "", dbg_str[event], rule, pos, (int)(length), buffer) #endif - +#define PCC_GETCHAR(auxil) fgetc(auxil) } @@ -22,6 +22,7 @@ static const char *dbg_str[] = { "Evaluating rule", "Matched rule", "Abandoning } %value "AstNode" +%auxil "FILE *" expr <- l:list { $$ = l; } @@ -36,8 +37,8 @@ list <- { $$ = astnode_new_list(); } ')' _ number <- < [0-9]+ > (! ident_char) _ { $$ = astnode_new_num(atoi($1)); } -ident <- < ident_char+ > _ { $$ = astnode_new_ident(strdup($1)); } -string <- '"' < [^"]* > '"' _ { $$ = astnode_new_string(strdup($1)); } +ident <- < ident_char+ > _ { $$ = astnode_new_ident($1); } +string <- '"' < [^"]* > '"' _ { $$ = astnode_new_string($1); } ident_char <- [-_a-zA-Z'+*/\\%=0-9<>] _ <- [ \t\n]* |