diff options
-rw-r--r-- | c/lexer.l | 24 | ||||
-rw-r--r-- | c/parser.y | 8 |
2 files changed, 27 insertions, 5 deletions
@@ -78,14 +78,32 @@ "%(" { return enter(QQSTRING_INTERP_START, YY_START, yyscanner); } - [a-z]+ { - yylval->literal = jv_string_sized(yytext, yyleng); - return QQSTRING_TEXT; + "%"[^(] { + return INVALID_CHARACTER; } ")" { yy_pop_state(yyscanner); return QQSTRING_END; } + "\\"[)%] { + char text[2] = {yytext[1], 0}; + yylval->literal = jv_string(text); + return QQSTRING_TEXT; + } + (\\[^u)%]|\\u[a-zA-Z0-9]{0,4})+ { + /* pass escapes to the json parser */ + jv escapes = jv_string_fmt("\"%.*s\"", yyleng, yytext); + yylval->literal = jv_parse_sized(jv_string_value(escapes), jv_string_length(jv_copy(escapes))); + jv_free(escapes); + return QQSTRING_TEXT; + } + [^\\)%]+ { + yylval->literal = jv_string_sized(yytext, yyleng); + return QQSTRING_TEXT; + } + . { + return INVALID_CHARACTER; + } } @@ -102,7 +102,7 @@ int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, block* answer, int* errors, if (tok == INVALID_CHARACTER) { FAIL(*yylloc, "Invalid character"); } else { - if (tok == LITERAL && !jv_is_valid(yylval->literal)) { + if ((tok == LITERAL || tok == QQSTRING_TEXT) && !jv_is_valid(yylval->literal)) { jv msg = jv_invalid_get_msg(jv_copy(yylval->literal)); if (jv_get_kind(msg) == JV_KIND_STRING) { FAIL(*yylloc, jv_string_value(msg)); @@ -147,6 +147,10 @@ static block gen_binop(block a, block b, int op) { return c; } +static block gen_format(block a) { + return block_join(a, gen_op_call(CALL_1_1, gen_op_block_unbound(CLOSURE_REF, "tostring"))); +} + static block gen_update(block a, block op, int optype) { block assign = a; block_append(&assign, gen_op_simple(DUP)); @@ -299,7 +303,7 @@ QQString QQSTRING_TEXT { $$ = gen_binop($1, gen_op_const(LOADK, $2), '+'); } | QQString QQSTRING_INTERP_START Exp QQSTRING_INTERP_END { - $$ = gen_binop($1, $3, '+'); + $$ = gen_binop($1, gen_format($3), '+'); } |