From a9877499f7dd5f028dbd77d98bf5567fd578e341 Mon Sep 17 00:00:00 2001 From: Mart Lubbers Date: Tue, 9 Feb 2021 16:06:31 +0100 Subject: [PATCH] fix pretty printing and make commandline interface --- .gitignore | 8 +++---- Makefile | 14 +++++------ ast.c | 11 ++------- ast.h | 6 ++--- expr.c | 18 -------------- input.txt | 6 +++++ parse.y | 30 ++++++++++------------- scan.l | 4 ++-- splc.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ util.c | 1 + 10 files changed, 106 insertions(+), 62 deletions(-) delete mode 100644 expr.c create mode 100644 splc.c diff --git a/.gitignore b/.gitignore index 039961a..d56d33c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -expr -parse.c -scan.c +splc +parse.[ch] +scan.[ch] *.o -y.tab.h +y.output diff --git a/Makefile b/Makefile index 7cd4c61..05c5649 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,14 @@ CFLAGS+=-Wall -Wextra -std=c99 -pedantic -D_XOPEN_SOURCE=700 -ggdb -YFLAGS+=-Wall -Wno-empty-rule -Wyacc -Wdangling-alias -d --locations -LFLAGS+=-X +YFLAGS+=-d --locations -v --defines=parse.h +LFLAGS+=--header-file=scan.h OBJECTS:=scan.o parse.o ast.o util.o -all: expr -expr: $(OBJECTS) -scan.c: scan.l y.tab.h -y.tab.h: parse.c +all: splc +splc: $(OBJECTS) +scan.c: scan.l parse.h +parse.h: parse.c expr.c: y.tab.h clean: - $(RM) $(OBJECTS) y.tab.h scan.c parse.c expr + $(RM) $(OBJECTS) y.output parse.h scan.h scan.c parse.c expr diff --git a/ast.c b/ast.c index 597dfa6..372234e 100644 --- a/ast.c +++ b/ast.c @@ -4,7 +4,7 @@ #include "util.h" #include "ast.h" -#include "y.tab.h" +#include "parse.h" static const char *binop_str[] = { [binor] = "||", [binand] = "&&", [eq] = "==", [neq] = "!=", @@ -37,7 +37,7 @@ struct vardecl *vardecl(struct type *type, char *ident, struct expr *expr) } struct decl *decl_fun(char *ident, struct list *args, struct list *atypes, - struct type *rtype, struct list *vars, struct list *body) + struct type *rtype, struct list *body) { struct decl *res = safe_malloc(sizeof(struct decl)); res->type = dfundecl; @@ -47,8 +47,6 @@ struct decl *decl_fun(char *ident, struct list *args, struct list *atypes, res->data.dfun.atypes = (struct type **) list_to_array(atypes, &res->data.dfun.natypes, true); res->data.dfun.rtype = rtype; - res->data.dfun.vars = (struct vardecl **) - list_to_array(vars, &res->data.dfun.nvar, true); res->data.dfun.body = (struct stmt **) list_to_array(body, &res->data.dfun.nbody, true); return res; @@ -330,8 +328,6 @@ void decl_print(struct decl *decl, int indent, FILE *out) type_print(decl->data.dfun.rtype, out); } safe_fprintf(out, " {\n"); - for (int i = 0; idata.dfun.nvar; i++) - vardecl_print(decl->data.dfun.vars[i], indent+1, out); for (int i = 0; idata.dfun.nbody; i++) stmt_print(decl->data.dfun.body[i], indent+1, out); pindent(indent, out); @@ -531,9 +527,6 @@ void decl_free(struct decl *decl) type_free(decl->data.dfun.atypes[i]); free(decl->data.dfun.atypes); type_free(decl->data.dfun.rtype); - for (int i = 0; idata.dfun.nvar; i++) - vardecl_free(decl->data.dfun.vars[i]); - free(decl->data.dfun.vars); for (int i = 0; idata.dfun.nbody; i++) stmt_free(decl->data.dfun.body[i]); free(decl->data.dfun.body); diff --git a/ast.h b/ast.h index 0332e84..f84f08b 100644 --- a/ast.h +++ b/ast.h @@ -6,7 +6,7 @@ #include "util.h" struct ast; -#include "y.tab.h" +#include "parse.h" struct ast { int ndecls; @@ -43,8 +43,6 @@ struct decl { int natypes; struct type **atypes; struct type *rtype; - int nvar; - struct vardecl **vars; int nbody; struct stmt **body; } dfun; @@ -129,7 +127,7 @@ struct ast *ast(struct list *decls); struct vardecl *vardecl(struct type *type, char *ident, struct expr *expr); struct decl *decl_fun(char *ident, struct list *args, struct list *atypes, - struct type *rtype, struct list *vars, struct list *body); + struct type *rtype, struct list *body); struct decl *decl_var(struct vardecl *vardecl); struct stmt *stmt_assign(char *ident, struct list *fields, struct expr *expr); diff --git a/expr.c b/expr.c deleted file mode 100644 index 96383c6..0000000 --- a/expr.c +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include - -#include "ast.h" -#include "y.tab.h" -extern int yylex_destroy(void); - -int main() -{ - struct ast *result; - int r = yyparse(&result); - if (r != 0) - return 1; - yylex_destroy(); - ast_print(result, stdout); - ast_free(result); - return 0; -} diff --git a/input.txt b/input.txt index 3f8969e..db93041 100644 --- a/input.txt +++ b/input.txt @@ -16,6 +16,12 @@ fun(x){ "a\br"; "a\br\""; "a\xaar\\\0377\01\xa"; + Int b = 5; + while(true) { + Bool b = true; + var l = []; + 5; + } return 5; f(); f(x); f(1, 2, []); diff --git a/parse.y b/parse.y index ee3a55a..6229385 100644 --- a/parse.y +++ b/parse.y @@ -2,15 +2,15 @@ #include #include "ast.h" -#include "y.tab.h" +#include "parse.h" int yylex(void); extern YYLTYPE yylloc; void yyerror(struct ast **result, const char *str) { - fprintf(stderr, "%d-%d: %s\n", yylloc.first_line, yylloc.last_column, str); (void)result; + fprintf(stderr, "%d-%d: %s\n", yylloc.first_line, yylloc.last_column, str); } int yywrap() @@ -20,6 +20,9 @@ int yywrap() %} +%define parse.lac full +%define parse.error verbose + %union { struct expr *expr; struct stmt *stmt; @@ -50,7 +53,7 @@ int yywrap() %type start %type fundecl %type expr -%type args body decls fargs field fnargs nargs funtype vardecls bbody +%type args body decls fargs field fnargs nargs funtype bbody %type stmt %type type ftype %type vardecl @@ -68,21 +71,17 @@ vardecl | type IDENT ASSIGN expr SEMICOLON { $$ = vardecl($1, $2, $4); } ; fundecl - : IDENT BOPEN args BCLOSE CONS CONS funtype ARROW ftype COPEN vardecls body CCLOSE - { $$ = decl_fun($1, $3, $7, $9, $11, $12); } - | IDENT BOPEN args BCLOSE COPEN vardecls body CCLOSE - { $$ = decl_fun($1, $3, NULL, NULL, $6, $7); } - ; -vardecls - : /* empty */ { $$ = NULL; } - | vardecls vardecl { $$ = list_cons($2, $1); } + : IDENT BOPEN args BCLOSE COPEN body CCLOSE + { $$ = decl_fun($1, $3, NULL, NULL, $6); } + | IDENT BOPEN args BCLOSE CONS CONS funtype ARROW ftype COPEN body CCLOSE + { $$ = decl_fun($1, $3, $7, $9, $11); } ; funtype : /* empty */ { $$ = NULL; } | funtype ftype { $$ = list_cons($2, $1); } ; /* don't allow vardecls to be fully polymorph, this complicates parsing a lot */ -type +type : BOPEN ftype COMMA ftype BCLOSE { $$ = type_tuple($2, $4); } | SOPEN ftype SCLOSE { $$ = type_list($2); } | TBOOL { $$ = type_basic(btbool); } @@ -91,12 +90,7 @@ type | TVOID { $$ = type_basic(btvoid); } ; ftype - : BOPEN ftype COMMA ftype BCLOSE { $$ = type_tuple($2, $4); } - | SOPEN ftype SCLOSE { $$ = type_list($2); } - | TBOOL { $$ = type_basic(btbool); } - | TCHAR { $$ = type_basic(btchar); } - | TINT { $$ = type_basic(btint); } - | TVOID { $$ = type_basic(btvoid); } + : type | IDENT { $$ = type_var($1); } ; args diff --git a/scan.l b/scan.l index 38dab0c..664868c 100644 --- a/scan.l +++ b/scan.l @@ -1,6 +1,6 @@ D [0-9] H [0-9a-fA-F] -E ([0\\abtnvfr]|x{H}{H}?|0[0-3]{O}{O}|0{O}{O}?) +E ([0\\abtnvfr]|x{H}?{H}|0[0-3]?{O}?{O}) I [a-zA-Z_] O [0-7] @@ -23,7 +23,7 @@ O [0-7] } #include "ast.h" -#include "y.tab.h" +#include "parse.h" %} diff --git a/splc.c b/splc.c new file mode 100644 index 0000000..8d7174c --- /dev/null +++ b/splc.c @@ -0,0 +1,70 @@ +#include +#include +#include + +#include "ast.h" +#include "parse.h" +#include "scan.h" +extern int yylex_destroy(void); + +void usage(FILE *out, char *arg0) +{ + fprintf(out, + "Usage: %s [OPTS] [FILE]\n" + "\n" + "Compile an spl file. If FILE is not specified stdin is used.\n" + "\n" + "Options:\n" + "\t-p\tJust parse and pretty print\n" + "\t-t\tJust parse and typecheck\n" + "\t-c\tparse, typecheck and compile (default)\n" + "\t-h\tShow this help\n" + , arg0); +} + +enum mode {parse,type,compile}; + +int main(int argc, char *argv[]) +{ + int opt; + enum mode mode = compile; + + while ((opt = getopt(argc, argv, "hptc")) != -1) { + switch (opt) { + case 'p': + mode = parse; + break; + case 't': + mode = type; + break; + case 'c': + mode = compile; + break; + case 'h': + usage(stdout, argv[0]); + return 0; + default: + usage(stderr, argv[0]); + return 1; + } + } + if (optind + 1 == argc && strcmp(argv[optind], "-") != 0) + if ((yyin = fopen(argv[optind], "r")) == NULL) + pdie("fopen"); + + struct ast *result = NULL; + int r = yyparse(&result); + if (r != 0) + return 1; + yylex_destroy(); + if (mode == parse) { + ast_print(result, stdout); + goto end; + } +end: + ast_free(result); + if (yyin == stdin) + if (fclose(yyin) == -1) + perror("fclose"); + return 0; +} diff --git a/util.c b/util.c index 09747c9..5103745 100644 --- a/util.c +++ b/util.c @@ -74,6 +74,7 @@ char *escape_char(char c, char *buf, bool str) case '\v': strcpy(buf, "\\v"); break; case '\f': strcpy(buf, "\\f"); break; case '\r': strcpy(buf, "\\r"); break; + case '\\': strcpy(buf, "\\\\"); break; case '\'': strcpy(buf, str ? "'" : "\\'"); break; case '"': strcpy(buf, str ? "\\\"" : "\""); break; default: -- 2.20.1