parent
148cf59e9d
commit
0a85cf2e1f
@ -8604,42 +8604,37 @@ yyrule149: // .|[ \t\n\r]
|
|||||||
yyrule150: // .|[ \t\n\r]
|
yyrule150: // .|[ \t\n\r]
|
||||||
{
|
{
|
||||||
|
|
||||||
F2:
|
currentChar := l.Prev
|
||||||
|
tb := []lex.Char{currentChar}
|
||||||
for {
|
for {
|
||||||
|
switch currentChar.Rune {
|
||||||
|
case '$':
|
||||||
|
if c == '{' || isValidFirstVarNameRune(rune(c)) {
|
||||||
|
l.ungetChars(1)
|
||||||
|
lval.Token(l.newToken(tb[:len(tb)-1]))
|
||||||
|
return T_ENCAPSED_AND_WHITESPACE
|
||||||
|
}
|
||||||
|
case '{':
|
||||||
|
if rune(c) == '$' {
|
||||||
|
l.ungetChars(1)
|
||||||
|
lval.Token(l.newToken(tb[:len(tb)-1]))
|
||||||
|
return T_ENCAPSED_AND_WHITESPACE
|
||||||
|
}
|
||||||
|
case '\\':
|
||||||
|
currentChar := l.Last
|
||||||
|
tb = append(tb, currentChar)
|
||||||
|
c = l.Next()
|
||||||
|
}
|
||||||
|
if rune(c) == '`' {
|
||||||
|
lval.Token(l.newToken(l.Token()))
|
||||||
|
return T_ENCAPSED_AND_WHITESPACE
|
||||||
|
}
|
||||||
|
currentChar = l.Last
|
||||||
|
tb = append(tb, currentChar)
|
||||||
|
c = l.Next()
|
||||||
if c == -1 {
|
if c == -1 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
switch c {
|
|
||||||
case '`':
|
|
||||||
lval.Token(l.newToken(l.Token()))
|
|
||||||
return T_ENCAPSED_AND_WHITESPACE
|
|
||||||
break F2
|
|
||||||
|
|
||||||
case '$':
|
|
||||||
c = l.Next()
|
|
||||||
if rune(c) == '{' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z' || c >= '\u007f' && c <= 'ÿ' {
|
|
||||||
l.ungetChars(1)
|
|
||||||
tb := l.Token()
|
|
||||||
lval.Token(l.newToken(tb[:len(tb)-1]))
|
|
||||||
return T_ENCAPSED_AND_WHITESPACE
|
|
||||||
break F2
|
|
||||||
}
|
|
||||||
l.ungetChars(0)
|
|
||||||
|
|
||||||
case '{':
|
|
||||||
c = l.Next()
|
|
||||||
if rune(c) == '$' {
|
|
||||||
l.ungetChars(1)
|
|
||||||
tb := l.Token()
|
|
||||||
lval.Token(l.newToken(tb[:len(tb)-1]))
|
|
||||||
return T_ENCAPSED_AND_WHITESPACE
|
|
||||||
break F2
|
|
||||||
}
|
|
||||||
l.ungetChars(0)
|
|
||||||
case '\\':
|
|
||||||
c = l.Next()
|
|
||||||
}
|
|
||||||
c = l.Next()
|
|
||||||
}
|
}
|
||||||
goto yystate0
|
goto yystate0
|
||||||
}
|
}
|
||||||
|
@ -531,44 +531,43 @@ NEW_LINE (\r|\n|\r\n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
<BACKQUOTE>.|[ \t\n\r]
|
<BACKQUOTE>.|[ \t\n\r]
|
||||||
F2:for {
|
currentChar := l.Prev
|
||||||
|
tb := []lex.Char{currentChar}
|
||||||
|
|
||||||
|
for {
|
||||||
|
switch currentChar.Rune {
|
||||||
|
case '$':
|
||||||
|
if c == '{' || isValidFirstVarNameRune(rune(c)) {
|
||||||
|
l.ungetChars(1)
|
||||||
|
lval.Token(l.newToken(tb[:len(tb)-1]));
|
||||||
|
return T_ENCAPSED_AND_WHITESPACE
|
||||||
|
}
|
||||||
|
|
||||||
|
case '{':
|
||||||
|
if rune(c) == '$' {
|
||||||
|
l.ungetChars(1)
|
||||||
|
lval.Token(l.newToken(tb[:len(tb)-1]));
|
||||||
|
return T_ENCAPSED_AND_WHITESPACE
|
||||||
|
}
|
||||||
|
|
||||||
|
case '\\':
|
||||||
|
currentChar := l.Last
|
||||||
|
tb = append(tb, currentChar)
|
||||||
|
c = l.Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
if rune(c) == '`' {
|
||||||
|
lval.Token(l.newToken(l.Token()));
|
||||||
|
return T_ENCAPSED_AND_WHITESPACE
|
||||||
|
}
|
||||||
|
|
||||||
|
currentChar = l.Last
|
||||||
|
tb = append(tb, currentChar)
|
||||||
|
c = l.Next()
|
||||||
|
|
||||||
if c == -1 {
|
if c == -1 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch c {
|
|
||||||
case '`' :
|
|
||||||
lval.Token(l.newToken(l.Token()));
|
|
||||||
return T_ENCAPSED_AND_WHITESPACE
|
|
||||||
break F2;
|
|
||||||
|
|
||||||
case '$':
|
|
||||||
c = l.Next();
|
|
||||||
if rune(c) == '{' || c >= 'A' && c <= 'Z' || c == '_' || c >= 'a' && c <= 'z' || c >= '\u007f' && c <= 'ÿ' {
|
|
||||||
l.ungetChars(1)
|
|
||||||
tb := l.Token()
|
|
||||||
lval.Token(l.newToken(tb[:len(tb)-1]));
|
|
||||||
return T_ENCAPSED_AND_WHITESPACE
|
|
||||||
break F2;
|
|
||||||
}
|
|
||||||
l.ungetChars(0)
|
|
||||||
|
|
||||||
case '{':
|
|
||||||
c = l.Next();
|
|
||||||
if rune(c) == '$' {
|
|
||||||
l.ungetChars(1)
|
|
||||||
tb := l.Token()
|
|
||||||
lval.Token(l.newToken(tb[:len(tb)-1]));
|
|
||||||
return T_ENCAPSED_AND_WHITESPACE
|
|
||||||
break F2;
|
|
||||||
}
|
|
||||||
l.ungetChars(0)
|
|
||||||
|
|
||||||
case '\\':
|
|
||||||
c = l.Next();
|
|
||||||
}
|
|
||||||
|
|
||||||
c = l.Next()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<HEREDOC>.|[ \t\n\r]
|
<HEREDOC>.|[ \t\n\r]
|
||||||
|
@ -433,8 +433,6 @@ func TestTeplateStringTokens(t *testing.T) {
|
|||||||
|
|
||||||
"foo $a{$b}"
|
"foo $a{$b}"
|
||||||
|
|
||||||
` + "`test $var {$var} ${var_name} {s $ \\$a `" + `
|
|
||||||
|
|
||||||
"test $var {$var} ${var_name} {s $ \$a "
|
"test $var {$var} ${var_name} {s $ \$a "
|
||||||
|
|
||||||
"{$var}"
|
"{$var}"
|
||||||
@ -460,20 +458,6 @@ func TestTeplateStringTokens(t *testing.T) {
|
|||||||
scanner.Rune2Class('}'),
|
scanner.Rune2Class('}'),
|
||||||
scanner.Rune2Class('"'),
|
scanner.Rune2Class('"'),
|
||||||
|
|
||||||
scanner.Rune2Class('`'),
|
|
||||||
scanner.T_ENCAPSED_AND_WHITESPACE,
|
|
||||||
scanner.T_VARIABLE,
|
|
||||||
scanner.T_ENCAPSED_AND_WHITESPACE,
|
|
||||||
scanner.T_CURLY_OPEN,
|
|
||||||
scanner.T_VARIABLE,
|
|
||||||
scanner.Rune2Class('}'),
|
|
||||||
scanner.T_ENCAPSED_AND_WHITESPACE,
|
|
||||||
scanner.T_DOLLAR_OPEN_CURLY_BRACES,
|
|
||||||
scanner.T_STRING_VARNAME,
|
|
||||||
scanner.Rune2Class('}'),
|
|
||||||
scanner.T_ENCAPSED_AND_WHITESPACE,
|
|
||||||
scanner.Rune2Class('`'),
|
|
||||||
|
|
||||||
scanner.Rune2Class('"'),
|
scanner.Rune2Class('"'),
|
||||||
scanner.T_ENCAPSED_AND_WHITESPACE,
|
scanner.T_ENCAPSED_AND_WHITESPACE,
|
||||||
scanner.T_VARIABLE,
|
scanner.T_VARIABLE,
|
||||||
@ -531,6 +515,91 @@ func TestTeplateStringTokens(t *testing.T) {
|
|||||||
assertEqual(t, expected, actual)
|
assertEqual(t, expected, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBackquoteStringTokens(t *testing.T) {
|
||||||
|
src := `<?php
|
||||||
|
` + "`foo $a`" + `
|
||||||
|
` + "`foo $a{$b}`" + `
|
||||||
|
|
||||||
|
` + "`test $var {$var} ${var_name} {s $ \\$a `" + `
|
||||||
|
|
||||||
|
` + "`{$var}`" + `
|
||||||
|
` + "`$foo/`" + `
|
||||||
|
` + "`$foo/100`" + `
|
||||||
|
` + "`$/$foo`" + `
|
||||||
|
` + "`$0$foo`" + `
|
||||||
|
`
|
||||||
|
|
||||||
|
expected := []int{
|
||||||
|
scanner.Rune2Class('`'),
|
||||||
|
scanner.T_ENCAPSED_AND_WHITESPACE,
|
||||||
|
scanner.T_VARIABLE,
|
||||||
|
scanner.Rune2Class('`'),
|
||||||
|
|
||||||
|
scanner.Rune2Class('`'),
|
||||||
|
scanner.T_ENCAPSED_AND_WHITESPACE,
|
||||||
|
scanner.T_VARIABLE,
|
||||||
|
scanner.T_CURLY_OPEN,
|
||||||
|
scanner.T_VARIABLE,
|
||||||
|
scanner.Rune2Class('}'),
|
||||||
|
scanner.Rune2Class('`'),
|
||||||
|
|
||||||
|
scanner.Rune2Class('`'),
|
||||||
|
scanner.T_ENCAPSED_AND_WHITESPACE,
|
||||||
|
scanner.T_VARIABLE,
|
||||||
|
scanner.T_ENCAPSED_AND_WHITESPACE,
|
||||||
|
scanner.T_CURLY_OPEN,
|
||||||
|
scanner.T_VARIABLE,
|
||||||
|
scanner.Rune2Class('}'),
|
||||||
|
scanner.T_ENCAPSED_AND_WHITESPACE,
|
||||||
|
scanner.T_DOLLAR_OPEN_CURLY_BRACES,
|
||||||
|
scanner.T_STRING_VARNAME,
|
||||||
|
scanner.Rune2Class('}'),
|
||||||
|
scanner.T_ENCAPSED_AND_WHITESPACE,
|
||||||
|
scanner.Rune2Class('`'),
|
||||||
|
|
||||||
|
scanner.Rune2Class('`'),
|
||||||
|
scanner.T_CURLY_OPEN,
|
||||||
|
scanner.T_VARIABLE,
|
||||||
|
scanner.Rune2Class('}'),
|
||||||
|
scanner.Rune2Class('`'),
|
||||||
|
|
||||||
|
scanner.Rune2Class('`'),
|
||||||
|
scanner.T_VARIABLE,
|
||||||
|
scanner.T_ENCAPSED_AND_WHITESPACE,
|
||||||
|
scanner.Rune2Class('`'),
|
||||||
|
|
||||||
|
scanner.Rune2Class('`'),
|
||||||
|
scanner.T_VARIABLE,
|
||||||
|
scanner.T_ENCAPSED_AND_WHITESPACE,
|
||||||
|
scanner.Rune2Class('`'),
|
||||||
|
|
||||||
|
scanner.Rune2Class('`'),
|
||||||
|
scanner.T_ENCAPSED_AND_WHITESPACE,
|
||||||
|
scanner.T_VARIABLE,
|
||||||
|
scanner.Rune2Class('`'),
|
||||||
|
|
||||||
|
scanner.Rune2Class('`'),
|
||||||
|
scanner.T_ENCAPSED_AND_WHITESPACE,
|
||||||
|
scanner.T_VARIABLE,
|
||||||
|
scanner.Rune2Class('`'),
|
||||||
|
}
|
||||||
|
|
||||||
|
lexer := scanner.NewLexer(bytes.NewBufferString(src), "test.php")
|
||||||
|
lv := &lval{}
|
||||||
|
actual := []int{}
|
||||||
|
|
||||||
|
for {
|
||||||
|
token := lexer.Lex(lv)
|
||||||
|
if token < 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
actual = append(actual, token)
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEqual(t, expected, actual)
|
||||||
|
}
|
||||||
|
|
||||||
func TestHereDocTokens(t *testing.T) {
|
func TestHereDocTokens(t *testing.T) {
|
||||||
src := `<?php
|
src := `<?php
|
||||||
<<<CAT
|
<<<CAT
|
||||||
|
Loading…
Reference in New Issue
Block a user