#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).returnTokenToPool(yyDollar, &yyVAL)
yylex.(*Parser).Begin(scanner.HALT_COMPILER)
}
| T_NAMESPACE namespace_name ';'
{

View File

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

View File

@ -137,7 +137,6 @@ func TestPhp7(t *testing.T) {
global $a, $b;
a:
goto a;
__halt_compiler();
if ($a) {}
if ($a) {} elseif ($b) {}
if ($a) {} else {}
@ -379,6 +378,10 @@ func TestPhp7(t *testing.T) {
$foo->{$bar[0]};
[1=>&$a, 2=>list($b)];
__halt_compiler();
parsing process must be terminated
`
expectedParams := []node.Node{
@ -1231,7 +1234,6 @@ func TestPhp7(t *testing.T) {
&stmt.Goto{
Label: &node.Identifier{Value: "a"},
},
&stmt.HaltCompiler{},
&stmt.If{
Cond: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
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]
}
func (l *Lexer) begin(state int) {
func (l *Lexer) Begin(state int) {
len := len(l.StateStack)
l.StateStack = l.StateStack[:len-1]
l.StateStack = append(l.StateStack, state)

View File

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

View File

@ -13,17 +13,18 @@ import (
)
const (
INITIAL = iota
PHP
STRING
STRING_VAR
STRING_VAR_INDEX
STRING_VAR_NAME
PROPERTY
HEREDOC_END
NOWDOC
HEREDOC
BACKQUOTE
INITIAL = iota
PHP
STRING
STRING_VAR
STRING_VAR_INDEX
STRING_VAR_NAME
PROPERTY
HEREDOC_END
NOWDOC
HEREDOC
BACKQUOTE
HALT_COMPILER
)
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'
%yyt l.getCurrentState()
@ -84,13 +85,13 @@ NEW_LINE (\r|\n|\r\n)
lval.Token(l.createToken(tb))
return T_INLINE_HTML
<INITIAL>\<\?php([ \t]|{NEW_LINE}) l.begin(PHP);
<INITIAL>\<\? l.begin(PHP);
<INITIAL>\<\?= l.begin(PHP);lval.Token(l.createToken(l.Token())); return T_ECHO;
<INITIAL>\<\?php([ \t]|{NEW_LINE}) l.Begin(PHP);
<INITIAL>\<\? l.Begin(PHP);
<INITIAL>\<\?= l.Begin(PHP);lval.Token(l.createToken(l.Token())); return T_ECHO;
<PHP>[ \t\n\r]+
<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>[;][ \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>{DNUM}|{EXPONENT_DNUM} lval.Token(l.createToken(l.Token())); return T_DNUMBER
<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_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>-> 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>. l.ungetChars(1);l.begin(PHP)
<PROPERTY>{VAR_NAME} l.Begin(PHP);lval.Token(l.createToken(l.Token())); return T_STRING;
<PROPERTY>. l.ungetChars(1);l.Begin(PHP)
<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]))
<BACKQUOTE>` l.begin(PHP); 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]))
<PHP>[b]?\<\<\<[ \t]*({VAR_NAME}|([']{VAR_NAME}['])|(["]{VAR_NAME}["])){NEW_LINE}
tb := l.Token()
@ -364,13 +365,13 @@ NEW_LINE (\r|\n|\r\n)
case '\'' :
lblFirst++
lblLast--
l.begin(NOWDOC)
l.Begin(NOWDOC)
case '"' :
lblFirst++
lblLast--
l.begin(HEREDOC)
l.Begin(HEREDOC)
default:
l.begin(HEREDOC)
l.Begin(HEREDOC)
}
l.heredocLabel = l.tokenString(tb[lblFirst:lblLast+1])
@ -389,7 +390,7 @@ NEW_LINE (\r|\n|\r\n)
ungetCnt++
c = l.Next()
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 l.heredocLabel + ";" == string(searchLabel) {
l.begin(HEREDOC_END)
l.Begin(HEREDOC_END)
tb = l.ungetChars(len(l.heredocLabel)+1)
break;
}
if l.heredocLabel == string(searchLabel) {
l.begin(HEREDOC_END)
l.Begin(HEREDOC_END)
tb = l.ungetChars(len(l.heredocLabel))
break;
}
@ -431,8 +432,8 @@ NEW_LINE (\r|\n|\r\n)
lval.Token(l.createToken(tb) )
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.Token())); 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
<PHP>[b]?[\"]
binPrefix := l.Token()[0].Rune == 'b'
@ -589,14 +590,14 @@ NEW_LINE (\r|\n|\r\n)
case '\n':
if l.heredocLabel + ";" == string(searchLabel) {
l.begin(HEREDOC_END)
l.Begin(HEREDOC_END)
tb = l.ungetChars(len(l.heredocLabel)+1+nls)
lval.Token(l.createToken(tb));
return T_ENCAPSED_AND_WHITESPACE
}
if l.heredocLabel == string(searchLabel) {
l.begin(HEREDOC_END)
l.Begin(HEREDOC_END)
tb = l.ungetChars(len(l.heredocLabel)+nls)
lval.Token(l.createToken(tb));
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>. l.ungetChars(1);l.popState();l.pushState(PHP)
<HALT_COMPILER>.|[ \t\n\r] // do nothing
%%
if c, ok := l.Abort(); ok { return int(c) }
goto yyAction