shithub: libmujs

Download patch

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);