From 316ed6e8514ae145997e34eaa2781d31efefd794 Mon Sep 17 00:00:00 2001 From: z7zmey Date: Tue, 10 Apr 2018 20:15:15 +0300 Subject: [PATCH] issue #8: cli - parse concurrently --- main.go | 116 ++++++++++++++++++++++++++++++------------------- parser.go | 17 ++++++++ php5/parser.go | 11 ++++- php7/parser.go | 11 ++++- 4 files changed, 106 insertions(+), 49 deletions(-) create mode 100644 parser.go diff --git a/main.go b/main.go index 9c837e7..b02b335 100644 --- a/main.go +++ b/main.go @@ -6,66 +6,50 @@ import ( "log" "os" "path/filepath" + "sync" "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" - "github.com/z7zmey/php-parser/position" "github.com/z7zmey/php-parser/visitor" ) -func main() { - var nodes node.Node - var comments comment.Comments - var positions position.Positions - var errors []*errors.Error +var wg sync.WaitGroup +var usePhp5 *bool - usePhp5 := flag.Bool("php5", false, "use PHP5 parser") +func main() { + usePhp5 = flag.Bool("php5", false, "use PHP5 parser") flag.Parse() - for _, path := range flag.Args() { + pathCh := make(chan string) + resultCh := make(chan Parser) + + // run 4 concurrent parsers + for i := 0; i < 4; i++ { + go parser(pathCh, resultCh) + } + + // run printer goroutine + go printer(resultCh) + + // process files + processPath(flag.Args(), pathCh) + + // wait the all files done + wg.Wait() + close(pathCh) + close(resultCh) +} + +func processPath(pathList []string, pathCh chan<- string) { + for _, path := range pathList { real, err := realpath.Realpath(path) checkErr(err) err = filepath.Walk(real, func(path string, f os.FileInfo, err error) error { if !f.IsDir() && filepath.Ext(path) == ".php" { - fmt.Printf("==> %s\n", path) - - src, _ := os.Open(string(path)) - if *usePhp5 { - parser := php5.NewParser(src, path) - parser.Parse() - nodes = parser.GetRootNode() - errors = parser.GetErrors() - comments = parser.GetComments() - positions = parser.GetPositions() - } else { - parser := php7.NewParser(src, path) - parser.Parse() - nodes = parser.GetRootNode() - errors = parser.GetErrors() - comments = parser.GetComments() - positions = parser.GetPositions() - } - - for _, e := range errors { - fmt.Println(e) - } - - nsResolver := visitor.NewNamespaceResolver() - nodes.Walk(nsResolver) - - dumper := visitor.Dumper{ - Writer: os.Stdout, - Indent: " | ", - Comments: comments, - Positions: positions, - NsResolver: nsResolver, - } - nodes.Walk(dumper) + wg.Add(1) + pathCh <- path } return nil }) @@ -73,6 +57,48 @@ func main() { } } +func parser(pathCh <-chan string, result chan<- Parser) { + var parser Parser + + for { + path := <-pathCh + src, _ := os.Open(path) + + if *usePhp5 { + parser = php5.NewParser(src, path) + } else { + parser = php7.NewParser(src, path) + } + + parser.Parse() + result <- parser + } +} + +func printer(result <-chan Parser) { + for { + parser := <-result + fmt.Printf("==> %s\n", parser.GetPath()) + + for _, e := range parser.GetErrors() { + fmt.Println(e) + } + + nsResolver := visitor.NewNamespaceResolver() + parser.GetRootNode().Walk(nsResolver) + + dumper := visitor.Dumper{ + Writer: os.Stdout, + Indent: " | ", + Comments: parser.GetComments(), + Positions: parser.GetPositions(), + NsResolver: nsResolver, + } + parser.GetRootNode().Walk(dumper) + wg.Done() + } +} + func checkErr(err error) { if err != nil { log.Fatal(err) diff --git a/parser.go b/parser.go new file mode 100644 index 0000000..3f23452 --- /dev/null +++ b/parser.go @@ -0,0 +1,17 @@ +package main + +import ( + "github.com/z7zmey/php-parser/comment" + "github.com/z7zmey/php-parser/errors" + "github.com/z7zmey/php-parser/node" + "github.com/z7zmey/php-parser/position" +) + +type Parser interface { + Parse() int + GetPath() string + GetRootNode() node.Node + GetErrors() []*errors.Error + GetComments() comment.Comments + GetPositions() position.Positions +} diff --git a/php5/parser.go b/php5/parser.go index 5d40e13..ffb9cc6 100644 --- a/php5/parser.go +++ b/php5/parser.go @@ -18,6 +18,7 @@ func (lval *yySymType) Token(t token.Token) { // Parser structure type Parser struct { *scanner.Lexer + path string lastToken *token.Token positionBuilder *position.Builder errors []*errors.Error @@ -27,11 +28,12 @@ type Parser struct { } // NewParser creates and returns new Parser -func NewParser(src io.Reader, fName string) *Parser { - lexer := scanner.NewLexer(src, fName) +func NewParser(src io.Reader, path string) *Parser { + lexer := scanner.NewLexer(src, path) return &Parser{ lexer, + path, nil, nil, nil, @@ -81,6 +83,11 @@ func (l *Parser) listGetFirstNodeComments(list []node.Node) []comment.Comment { return l.comments[node] } +// GetPath return path to file +func (l *Parser) GetPath() string { + return l.path +} + // GetRootNode returns root node func (l *Parser) GetRootNode() node.Node { return l.rootNode diff --git a/php7/parser.go b/php7/parser.go index c17c64b..a8d3bd2 100644 --- a/php7/parser.go +++ b/php7/parser.go @@ -18,6 +18,7 @@ func (lval *yySymType) Token(t token.Token) { // Parser structure type Parser struct { *scanner.Lexer + path string lastToken *token.Token positionBuilder *position.Builder errors []*errors.Error @@ -27,11 +28,12 @@ type Parser struct { } // NewParser creates and returns new Parser -func NewParser(src io.Reader, fName string) *Parser { - lexer := scanner.NewLexer(src, fName) +func NewParser(src io.Reader, path string) *Parser { + lexer := scanner.NewLexer(src, path) return &Parser{ lexer, + path, nil, nil, nil, @@ -81,6 +83,11 @@ func (l *Parser) listGetFirstNodeComments(list []node.Node) []comment.Comment { return l.comments[node] } +// GetPath return path to file +func (l *Parser) GetPath() string { + return l.path +} + // GetRootNode returns root node func (l *Parser) GetRootNode() node.Node { return l.rootNode