From 45e2f80a80b796cdb4f4c50c30bc0ff2b765a6e2 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Fri, 10 Jan 2014 01:35:37 +0100 Subject: [PATCH] Clean up interface between lexer and parser. --- js-ast.c | 8 +++---- js-ast.h | 4 ++-- js-lex.c | 62 ++++++++++++++++++++++++++++++------------------------ js-load.c | 17 ++++----------- js-parse.c | 30 ++++++++++++++------------ js-state.c | 2 +- js.h | 30 ++++++++++++++------------ 7 files changed, 78 insertions(+), 75 deletions(-) diff --git a/js-ast.c b/js-ast.c index 615fb53..258d705 100644 --- a/js-ast.c +++ b/js-ast.c @@ -6,7 +6,7 @@ js_Ast *jsP_newnode(js_State *J, int type, js_Ast *a, js_Ast *b, js_Ast *c, js_A js_Ast *node = malloc(sizeof(js_Ast)); node->type = type; - node->line = J->yyline; + node->line = J->line; node->a = a; node->b = b; node->c = c; @@ -20,14 +20,14 @@ js_Ast *jsP_newnode(js_State *J, int type, js_Ast *a, js_Ast *b, js_Ast *c, js_A return node; } -js_Ast *jsP_newsnode(js_State *J, int type, const char *s) +js_Ast *jsP_newstrnode(js_State *J, int type, const char *s) { js_Ast *node = jsP_newnode(J, type, 0, 0, 0, 0); - node->s = js_intern(J, s); + node->s = s; return node; } -js_Ast *jsP_newnnode(js_State *J, int type, double n) +js_Ast *jsP_newnumnode(js_State *J, int type, double n) { js_Ast *node = jsP_newnode(J, type, 0, 0, 0, 0); node->n = n; diff --git a/js-ast.h b/js-ast.h index ed8d495..687e795 100644 --- a/js-ast.h +++ b/js-ast.h @@ -117,8 +117,8 @@ enum }; js_Ast *jsP_newnode(js_State *J, int type, js_Ast *a, js_Ast *b, js_Ast *c, js_Ast *d); -js_Ast *jsP_newsnode(js_State *J, int type, const char *s); -js_Ast *jsP_newnnode(js_State *J, int type, double n); +js_Ast *jsP_newstrnode(js_State *J, int type, const char *s); +js_Ast *jsP_newnumnode(js_State *J, int type, double n); void jsP_freeast(js_State *J); void printast(js_Ast *n, int level); diff --git a/js-lex.c b/js-lex.c index 9f54d1e..c1dde91 100644 --- a/js-lex.c +++ b/js-lex.c @@ -39,14 +39,17 @@ static inline int findword(const char *s, const char **list, int num) static inline int findkeyword(js_State *J, const char *s) { int i = findword(s, keywords, nelem(keywords)); - if (i >= 0) + if (i >= 0) { + J->text = keywords[i]; return TK_BREAK + i; /* first keyword + i */ + } if (findword(s, futurewords, nelem(futurewords)) >= 0) return jsP_error(J, "'%s' is a future reserved word", s); if (J->strict && findword(s, strictfuturewords, nelem(strictfuturewords)) >= 0) return jsP_error(J, "'%s' is a strict mode future reserved word", s); + J->text = js_intern(J, s); return TK_IDENTIFIER; } @@ -59,25 +62,26 @@ static inline int findkeyword(js_State *J, const char *s) static void textinit(js_State *J) { - if (!J->yytext) { - J->yycap = 4096; - J->yytext = malloc(J->yycap); + if (!J->buf.text) { + J->buf.cap = 4096; + J->buf.text = malloc(J->buf.cap); } - J->yylen = 0; + J->buf.len = 0; } static inline void textpush(js_State *J, int c) { - if (J->yylen >= J->yycap) { - J->yycap = J->yycap * 2; - J->yytext = realloc(J->yytext, J->yycap); + if (J->buf.len >= J->buf.cap) { + J->buf.cap = J->buf.cap * 2; + J->buf.text = realloc(J->buf.text, J->buf.cap); } - J->yytext[J->yylen++] = c; + J->buf.text[J->buf.len++] = c; } -static inline void textend(js_State *J) +static inline char *textend(js_State *J) { textpush(J, 0); + return J->buf.text; } static inline int iswhite(int c) @@ -200,7 +204,7 @@ static inline int lexnumber(js_State *J, const char **sp) *sp += 2; if (!ishex(PEEK())) return jsP_error(J, "0x not followed by hexademical digit"); - J->yynumber = lexhex(sp); + J->number = lexhex(sp); return TK_NUMBER; } @@ -215,7 +219,7 @@ static inline int lexnumber(js_State *J, const char **sp) if (isidentifierstart(PEEK())) return jsP_error(J, "number with letter suffix"); - J->yynumber = n; + J->number = n; return TK_NUMBER; } @@ -260,6 +264,7 @@ static inline int lexescape(js_State *J, const char **sp) static inline int lexstring(js_State *J, const char **sp, int q) { + const char *s; int c = GET(); textinit(J); @@ -276,8 +281,9 @@ static inline int lexstring(js_State *J, const char **sp, int q) c = GET(); } - textend(J); + s = textend(J); + J->text = js_intern(J, s); return TK_STRING; } @@ -302,6 +308,7 @@ static int isregexpcontext(int last) static int lexregexp(js_State *J, const char **sp) { + const char *s; int c; textinit(J); @@ -324,23 +331,24 @@ static int lexregexp(js_State *J, const char **sp) } } - textend(J); + s = textend(J); /* regexp flags */ - J->yyflags.g = J->yyflags.i = J->yyflags.m = 0; + J->flags.g = J->flags.i = J->flags.m = 0; c = PEEK(); while (isidentifierpart(c)) { - if (c == 'g') J->yyflags.g ++; - else if (c == 'i') J->yyflags.i ++; - else if (c == 'm') J->yyflags.m ++; + if (c == 'g') J->flags.g ++; + else if (c == 'i') J->flags.i ++; + else if (c == 'm') J->flags.m ++; else return jsP_error(J, "illegal flag in regular expression: %c", c); c = NEXTPEEK(); } - if (J->yyflags.g > 1 || J->yyflags.i > 1 || J->yyflags.m > 1) + if (J->flags.g > 1 || J->flags.i > 1 || J->flags.m > 1) return jsP_error(J, "duplicated flag in regular expression"); + J->text = js_intern(J, s); return TK_REGEXP; } @@ -372,7 +380,7 @@ static int lex(js_State *J, const char **sp) /* consume CR LF as one unit */ if (c == '\r' && PEEK() == '\n') NEXT(); - J->yyline++; + J->line++; J->newline = 1; if (isnlthcontext(J->lasttoken)) return ';'; @@ -408,7 +416,7 @@ static int lex(js_State *J, const char **sp) textend(J); - return findkeyword(J, J->yytext); + return findkeyword(J, J->buf.text); } if (c >= '0' && c <= '9') { @@ -535,17 +543,15 @@ static int lex(js_State *J, const char **sp) } } -void jsP_initlex(js_State *J, const char *source) +void jsP_initlex(js_State *J, const char *filename, const char *source) { - J->yysource = source; - J->yyline = 1; + J->filename = filename; + J->source = source; + J->line = 1; J->lasttoken = 0; } int jsP_lex(js_State *J) { - int t = lex(J, &J->yysource); - // TODO: move yytext/yynumber into jsP_lval - J->lasttoken = t; - return t; + return J->lasttoken = lex(J, &J->source); } diff --git a/js-load.c b/js-load.c index 0895f00..390c98c 100644 --- a/js-load.c +++ b/js-load.c @@ -1,22 +1,14 @@ #include "js.h" #include "js-parse.h" -static int jsP_loadstring(js_State *J, const char *source) +static int jsP_loadstring(js_State *J, const char *filename, const char *source) { - int t; - - jsP_initlex(J, source); - t = jsP_parse(J); - printf("parse result = %d\n", t); - - return 0; + return jsP_parse(J, filename, source); } - int js_loadstring(js_State *J, const char *source) { - J->yyfilename = "(string)"; - return jsP_loadstring(J, source); + return jsP_loadstring(J, "(string)", source); } int js_loadfile(js_State *J, const char *filename) @@ -48,8 +40,7 @@ int js_loadfile(js_State *J, const char *filename) s[n] = 0; /* zero-terminate string containing file data */ - J->yyfilename = filename; - t = jsP_loadstring(J, s); + t = jsP_loadstring(J, filename, s); free(s); fclose(f); diff --git a/js-parse.c b/js-parse.c index 7028e82..9694c48 100644 --- a/js-parse.c +++ b/js-parse.c @@ -68,12 +68,12 @@ static const char *tokenstring[] = { "'void'", "'while'", "'with'", }; -static void next(js_State *J) +static inline void next(js_State *J) { J->lookahead = jsP_lex(J); } -static int accept(js_State *J, int t) +static inline int accept(js_State *J, int t) { if (J->lookahead == t) { next(J); @@ -82,7 +82,7 @@ static int accept(js_State *J, int t) return 0; } -static void expect(js_State *J, int t) +static inline void expect(js_State *J, int t) { if (accept(J, t)) return; @@ -103,7 +103,7 @@ static void semicolon(js_State *J) static js_Ast *identifier(js_State *J) { if (J->lookahead == TK_IDENTIFIER) { - js_Ast *a = jsP_newsnode(J, AST_IDENTIFIER, J->yytext); + js_Ast *a = jsP_newstrnode(J, AST_IDENTIFIER, J->text); next(J); return a; } @@ -121,7 +121,7 @@ static js_Ast *identifieropt(js_State *J) static js_Ast *identifiername(js_State *J) { if (J->lookahead == TK_IDENTIFIER || J->lookahead >= TK_BREAK) { - js_Ast *a = jsP_newsnode(J, AST_IDENTIFIER, J->yytext); + js_Ast *a = jsP_newstrnode(J, AST_IDENTIFIER, J->text); next(J); return a; } @@ -172,10 +172,10 @@ static js_Ast *propname(js_State *J) { js_Ast *name; if (J->lookahead == TK_NUMBER) { - name = jsP_newnnode(J, AST_NUMBER, J->yynumber); + name = jsP_newnumnode(J, AST_NUMBER, J->number); next(J); } else if (J->lookahead == TK_STRING) { - name = jsP_newsnode(J, AST_STRING, J->yytext); + name = jsP_newstrnode(J, AST_STRING, J->text); next(J); } else { name = identifiername(J); @@ -187,7 +187,7 @@ static js_Ast *propassign(js_State *J) { js_Ast *name, *value, *arg, *body; - if (J->lookahead == TK_IDENTIFIER && !strcmp(J->yytext, "get")) { + if (J->lookahead == TK_IDENTIFIER && !strcmp(J->text, "get")) { next(J); name = propname(J); expect(J, '('); @@ -196,7 +196,7 @@ static js_Ast *propassign(js_State *J) return EXP2(PROP_GET, name, body); } - if (J->lookahead == TK_IDENTIFIER && !strcmp(J->yytext, "set")) { + if (J->lookahead == TK_IDENTIFIER && !strcmp(J->text, "set")) { next(J); name = propname(J); expect(J, '('); @@ -234,17 +234,17 @@ static js_Ast *primary(js_State *J) { js_Ast *a; if (J->lookahead == TK_IDENTIFIER) { - a = jsP_newsnode(J, AST_IDENTIFIER, J->yytext); + a = jsP_newstrnode(J, AST_IDENTIFIER, J->text); next(J); return a; } if (J->lookahead == TK_STRING) { - a = jsP_newsnode(J, AST_STRING, J->yytext); + a = jsP_newstrnode(J, AST_STRING, J->text); next(J); return a; } if (J->lookahead == TK_NUMBER) { - a = jsP_newnnode(J, AST_NUMBER, J->yynumber); + a = jsP_newnumnode(J, AST_NUMBER, J->number); next(J); return a; } @@ -808,7 +808,7 @@ int jsP_error(js_State *J, const char *fmt, ...) { va_list ap; - fprintf(stderr, "syntax error: %s:%d: ", J->yyfilename, J->yyline); + fprintf(stderr, "syntax error: %s:%d: ", J->filename, J->line); va_start(ap, fmt); vfprintf(stderr, fmt, ap); @@ -820,8 +820,10 @@ int jsP_error(js_State *J, const char *fmt, ...) return 0; } -int jsP_parse(js_State *J) +int jsP_parse(js_State *J, const char *filename, const char *source) { + jsP_initlex(J, filename, source); + if (setjmp(J->jb)) { jsP_freeast(J); return 1; diff --git a/js-state.c b/js-state.c index 8fb5c39..213446f 100644 --- a/js-state.c +++ b/js-state.c @@ -9,7 +9,7 @@ js_State *js_newstate(void) void js_close(js_State *J) { - free(J->yytext); + free(J->buf.text); free(J); } diff --git a/js.h b/js.h index 897a83c..bf18a57 100644 --- a/js.h +++ b/js.h @@ -28,33 +28,37 @@ const char *js_intern(js_State *J, const char *s); typedef struct js_Ast js_Ast; -void jsP_initlex(js_State *J, const char *source); +void jsP_initlex(js_State *J, const char *filename, const char *source); int jsP_lex(js_State *J); -int jsP_parse(js_State *J); +int jsP_parse(js_State *J, const char *filename, const char *source); int jsP_error(js_State *J, const char *fmt, ...); void js_printstringtree(js_State *J); struct js_State { - const char *yyfilename; - const char *yysource; - int yyline; + jmp_buf jb; /* setjmp buffer for error handling in parser */ - char *yytext; - size_t yylen, yycap; - double yynumber; - struct { int g, i, m; } yyflags; + js_StringNode *strings; + + /* input */ + const char *filename; + const char *source; + int line; + + /* lexer */ + struct { char *text; size_t len, cap; } buf; int lasttoken; int newline; - int strict; - + /* parser */ int lookahead; - jmp_buf jb; /* setjmp buffer for error handling in parser */ + const char *text; + double number; + struct { char g, i, m; } flags; js_Ast *ast; /* list of allocated nodes to free after parsing */ - js_StringNode *strings; + int strict; }; #endif