diff --git a/js-lex.c b/js-lex.c index d94dfdf..c98ab59 100644 --- a/js-lex.c +++ b/js-lex.c @@ -333,7 +333,71 @@ static inline js_Token lexstring(js_State *J, const char **sp, int q) return JS_STRING; } -js_Token js_lex(js_State *J, const char **sp) +/* the ugliest language wart ever... */ +static int isregexpcontext(js_Token last) +{ + switch (last) + { + case JS_IDENTIFIER: + case JS_NULL: + case JS_TRUE: + case JS_FALSE: + case JS_THIS: + case JS_NUMBER: + case JS_STRING: + case JS_RSQUARE: + case JS_RPAREN: + return 0; + default: + return 1; + } +} + +static js_Token lexregexp(js_State *J, const char **sp) +{ + int c; + + textinit(J); + + /* regexp body */ + c = GET(); + while (c != '/') { + if (c == 0 || isnewline(c)) { + return JS_ERROR; + } else if (c == '\\') { + textpush(J, c); + c = GET(); + if (c == 0 || isnewline(c)) + return JS_ERROR; + textpush(J, c); + c = GET(); + } else { + textpush(J, c); + c = GET(); + } + } + + textend(J); + + /* regexp flags */ + J->yyflags.g = J->yyflags.i = J->yyflags.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 ++; + else return JS_ERROR; + c = NEXTPEEK(); + } + + if (J->yyflags.g > 1 || J->yyflags.i > 1 || J->yyflags.m > 1) + return JS_ERROR; + + return JS_REGEXP; +} + +static js_Token js_leximp(js_State *J, const char **sp) { int c = GET(); while (c) { @@ -349,6 +413,8 @@ js_Token js_lex(js_State *J, const char **sp) } else if (LOOK('*')) { if (lexcomment(sp)) return JS_ERROR; + } else if (isregexpcontext(J->lasttoken)) { + return lexregexp(J, sp); } else if (LOOK('=')) { return JS_SLASH_EQ; } else { @@ -492,3 +558,10 @@ js_Token js_lex(js_State *J, const char **sp) return JS_EOF; } + +js_Token js_lex(js_State *J, const char **sp) +{ + js_Token t = js_leximp(J, sp); + J->lasttoken = t; + return t; +} diff --git a/js-load.c b/js-load.c index cad32c6..8ab8822 100644 --- a/js-load.c +++ b/js-load.c @@ -13,6 +13,8 @@ int js_loadstring(js_State *J, const char *source) printf("id:%s\n", J->yytext); else if (t == JS_STRING) printf("'%s'\n", J->yytext); + else if (t == JS_REGEXP) + printf("/%s/\n", J->yytext); else printf("%s\n", js_tokentostring(t)); } while (t != JS_EOF && t != JS_ERROR); diff --git a/js.h b/js.h index 71d1433..3517f34 100644 --- a/js.h +++ b/js.h @@ -155,6 +155,8 @@ struct js_State char *yytext; size_t yylen, yycap; double yynumber; + struct { int g, i, m; } yyflags; + js_Token lasttoken; }; js_Token js_lex(js_State *J, const char **sp);