summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ast.c29
-rw-r--r--ast.h5
-rw-r--r--com.c44
-rw-r--r--g.peg7
4 files changed, 65 insertions, 20 deletions
diff --git a/ast.c b/ast.c
index fda03d3..b6fcbcf 100644
--- a/ast.c
+++ b/ast.c
@@ -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:
diff --git a/ast.h b/ast.h
index 0d5c190..ead9cc6 100644
--- a/ast.h
+++ b/ast.h
@@ -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);
diff --git a/com.c b/com.c
index 8102497..d95cdb5 100644
--- a/com.c
+++ b/com.c
@@ -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);
diff --git a/g.peg b/g.peg
index a3314f3..dccf361 100644
--- a/g.peg
+++ b/g.peg
@@ -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]*