mirror of
https://github.com/ccxvii/mujs.git
synced 2026-09-21 22:53:41 +08:00
Preserve regexp flags. Escape more characters when dumping strings.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user