ref: a476ffcc12421c576ed0658f0050a511adfc208f
parent: 33c60e4d7b9d598543fe19347bc3f6ef23ccb288
author: Tor Andersson <tor.andersson@artifex.com>
date: Sat Jan 11 07:47:08 EST 2014
Preserve regexp flags. Escape more characters when dumping strings.
--- a/js.h
+++ b/js.h
@@ -13,6 +13,10 @@
typedef struct js_StringNode js_StringNode;
typedef struct js_Ast js_Ast;
+#define JS_REGEXP_G 1
+#define JS_REGEXP_I 2
+#define JS_REGEXP_M 4
+
typedef int (*js_CFunction)(js_State *J);
js_State *js_newstate(void);
--- a/jsdump.c
+++ b/jsdump.c
@@ -92,17 +92,29 @@
static void pstr(const char *s)
{
+ int c;
pc('"');
- while (*s) {
- if (*s == '"')
- ps("\\\"");
- else
- pc(*s);
- ++s;
+ while ((c = *s++)) {
+ switch (c) {
+ case '"': ps("\\\""); break;
+ case '\\': ps("\\\\"); break;
+ case '\n': ps("\\n"); break;
+ default: pc(c); break;
+ }
}
pc('"');
}
+static void pregexp(const char *prog, int flags)
+{
+ pc('/');
+ ps(prog);
+ pc('/');
+ if (flags & JS_REGEXP_G) pc('g');
+ if (flags & JS_REGEXP_I) pc('i');
+ if (flags & JS_REGEXP_M) pc('m');
+}
+
static void pbin(int d, int i, js_Ast *exp, const char *op)
{
if (i) pc('(');
@@ -127,7 +139,7 @@
case AST_IDENTIFIER: ps(exp->string); break;
case AST_NUMBER: printf("%.9g", exp->number); break;
case AST_STRING: pstr(exp->string); break;
- case AST_REGEXP: pc('/'); ps(exp->string); pc('/'); break;
+ case AST_REGEXP: pregexp(exp->string, exp->number); break;
case EXP_NULL: ps("null"); break;
case EXP_TRUE: ps("true"); break;
@@ -516,7 +528,7 @@
switch (node->type) {
case AST_IDENTIFIER: pc(' '); ps(node->string); break;
case AST_STRING: pc(' '); pstr(node->string); break;
- case AST_REGEXP: printf(" /%s/", node->string); break;
+ case AST_REGEXP: pc(' '); pregexp(node->string, node->number); break;
case AST_NUMBER: printf(" %.9g", node->number); break;
case STM_BLOCK: afun = sblock; break;
case STM_FUNC: case EXP_FUNC: cfun = sblock; break;
--- a/jslex.c
+++ b/jslex.c
@@ -361,6 +361,7 @@
static int lexregexp(js_State *J, const char **sp)
{
const char *s;
+ int g, m, i;
int c;
textinit(J);
@@ -386,21 +387,25 @@
s = textend(J);
/* regexp flags */
- J->flags.g = J->flags.i = J->flags.m = 0;
+ g = i = m = 0;
c = PEEK();
while (isidentifierpart(c)) {
- if (c == 'g') J->flags.g ++;
- else if (c == 'i') J->flags.i ++;
- else if (c == 'm') J->flags.m ++;
+ if (c == 'g') ++g;
+ else if (c == 'i') ++i;
+ else if (c == 'm') ++m;
else return jsP_error(J, "illegal flag in regular expression: %c", c);
c = NEXTPEEK();
}
- if (J->flags.g > 1 || J->flags.i > 1 || J->flags.m > 1)
+ if (g > 1 || i > 1 || m > 1)
return jsP_error(J, "duplicated flag in regular expression");
J->text = js_intern(J, s);
+ J->number = 0;
+ if (g) J->number += JS_REGEXP_G;
+ if (i) J->number += JS_REGEXP_I;
+ if (m) J->number += JS_REGEXP_M;
return TK_REGEXP;
}
--- a/jsparse.c
+++ b/jsparse.c
@@ -227,7 +227,7 @@
}
if (J->lookahead == TK_REGEXP) {
a = jsP_newstrnode(J, AST_REGEXP, J->text);
- // TODO: flags
+ a->number = J->number;
next(J);
return a;
}
--- a/jsstate.h
+++ b/jsstate.h
@@ -21,7 +21,6 @@
int lookahead;
const char *text;
double number;
- struct { char g, i, m; } flags;
js_Ast *ast; /* list of allocated nodes to free after parsing */
int strict;