node: better handling for unquoting heredoc fragments

This commit is contained in:
mappu 2020-04-16 18:38:05 +12:00
parent fe654d70cc
commit fd59ff9bb4
2 changed files with 20 additions and 6 deletions

11
node.go
View File

@ -1614,10 +1614,13 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
case *scalar.EncapsedStringPart:
// The n.Value that we receive here does not contain quotes at all
// TODO what happens with embedded escape characters? Did the parser
// remove them for us already or do we just have to assume we are in
// a double-quoted-equivalent situation?
return quoteGoString(n.Value), nil // Go source code quoting format
// But it is still a fragment of a double-quoted string
rawValue, err := phpUnquote(`"` + strings.Replace(n.Value, `"`, `\"`, -1) + `"`)
if err != nil {
return "", parseErr{n, err}
}
return quoteGoString(rawValue), nil // Go source code quoting format
case *scalar.Encapsed:
return this.convertEncapsedString(n.Parts)

View File

@ -2,6 +2,7 @@ package main
import (
"errors"
"fmt"
"strconv"
"strings"
)
@ -13,10 +14,20 @@ func phpUnquote(s string) (string, error) {
if s[0] == '"' {
// Quote system is similar enough to Go's that strconv will probably just work
// PHP has some lax parsing for unknown escape sequences
// PROBLEM 1: PHP has some lax parsing for unknown escape sequences
// e.g. regex("foo\.") will be silently parsed as regex("foo.")
return strconv.Unquote(s)
// PROBLEM 2: PHP supports multiline string literals, strconv.Unquote does not
// Apply fixup
s2 := strings.Replace(strings.Replace(s, "\r", `\r`, -1), "\n", `\n`, -1)
ret, err := strconv.Unquote(s2)
if err != nil {
return "", fmt.Errorf("Parsing string literal `%s`: %v", s, err)
}
return ret, nil
}
if s[0] == '\'' {