error tolerant parsing
This commit is contained in:
parent
ebe06da6e0
commit
83a1400a4f
31
errors/error.go
Normal file
31
errors/error.go
Normal file
@ -0,0 +1,31 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/z7zmey/php-parser/position"
|
||||
"github.com/z7zmey/php-parser/token"
|
||||
)
|
||||
|
||||
// Error parsing error
|
||||
type Error struct {
|
||||
Msg string
|
||||
Pos position.Position
|
||||
}
|
||||
|
||||
// NewError creates and returns new Error
|
||||
func NewError(msg string, t token.Token) *Error {
|
||||
return &Error{
|
||||
Msg: msg,
|
||||
Pos: position.Position{
|
||||
StartLine: t.StartLine,
|
||||
EndLine: t.EndLine,
|
||||
StartPos: t.StartPos,
|
||||
EndPos: t.EndPos,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Error) String() string {
|
||||
return fmt.Sprintf("%s at line %d", e.Msg, e.Pos.StartLine)
|
||||
}
|
10
main.go
10
main.go
@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/yookoala/realpath"
|
||||
"github.com/z7zmey/php-parser/comment"
|
||||
"github.com/z7zmey/php-parser/errors"
|
||||
"github.com/z7zmey/php-parser/node"
|
||||
"github.com/z7zmey/php-parser/php5"
|
||||
"github.com/z7zmey/php-parser/php7"
|
||||
@ -20,6 +21,7 @@ func main() {
|
||||
var nodes node.Node
|
||||
var comments comment.Comments
|
||||
var positions position.Positions
|
||||
var errors []*errors.Error
|
||||
|
||||
usePhp5 := flag.Bool("php5", false, "use PHP5 parser")
|
||||
flag.Parse()
|
||||
@ -34,9 +36,13 @@ func main() {
|
||||
|
||||
src, _ := os.Open(string(path))
|
||||
if *usePhp5 {
|
||||
nodes, comments, positions = php5.Parse(src, path)
|
||||
nodes, comments, positions, errors = php5.Parse(src, path)
|
||||
} else {
|
||||
nodes, comments, positions = php7.Parse(src, path)
|
||||
nodes, comments, positions, errors = php7.Parse(src, path)
|
||||
}
|
||||
|
||||
for _, e := range errors {
|
||||
fmt.Println(e)
|
||||
}
|
||||
|
||||
nsResolver := visitor.NewNamespaceResolver()
|
||||
|
@ -7,16 +7,26 @@ import (
|
||||
|
||||
"github.com/cznic/golex/lex"
|
||||
|
||||
"github.com/z7zmey/php-parser/errors"
|
||||
"github.com/z7zmey/php-parser/scanner"
|
||||
"github.com/z7zmey/php-parser/token"
|
||||
)
|
||||
|
||||
type lexer struct {
|
||||
scanner.Lexer
|
||||
lastToken *token.Token
|
||||
errors []*errors.Error
|
||||
}
|
||||
|
||||
func (l *lexer) Lex(lval *yySymType) int {
|
||||
return l.Lexer.Lex(lval)
|
||||
t := l.Lexer.Lex(lval)
|
||||
l.lastToken = &lval.token
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
func (l *lexer) Error(msg string) {
|
||||
l.errors = append(l.errors, errors.NewError(msg, *l.lastToken))
|
||||
}
|
||||
|
||||
func (lval *yySymType) Token(t token.Token) {
|
||||
@ -30,12 +40,16 @@ func newLexer(src io.Reader, fName string) *lexer {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
scanner := scanner.Lexer{
|
||||
Lexer: lx,
|
||||
StateStack: []int{0},
|
||||
PhpDocComment: "",
|
||||
Comments: nil,
|
||||
}
|
||||
|
||||
return &lexer{
|
||||
scanner.Lexer{
|
||||
Lexer: lx,
|
||||
StateStack: []int{0},
|
||||
PhpDocComment: "",
|
||||
Comments: nil,
|
||||
},
|
||||
scanner,
|
||||
nil,
|
||||
nil,
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ package php5
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/z7zmey/php-parser/errors"
|
||||
"github.com/z7zmey/php-parser/node/expr"
|
||||
|
||||
"github.com/z7zmey/php-parser/comment"
|
||||
@ -21,15 +22,17 @@ var positionBuilder position.Builder
|
||||
var parentNode node.Node
|
||||
|
||||
// Parse the php5 parser entrypoint
|
||||
func Parse(src io.Reader, fName string) (node.Node, comment.Comments, position.Positions) {
|
||||
func Parse(src io.Reader, fName string) (node.Node, comment.Comments, position.Positions, []*errors.Error) {
|
||||
yyDebug = 0
|
||||
yyErrorVerbose = true
|
||||
rootnode = stmt.NewStmtList([]node.Node{}) //reset
|
||||
comments = comment.Comments{}
|
||||
positions = position.Positions{}
|
||||
positionBuilder = position.Builder{Positions: &positions}
|
||||
yyParse(newLexer(src, fName))
|
||||
return rootnode, comments, positions
|
||||
|
||||
lexer := newLexer(src, fName)
|
||||
yyParse(lexer)
|
||||
return rootnode, comments, positions, lexer.errors
|
||||
}
|
||||
|
||||
// ListGetFirstNodeComments returns comments of a first node in the list
|
||||
|
5606
php5/php5.go
5606
php5/php5.go
File diff suppressed because it is too large
Load Diff
27
php5/php5.y
27
php5/php5.y
@ -239,7 +239,12 @@ start:
|
||||
;
|
||||
|
||||
top_statement_list:
|
||||
top_statement_list top_statement { $$ = append($1, $2) }
|
||||
top_statement_list top_statement
|
||||
{
|
||||
if $2 != nil {
|
||||
$$ = append($1, $2)
|
||||
}
|
||||
}
|
||||
| /* empty */ { $$ = []node.Node{} }
|
||||
;
|
||||
|
||||
@ -261,7 +266,12 @@ namespace_name:
|
||||
;
|
||||
|
||||
top_statement:
|
||||
statement
|
||||
error
|
||||
{
|
||||
// error
|
||||
$$ = nil
|
||||
}
|
||||
| statement
|
||||
{ $$ = $1 }
|
||||
| function_declaration_statement
|
||||
{ $$ = $1 }
|
||||
@ -534,14 +544,23 @@ constant_declaration:
|
||||
|
||||
inner_statement_list:
|
||||
inner_statement_list inner_statement
|
||||
{ $$ = append($1, $2) }
|
||||
{
|
||||
if $2 != nil {
|
||||
$$ = append($1, $2)
|
||||
}
|
||||
}
|
||||
| /* empty */
|
||||
{ $$ = []node.Node{} }
|
||||
;
|
||||
|
||||
|
||||
inner_statement:
|
||||
statement
|
||||
error
|
||||
{
|
||||
// error
|
||||
$$ = nil
|
||||
}
|
||||
| statement
|
||||
{ $$ = $1 }
|
||||
| function_declaration_statement
|
||||
{ $$ = $1 }
|
||||
|
@ -7,16 +7,26 @@ import (
|
||||
|
||||
"github.com/cznic/golex/lex"
|
||||
|
||||
"github.com/z7zmey/php-parser/errors"
|
||||
"github.com/z7zmey/php-parser/scanner"
|
||||
"github.com/z7zmey/php-parser/token"
|
||||
)
|
||||
|
||||
type lexer struct {
|
||||
scanner.Lexer
|
||||
lastToken *token.Token
|
||||
errors []*errors.Error
|
||||
}
|
||||
|
||||
func (l *lexer) Lex(lval *yySymType) int {
|
||||
return l.Lexer.Lex(lval)
|
||||
t := l.Lexer.Lex(lval)
|
||||
l.lastToken = &lval.token
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
func (l *lexer) Error(msg string) {
|
||||
l.errors = append(l.errors, errors.NewError(msg, *l.lastToken))
|
||||
}
|
||||
|
||||
func (lval *yySymType) Token(t token.Token) {
|
||||
@ -30,12 +40,16 @@ func newLexer(src io.Reader, fName string) *lexer {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
scanner := scanner.Lexer{
|
||||
Lexer: lx,
|
||||
StateStack: []int{0},
|
||||
PhpDocComment: "",
|
||||
Comments: nil,
|
||||
}
|
||||
|
||||
return &lexer{
|
||||
scanner.Lexer{
|
||||
Lexer: lx,
|
||||
StateStack: []int{0},
|
||||
PhpDocComment: "",
|
||||
Comments: nil,
|
||||
},
|
||||
scanner,
|
||||
nil,
|
||||
nil,
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/z7zmey/php-parser/comment"
|
||||
"github.com/z7zmey/php-parser/errors"
|
||||
"github.com/z7zmey/php-parser/node"
|
||||
"github.com/z7zmey/php-parser/node/stmt"
|
||||
"github.com/z7zmey/php-parser/position"
|
||||
@ -17,15 +18,17 @@ var positions position.Positions
|
||||
var positionBuilder position.Builder
|
||||
|
||||
// Parse the php7 parser entrypoint
|
||||
func Parse(src io.Reader, fName string) (node.Node, comment.Comments, position.Positions) {
|
||||
func Parse(src io.Reader, fName string) (node.Node, comment.Comments, position.Positions, []*errors.Error) {
|
||||
yyDebug = 0
|
||||
yyErrorVerbose = true
|
||||
rootnode = stmt.NewStmtList([]node.Node{}) //reset
|
||||
comments = comment.Comments{}
|
||||
positions = position.Positions{}
|
||||
positionBuilder = position.Builder{&positions}
|
||||
yyParse(newLexer(src, fName))
|
||||
return rootnode, comments, positions
|
||||
|
||||
lexer := newLexer(src, fName)
|
||||
yyParse(lexer)
|
||||
return rootnode, comments, positions, lexer.errors
|
||||
}
|
||||
|
||||
// ListGetFirstNodeComments returns comments of a first node in the list
|
||||
|
4590
php7/php7.go
4590
php7/php7.go
File diff suppressed because it is too large
Load Diff
28
php7/php7.y
28
php7/php7.y
@ -281,7 +281,12 @@ identifier:
|
||||
;
|
||||
|
||||
top_statement_list:
|
||||
top_statement_list top_statement { $$ = append($1, $2) }
|
||||
top_statement_list top_statement
|
||||
{
|
||||
if $2 != nil {
|
||||
$$ = append($1, $2)
|
||||
}
|
||||
}
|
||||
| /* empty */ { $$ = []node.Node{} }
|
||||
;
|
||||
|
||||
@ -324,7 +329,12 @@ name:
|
||||
;
|
||||
|
||||
top_statement:
|
||||
statement { $$ = $1; }
|
||||
error
|
||||
{
|
||||
// error
|
||||
$$ = nil
|
||||
}
|
||||
| statement { $$ = $1; }
|
||||
| function_declaration_statement { $$ = $1; }
|
||||
| class_declaration_statement { $$ = $1; }
|
||||
| trait_declaration_statement { $$ = $1; }
|
||||
@ -498,12 +508,22 @@ const_list:
|
||||
;
|
||||
|
||||
inner_statement_list:
|
||||
inner_statement_list inner_statement { $$ = append($1, $2) }
|
||||
inner_statement_list inner_statement
|
||||
{
|
||||
if $2 != nil {
|
||||
$$ = append($1, $2)
|
||||
}
|
||||
}
|
||||
| /* empty */ { $$ = []node.Node{} }
|
||||
;
|
||||
|
||||
inner_statement:
|
||||
statement { $$ = $1; }
|
||||
error
|
||||
{
|
||||
// error
|
||||
$$ = nil
|
||||
}
|
||||
| statement { $$ = $1; }
|
||||
| function_declaration_statement { $$ = $1; }
|
||||
| class_declaration_statement { $$ = $1; }
|
||||
| trait_declaration_statement { $$ = $1; }
|
||||
|
Loading…
Reference in New Issue
Block a user