string nodes

This commit is contained in:
z7zmey 2017-12-03 23:29:17 +02:00
parent 4da2844ea8
commit 1c1926516e
9 changed files with 4064 additions and 4073 deletions

View File

@ -27,13 +27,17 @@ $a = "string
with $var with $var
"; ";
$a = 'string $a = "string
with out $var'; with out \$var";
$a = <<<test $a = <<<test
string string $var
test; test;
`test
$var
`;
?> ?>
<?= $b = 22; $b ?> <?= $b = 22; $b ?>

View File

@ -0,0 +1,33 @@
package node
import (
"fmt"
"github.com/z7zmey/php-parser/token"
"io"
)
type NodeExprShellExec struct {
*simpleNode
startToken token.Token
endToken token.Token
parts []Node
}
func NewNodeExprShellExec(startToken token.Token, parts []Node, endToken token.Token) Node {
return NodeExprShellExec{
&simpleNode{name: "NodeExprShellExec", attributes: make(map[string]string)},
startToken,
endToken,
parts,
}
}
func (n NodeExprShellExec) Print(out io.Writer, indent string) {
fmt.Fprintf(out, "\n%v%v [%d %d]", indent, n.name, n.startToken.StartLine, n.endToken.EndLine)
fmt.Fprintf(out, "\n%vparts:", indent+" ",)
for _, nn := range n.parts {
nn.Print(out, indent+" ")
}
}

View File

@ -0,0 +1,33 @@
package node
import (
"fmt"
"github.com/z7zmey/php-parser/token"
"io"
)
type NodeScalarEncapsed struct {
*simpleNode
startToken token.Token
endToken token.Token
parts []Node
}
func NewNodeScalarEncapsed(startToken token.Token, parts []Node, endToken token.Token) Node {
return NodeScalarEncapsed{
&simpleNode{name: "NodeScalarEncapsed", attributes: make(map[string]string)},
startToken,
endToken,
parts,
}
}
func (n NodeScalarEncapsed) Print(out io.Writer, indent string) {
fmt.Fprintf(out, "\n%v%v [%d %d]", indent, n.name, n.startToken.StartLine, n.endToken.EndLine)
fmt.Fprintf(out, "\n%vparts:", indent+" ",)
for _, nn := range n.parts {
nn.Print(out, indent+" ")
}
}

View File

@ -0,0 +1,27 @@
package node
import (
"fmt"
"github.com/z7zmey/php-parser/token"
"io"
)
type NodeScalarEncapsedStringPart struct {
*simpleNode
token token.Token
}
func NewNodeScalarEncapsedStringPart(t token.Token) Node {
return NodeScalarEncapsedStringPart{
&simpleNode{name: "NodeScalarEncapsedStringPart", attributes: make(map[string]string)},
t,
}
}
func (n NodeScalarEncapsedStringPart) Print(out io.Writer, indent string) {
fmt.Fprintf(out, "\n%v%v [%d %d] %q", indent, n.name, n.token.StartLine, n.token.EndLine, n.token.Value)
for _, nn := range n.children {
nn.Print(out, indent+" ")
}
}

View File

@ -0,0 +1,28 @@
package node
import (
"fmt"
"github.com/z7zmey/php-parser/token"
"io"
)
type NodeScalarString struct {
*simpleNode
token token.Token
}
func NewNodeScalarString(t token.Token) Node {
return NodeScalarString{
&simpleNode{name: "NodeScalarString", attributes: make(map[string]string)},
t,
}
}
func (n NodeScalarString) Print(out io.Writer, indent string) {
fmt.Fprintf(out, "\n%v%v [%d %d] %q", indent, n.name, n.token.StartLine, n.token.EndLine, n.token.Value)
for _, nn := range n.children {
nn.Print(out, indent+" ")
}
}

