diff --git a/expressions/expressions_test.go b/expressions/expressions_test.go index f381c52..ead545b 100644 --- a/expressions/expressions_test.go +++ b/expressions/expressions_test.go @@ -21,6 +21,12 @@ var evaluatorTests = []struct { {`'abc'`, "abc"}, {`"abc"`, "abc"}, + {`"a\\bc"`, "a\\bc"}, + {`"a\"bc"`, "a\"bc"}, + {`"\u007b\u007b abc \u007d\u007d"`, "{{ abc }}"}, + // TODO: single-quoted cannot be escaped + // {`'a\'bc'`, "a'bc"}, + // Variables {`n`, 123}, diff --git a/expressions/scanner.rl b/expressions/scanner.rl index 20a6e2a..da00468 100644 --- a/expressions/scanner.rl +++ b/expressions/scanner.rl @@ -65,8 +65,20 @@ func (lex *lexer) Lex(out *yySymType) int { } action String { tok = LITERAL - // TODO unescape \x - out.val = string(lex.data[lex.ts+1:lex.te-1]) + + var s string + // TODO: single-quoted cannot be escaped + if lex.data[lex.ts] == '\'' { + s = string(lex.data[lex.ts+1:lex.te-1]) + } else { + unquotedStr, err := strconv.Unquote(string(lex.data[lex.ts:lex.te])) + if err != nil { + panic(err) + } + s = unquotedStr + } + + out.val = s fbreak; } action Relation { tok = RELATION; out.name = lex.token(); fbreak; } @@ -76,7 +88,9 @@ func (lex *lexer) Lex(out *yySymType) int { property = '.' (alpha | '_') . (alnum | '_' | '-')* '?' ? ; int = '-'? digit+ ; float = '-'? digit+ ('.' digit+)? ; - string = '"' (any - '"')* '"' | "'" (any - "'")* "'" ; # TODO escapes + + dqchar = [^"\\] | ( '\\' any ); + string = '"' . dqchar* . '"' | "'" (any - "'")* "'" ; main := |* # statement selectors, should match constants in parser.go