Clean up interface between lexer and parser.

This commit is contained in:
Tor Andersson
2014-01-10 01:48:38 +01:00
parent 08c76bd534
commit 45e2f80a80
7 changed files with 78 additions and 75 deletions
+4 -4
View File
@@ -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;
+2 -2
View File
@@ -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);
+34 -28
View File
@@ -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);
}
+4 -13
View File
@@ -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);
+16 -14
View File
@@ -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;
+1 -1
View File
@@ -9,7 +9,7 @@ js_State *js_newstate(void)
void js_close(js_State *J)
{
free(J->yytext);
free(J->buf.text);
free(J);
}
+17 -13
View File
@@ -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