ref: e37029624df5c6c7cf82f0ba60af735c8c34ea64
parent: db3ae4ed23db3e5a63dac755cbd0af9c53909a68
author: Tor Andersson <tor@ccxvii.net>
date: Mon Dec 23 19:35:46 EST 2013
Lex regular expression literals.
--- a/js-lex.c
+++ b/js-lex.c
@@ -333,8 +333,72 @@
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) {
while (iswhite(c))
@@ -349,6 +413,8 @@
} 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 {
@@ -491,4 +557,11 @@
}
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;
}
--- a/js-load.c
+++ b/js-load.c
@@ -13,6 +13,8 @@
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);
--- a/js.h
+++ b/js.h
@@ -155,6 +155,8 @@
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);