ref: 45e2f80a80b796cdb4f4c50c30bc0ff2b765a6e2
parent: 08c76bd5343c15ac8e2d0f0b519c1a3ffae45856
author: Tor Andersson <[email protected]>
date: Thu Jan 9 20:35:37 EST 2014
Clean up interface between lexer and parser.
--- a/js-ast.c
+++ b/js-ast.c
@@ -6,7 +6,7 @@
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 @@
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;
--- a/js-ast.h
+++ b/js-ast.h
@@ -117,8 +117,8 @@
};
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);
--- a/js-lex.c
+++ b/js-lex.c
@@ -39,8 +39,10 @@
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);
@@ -47,6 +49,7 @@
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 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 @@
*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 @@
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 lexstring(js_State *J, const char **sp, int q)
{
+ const char *s;
int c = GET();
textinit(J);
@@ -276,8 +281,9 @@
c = GET();
}
- textend(J);
+ s = textend(J);
+ J->text = js_intern(J, s);
return TK_STRING;
}
@@ -302,6 +308,7 @@
static int lexregexp(js_State *J, const char **sp)
{
+ const char *s;
int c;
textinit(J);
@@ -324,23 +331,24 @@
}
}
- 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 @@
/* 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 @@
textend(J);
- return findkeyword(J, J->yytext);
+ return findkeyword(J, J->buf.text);
}
if (c >= '0' && c <= '9') {
@@ -535,17 +543,15 @@
}
}
-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);
}
--- 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 @@
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);
--- a/js-parse.c
+++ b/js-parse.c
@@ -68,12 +68,12 @@
"'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 @@
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 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 *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 @@
{
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 @@
{
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 @@
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 @@
{
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 @@
{
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 @@
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;
--- a/js-state.c
+++ b/js-state.c
@@ -9,7 +9,7 @@
void js_close(js_State *J)
{
- free(J->yytext);
+ free(J->buf.text);
free(J);
}
--- a/js.h
+++ b/js.h
@@ -28,9 +28,9 @@
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);
@@ -37,24 +37,28 @@
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