2334
parser.go

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,8 @@ import (
var rootnode = node.SimpleNode("Root") var rootnode = node.SimpleNode("Root")
func parse(src io.Reader, fName string) node.Node { func parse(src io.Reader, fName string) node.Node {
yyDebug = 0
yyErrorVerbose = true
rootnode = node.SimpleNode("Root") //reset rootnode = node.SimpleNode("Root") //reset
yyParse(newLexer(src, fName)) yyParse(newLexer(src, fName))
return rootnode return rootnode
@ -21,6 +23,7 @@ func parse(src io.Reader, fName string) node.Node {
node node.Node node node.Node
token token.Token token token.Token
value string value string
list []node.Node
} }
%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE %left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
@ -158,6 +161,8 @@ func parse(src io.Reader, fName string) node.Node {
%token <token> T_PRIVATE %token <token> T_PRIVATE
%token <token> T_PROTECTED %token <token> T_PROTECTED
%token <token> T_PUBLIC %token <token> T_PUBLIC
%token <token> '"'
%token <token> '`'
%type <value> is_reference %type <value> is_reference
%type <value> is_variadic %type <value> is_variadic
@ -180,7 +185,7 @@ func parse(src io.Reader, fName string) node.Node {
%type <node> absolute_trait_method_reference trait_method_reference property echo_expr %type <node> absolute_trait_method_reference trait_method_reference property echo_expr
%type <node> new_expr anonymous_class class_name class_name_reference simple_variable %type <node> new_expr anonymous_class class_name class_name_reference simple_variable
%type <node> internal_functions_in_yacc %type <node> internal_functions_in_yacc
%type <node> exit_expr scalar backticks_expr lexical_var function_call member_name property_name %type <node> exit_expr scalar lexical_var function_call member_name property_name
%type <node> variable_class_name dereferencable_scalar constant dereferencable %type <node> variable_class_name dereferencable_scalar constant dereferencable
%type <node> callable_expr callable_variable static_member new_variable %type <node> callable_expr callable_variable static_member new_variable
%type <node> encaps_var encaps_var_offset isset_variables %type <node> encaps_var encaps_var_offset isset_variables
@ -191,7 +196,7 @@ func parse(src io.Reader, fName string) node.Node {
%type <node> non_empty_parameter_list argument_list non_empty_argument_list property_list %type <node> non_empty_parameter_list argument_list non_empty_argument_list property_list
%type <node> class_const_list class_const_decl name_list trait_adaptations method_body non_empty_for_exprs %type <node> class_const_list class_const_decl name_list trait_adaptations method_body non_empty_for_exprs
%type <node> ctor_arguments alt_if_stmt_without_else trait_adaptation_list lexical_vars %type <node> ctor_arguments alt_if_stmt_without_else trait_adaptation_list lexical_vars
%type <node> lexical_var_list encaps_list %type <node> lexical_var_list
%type <node> array_pair non_empty_array_pair_list array_pair_list possible_array_pair %type <node> array_pair non_empty_array_pair_list array_pair_list possible_array_pair
%type <node> isset_variable type return_type type_expr %type <node> isset_variable type return_type type_expr
%type <node> identifier %type <node> identifier
@ -200,6 +205,8 @@ func parse(src io.Reader, fName string) node.Node {
%type <node> method_modifiers non_empty_member_modifiers member_modifier %type <node> method_modifiers non_empty_member_modifiers member_modifier
%type <node> class_modifiers use_type %type <node> class_modifiers use_type
%type <list> encaps_list backticks_expr
%% %%
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
@ -900,7 +907,7 @@ expr_without_variable:
| T_EXIT exit_expr { $$ = node.SimpleNode("Exit").Append($2); } | T_EXIT exit_expr { $$ = node.SimpleNode("Exit").Append($2); }
| '@' expr { $$ = node.SimpleNode("Silence").Append($2); } | '@' expr { $$ = node.SimpleNode("Silence").Append($2); }
| scalar { $$ = $1; } | scalar { $$ = $1; }
| '`' backticks_expr '`' { $$ = node.SimpleNode("ShellExec").Append($2) } | '`' backticks_expr '`' { $$ = node.NewNodeExprShellExec($1, $2, $3) }
| T_PRINT expr { $$ = node.SimpleNode("Print").Append($2); } | T_PRINT expr { $$ = node.SimpleNode("Print").Append($2); }
| T_YIELD { $$ = node.SimpleNode("Yield"); } | T_YIELD { $$ = node.SimpleNode("Yield"); }
| T_YIELD expr { $$ = node.SimpleNode("Yield").Append($2); } | T_YIELD expr { $$ = node.SimpleNode("Yield").Append($2); }
@ -971,8 +978,8 @@ exit_expr:
; ;
backticks_expr: backticks_expr:
/* empty */ { $$ = node.SimpleNode("EmptyBackticks") } /* empty */ { $$ = []node.Node{} }
| T_ENCAPSED_AND_WHITESPACE { $$ = node.TokenNode("String", $1) } | T_ENCAPSED_AND_WHITESPACE { $$ = []node.Node{node.NewNodeScalarEncapsedStringPart($1)} }
| encaps_list { $$ = $1; } | encaps_list { $$ = $1; }
; ;
@ -984,7 +991,7 @@ ctor_arguments:
dereferencable_scalar: dereferencable_scalar:
T_ARRAY '(' array_pair_list ')' { $$ = $3; } T_ARRAY '(' array_pair_list ')' { $$ = $3; }
| '[' array_pair_list ']' { $$ = $2; } | '[' array_pair_list ']' { $$ = $2; }
| T_CONSTANT_ENCAPSED_STRING { $$ = node.TokenNode("String", $1) } | T_CONSTANT_ENCAPSED_STRING { $$ = node.NewNodeScalarString($1) }
; ;
scalar: scalar:
@ -999,11 +1006,11 @@ scalar:
| T_NS_C { $$ = node.TokenNode("MagicConst", $1) } | T_NS_C { $$ = node.TokenNode("MagicConst", $1) }
| T_CLASS_C { $$ = node.TokenNode("MagicConst", $1) } | T_CLASS_C { $$ = node.TokenNode("MagicConst", $1) }
| T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC
{ $$ = node.SimpleNode("Scalar").Append(node.TokenNode("Heredoc", $1)).Append(node.TokenNode("string", $2)).Append(node.TokenNode("HeredocEnd", $3)) } { $$ = node.NewNodeScalarString($2) /* TODO: mark as Heredoc*/ }
| T_START_HEREDOC T_END_HEREDOC | T_START_HEREDOC T_END_HEREDOC
{ $$ = node.SimpleNode("Scalar").Append(node.TokenNode("Heredoc", $1)).Append(node.TokenNode("HeredocEnd", $2)) } { $$ = node.SimpleNode("Scalar").Append(node.TokenNode("Heredoc", $1)).Append(node.TokenNode("HeredocEnd", $2)) }
| '"' encaps_list '"' { $$ = $2; } | '"' encaps_list '"' { $$ = node.NewNodeScalarEncapsed($1, $2, $3) }
| T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $2; } | T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = node.NewNodeScalarEncapsed($1, $2, $3) }
| dereferencable_scalar { $$ = $1; } | dereferencable_scalar { $$ = $1; }
| constant { $$ = $1; } | constant { $$ = $1; }
; ;
@ -1127,10 +1134,10 @@ array_pair:
; ;
encaps_list: encaps_list:
encaps_list encaps_var { $$ = $1.Append($2) } encaps_list encaps_var { $$ = append($1, $2) }
| encaps_list T_ENCAPSED_AND_WHITESPACE { $$ = $1.Append(node.SimpleNode("String").Attribute("value", $2.String())) } | encaps_list T_ENCAPSED_AND_WHITESPACE { $$ = append($1, node.NewNodeScalarEncapsedStringPart($2)) }
| encaps_var { $$ = node.SimpleNode("EncapsList").Append($1) } | encaps_var { $$ = []node.Node{$1} }
| T_ENCAPSED_AND_WHITESPACE encaps_var { $$ = node.SimpleNode("EncapsList").Append(node.SimpleNode("String").Attribute("value", $1.String())).Append($2) } | T_ENCAPSED_AND_WHITESPACE encaps_var { $$ = []node.Node{node.NewNodeScalarEncapsedStringPart($1), $2} }
; ;
encaps_var: encaps_var:

5632
scanner.go

File diff suppressed because it is too large Load Diff

View File

@ -241,7 +241,6 @@ NEW_LINE (\r|\n|\r\n)
<PHP>(#|[/][/]).*{NEW_LINE} lval.token = token.NewToken(l.handleNewLine(l.TokenBytes(nil)));// return T_COMMENT; // TODO: handle ?> <PHP>(#|[/][/]).*{NEW_LINE} lval.token = token.NewToken(l.handleNewLine(l.TokenBytes(nil)));// return T_COMMENT; // TODO: handle ?>
<PHP>[/][*][^*]*[*]+([^*/][^*]*[*]+)*[/] lval.token = token.NewToken(l.handleNewLine(l.TokenBytes(nil)));// return T_COMMENT; // TODO: handle ?> <PHP>[/][*][^*]*[*]+([^*/][^*]*[*]+)*[/] lval.token = token.NewToken(l.handleNewLine(l.TokenBytes(nil)));// return T_COMMENT; // TODO: handle ?>
<PHP>[/][*][*][^*]*[*]+([^*/][^*]*[*]+)*[/] lval.token = token.NewToken(l.handleNewLine(l.TokenBytes(nil)));// return T_DOC_COMMENT; // TODO: handle ?> <PHP>[/][*][*][^*]*[*]+([^*/][^*]*[*]+)*[/] lval.token = token.NewToken(l.handleNewLine(l.TokenBytes(nil)));// return T_DOC_COMMENT; // TODO: handle ?>
<PHP>'[^']*(\\')*' lval.token = token.NewToken(l.handleNewLine(l.TokenBytes(nil))); return T_CONSTANT_ENCAPSED_STRING
<PHP>{OPERATORS} lval.token = token.NewToken(l.handleNewLine(l.TokenBytes(nil))); return rune2Class(rune(l.TokenBytes(nil)[0])) <PHP>{OPERATORS} lval.token = token.NewToken(l.handleNewLine(l.TokenBytes(nil))); return rune2Class(rune(l.TokenBytes(nil)[0]))
<PHP>\{ l.pushState(PHP); lval.token = token.NewToken(l.handleNewLine(l.TokenBytes(nil))); return rune2Class(rune(l.TokenBytes(nil)[0])) <PHP>\{ l.pushState(PHP); lval.token = token.NewToken(l.handleNewLine(l.TokenBytes(nil))); return rune2Class(rune(l.TokenBytes(nil)[0]))
@ -257,8 +256,8 @@ NEW_LINE (\r|\n|\r\n)
<PHP>[\']([^\\\']*([\\][\'])*)*[\'] lval.token = token.NewToken(l.handleNewLine(l.TokenBytes(nil))); return T_CONSTANT_ENCAPSED_STRING; <PHP>[\']([^\\\']*([\\][\'])*)*[\'] lval.token = token.NewToken(l.handleNewLine(l.TokenBytes(nil))); return T_CONSTANT_ENCAPSED_STRING;
<PHP>` l.begin(BACKQUOTE); lval.token = token.NewToken(l.handleNewLine(l.TokenBytes(nil))); rune2Class(rune(l.TokenBytes(nil)[0])) <PHP>` l.begin(BACKQUOTE); lval.token = token.NewToken(l.handleNewLine(l.TokenBytes(nil))); return rune2Class(rune(l.TokenBytes(nil)[0]))
<BACKQUOTE>` l.begin(PHP); lval.token = token.NewToken(l.handleNewLine(l.TokenBytes(nil))); rune2Class(rune(l.TokenBytes(nil)[0])) <BACKQUOTE>` l.begin(PHP); lval.token = token.NewToken(l.handleNewLine(l.TokenBytes(nil))); 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.TokenBytes(nil) tb := l.TokenBytes(nil)
@ -442,7 +441,7 @@ NEW_LINE (\r|\n|\r\n)
c = l.Next() c = l.Next()
} }
<BACKQUOTE>. <BACKQUOTE>.|[ \t\n\r]
F2:for { F2:for {
if c == -1 { if c == -1 {
break; break;