error tolerant parsing

This commit is contained in:
z7zmey 2018-04-09 23:08:29 +03:00
parent ebe06da6e0
commit 83a1400a4f
10 changed files with 5294 additions and 5072 deletions

31
errors/error.go Normal file
View 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
View File

@ -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()

View File

@ -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)
}
return &lexer{
scanner.Lexer{
scanner := scanner.Lexer{
Lexer: lx,
StateStack: []int{0},
PhpDocComment: "",
Comments: nil,
},
}
return &lexer{
scanner,
nil,
nil,
}
}

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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 }

View File

@ -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)
}
return &lexer{
scanner.Lexer{
scanner := scanner.Lexer{
Lexer: lx,
StateStack: []int{0},
PhpDocComment: "",
Comments: nil,
},
}
return &lexer{
scanner,
nil,
nil,
}
}

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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; }