diff --git a/js.h b/js.h index b0c6007..8b9757a 100644 --- a/js.h +++ b/js.h @@ -13,6 +13,10 @@ typedef struct js_State js_State; 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); diff --git a/jsdump.c b/jsdump.c index 21daa54..4125187 100644 --- a/jsdump.c +++ b/jsdump.c @@ -92,17 +92,29 @@ static void pobject(int d, js_Ast *list) 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 @@ static void pexpi(int d, int i, js_Ast *exp) 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 @@ static void snode(int d, js_Ast *node) 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; diff --git a/jslex.c b/jslex.c index f0ea983..f592dc1 100644 --- a/jslex.c +++ b/jslex.c @@ -361,6 +361,7 @@ static int isregexpcontext(int last) static int lexregexp(js_State *J, const char **sp) { const char *s; + int g, m, i; int c; textinit(J); @@ -386,21 +387,25 @@ static int lexregexp(js_State *J, const char **sp) 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; } diff --git a/jsparse.c b/jsparse.c index 2d3017c..05fba2e 100644 --- a/jsparse.c +++ b/jsparse.c @@ -227,7 +227,7 @@ static js_Ast *primary(js_State *J) } if (J->lookahead == TK_REGEXP) { a = jsP_newstrnode(J, AST_REGEXP, J->text); - // TODO: flags + a->number = J->number; next(J); return a; } diff --git a/jsstate.h b/jsstate.h index d90769a..19a5167 100644 --- a/jsstate.h +++ b/jsstate.h @@ -21,7 +21,6 @@ struct js_State 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;