#56: now, __halt_compiler(); terminates parsing process

This commit is contained in:
z7zmey 2018-07-24 21:49:26 +03:00
parent 1a495d615b
commit 623a90a418
9 changed files with 1011 additions and 969 deletions

File diff suppressed because it is too large Load Diff

View File

@ -373,6 +373,8 @@ top_statement:
yylex.(*Parser).comments.AddFromToken($$, $4, comment.SemiColonToken) yylex.(*Parser).comments.AddFromToken($$, $4, comment.SemiColonToken)
yylex.(*Parser).returnTokenToPool(yyDollar, &yyVAL) yylex.(*Parser).returnTokenToPool(yyDollar, &yyVAL)
yylex.(*Parser).Begin(scanner.HALT_COMPILER)
} }
| T_NAMESPACE namespace_name ';' | T_NAMESPACE namespace_name ';'
{ {

View File

@ -120,7 +120,6 @@ func TestPhp5(t *testing.T) {
function foo() {} function foo() {}
function foo() { function foo() {
__halt_compiler();
function bar() {} function bar() {}
class Baz {} class Baz {}
return $a; return $a;
@ -132,7 +131,6 @@ func TestPhp5(t *testing.T) {
global $a, $b, $$c, ${foo()}; global $a, $b, $$c, ${foo()};
a: a:
goto a; goto a;
__halt_compiler();
if ($a) {} if ($a) {}
if ($a) {} elseif ($b) {} if ($a) {} elseif ($b) {}
if ($a) {} else {} if ($a) {} else {}
@ -411,6 +409,10 @@ func TestPhp5(t *testing.T) {
${$a}; ${$a};
$foo::{$bar}(); $foo::{$bar}();
$foo::bar; $foo::bar;
__halt_compiler();
parsing process must be terminated
` `
expectedParams := []node.Node{ expectedParams := []node.Node{
@ -1093,7 +1095,6 @@ func TestPhp5(t *testing.T) {
PhpDocComment: "", PhpDocComment: "",
FunctionName: &node.Identifier{Value: "foo"}, FunctionName: &node.Identifier{Value: "foo"},
Stmts: []node.Node{ Stmts: []node.Node{
&stmt.HaltCompiler{},
&stmt.Function{ &stmt.Function{
ReturnsRef: false, ReturnsRef: false,
PhpDocComment: "", PhpDocComment: "",
@ -1171,7 +1172,6 @@ func TestPhp5(t *testing.T) {
&stmt.Goto{ &stmt.Goto{
Label: &node.Identifier{Value: "a"}, Label: &node.Identifier{Value: "a"},
}, },
&stmt.HaltCompiler{},
&stmt.If{ &stmt.If{
Cond: &expr.Variable{VarName: &node.Identifier{Value: "a"}}, Cond: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
Stmt: &stmt.StmtList{Stmts: []node.Node{}}, Stmt: &stmt.StmtList{Stmts: []node.Node{}},
@ -3634,6 +3634,7 @@ func TestPhp5(t *testing.T) {
ConstantName: &node.Identifier{Value: "bar"}, ConstantName: &node.Identifier{Value: "bar"},
}, },
}, },
&stmt.HaltCompiler{},
}, },
} }

File diff suppressed because it is too large Load Diff

View File

@ -472,6 +472,8 @@ top_statement:
yylex.(*Parser).comments.AddFromToken($$, $4, comment.SemiColonToken) yylex.(*Parser).comments.AddFromToken($$, $4, comment.SemiColonToken)
yylex.(*Parser).returnTokenToPool(yyDollar, &yyVAL) yylex.(*Parser).returnTokenToPool(yyDollar, &yyVAL)
yylex.(*Parser).Begin(scanner.HALT_COMPILER)
} }
| T_NAMESPACE namespace_name ';' | T_NAMESPACE namespace_name ';'
{ {

View File

@ -137,7 +137,6 @@ func TestPhp7(t *testing.T) {
global $a, $b; global $a, $b;
a: a:
goto a; goto a;
__halt_compiler();
if ($a) {} if ($a) {}
if ($a) {} elseif ($b) {} if ($a) {} elseif ($b) {}
if ($a) {} else {} if ($a) {} else {}
@ -379,6 +378,10 @@ func TestPhp7(t *testing.T) {
$foo->{$bar[0]}; $foo->{$bar[0]};
[1=>&$a, 2=>list($b)]; [1=>&$a, 2=>list($b)];
__halt_compiler();
parsing process must be terminated
` `
expectedParams := []node.Node{ expectedParams := []node.Node{
@ -1231,7 +1234,6 @@ func TestPhp7(t *testing.T) {
&stmt.Goto{ &stmt.Goto{
Label: &node.Identifier{Value: "a"}, Label: &node.Identifier{Value: "a"},
}, },
&stmt.HaltCompiler{},
&stmt.If{ &stmt.If{
Cond: &expr.Variable{VarName: &node.Identifier{Value: "a"}}, Cond: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
Stmt: &stmt.StmtList{Stmts: []node.Node{}}, Stmt: &stmt.StmtList{Stmts: []node.Node{}},
@ -3218,6 +3220,7 @@ func TestPhp7(t *testing.T) {
}, },
}, },
}, },
&stmt.HaltCompiler{},
}, },
} }

View File

@ -521,7 +521,7 @@ func (l *Lexer) popState() {
l.StateStack = l.StateStack[:len-1] l.StateStack = l.StateStack[:len-1]
} }
func (l *Lexer) begin(state int) { func (l *Lexer) Begin(state int) {
len := len(l.StateStack) len := len(l.StateStack)
l.StateStack = l.StateStack[:len-1] l.StateStack = l.StateStack[:len-1]
l.StateStack = append(l.StateStack, state) l.StateStack = append(l.StateStack, state)

View File

@ -25,6 +25,7 @@ const (
NOWDOC NOWDOC
HEREDOC HEREDOC
BACKQUOTE BACKQUOTE
HALT_COMPILER
) )
func isValidFirstVarNameRune(r rune) bool { func isValidFirstVarNameRune(r rune) bool {
@ -65,6 +66,8 @@ yystate0:
goto yystart595 goto yystart595
case 10: // start condition: BACKQUOTE case 10: // start condition: BACKQUOTE
goto yystart599 goto yystart599
case 11: // start condition: HALT_COMPILER
goto yystart604
} }
goto yystate0 // silence unused label error goto yystate0 // silence unused label error
@ -405,6 +408,8 @@ yyAction:
goto yyrule166 goto yyrule166
case 167: case 167:
goto yyrule167 goto yyrule167
case 168:
goto yyrule168
} }
goto yystate1 // silence unused label error goto yystate1 // silence unused label error
yystate1: yystate1:
@ -7540,6 +7545,23 @@ yystate603:
goto yystate549 goto yystate549
} }
goto yystate604 // silence unused label error
yystate604:
c = l.Next()
yystart604:
switch {
default:
goto yyabort
case c >= '\x01' && c <= 'ÿ':
goto yystate605
}
yystate605:
c = l.Next()
yyrule = 168
l.Mark()
goto yyrule168
yyrule1: // [ \t\n\r]+ yyrule1: // [ \t\n\r]+
goto yystate0 goto yystate0
@ -7568,17 +7590,17 @@ yyrule2: // .
} }
yyrule3: // \<\?php([ \t]|{NEW_LINE}) yyrule3: // \<\?php([ \t]|{NEW_LINE})
{ {
l.begin(PHP) l.Begin(PHP)
goto yystate0 goto yystate0
} }
yyrule4: // \<\? yyrule4: // \<\?
{ {
l.begin(PHP) l.Begin(PHP)
goto yystate0 goto yystate0
} }
yyrule5: // \<\?= yyrule5: // \<\?=
{ {
l.begin(PHP) l.Begin(PHP)
lval.Token(l.createToken(l.Token())) lval.Token(l.createToken(l.Token()))
return T_ECHO return T_ECHO
goto yystate0 goto yystate0
@ -7588,14 +7610,14 @@ yyrule6: // [ \t\n\r]+
goto yystate0 goto yystate0
yyrule7: // [;][ \t\n\r]*\?\>{NEW_LINE}? yyrule7: // [;][ \t\n\r]*\?\>{NEW_LINE}?
{ {
l.begin(INITIAL) l.Begin(INITIAL)
lval.Token(l.createToken(l.Token())) lval.Token(l.createToken(l.Token()))
return Rune2Class(';') return Rune2Class(';')
goto yystate0 goto yystate0
} }
yyrule8: // \?\>{NEW_LINE}? yyrule8: // \?\>{NEW_LINE}?
{ {
l.begin(INITIAL) l.Begin(INITIAL)
lval.Token(l.createToken(l.Token())) lval.Token(l.createToken(l.Token()))
return Rune2Class(';') return Rune2Class(';')
goto yystate0 goto yystate0
@ -8452,7 +8474,7 @@ yyrule133: // {VAR_NAME}
} }
yyrule134: // -> yyrule134: // ->
{ {
l.begin(PROPERTY) l.Begin(PROPERTY)
lval.Token(l.createToken(l.Token())) lval.Token(l.createToken(l.Token()))
return T_OBJECT_OPERATOR return T_OBJECT_OPERATOR
goto yystate0 goto yystate0
@ -8468,7 +8490,7 @@ yyrule136: // ->
} }
yyrule137: // {VAR_NAME} yyrule137: // {VAR_NAME}
{ {
l.begin(PHP) l.Begin(PHP)
lval.Token(l.createToken(l.Token())) lval.Token(l.createToken(l.Token()))
return T_STRING return T_STRING
goto yystate0 goto yystate0
@ -8476,7 +8498,7 @@ yyrule137: // {VAR_NAME}
yyrule138: // . yyrule138: // .
{ {
l.ungetChars(1) l.ungetChars(1)
l.begin(PHP) l.Begin(PHP)
goto yystate0 goto yystate0
} }
yyrule139: // [\']([^\\\']*(\\(.|\n))*)*[\'] yyrule139: // [\']([^\\\']*(\\(.|\n))*)*[\']
@ -8487,14 +8509,14 @@ yyrule139: // [\']([^\\\']*(\\(.|\n))*)*[\']
} }
yyrule140: // ` yyrule140: // `
{ {
l.begin(BACKQUOTE) l.Begin(BACKQUOTE)
lval.Token(l.createToken(l.Token())) lval.Token(l.createToken(l.Token()))
return Rune2Class(rune(l.TokenBytes(nil)[0])) return Rune2Class(rune(l.TokenBytes(nil)[0]))
goto yystate0 goto yystate0
} }
yyrule141: // ` yyrule141: // `
{ {
l.begin(PHP) l.Begin(PHP)
lval.Token(l.createToken(l.Token())) lval.Token(l.createToken(l.Token()))
return Rune2Class(rune(l.TokenBytes(nil)[0])) return Rune2Class(rune(l.TokenBytes(nil)[0]))
goto yystate0 goto yystate0
@ -8526,13 +8548,13 @@ yyrule142: // [b]?\<\<\<[ \t]*({VAR_NAME}|([']{VAR_NAME}['])|(["]{VAR_NAME}["]))
case '\'': case '\'':
lblFirst++ lblFirst++
lblLast-- lblLast--
l.begin(NOWDOC) l.Begin(NOWDOC)
case '"': case '"':
lblFirst++ lblFirst++
lblLast-- lblLast--
l.begin(HEREDOC) l.Begin(HEREDOC)
default: default:
l.begin(HEREDOC) l.Begin(HEREDOC)
} }
l.heredocLabel = l.tokenString(tb[lblFirst : lblLast+1]) l.heredocLabel = l.tokenString(tb[lblFirst : lblLast+1])
@ -8549,7 +8571,7 @@ yyrule142: // [b]?\<\<\<[ \t]*({VAR_NAME}|([']{VAR_NAME}['])|(["]{VAR_NAME}["]))
ungetCnt++ ungetCnt++
c = l.Next() c = l.Next()
if '\n' == rune(c) || '\r' == rune(c) { if '\n' == rune(c) || '\r' == rune(c) {
l.begin(HEREDOC_END) l.Begin(HEREDOC_END)
} }
} }
l.ungetChars(ungetCnt) l.ungetChars(ungetCnt)
@ -8568,12 +8590,12 @@ yyrule143: // .|[ \t\n\r]
} }
if '\n' == rune(c) || '\r' == rune(c) { if '\n' == rune(c) || '\r' == rune(c) {
if l.heredocLabel+";" == string(searchLabel) { if l.heredocLabel+";" == string(searchLabel) {
l.begin(HEREDOC_END) l.Begin(HEREDOC_END)
tb = l.ungetChars(len(l.heredocLabel) + 1) tb = l.ungetChars(len(l.heredocLabel) + 1)
break break
} }
if l.heredocLabel == string(searchLabel) { if l.heredocLabel == string(searchLabel) {
l.begin(HEREDOC_END) l.Begin(HEREDOC_END)
tb = l.ungetChars(len(l.heredocLabel)) tb = l.ungetChars(len(l.heredocLabel))
break break
} }
@ -8589,14 +8611,14 @@ yyrule143: // .|[ \t\n\r]
} }
yyrule144: // {VAR_NAME}\; yyrule144: // {VAR_NAME}\;
{ {
l.begin(PHP) l.Begin(PHP)
lval.Token(l.createToken(l.ungetChars(1))) lval.Token(l.createToken(l.ungetChars(1)))
return T_END_HEREDOC return T_END_HEREDOC
goto yystate0 goto yystate0
} }
yyrule145: // {VAR_NAME} yyrule145: // {VAR_NAME}
{ {
l.begin(PHP) l.Begin(PHP)
lval.Token(l.createToken(l.Token())) lval.Token(l.createToken(l.Token()))
return T_END_HEREDOC return T_END_HEREDOC
goto yystate0 goto yystate0
@ -8774,13 +8796,13 @@ yyrule153: // .|[ \t\n\r]
fallthrough fallthrough
case '\n': case '\n':
if l.heredocLabel+";" == string(searchLabel) { if l.heredocLabel+";" == string(searchLabel) {
l.begin(HEREDOC_END) l.Begin(HEREDOC_END)
tb = l.ungetChars(len(l.heredocLabel) + 1 + nls) tb = l.ungetChars(len(l.heredocLabel) + 1 + nls)
lval.Token(l.createToken(tb)) lval.Token(l.createToken(tb))
return T_ENCAPSED_AND_WHITESPACE return T_ENCAPSED_AND_WHITESPACE
} }
if l.heredocLabel == string(searchLabel) { if l.heredocLabel == string(searchLabel) {
l.begin(HEREDOC_END) l.Begin(HEREDOC_END)
tb = l.ungetChars(len(l.heredocLabel) + nls) tb = l.ungetChars(len(l.heredocLabel) + nls)
lval.Token(l.createToken(tb)) lval.Token(l.createToken(tb))
return T_ENCAPSED_AND_WHITESPACE return T_ENCAPSED_AND_WHITESPACE
@ -8911,6 +8933,11 @@ yyrule167: // .
l.pushState(PHP) l.pushState(PHP)
goto yystate0 goto yystate0
} }
yyrule168: // .|[ \t\n\r]
{
// do nothing
goto yystate0
}
panic("unreachable") panic("unreachable")
goto yyabort // silence unused label error goto yyabort // silence unused label error

View File

@ -24,6 +24,7 @@ const (
NOWDOC NOWDOC
HEREDOC HEREDOC
BACKQUOTE BACKQUOTE
HALT_COMPILER
) )
func isValidFirstVarNameRune(r rune) bool { func isValidFirstVarNameRune(r rune) bool {
@ -36,7 +37,7 @@ func (l *Lexer) Lex(lval Lval) int {
%} %}
%s PHP STRING STRING_VAR STRING_VAR_INDEX STRING_VAR_NAME PROPERTY HEREDOC_END NOWDOC HEREDOC BACKQUOTE %s PHP STRING STRING_VAR STRING_VAR_INDEX STRING_VAR_NAME PROPERTY HEREDOC_END NOWDOC HEREDOC BACKQUOTE HALT_COMPILER
%yyb last == '\n' || last = '\0' %yyb last == '\n' || last = '\0'
%yyt l.getCurrentState() %yyt l.getCurrentState()
@ -84,13 +85,13 @@ NEW_LINE (\r|\n|\r\n)
lval.Token(l.createToken(tb)) lval.Token(l.createToken(tb))
return T_INLINE_HTML return T_INLINE_HTML
<INITIAL>\<\?php([ \t]|{NEW_LINE}) l.begin(PHP); <INITIAL>\<\?php([ \t]|{NEW_LINE}) l.Begin(PHP);
<INITIAL>\<\? l.begin(PHP); <INITIAL>\<\? l.Begin(PHP);
<INITIAL>\<\?= l.begin(PHP);lval.Token(l.createToken(l.Token())); return T_ECHO; <INITIAL>\<\?= l.Begin(PHP);lval.Token(l.createToken(l.Token())); return T_ECHO;
<PHP>[ \t\n\r]+ <PHP>[ \t\n\r]+
<PHP>[;][ \t\n\r]*\?\>{NEW_LINE}? l.begin(INITIAL);lval.Token(l.createToken(l.Token())); return Rune2Class(';'); <PHP>[;][ \t\n\r]*\?\>{NEW_LINE}? l.Begin(INITIAL);lval.Token(l.createToken(l.Token())); return Rune2Class(';');
<PHP>\?\>{NEW_LINE}? l.begin(INITIAL);lval.Token(l.createToken(l.Token())); return Rune2Class(';'); <PHP>\?\>{NEW_LINE}? l.Begin(INITIAL);lval.Token(l.createToken(l.Token())); return Rune2Class(';');
<PHP>{DNUM}|{EXPONENT_DNUM} lval.Token(l.createToken(l.Token())); return T_DNUMBER <PHP>{DNUM}|{EXPONENT_DNUM} lval.Token(l.createToken(l.Token())); return T_DNUMBER
<PHP>{BNUM} <PHP>{BNUM}
@ -324,16 +325,16 @@ NEW_LINE (\r|\n|\r\n)
<PHP>\${VAR_NAME} lval.Token(l.createToken(l.Token())); return T_VARIABLE <PHP>\${VAR_NAME} lval.Token(l.createToken(l.Token())); return T_VARIABLE
<PHP>{VAR_NAME} lval.Token(l.createToken(l.Token())); return T_STRING <PHP>{VAR_NAME} lval.Token(l.createToken(l.Token())); return T_STRING
<PHP>-> l.begin(PROPERTY);lval.Token(l.createToken(l.Token())); return T_OBJECT_OPERATOR; <PHP>-> l.Begin(PROPERTY);lval.Token(l.createToken(l.Token())); return T_OBJECT_OPERATOR;
<PROPERTY>[ \t\n\r]+ <PROPERTY>[ \t\n\r]+
<PROPERTY>-> lval.Token(l.createToken(l.Token())); return T_OBJECT_OPERATOR; <PROPERTY>-> lval.Token(l.createToken(l.Token())); return T_OBJECT_OPERATOR;
<PROPERTY>{VAR_NAME} l.begin(PHP);lval.Token(l.createToken(l.Token())); return T_STRING; <PROPERTY>{VAR_NAME} l.Begin(PHP);lval.Token(l.createToken(l.Token())); return T_STRING;
<PROPERTY>. l.ungetChars(1);l.begin(PHP) <PROPERTY>. l.ungetChars(1);l.Begin(PHP)
<PHP>[\']([^\\\']*(\\(.|\n))*)*[\'] lval.Token(l.createToken(l.Token())); return T_CONSTANT_ENCAPSED_STRING; <PHP>[\']([^\\\']*(\\(.|\n))*)*[\'] lval.Token(l.createToken(l.Token())); return T_CONSTANT_ENCAPSED_STRING;
<PHP>` l.begin(BACKQUOTE); lval.Token(l.createToken(l.Token())); return Rune2Class(rune(l.TokenBytes(nil)[0])) <PHP>` l.Begin(BACKQUOTE); lval.Token(l.createToken(l.Token())); return Rune2Class(rune(l.TokenBytes(nil)[0]))
<BACKQUOTE>` l.begin(PHP); lval.Token(l.createToken(l.Token())); return Rune2Class(rune(l.TokenBytes(nil)[0])) <BACKQUOTE>` l.Begin(PHP); lval.Token(l.createToken(l.Token())); return Rune2Class(rune(l.TokenBytes(nil)[0]))
<PHP>[b]?\<\<\<[ \t]*({VAR_NAME}|([']{VAR_NAME}['])|(["]{VAR_NAME}["])){NEW_LINE} <PHP>[b]?\<\<\<[ \t]*({VAR_NAME}|([']{VAR_NAME}['])|(["]{VAR_NAME}["])){NEW_LINE}
tb := l.Token() tb := l.Token()
@ -364,13 +365,13 @@ NEW_LINE (\r|\n|\r\n)
case '\'' : case '\'' :
lblFirst++ lblFirst++
lblLast-- lblLast--
l.begin(NOWDOC) l.Begin(NOWDOC)
case '"' : case '"' :
lblFirst++ lblFirst++
lblLast-- lblLast--
l.begin(HEREDOC) l.Begin(HEREDOC)
default: default:
l.begin(HEREDOC) l.Begin(HEREDOC)
} }
l.heredocLabel = l.tokenString(tb[lblFirst:lblLast+1]) l.heredocLabel = l.tokenString(tb[lblFirst:lblLast+1])
@ -389,7 +390,7 @@ NEW_LINE (\r|\n|\r\n)
ungetCnt++ ungetCnt++
c = l.Next() c = l.Next()
if '\n' == rune(c) || '\r' == rune(c) { if '\n' == rune(c) || '\r' == rune(c) {
l.begin(HEREDOC_END) l.Begin(HEREDOC_END)
} }
} }
@ -409,13 +410,13 @@ NEW_LINE (\r|\n|\r\n)
if '\n' == rune(c) || '\r' == rune(c) { if '\n' == rune(c) || '\r' == rune(c) {
if l.heredocLabel + ";" == string(searchLabel) { if l.heredocLabel + ";" == string(searchLabel) {
l.begin(HEREDOC_END) l.Begin(HEREDOC_END)
tb = l.ungetChars(len(l.heredocLabel)+1) tb = l.ungetChars(len(l.heredocLabel)+1)
break; break;
} }
if l.heredocLabel == string(searchLabel) { if l.heredocLabel == string(searchLabel) {
l.begin(HEREDOC_END) l.Begin(HEREDOC_END)
tb = l.ungetChars(len(l.heredocLabel)) tb = l.ungetChars(len(l.heredocLabel))
break; break;
} }
@ -431,8 +432,8 @@ NEW_LINE (\r|\n|\r\n)
lval.Token(l.createToken(tb) ) lval.Token(l.createToken(tb) )
return T_ENCAPSED_AND_WHITESPACE return T_ENCAPSED_AND_WHITESPACE
<HEREDOC_END>{VAR_NAME}\; l.begin(PHP);lval.Token(l.createToken(l.ungetChars(1))); return T_END_HEREDOC <HEREDOC_END>{VAR_NAME}\; l.Begin(PHP);lval.Token(l.createToken(l.ungetChars(1))); return T_END_HEREDOC
<HEREDOC_END>{VAR_NAME} l.begin(PHP);lval.Token(l.createToken(l.Token())); return T_END_HEREDOC <HEREDOC_END>{VAR_NAME} l.Begin(PHP);lval.Token(l.createToken(l.Token())); return T_END_HEREDOC
<PHP>[b]?[\"] <PHP>[b]?[\"]
binPrefix := l.Token()[0].Rune == 'b' binPrefix := l.Token()[0].Rune == 'b'
@ -589,14 +590,14 @@ NEW_LINE (\r|\n|\r\n)
case '\n': case '\n':
if l.heredocLabel + ";" == string(searchLabel) { if l.heredocLabel + ";" == string(searchLabel) {
l.begin(HEREDOC_END) l.Begin(HEREDOC_END)
tb = l.ungetChars(len(l.heredocLabel)+1+nls) tb = l.ungetChars(len(l.heredocLabel)+1+nls)
lval.Token(l.createToken(tb)); lval.Token(l.createToken(tb));
return T_ENCAPSED_AND_WHITESPACE return T_ENCAPSED_AND_WHITESPACE
} }
if l.heredocLabel == string(searchLabel) { if l.heredocLabel == string(searchLabel) {
l.begin(HEREDOC_END) l.Begin(HEREDOC_END)
tb = l.ungetChars(len(l.heredocLabel)+nls) tb = l.ungetChars(len(l.heredocLabel)+nls)
lval.Token(l.createToken(tb)); lval.Token(l.createToken(tb));
return T_ENCAPSED_AND_WHITESPACE return T_ENCAPSED_AND_WHITESPACE
@ -652,6 +653,8 @@ NEW_LINE (\r|\n|\r\n)
<STRING_VAR_NAME>{VAR_NAME}[\[\}] l.popState();l.pushState(PHP);lval.Token(l.createToken(l.ungetChars(1))); return T_STRING_VARNAME <STRING_VAR_NAME>{VAR_NAME}[\[\}] l.popState();l.pushState(PHP);lval.Token(l.createToken(l.ungetChars(1))); return T_STRING_VARNAME
<STRING_VAR_NAME>. l.ungetChars(1);l.popState();l.pushState(PHP) <STRING_VAR_NAME>. l.ungetChars(1);l.popState();l.pushState(PHP)
<HALT_COMPILER>.|[ \t\n\r] // do nothing
%% %%
if c, ok := l.Abort(); ok { return int(c) } if c, ok := l.Abort(); ok { return int(c) }
goto yyAction goto yyAction