lang: interpolate: Fix string interpolation of dollar symbols
Dollar symbols were failing to parse when not followed by a non-brace,
non-dollar, non-EOF token and causing expected tests to fail. This
simplifies the rules to allow the remaining tests to succeed.
Fix and reinstate the final few failing tests, and add another.
Allow any escape sequence to be matched so that invalid sequences
produce a meaningful error message instead of a generic "cannot parse":
ast: interpolate: interpolating: V: \?
unhandled escape sequence token: \?
Tidy the related Makefile rule for generating the ragel parser.
Signed-off-by: Joe Groocock <me@frebib.net>
This commit is contained in:
@@ -47,13 +47,10 @@ endif
|
|||||||
|
|
||||||
interpolate/parse.generated.go: interpolate/parse.rl
|
interpolate/parse.generated.go: interpolate/parse.rl
|
||||||
@echo "Generating: interpolation..."
|
@echo "Generating: interpolation..."
|
||||||
ragel -Z -G2 -o interpolate/parse.generated.go interpolate/parse.rl
|
ragel -Z -G2 -o $@ $<
|
||||||
#@ROOT="$$( cd "$$( dirname "$${BASH_SOURCE[0]}" )" && cd .. && pwd )" && $$ROOT/misc/header.sh 'interpolate/parse.generated.go'
|
|
||||||
# XXX: I have no idea why I need to sed twice. I give up :P
|
|
||||||
# remove the ragel header so our header test passes
|
# remove the ragel header so our header test passes
|
||||||
@sed -i -e "1d" 'interpolate/parse.generated.go'
|
sed -i -e 1,2d $@
|
||||||
@sed -i -e "1d" 'interpolate/parse.generated.go'
|
gofmt -s -w $@
|
||||||
gofmt -s -w 'interpolate/parse.generated.go'
|
|
||||||
|
|
||||||
fuzz:
|
fuzz:
|
||||||
@$(MAKE) --quiet -C fuzz
|
@$(MAKE) --quiet -C fuzz
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ func Parse(data string) (out Stream, _ error) {
|
|||||||
var = '${' var_name '}' ;
|
var = '${' var_name '}' ;
|
||||||
|
|
||||||
# Any special escape characters are matched here.
|
# Any special escape characters are matched here.
|
||||||
escaped_lit = '\\' ( 'a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\\' | '"' | '$' )
|
escaped_lit = '\\' (any)
|
||||||
@{
|
@{
|
||||||
switch s := data[fpc:fpc+1]; s {
|
switch s := data[fpc:fpc+1]; s {
|
||||||
case "a":
|
case "a":
|
||||||
@@ -105,23 +105,16 @@ func Parse(data string) (out Stream, _ error) {
|
|||||||
// x = "\x00"
|
// x = "\x00"
|
||||||
default:
|
default:
|
||||||
//x = s // in case we want to avoid erroring
|
//x = s // in case we want to avoid erroring
|
||||||
// this is a programming (parser) error I think
|
return nil, fmt.Errorf("unknown escape sequence: \\%s", s)
|
||||||
return nil, fmt.Errorf("unhandled escape sequence token: %s", s)
|
|
||||||
}
|
}
|
||||||
l = Literal{Value: x}
|
l = Literal{Value: x}
|
||||||
};
|
};
|
||||||
|
|
||||||
# XXX: explicitly try and add this one?
|
# A lone dollar is a literal, if it is not a var. The `token` rule
|
||||||
#escape_lit = '\\\\'
|
# declares a var match is attempted first, else a `lit` and thus this.
|
||||||
#@{
|
dollar_lit = '$'
|
||||||
# l = Literal{Value: "\\\\"}
|
|
||||||
#};
|
|
||||||
|
|
||||||
# Anything followed by a '$' that is not a '{' is used as-is
|
|
||||||
# with the dollar.
|
|
||||||
dollar_lit = '$' (any - '{')
|
|
||||||
@{
|
@{
|
||||||
l = Literal{Value: data[fpc-1:fpc+1]}
|
l = Literal{Value: data[fpc:fpc+1]}
|
||||||
};
|
};
|
||||||
|
|
||||||
# Literal strings that don't contain '$' or '\'.
|
# Literal strings that don't contain '$' or '\'.
|
||||||
|
|||||||
@@ -19,3 +19,8 @@ Vertex: test[R: \This is r1 EOF]
|
|||||||
Vertex: test[S: \$ EOF]
|
Vertex: test[S: \$ EOF]
|
||||||
Vertex: test[T: newline
|
Vertex: test[T: newline
|
||||||
EOF]
|
EOF]
|
||||||
|
Vertex: test[U: tab \ tabEOF]
|
||||||
|
Vertex: test[W: \$]
|
||||||
|
Vertex: test[X: $This is x1 EOF]
|
||||||
|
Vertex: test[Y: ${unused} EOF]
|
||||||
|
Vertex: test[Z: $$$]
|
||||||
|
|||||||
@@ -46,23 +46,17 @@ test "S: \\$ EOF" {}
|
|||||||
|
|
||||||
test "T: newline\nEOF" {}
|
test "T: newline\nEOF" {}
|
||||||
|
|
||||||
# XXX: possible bugs or misunderstood expectations:
|
test "U: tab\t\\\ttabEOF" {}
|
||||||
|
|
||||||
#test "W: \\$" {}
|
# test "V: " {}
|
||||||
# got: <error>
|
|
||||||
# exp: W: \$
|
|
||||||
|
|
||||||
#$x1 = "This is x1"
|
test "W: \\$" {}
|
||||||
#test "X: $${x1} EOF" {}
|
|
||||||
# got: X: $${x1} EOF
|
|
||||||
# exp: X: $This is x1 EOF
|
|
||||||
|
|
||||||
#$unused = "i am unused"
|
$x1 = "This is x1"
|
||||||
#$y1 = "{unused}"
|
test "X: $${x1} EOF" {}
|
||||||
#test "Y: $${y1} EOF" {} # check there isn't double parsing
|
|
||||||
# got: Y: $${y1} EOF
|
|
||||||
# exp: Y: ${unused} EOF
|
|
||||||
|
|
||||||
#test "Z: $$$" {}
|
$unused = "i am unused"
|
||||||
# got: <error>
|
$y1 = "{unused}"
|
||||||
# exp: Z: $$$ EOF
|
test "Y: $${y1} EOF" {} # check there isn't double parsing
|
||||||
|
|
||||||
|
test "Z: $$$" {}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
# err: errInterpolate: parser failed: cannot parse string: X: \z
|
# err: errInterpolate: parser failed: unknown escape sequence: \z
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
# err: errInterpolate: parser failed: cannot parse string: X: there is no \j sequence
|
# err: errInterpolate: parser failed: unknown escape sequence: \j
|
||||||
|
|||||||
Reference in New Issue
Block a user