Preserve regexp flags. Escape more characters when dumping strings.

This commit is contained in:
Tor Andersson
2014-01-11 12:47:08 +01:00
parent 33c60e4d7b
commit a476ffcc12
5 changed files with 35 additions and 15 deletions
+4
View File
@@ -13,6 +13,10 @@ typedef struct js_State js_State;
typedef struct js_StringNode js_StringNode; typedef struct js_StringNode js_StringNode;
typedef struct js_Ast js_Ast; 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); typedef int (*js_CFunction)(js_State *J);
js_State *js_newstate(void); js_State *js_newstate(void);
+20 -8
View File
@@ -92,17 +92,29 @@ static void pobject(int d, js_Ast *list)
static void pstr(const char *s) static void pstr(const char *s)
{ {
int c;
pc('"'); pc('"');
while (*s) { while ((c = *s++)) {
if (*s == '"') switch (c) {
ps("\\\""); case '"': ps("\\\""); break;
else case '\\': ps("\\\\"); break;
pc(*s); case '\n': ps("\\n"); break;
++s; default: pc(c); break;
}
} }
pc('"'); 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) static void pbin(int d, int i, js_Ast *exp, const char *op)
{ {
if (i) pc('('); if (i) pc('(');
@@ -127,7 +139,7 @@ static void pexpi(int d, int i, js_Ast *exp)
case AST_IDENTIFIER: ps(exp->string); break; case AST_IDENTIFIER: ps(exp->string); break;
case AST_NUMBER: printf("%.9g", exp->number); break; case AST_NUMBER: printf("%.9g", exp->number); break;
case AST_STRING: pstr(exp->string); 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_NULL: ps("null"); break;
case EXP_TRUE: ps("true"); break; case EXP_TRUE: ps("true"); break;
@@ -516,7 +528,7 @@ static void snode(int d, js_Ast *node)
switch (node->type) { switch (node->type) {
case AST_IDENTIFIER: pc(' '); ps(node->string); break; case AST_IDENTIFIER: pc(' '); ps(node->string); break;
case AST_STRING: pc(' '); pstr(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 AST_NUMBER: printf(" %.9g", node->number); break;
case STM_BLOCK: afun = sblock; break; case STM_BLOCK: afun = sblock; break;
case STM_FUNC: case EXP_FUNC: cfun = sblock; break; case STM_FUNC: case EXP_FUNC: cfun = sblock; break;
+10 -5
View File
@@ -361,6 +361,7 @@ static int isregexpcontext(int last)
static int lexregexp(js_State *J, const char **sp) static int lexregexp(js_State *J, const char **sp)
{ {
const char *s; const char *s;
int g, m, i;
int c; int c;
textinit(J); textinit(J);
@@ -386,21 +387,25 @@ static int lexregexp(js_State *J, const char **sp)
s = textend(J); s = textend(J);
/* regexp flags */ /* regexp flags */
J->flags.g = J->flags.i = J->flags.m = 0; g = i = m = 0;
c = PEEK(); c = PEEK();
while (isidentifierpart(c)) { while (isidentifierpart(c)) {
if (c == 'g') J->flags.g ++; if (c == 'g') ++g;
else if (c == 'i') J->flags.i ++; else if (c == 'i') ++i;
else if (c == 'm') J->flags.m ++; else if (c == 'm') ++m;
else return jsP_error(J, "illegal flag in regular expression: %c", c); else return jsP_error(J, "illegal flag in regular expression: %c", c);
c = NEXTPEEK(); 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"); return jsP_error(J, "duplicated flag in regular expression");
J->text = js_intern(J, s); 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; return TK_REGEXP;
} }
+1 -1
View File
@@ -227,7 +227,7 @@ static js_Ast *primary(js_State *J)
} }
if (J->lookahead == TK_REGEXP) { if (J->lookahead == TK_REGEXP) {
a = jsP_newstrnode(J, AST_REGEXP, J->text); a = jsP_newstrnode(J, AST_REGEXP, J->text);
// TODO: flags a->number = J->number;
next(J); next(J);
return a; return a;
} }
-1
View File
@@ -21,7 +21,6 @@ struct js_State
int lookahead; int lookahead;
const char *text; const char *text;
double number; double number;
struct { char g, i, m; } flags;
js_Ast *ast; /* list of allocated nodes to free after parsing */ js_Ast *ast; /* list of allocated nodes to free after parsing */
int strict; int strict;