From 34050ca8de7c6ef84fc1f829a3bb7a473723429c Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 26 Mar 2009 22:16:06 -0700 Subject: [PATCH] - adjustments to match slightly changed scanner interface - more comments on parser, various cleanups TBR=r OCL=26813 CL=26813 --- usr/gri/pretty/compilation.go | 2 +- usr/gri/pretty/parser.go | 1373 +++++++++++++++++---------------- 2 files changed, 689 insertions(+), 686 deletions(-) diff --git a/usr/gri/pretty/compilation.go b/usr/gri/pretty/compilation.go index 8d74ea5b72..17906c50e1 100644 --- a/usr/gri/pretty/compilation.go +++ b/usr/gri/pretty/compilation.go @@ -101,7 +101,7 @@ func Compile(src_file string, flags *Flags) (*ast.Package, ErrorList) { if flags.Verbose { pflags |= parser.Trace; } - prog := parser.Parse(&scanner, &err, parser.ParseEntirePackage, pflags); + prog, nerrs := parser.Parse(&scanner, &err, parser.ParseEntirePackage, pflags); if err.errors.Len() == 0 { TypeChecker.CheckProgram(&err, prog); diff --git a/usr/gri/pretty/parser.go b/usr/gri/pretty/parser.go index 073fd2a014..92ff4622a6 100644 --- a/usr/gri/pretty/parser.go +++ b/usr/gri/pretty/parser.go @@ -4,7 +4,8 @@ // A parser for Go source text. The input is a stream of lexical tokens // provided via the Scanner interface. The output is an abstract syntax -// tree (AST) representing the Go source. +// tree (AST) representing the Go source. The parser is invoked by calling +// Parse. // package parser @@ -16,26 +17,22 @@ import ( ) -type interval struct { - beg, end int; -} - - // An implementation of a Scanner must be provided to the Parser. // The parser calls Scan() repeatedly until token.EOF is returned. // Scan must return the current token position pos, the token value -// tok, and the corresponding token literal string lit if the token -// is a literal (i.e., if tok.IsLiteral() is true). +// tok, and the corresponding token literal string lit; lit can be +// undefined/nil unless the token is a literal (i.e., tok.IsLiteral() +// is true). // type Scanner interface { Scan() (pos token.Position, tok token.Token, lit []byte); } -// An implementation of an ErrorHandler must be provided to the parser. -// If a syntax error is encountered, Error is called with a position and -// an error message. The position points to the beginning of the offending -// token. +// An implementation of an ErrorHandler may be provided to the parser. +// If a syntax error is encountered and a handler was installed, Error +// is called with a position and an error message. The position points +// to the beginning of the offending token. // type ErrorHandler interface { Error(pos token.Position, msg string); @@ -46,24 +43,31 @@ type ErrorHandler interface { // flags (or 0) must be provided as a parameter to the Parse function. // const ( - Trace = 1 << iota; + Trace = 1 << iota; // print a trace of parsed productions ) +type interval struct { + beg, end int; +} + + // The parser structure holds the parser's internal state. type parser struct { scanner Scanner; - err ErrorHandler; + err ErrorHandler; // nil if no handler installed + errorCount int; // Tracing/debugging trace bool; indent uint; + // Comments comments vector.Vector; // list of collected, unassociated comments last_doc interval; // last comments interval of consecutive comments // The next token - pos token.Position; // token location + pos token.Position; // token position tok token.Token; // one token look-ahead lit []byte; // token literal @@ -73,8 +77,8 @@ type parser struct { }; -// When we don't have a location use nopos. -// TODO make sure we always have a location. +// When we don't have a position use nopos. +// TODO make sure we always have a position. var nopos token.Position; @@ -89,8 +93,8 @@ func unreachable() { // ---------------------------------------------------------------------------- // Parsing support -func (P *parser) printIndent() { - i := P.indent; +func (p *parser) printIndent() { + i := p.indent; // reduce printing time by a factor of 2 or more for ; i > 10; i -= 10 { fmt.Printf(". . . . . . . . . . "); @@ -101,38 +105,38 @@ func (P *parser) printIndent() { } -func trace(P *parser, msg string) *parser { - P.printIndent(); +func trace(p *parser, msg string) *parser { + p.printIndent(); fmt.Printf("%s (\n", msg); - P.indent++; - return P; + p.indent++; + return p; } -func un/*trace*/(P *parser) { - P.indent--; - P.printIndent(); +func un/*trace*/(p *parser) { + p.indent--; + p.printIndent(); fmt.Printf(")\n"); } -func (P *parser) next0() { - P.pos, P.tok, P.lit = P.scanner.Scan(); - P.opt_semi = false; +func (p *parser) next0() { + p.pos, p.tok, p.lit = p.scanner.Scan(); + p.opt_semi = false; - if P.trace { - P.printIndent(); - switch P.tok { + if p.trace { + p.printIndent(); + switch p.tok { case token.IDENT, token.INT, token.FLOAT, token.CHAR, token.STRING: - fmt.Printf("%d:%d: %s = %s\n", P.pos.Line, P.pos.Column, P.tok.String(), P.lit); + fmt.Printf("%d:%d: %s = %s\n", p.pos.Line, p.pos.Column, p.tok.String(), p.lit); case token.LPAREN: // don't print '(' - screws up selection in terminal window - fmt.Printf("%d:%d: LPAREN\n", P.pos.Line, P.pos.Column); + fmt.Printf("%d:%d: LPAREN\n", p.pos.Line, p.pos.Column); case token.RPAREN: // don't print ')' - screws up selection in terminal window - fmt.Printf("%d:%d: RPAREN\n", P.pos.Line, P.pos.Column); + fmt.Printf("%d:%d: RPAREN\n", p.pos.Line, p.pos.Column); default: - fmt.Printf("%d:%d: %s\n", P.pos.Line, P.pos.Column, P.tok.String()); + fmt.Printf("%d:%d: %s\n", p.pos.Line, p.pos.Column, p.tok.String()); } } } @@ -140,71 +144,74 @@ func (P *parser) next0() { // Collect a comment in the parser's comment list and return the line // on which the comment ends. -func (P *parser) collectComment() int { +func (p *parser) collectComment() int { // For /*-style comments, the comment may end on a different line. // Scan the comment for '\n' chars and adjust the end line accordingly. // (Note that the position of the next token may be even further down // as there may be more whitespace lines after the comment.) - endline := P.pos.Line; - if P.lit[1] == '*' { - for i, b := range P.lit { + endline := p.pos.Line; + if p.lit[1] == '*' { + for i, b := range p.lit { if b == '\n' { endline++; } } } - P.comments.Push(&ast.Comment{P.pos, P.lit, endline}); - P.next0(); + p.comments.Push(&ast.Comment{p.pos, p.lit, endline}); + p.next0(); return endline; } -func (P *parser) getComments() interval { +func (p *parser) getComments() interval { // group adjacent comments, an empty line terminates a group - beg := P.comments.Len(); - endline := P.pos.Line; - for P.tok == token.COMMENT && endline+1 >= P.pos.Line { - endline = P.collectComment(); + beg := p.comments.Len(); + endline := p.pos.Line; + for p.tok == token.COMMENT && endline+1 >= p.pos.Line { + endline = p.collectComment(); } - end := P.comments.Len(); + end := p.comments.Len(); return interval {beg, end}; } -func (P *parser) next() { - P.next0(); - P.last_doc = interval{0, 0}; - for P.tok == token.COMMENT { - P.last_doc = P.getComments(); +func (p *parser) next() { + p.next0(); + p.last_doc = interval{0, 0}; + for p.tok == token.COMMENT { + p.last_doc = p.getComments(); } } -func (P *parser) error(pos token.Position, msg string) { - P.err.Error(pos, msg); +func (p *parser) error(pos token.Position, msg string) { + if p.err != nil { + p.err.Error(pos, msg); + } + p.errorCount++; } -func (P *parser) expect(tok token.Token) token.Position { - if P.tok != tok { - msg := "expected '" + tok.String() + "', found '" + P.tok.String() + "'"; - if P.tok.IsLiteral() { - msg += " " + string(P.lit); +func (p *parser) expect(tok token.Token) token.Position { + if p.tok != tok { + msg := "expected '" + tok.String() + "', found '" + p.tok.String() + "'"; + if p.tok.IsLiteral() { + msg += " " + string(p.lit); } - P.error(P.pos, msg); + p.error(p.pos, msg); } - loc := P.pos; - P.next(); // make progress in any case - return loc; + pos := p.pos; + p.next(); // make progress in any case + return pos; } -func (P *parser) getDoc() ast.Comments { - doc := P.last_doc; +func (p *parser) getDoc() ast.Comments { + doc := p.last_doc; n := doc.end - doc.beg; - if n <= 0 || P.comments.At(doc.end - 1).(*ast.Comment).EndLine + 1 < P.pos.Line { + if n <= 0 || p.comments.At(doc.end - 1).(*ast.Comment).EndLine + 1 < p.pos.Line { // no comments or empty line between last comment and current token; // do not use as documentation return nil; @@ -214,10 +221,12 @@ func (P *parser) getDoc() ast.Comments { // use as documentation c := make(ast.Comments, n); for i := 0; i < n; i++ { - c[i] = P.comments.At(doc.beg + i).(*ast.Comment); - // TODO find a better way to do this - P.comments.Set(doc.beg + i, nil); // remove the comment from the general list + c[i] = p.comments.At(doc.beg + i).(*ast.Comment); } + + // remove comments from the general list + p.comments.Cut(doc.beg, doc.end); + return c; } @@ -225,41 +234,41 @@ func (P *parser) getDoc() ast.Comments { // ---------------------------------------------------------------------------- // Common productions -func (P *parser) tryType() ast.Expr; -func (P *parser) parseExpression(prec int) ast.Expr; -func (P *parser) parseStatement() ast.Stmt; -func (P *parser) parseDeclaration() ast.Decl; +func (p *parser) tryType() ast.Expr; +func (p *parser) parseExpression(prec int) ast.Expr; +func (p *parser) parseStatement() ast.Stmt; +func (p *parser) parseDeclaration() ast.Decl; -func (P *parser) parseIdent() *ast.Ident { - if P.trace { - defer un(trace(P, "Ident")); +func (p *parser) parseIdent() *ast.Ident { + if p.trace { + defer un(trace(p, "Ident")); } - if P.tok == token.IDENT { - x := &ast.Ident{P.pos, P.lit}; - P.next(); + if p.tok == token.IDENT { + x := &ast.Ident{p.pos, p.lit}; + p.next(); return x; } - P.expect(token.IDENT); // use expect() error handling + p.expect(token.IDENT); // use expect() error handling - return &ast.Ident{P.pos, [0]byte{}}; + return &ast.Ident{p.pos, [0]byte{}}; } -func (P *parser) parseIdentList(x ast.Expr) []*ast.Ident { - if P.trace { - defer un(trace(P, "IdentList")); +func (p *parser) parseIdentList(x ast.Expr) []*ast.Ident { + if p.trace { + defer un(trace(p, "IdentList")); } list := vector.New(0); if x == nil { - x = P.parseIdent(); + x = p.parseIdent(); } list.Push(x); - for P.tok == token.COMMA { - P.next(); - list.Push(P.parseIdent()); + for p.tok == token.COMMA { + p.next(); + list.Push(p.parseIdent()); } // convert vector @@ -272,16 +281,16 @@ func (P *parser) parseIdentList(x ast.Expr) []*ast.Ident { } -func (P *parser) parseExpressionList() []ast.Expr { - if P.trace { - defer un(trace(P, "ExpressionList")); +func (p *parser) parseExpressionList() []ast.Expr { + if p.trace { + defer un(trace(p, "ExpressionList")); } list := vector.New(0); - list.Push(P.parseExpression(1)); - for P.tok == token.COMMA { - P.next(); - list.Push(P.parseExpression(1)); + list.Push(p.parseExpression(1)); + for p.tok == token.COMMA { + p.next(); + list.Push(p.parseExpression(1)); } // convert list @@ -297,149 +306,140 @@ func (P *parser) parseExpressionList() []ast.Expr { // ---------------------------------------------------------------------------- // Types -func (P *parser) parseType() ast.Expr { - if P.trace { - defer un(trace(P, "Type")); +func (p *parser) parseType() ast.Expr { + if p.trace { + defer un(trace(p, "Type")); } - typ := P.tryType(); + typ := p.tryType(); if typ == nil { - P.error(P.pos, "type expected"); - typ = &ast.BadExpr{P.pos}; + p.error(p.pos, "type expected"); + typ = &ast.BadExpr{p.pos}; } return typ; } -func (P *parser) parseVarType() ast.Expr { - if P.trace { - defer un(trace(P, "VarType")); - } - - return P.parseType(); -} - - -func (P *parser) parseQualifiedIdent() ast.Expr { - if P.trace { - defer un(trace(P, "QualifiedIdent")); +func (p *parser) parseQualifiedIdent() ast.Expr { + if p.trace { + defer un(trace(p, "QualifiedIdent")); } - var x ast.Expr = P.parseIdent(); - for P.tok == token.PERIOD { - P.next(); - sel := P.parseIdent(); + var x ast.Expr = p.parseIdent(); + for p.tok == token.PERIOD { + p.next(); + sel := p.parseIdent(); x = &ast.SelectorExpr{x, sel}; } return x; } -func (P *parser) parseTypeName() ast.Expr { - if P.trace { - defer un(trace(P, "TypeName")); +func (p *parser) parseTypeName() ast.Expr { + if p.trace { + defer un(trace(p, "TypeName")); } - return P.parseQualifiedIdent(); + return p.parseQualifiedIdent(); } -func (P *parser) parseArrayType() *ast.ArrayType { - if P.trace { - defer un(trace(P, "ArrayType")); +func (p *parser) parseArrayType() *ast.ArrayType { + if p.trace { + defer un(trace(p, "ArrayType")); } - lbrack := P.expect(token.LBRACK); + lbrack := p.expect(token.LBRACK); var len ast.Expr; - if P.tok == token.ELLIPSIS { - len = &ast.Ellipsis{P.pos}; - P.next(); - } else if P.tok != token.RBRACK { - len = P.parseExpression(1); + if p.tok == token.ELLIPSIS { + len = &ast.Ellipsis{p.pos}; + p.next(); + } else if p.tok != token.RBRACK { + len = p.parseExpression(1); } - P.expect(token.RBRACK); - elt := P.parseType(); + p.expect(token.RBRACK); + elt := p.parseType(); return &ast.ArrayType{lbrack, len, elt}; } -func (P *parser) parseChannelType() *ast.ChannelType { - if P.trace { - defer un(trace(P, "ChannelType")); +func (p *parser) parseChannelType() *ast.ChannelType { + if p.trace { + defer un(trace(p, "ChannelType")); } - pos := P.pos; + pos := p.pos; dir := ast.SEND | ast.RECV; - if P.tok == token.CHAN { - P.next(); - if P.tok == token.ARROW { - P.next(); + if p.tok == token.CHAN { + p.next(); + if p.tok == token.ARROW { + p.next(); dir = ast.SEND; } } else { - P.expect(token.ARROW); - P.expect(token.CHAN); + p.expect(token.ARROW); + p.expect(token.CHAN); dir = ast.RECV; } - value := P.parseVarType(); + value := p.parseType(); return &ast.ChannelType{pos, dir, value}; } -func (P *parser) tryParameterType() ast.Expr { - if P.tok == token.ELLIPSIS { - loc := P.pos; - P.next(); - return &ast.Ellipsis{loc}; +func (p *parser) tryParameterType() ast.Expr { + if p.tok == token.ELLIPSIS { + x := &ast.Ellipsis{p.pos}; + p.next(); + return x; } - return P.tryType(); + return p.tryType(); } -func (P *parser) parseParameterType() ast.Expr { - typ := P.tryParameterType(); +func (p *parser) parseParameterType() ast.Expr { + typ := p.tryParameterType(); if typ == nil { - P.error(P.pos, "type expected"); - typ = &ast.BadExpr{P.pos}; + p.error(p.pos, "type expected"); + typ = &ast.BadExpr{p.pos}; } return typ; } -func (P *parser) parseParameterDecl(ellipsis_ok bool) (*vector.Vector, ast.Expr) { - if P.trace { - defer un(trace(P, "ParameterDecl")); +func (p *parser) parseParameterDecl(ellipsis_ok bool) (*vector.Vector, ast.Expr) { + if p.trace { + defer un(trace(p, "ParameterDecl")); } // a list of identifiers looks like a list of type names list := vector.New(0); for { // TODO do not allow ()'s here - list.Push(P.parseParameterType()); - if P.tok == token.COMMA { - P.next(); + list.Push(p.parseParameterType()); + if p.tok == token.COMMA { + p.next(); } else { break; } } // if we had a list of identifiers, it must be followed by a type - typ := P.tryParameterType(); + typ := p.tryParameterType(); return list, typ; } -func (P *parser) parseParameterList(ellipsis_ok bool) []*ast.Field { - if P.trace { - defer un(trace(P, "ParameterList")); +func (p *parser) parseParameterList(ellipsis_ok bool) []*ast.Field { + if p.trace { + defer un(trace(p, "ParameterList")); } - list, typ := P.parseParameterDecl(false); + list, typ := p.parseParameterDecl(false); if typ != nil { // IdentifierList Type // convert list of identifiers into []*Ident @@ -450,10 +450,10 @@ func (P *parser) parseParameterList(ellipsis_ok bool) []*ast.Field { list.Init(0); list.Push(&ast.Field{nil, idents, typ, nil}); - for P.tok == token.COMMA { - P.next(); - idents := P.parseIdentList(nil); - typ := P.parseParameterType(); + for p.tok == token.COMMA { + p.next(); + idents := p.parseIdentList(nil); + typ := p.parseParameterType(); list.Push(&ast.Field{nil, idents, typ, nil}); } @@ -476,32 +476,32 @@ func (P *parser) parseParameterList(ellipsis_ok bool) []*ast.Field { // TODO make sure Go spec is updated -func (P *parser) parseParameters(ellipsis_ok bool) []*ast.Field { - if P.trace { - defer un(trace(P, "Parameters")); +func (p *parser) parseParameters(ellipsis_ok bool) []*ast.Field { + if p.trace { + defer un(trace(p, "Parameters")); } var params []*ast.Field; - P.expect(token.LPAREN); - if P.tok != token.RPAREN { - params = P.parseParameterList(ellipsis_ok); + p.expect(token.LPAREN); + if p.tok != token.RPAREN { + params = p.parseParameterList(ellipsis_ok); } - P.expect(token.RPAREN); + p.expect(token.RPAREN); return params; } -func (P *parser) parseResult() []*ast.Field { - if P.trace { - defer un(trace(P, "Result")); +func (p *parser) parseResult() []*ast.Field { + if p.trace { + defer un(trace(p, "Result")); } var results []*ast.Field; - if P.tok == token.LPAREN { - results = P.parseParameters(false); - } else if P.tok != token.FUNC { - typ := P.tryType(); + if p.tok == token.LPAREN { + results = p.parseParameters(false); + } else if p.tok != token.FUNC { + typ := p.tryType(); if typ != nil { results = make([]*ast.Field, 1); results[0] = &ast.Field{nil, nil, typ, nil}; @@ -518,43 +518,43 @@ func (P *parser) parseResult() []*ast.Field { // (params) type // (params) (results) -func (P *parser) parseSignature() (params []*ast.Field, results []*ast.Field) { - if P.trace { - defer un(trace(P, "Signature")); +func (p *parser) parseSignature() (params []*ast.Field, results []*ast.Field) { + if p.trace { + defer un(trace(p, "Signature")); } - params = P.parseParameters(true); // TODO find better solution - results = P.parseResult(); + params = p.parseParameters(true); // TODO find better solution + results = p.parseResult(); return params, results; } -func (P *parser) parseFunctionType() *ast.FunctionType { - if P.trace { - defer un(trace(P, "FunctionType")); +func (p *parser) parseFunctionType() *ast.FunctionType { + if p.trace { + defer un(trace(p, "FunctionType")); } - pos := P.expect(token.FUNC); - params, results := P.parseSignature(); + pos := p.expect(token.FUNC); + params, results := p.parseSignature(); return &ast.FunctionType{pos, params, results}; } -func (P *parser) parseMethodSpec() *ast.Field { - if P.trace { - defer un(trace(P, "MethodSpec")); +func (p *parser) parseMethodSpec() *ast.Field { + if p.trace { + defer un(trace(p, "MethodSpec")); } - doc := P.getDoc(); + doc := p.getDoc(); var idents []*ast.Ident; var typ ast.Expr; - x := P.parseQualifiedIdent(); - if tmp, is_ident := x.(*ast.Ident); is_ident && (P.tok == token.COMMA || P.tok == token.LPAREN) { + x := p.parseQualifiedIdent(); + if tmp, is_ident := x.(*ast.Ident); is_ident && (p.tok == token.COMMA || p.tok == token.LPAREN) { // method(s) - idents = P.parseIdentList(x); - params, results := P.parseSignature(); + idents = p.parseIdentList(x); + params, results := p.parseSignature(); typ = &ast.FunctionType{nopos, params, results}; } else { // embedded interface @@ -565,28 +565,28 @@ func (P *parser) parseMethodSpec() *ast.Field { } -func (P *parser) parseInterfaceType() *ast.InterfaceType { - if P.trace { - defer un(trace(P, "InterfaceType")); +func (p *parser) parseInterfaceType() *ast.InterfaceType { + if p.trace { + defer un(trace(p, "InterfaceType")); } - pos := P.expect(token.INTERFACE); + pos := p.expect(token.INTERFACE); var lbrace, rbrace token.Position; var methods []*ast.Field; - if P.tok == token.LBRACE { - lbrace = P.pos; - P.next(); + if p.tok == token.LBRACE { + lbrace = p.pos; + p.next(); list := vector.New(0); - for P.tok == token.IDENT { - list.Push(P.parseMethodSpec()); - if P.tok != token.RBRACE { - P.expect(token.SEMICOLON); + for p.tok == token.IDENT { + list.Push(p.parseMethodSpec()); + if p.tok != token.RBRACE { + p.expect(token.SEMICOLON); } } - rbrace = P.expect(token.RBRACE); - P.opt_semi = true; + rbrace = p.expect(token.RBRACE); + p.opt_semi = true; // convert vector methods = make([]*ast.Field, list.Len()); @@ -599,49 +599,49 @@ func (P *parser) parseInterfaceType() *ast.InterfaceType { } -func (P *parser) parseMapType() *ast.MapType { - if P.trace { - defer un(trace(P, "MapType")); +func (p *parser) parseMapType() *ast.MapType { + if p.trace { + defer un(trace(p, "MapType")); } - pos := P.expect(token.MAP); - P.expect(token.LBRACK); - key := P.parseVarType(); - P.expect(token.RBRACK); - value := P.parseVarType(); + pos := p.expect(token.MAP); + p.expect(token.LBRACK); + key := p.parseType(); + p.expect(token.RBRACK); + value := p.parseType(); return &ast.MapType{pos, key, value}; } -func (P *parser) parseStringList(x *ast.StringLit) []*ast.StringLit +func (p *parser) parseStringList(x *ast.StringLit) []*ast.StringLit -func (P *parser) parseFieldDecl() *ast.Field { - if P.trace { - defer un(trace(P, "FieldDecl")); +func (p *parser) parseFieldDecl() *ast.Field { + if p.trace { + defer un(trace(p, "FieldDecl")); } - doc := P.getDoc(); + doc := p.getDoc(); // a list of identifiers looks like a list of type names list := vector.New(0); for { // TODO do not allow ()'s here - list.Push(P.parseType()); - if P.tok == token.COMMA { - P.next(); + list.Push(p.parseType()); + if p.tok == token.COMMA { + p.next(); } else { break; } } // if we had a list of identifiers, it must be followed by a type - typ := P.tryType(); + typ := p.tryType(); // optional tag var tag []*ast.StringLit; - if P.tok == token.STRING { - tag = P.parseStringList(nil); + if p.tok == token.STRING { + tag = p.parseStringList(nil); } // analyze case @@ -653,7 +653,7 @@ func (P *parser) parseFieldDecl() *ast.Field { if ident, is_ident := list.At(i).(*ast.Ident); is_ident { idents[i] = ident; } else { - P.error(list.At(i).(ast.Expr).Pos(), "identifier expected"); + p.error(list.At(i).(ast.Expr).Pos(), "identifier expected"); } } } else { @@ -662,7 +662,7 @@ func (P *parser) parseFieldDecl() *ast.Field { // TODO should do more checks here typ = list.At(0).(ast.Expr); } else { - P.error(P.pos, "anonymous field expected"); + p.error(p.pos, "anonymous field expected"); } } @@ -670,33 +670,33 @@ func (P *parser) parseFieldDecl() *ast.Field { } -func (P *parser) parseStructType() *ast.StructType { - if P.trace { - defer un(trace(P, "StructType")); +func (p *parser) parseStructType() *ast.StructType { + if p.trace { + defer un(trace(p, "StructType")); } - pos := P.expect(token.STRUCT); + pos := p.expect(token.STRUCT); var lbrace, rbrace token.Position; var fields []*ast.Field; - if P.tok == token.LBRACE { - lbrace = P.pos; - P.next(); + if p.tok == token.LBRACE { + lbrace = p.pos; + p.next(); list := vector.New(0); - for P.tok != token.RBRACE && P.tok != token.EOF { - list.Push(P.parseFieldDecl()); - if P.tok == token.SEMICOLON { - P.next(); + for p.tok != token.RBRACE && p.tok != token.EOF { + list.Push(p.parseFieldDecl()); + if p.tok == token.SEMICOLON { + p.next(); } else { break; } } - if P.tok == token.SEMICOLON { - P.next(); + if p.tok == token.SEMICOLON { + p.next(); } - rbrace = P.expect(token.RBRACE); - P.opt_semi = true; + rbrace = p.expect(token.RBRACE); + p.opt_semi = true; // convert vector fields = make([]*ast.Field, list.Len()); @@ -709,37 +709,37 @@ func (P *parser) parseStructType() *ast.StructType { } -func (P *parser) parsePointerType() *ast.StarExpr { - if P.trace { - defer un(trace(P, "PointerType")); +func (p *parser) parsePointerType() *ast.StarExpr { + if p.trace { + defer un(trace(p, "PointerType")); } - star := P.expect(token.MUL); - base := P.parseType(); + star := p.expect(token.MUL); + base := p.parseType(); return &ast.StarExpr{star, base}; } -func (P *parser) tryType() ast.Expr { - if P.trace { - defer un(trace(P, "Type (try)")); +func (p *parser) tryType() ast.Expr { + if p.trace { + defer un(trace(p, "Type (try)")); } - switch P.tok { - case token.IDENT: return P.parseTypeName(); - case token.LBRACK: return P.parseArrayType(); - case token.CHAN, token.ARROW: return P.parseChannelType(); - case token.INTERFACE: return P.parseInterfaceType(); - case token.FUNC: return P.parseFunctionType(); - case token.MAP: return P.parseMapType(); - case token.STRUCT: return P.parseStructType(); - case token.MUL: return P.parsePointerType(); + switch p.tok { + case token.IDENT: return p.parseTypeName(); + case token.LBRACK: return p.parseArrayType(); + case token.CHAN, token.ARROW: return p.parseChannelType(); + case token.INTERFACE: return p.parseInterfaceType(); + case token.FUNC: return p.parseFunctionType(); + case token.MAP: return p.parseMapType(); + case token.STRUCT: return p.parseStructType(); + case token.MUL: return p.parsePointerType(); case token.LPAREN: - lparen := P.pos; - P.next(); - x := P.parseType(); - rparen := P.expect(token.RPAREN); + lparen := p.pos; + p.next(); + x := p.parseType(); + rparen := p.expect(token.RPAREN); return &ast.ParenExpr{lparen, x, rparen}; } @@ -760,23 +760,23 @@ func asStmtList(list *vector.Vector) []ast.Stmt { } -func (P *parser) parseStatementList() []ast.Stmt { - if P.trace { - defer un(trace(P, "StatementList")); +func (p *parser) parseStatementList() []ast.Stmt { + if p.trace { + defer un(trace(p, "StatementList")); } list := vector.New(0); expect_semi := false; - for P.tok != token.CASE && P.tok != token.DEFAULT && P.tok != token.RBRACE && P.tok != token.EOF { + for p.tok != token.CASE && p.tok != token.DEFAULT && p.tok != token.RBRACE && p.tok != token.EOF { if expect_semi { - P.expect(token.SEMICOLON); + p.expect(token.SEMICOLON); expect_semi = false; } - list.Push(P.parseStatement()); - if P.tok == token.SEMICOLON { - P.next(); - } else if P.opt_semi { - P.opt_semi = false; // "consume" optional semicolon + list.Push(p.parseStatement()); + if p.tok == token.SEMICOLON { + p.next(); + } else if p.opt_semi { + p.opt_semi = false; // "consume" optional semicolon } else { expect_semi = true; } @@ -786,15 +786,15 @@ func (P *parser) parseStatementList() []ast.Stmt { } -func (P *parser) parseBlockStmt() *ast.BlockStmt { - if P.trace { - defer un(trace(P, "compositeStmt")); +func (p *parser) parseBlockStmt() *ast.BlockStmt { + if p.trace { + defer un(trace(p, "compositeStmt")); } - lbrace := P.expect(token.LBRACE); - list := P.parseStatementList(); - rbrace := P.expect(token.RBRACE); - P.opt_semi = true; + lbrace := p.expect(token.LBRACE); + list := p.parseStatementList(); + rbrace := p.expect(token.RBRACE); + p.opt_semi = true; return &ast.BlockStmt{lbrace, list, rbrace}; } @@ -803,23 +803,23 @@ func (P *parser) parseBlockStmt() *ast.BlockStmt { // ---------------------------------------------------------------------------- // Expressions -func (P *parser) parseFunctionLit() ast.Expr { - if P.trace { - defer un(trace(P, "FunctionLit")); +func (p *parser) parseFunctionLit() ast.Expr { + if p.trace { + defer un(trace(p, "FunctionLit")); } - typ := P.parseFunctionType(); - P.expr_lev++; - body := P.parseBlockStmt(); - P.expr_lev--; + typ := p.parseFunctionType(); + p.expr_lev++; + body := p.parseBlockStmt(); + p.expr_lev--; return &ast.FunctionLit{typ, body}; } -func (P *parser) parseStringList(x *ast.StringLit) []*ast.StringLit { - if P.trace { - defer un(trace(P, "StringList")); +func (p *parser) parseStringList(x *ast.StringLit) []*ast.StringLit { + if p.trace { + defer un(trace(p, "StringList")); } list := vector.New(0); @@ -827,9 +827,9 @@ func (P *parser) parseStringList(x *ast.StringLit) []*ast.StringLit { list.Push(x); } - for P.tok == token.STRING { - list.Push(&ast.StringLit{P.pos, P.lit}); - P.next(); + for p.tok == token.STRING { + list.Push(&ast.StringLit{p.pos, p.lit}); + p.next(); } // convert list @@ -842,87 +842,87 @@ func (P *parser) parseStringList(x *ast.StringLit) []*ast.StringLit { } -func (P *parser) parseOperand() ast.Expr { - if P.trace { - defer un(trace(P, "Operand")); +func (p *parser) parseOperand() ast.Expr { + if p.trace { + defer un(trace(p, "Operand")); } - switch P.tok { + switch p.tok { case token.IDENT: - return P.parseIdent(); + return p.parseIdent(); case token.INT: - x := &ast.IntLit{P.pos, P.lit}; - P.next(); + x := &ast.IntLit{p.pos, p.lit}; + p.next(); return x; case token.FLOAT: - x := &ast.FloatLit{P.pos, P.lit}; - P.next(); + x := &ast.FloatLit{p.pos, p.lit}; + p.next(); return x; case token.CHAR: - x := &ast.CharLit{P.pos, P.lit}; - P.next(); + x := &ast.CharLit{p.pos, p.lit}; + p.next(); return x; case token.STRING: - x := &ast.StringLit{P.pos, P.lit}; - P.next(); - if P.tok == token.STRING { - return &ast.StringList{P.parseStringList(x)}; + x := &ast.StringLit{p.pos, p.lit}; + p.next(); + if p.tok == token.STRING { + return &ast.StringList{p.parseStringList(x)}; } return x; case token.LPAREN: - lparen := P.pos; - P.next(); - P.expr_lev++; - x := P.parseExpression(1); - P.expr_lev--; - rparen := P.expect(token.RPAREN); + lparen := p.pos; + p.next(); + p.expr_lev++; + x := p.parseExpression(1); + p.expr_lev--; + rparen := p.expect(token.RPAREN); return &ast.ParenExpr{lparen, x, rparen}; case token.FUNC: - return P.parseFunctionLit(); + return p.parseFunctionLit(); default: - t := P.tryType(); + t := p.tryType(); if t != nil { return t; } else { - P.error(P.pos, "operand expected"); - P.next(); // make progress + p.error(p.pos, "operand expected"); + p.next(); // make progress } } - return &ast.BadExpr{P.pos}; + return &ast.BadExpr{p.pos}; } -func (P *parser) parseSelectorOrTypeAssertion(x ast.Expr) ast.Expr { - if P.trace { - defer un(trace(P, "SelectorOrTypeAssertion")); +func (p *parser) parseSelectorOrTypeAssertion(x ast.Expr) ast.Expr { + if p.trace { + defer un(trace(p, "SelectorOrTypeAssertion")); } - P.expect(token.PERIOD); - if P.tok == token.IDENT { + p.expect(token.PERIOD); + if p.tok == token.IDENT { // selector - sel := P.parseIdent(); + sel := p.parseIdent(); return &ast.SelectorExpr{x, sel}; } else { // type assertion - P.expect(token.LPAREN); + p.expect(token.LPAREN); var typ ast.Expr; - if P.tok == token.TYPE { + if p.tok == token.TYPE { // special case for type switch syntax - typ = &ast.Ident{P.pos, P.lit}; - P.next(); + typ = &ast.Ident{p.pos, p.lit}; + p.next(); } else { - typ = P.parseType(); + typ = p.parseType(); } - P.expect(token.RPAREN); + p.expect(token.RPAREN); return &ast.TypeAssertExpr{x, typ}; } @@ -931,56 +931,56 @@ func (P *parser) parseSelectorOrTypeAssertion(x ast.Expr) ast.Expr { } -func (P *parser) parseIndexOrSlice(x ast.Expr) ast.Expr { - if P.trace { - defer un(trace(P, "IndexOrSlice")); +func (p *parser) parseIndexOrSlice(x ast.Expr) ast.Expr { + if p.trace { + defer un(trace(p, "IndexOrSlice")); } - P.expect(token.LBRACK); - P.expr_lev++; - index := P.parseExpression(1); - P.expr_lev--; + p.expect(token.LBRACK); + p.expr_lev++; + index := p.parseExpression(1); + p.expr_lev--; - if P.tok == token.RBRACK { + if p.tok == token.RBRACK { // index - P.next(); + p.next(); return &ast.IndexExpr{x, index}; } // slice - P.expect(token.COLON); - P.expr_lev++; - end := P.parseExpression(1); - P.expr_lev--; - P.expect(token.RBRACK); + p.expect(token.COLON); + p.expr_lev++; + end := p.parseExpression(1); + p.expr_lev--; + p.expect(token.RBRACK); return &ast.SliceExpr{x, index, end}; } -func (P *parser) parseCall(fun ast.Expr) *ast.CallExpr { - if P.trace { - defer un(trace(P, "Call")); +func (p *parser) parseCall(fun ast.Expr) *ast.CallExpr { + if p.trace { + defer un(trace(p, "Call")); } - lparen := P.expect(token.LPAREN); + lparen := p.expect(token.LPAREN); var args []ast.Expr; - if P.tok != token.RPAREN { - args = P.parseExpressionList(); + if p.tok != token.RPAREN { + args = p.parseExpressionList(); } - rparen := P.expect(token.RPAREN); + rparen := p.expect(token.RPAREN); return &ast.CallExpr{fun, lparen, args, rparen}; } -func (P *parser) parseElementList() []ast.Expr { - if P.trace { - defer un(trace(P, "ElementList")); +func (p *parser) parseElementList() []ast.Expr { + if p.trace { + defer un(trace(p, "ElementList")); } list := vector.New(0); singles := true; - for P.tok != token.RBRACE { - x := P.parseExpression(0); + for p.tok != token.RBRACE { + x := p.parseExpression(0); if list.Len() == 0 { // first element determines syntax for remaining elements if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Op == token.COLON { @@ -990,19 +990,19 @@ func (P *parser) parseElementList() []ast.Expr { // not the first element - check syntax if singles { if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Op == token.COLON { - P.error(t.X.Pos(), "single value expected; found pair"); + p.error(t.X.Pos(), "single value expected; found pair"); } } else { if t, is_binary := x.(*ast.BinaryExpr); !is_binary || t.Op != token.COLON { - P.error(x.Pos(), "key:value pair expected; found single value"); + p.error(x.Pos(), "key:value pair expected; found single value"); } } } list.Push(x); - if P.tok == token.COMMA { - P.next(); + if p.tok == token.COMMA { + p.next(); } else { break; } @@ -1018,35 +1018,35 @@ func (P *parser) parseElementList() []ast.Expr { } -func (P *parser) parseCompositeLit(typ ast.Expr) ast.Expr { - if P.trace { - defer un(trace(P, "CompositeLit")); +func (p *parser) parseCompositeLit(typ ast.Expr) ast.Expr { + if p.trace { + defer un(trace(p, "CompositeLit")); } - lbrace := P.expect(token.LBRACE); + lbrace := p.expect(token.LBRACE); var elts []ast.Expr; - if P.tok != token.RBRACE { - elts = P.parseElementList(); + if p.tok != token.RBRACE { + elts = p.parseElementList(); } - rbrace := P.expect(token.RBRACE); + rbrace := p.expect(token.RBRACE); return &ast.CompositeLit{typ, lbrace, elts, rbrace}; } -func (P *parser) parsePrimaryExpr() ast.Expr { - if P.trace { - defer un(trace(P, "PrimaryExpr")); +func (p *parser) parsePrimaryExpr() ast.Expr { + if p.trace { + defer un(trace(p, "PrimaryExpr")); } - x := P.parseOperand(); + x := p.parseOperand(); for { - switch P.tok { - case token.PERIOD: x = P.parseSelectorOrTypeAssertion(x); - case token.LBRACK: x = P.parseIndexOrSlice(x); - case token.LPAREN: x = P.parseCall(x); + switch p.tok { + case token.PERIOD: x = p.parseSelectorOrTypeAssertion(x); + case token.LBRACK: x = p.parseIndexOrSlice(x); + case token.LPAREN: x = p.parseCall(x); case token.LBRACE: - if P.expr_lev >= 0 { - x = P.parseCompositeLit(x); + if p.expr_lev >= 0 { + x = p.parseCompositeLit(x); } else { return x; } @@ -1060,41 +1060,41 @@ func (P *parser) parsePrimaryExpr() ast.Expr { } -func (P *parser) parseUnaryExpr() ast.Expr { - if P.trace { - defer un(trace(P, "UnaryExpr")); +func (p *parser) parseUnaryExpr() ast.Expr { + if p.trace { + defer un(trace(p, "UnaryExpr")); } - switch P.tok { + switch p.tok { case token.ADD, token.SUB, token.NOT, token.XOR, token.ARROW, token.AND, token.RANGE: - pos, tok := P.pos, P.tok; - P.next(); - x := P.parseUnaryExpr(); + pos, tok := p.pos, p.tok; + p.next(); + x := p.parseUnaryExpr(); return &ast.UnaryExpr{pos, tok, x}; case token.MUL: // unary "*" expression or pointer type - pos := P.pos; - P.next(); - x := P.parseUnaryExpr(); + pos := p.pos; + p.next(); + x := p.parseUnaryExpr(); return &ast.StarExpr{pos, x}; } - return P.parsePrimaryExpr(); + return p.parsePrimaryExpr(); } -func (P *parser) parseBinaryExpr(prec1 int) ast.Expr { - if P.trace { - defer un(trace(P, "BinaryExpr")); +func (p *parser) parseBinaryExpr(prec1 int) ast.Expr { + if p.trace { + defer un(trace(p, "BinaryExpr")); } - x := P.parseUnaryExpr(); - for prec := P.tok.Precedence(); prec >= prec1; prec-- { - for P.tok.Precedence() == prec { - pos, tok := P.pos, P.tok; - P.next(); - y := P.parseBinaryExpr(prec + 1); + x := p.parseUnaryExpr(); + for prec := p.tok.Precedence(); prec >= prec1; prec-- { + for p.tok.Precedence() == prec { + pos, tok := p.pos, p.tok; + p.next(); + y := p.parseBinaryExpr(prec + 1); x = &ast.BinaryExpr{x, pos, tok, y}; } } @@ -1103,16 +1103,16 @@ func (P *parser) parseBinaryExpr(prec1 int) ast.Expr { } -func (P *parser) parseExpression(prec int) ast.Expr { - if P.trace { - defer un(trace(P, "Expression")); +func (p *parser) parseExpression(prec int) ast.Expr { + if p.trace { + defer un(trace(p, "Expression")); } if prec < 0 { panic("precedence must be >= 0"); } - return P.parseBinaryExpr(prec); + return p.parseBinaryExpr(prec); } @@ -1120,23 +1120,23 @@ func (P *parser) parseExpression(prec int) ast.Expr { // Statements -func (P *parser) parseSimpleStmt() ast.Stmt { - if P.trace { - defer un(trace(P, "SimpleStmt")); +func (p *parser) parseSimpleStmt() ast.Stmt { + if p.trace { + defer un(trace(p, "SimpleStmt")); } - x := P.parseExpressionList(); + x := p.parseExpressionList(); - switch P.tok { + switch p.tok { case token.COLON: // labeled statement - P.expect(token.COLON); + p.expect(token.COLON); if len(x) == 1 { if label, is_ident := x[0].(*ast.Ident); is_ident { - return &ast.LabeledStmt{label, P.parseStatement()}; + return &ast.LabeledStmt{label, p.parseStatement()}; } } - P.error(x[0].Pos(), "illegal label declaration"); + p.error(x[0].Pos(), "illegal label declaration"); return &ast.BadStmt{x[0].Pos()}; case @@ -1145,24 +1145,24 @@ func (P *parser) parseSimpleStmt() ast.Stmt { token.REM_ASSIGN, token.AND_ASSIGN, token.OR_ASSIGN, token.XOR_ASSIGN, token.SHL_ASSIGN, token.SHR_ASSIGN: // assignment statement - pos, tok := P.pos, P.tok; - P.next(); - y := P.parseExpressionList(); + pos, tok := p.pos, p.tok; + p.next(); + y := p.parseExpressionList(); if len(x) > 1 && len(y) > 1 && len(x) != len(y) { - P.error(x[0].Pos(), "arity of lhs doesn't match rhs"); + p.error(x[0].Pos(), "arity of lhs doesn't match rhs"); } return &ast.AssignStmt{x, pos, tok, y}; } if len(x) > 1 { - P.error(x[0].Pos(), "only one expression allowed"); + p.error(x[0].Pos(), "only one expression allowed"); // continue with first expression } - if P.tok == token.INC || P.tok == token.DEC { + if p.tok == token.INC || p.tok == token.DEC { // increment or decrement - s := &ast.IncDecStmt{x[0], P.tok}; - P.next(); // consume "++" or "--" + s := &ast.IncDecStmt{x[0], p.tok}; + p.next(); // consume "++" or "--" return s; } @@ -1171,23 +1171,23 @@ func (P *parser) parseSimpleStmt() ast.Stmt { } -func (P *parser) parseCallExpr() *ast.CallExpr { - x := P.parseExpression(1); +func (p *parser) parseCallExpr() *ast.CallExpr { + x := p.parseExpression(1); if call, is_call := x.(*ast.CallExpr); is_call { return call; } - P.error(x.Pos(), "expected function/method call"); + p.error(x.Pos(), "expected function/method call"); return nil; } -func (P *parser) parseGoStmt() ast.Stmt { - if P.trace { - defer un(trace(P, "GoStmt")); +func (p *parser) parseGoStmt() ast.Stmt { + if p.trace { + defer un(trace(p, "GoStmt")); } - pos := P.expect(token.GO); - call := P.parseCallExpr(); + pos := p.expect(token.GO); + call := p.parseCallExpr(); if call != nil { return &ast.GoStmt{pos, call}; } @@ -1195,13 +1195,13 @@ func (P *parser) parseGoStmt() ast.Stmt { } -func (P *parser) parseDeferStmt() ast.Stmt { - if P.trace { - defer un(trace(P, "DeferStmt")); +func (p *parser) parseDeferStmt() ast.Stmt { + if p.trace { + defer un(trace(p, "DeferStmt")); } - pos := P.expect(token.DEFER); - call := P.parseCallExpr(); + pos := p.expect(token.DEFER); + call := p.parseCallExpr(); if call != nil { return &ast.DeferStmt{pos, call}; } @@ -1209,38 +1209,38 @@ func (P *parser) parseDeferStmt() ast.Stmt { } -func (P *parser) parseReturnStmt() *ast.ReturnStmt { - if P.trace { - defer un(trace(P, "ReturnStmt")); +func (p *parser) parseReturnStmt() *ast.ReturnStmt { + if p.trace { + defer un(trace(p, "ReturnStmt")); } - loc := P.pos; - P.expect(token.RETURN); + pos := p.pos; + p.expect(token.RETURN); var x []ast.Expr; - if P.tok != token.SEMICOLON && P.tok != token.RBRACE { - x = P.parseExpressionList(); + if p.tok != token.SEMICOLON && p.tok != token.RBRACE { + x = p.parseExpressionList(); } - return &ast.ReturnStmt{loc, x}; + return &ast.ReturnStmt{pos, x}; } -func (P *parser) parseBranchStmt(tok token.Token) *ast.BranchStmt { - if P.trace { - defer un(trace(P, "BranchStmt")); +func (p *parser) parseBranchStmt(tok token.Token) *ast.BranchStmt { + if p.trace { + defer un(trace(p, "BranchStmt")); } - s := &ast.BranchStmt{P.pos, tok, nil}; - P.expect(tok); - if tok != token.FALLTHROUGH && P.tok == token.IDENT { - s.Label = P.parseIdent(); + s := &ast.BranchStmt{p.pos, tok, nil}; + p.expect(tok); + if tok != token.FALLTHROUGH && p.tok == token.IDENT { + s.Label = p.parseIdent(); } return s; } -func (P *parser) isExpr(s ast.Stmt) bool { +func (p *parser) isExpr(s ast.Stmt) bool { if s == nil { return true; } @@ -1249,145 +1249,145 @@ func (P *parser) isExpr(s ast.Stmt) bool { } -func (P *parser) asExpr(s ast.Stmt) ast.Expr { +func (p *parser) asExpr(s ast.Stmt) ast.Expr { if s == nil { return nil; } if es, is_expr := s.(*ast.ExprStmt); is_expr { return es.X; } - P.error(s.Pos(), "condition expected; found simple statement"); + p.error(s.Pos(), "condition expected; found simple statement"); return &ast.BadExpr{s.Pos()}; } -func (P *parser) parseControlClause(isForStmt bool) (s1, s2, s3 ast.Stmt) { - if P.trace { - defer un(trace(P, "ControlClause")); +func (p *parser) parseControlClause(isForStmt bool) (s1, s2, s3 ast.Stmt) { + if p.trace { + defer un(trace(p, "ControlClause")); } - if P.tok != token.LBRACE { - prev_lev := P.expr_lev; - P.expr_lev = -1; + if p.tok != token.LBRACE { + prev_lev := p.expr_lev; + p.expr_lev = -1; - if P.tok != token.SEMICOLON { - s1 = P.parseSimpleStmt(); + if p.tok != token.SEMICOLON { + s1 = p.parseSimpleStmt(); } - if P.tok == token.SEMICOLON { - P.next(); - if P.tok != token.LBRACE && P.tok != token.SEMICOLON { - s2 = P.parseSimpleStmt(); + if p.tok == token.SEMICOLON { + p.next(); + if p.tok != token.LBRACE && p.tok != token.SEMICOLON { + s2 = p.parseSimpleStmt(); } if isForStmt { // for statements have a 3rd section - P.expect(token.SEMICOLON); - if P.tok != token.LBRACE { - s3 = P.parseSimpleStmt(); + p.expect(token.SEMICOLON); + if p.tok != token.LBRACE { + s3 = p.parseSimpleStmt(); } } } else { s1, s2 = nil, s1; } - P.expr_lev = prev_lev; + p.expr_lev = prev_lev; } return s1, s2, s3; } -func (P *parser) parseIfStmt() *ast.IfStmt { - if P.trace { - defer un(trace(P, "IfStmt")); +func (p *parser) parseIfStmt() *ast.IfStmt { + if p.trace { + defer un(trace(p, "IfStmt")); } - pos := P.expect(token.IF); - s1, s2, dummy := P.parseControlClause(false); - body := P.parseBlockStmt(); + pos := p.expect(token.IF); + s1, s2, dummy := p.parseControlClause(false); + body := p.parseBlockStmt(); var else_ ast.Stmt; - if P.tok == token.ELSE { - P.next(); - else_ = P.parseStatement(); + if p.tok == token.ELSE { + p.next(); + else_ = p.parseStatement(); } - return &ast.IfStmt{pos, s1, P.asExpr(s2), body, else_}; + return &ast.IfStmt{pos, s1, p.asExpr(s2), body, else_}; } -func (P *parser) parseCaseClause() *ast.CaseClause { - if P.trace { - defer un(trace(P, "CaseClause")); +func (p *parser) parseCaseClause() *ast.CaseClause { + if p.trace { + defer un(trace(p, "CaseClause")); } // SwitchCase - loc := P.pos; + pos := p.pos; var x []ast.Expr; - if P.tok == token.CASE { - P.next(); - x = P.parseExpressionList(); + if p.tok == token.CASE { + p.next(); + x = p.parseExpressionList(); } else { - P.expect(token.DEFAULT); + p.expect(token.DEFAULT); } - colon := P.expect(token.COLON); - body := P.parseStatementList(); + colon := p.expect(token.COLON); + body := p.parseStatementList(); - return &ast.CaseClause{loc, x, colon, body}; + return &ast.CaseClause{pos, x, colon, body}; } -func (P *parser) parseTypeCaseClause() *ast.TypeCaseClause { - if P.trace { - defer un(trace(P, "CaseClause")); +func (p *parser) parseTypeCaseClause() *ast.TypeCaseClause { + if p.trace { + defer un(trace(p, "CaseClause")); } // TypeSwitchCase - pos := P.pos; + pos := p.pos; var typ ast.Expr; - if P.tok == token.CASE { - P.next(); - typ = P.parseType(); + if p.tok == token.CASE { + p.next(); + typ = p.parseType(); } else { - P.expect(token.DEFAULT); + p.expect(token.DEFAULT); } - colon := P.expect(token.COLON); - body := P.parseStatementList(); + colon := p.expect(token.COLON); + body := p.parseStatementList(); return &ast.TypeCaseClause{pos, typ, colon, body}; } -func (P *parser) parseSwitchStmt() ast.Stmt { - if P.trace { - defer un(trace(P, "SwitchStmt")); +func (p *parser) parseSwitchStmt() ast.Stmt { + if p.trace { + defer un(trace(p, "SwitchStmt")); } - pos := P.expect(token.SWITCH); - s1, s2, dummy := P.parseControlClause(false); + pos := p.expect(token.SWITCH); + s1, s2, dummy := p.parseControlClause(false); - if P.isExpr(s2) { + if p.isExpr(s2) { // expression switch - lbrace := P.expect(token.LBRACE); + lbrace := p.expect(token.LBRACE); cases := vector.New(0); - for P.tok == token.CASE || P.tok == token.DEFAULT { - cases.Push(P.parseCaseClause()); + for p.tok == token.CASE || p.tok == token.DEFAULT { + cases.Push(p.parseCaseClause()); } - rbrace := P.expect(token.RBRACE); - P.opt_semi = true; + rbrace := p.expect(token.RBRACE); + p.opt_semi = true; body := &ast.BlockStmt{lbrace, asStmtList(cases), rbrace}; - return &ast.SwitchStmt{pos, s1, P.asExpr(s2), body}; + return &ast.SwitchStmt{pos, s1, p.asExpr(s2), body}; } else { // type switch // TODO do all the checks! - lbrace := P.expect(token.LBRACE); + lbrace := p.expect(token.LBRACE); cases := vector.New(0); - for P.tok == token.CASE || P.tok == token.DEFAULT { - cases.Push(P.parseTypeCaseClause()); + for p.tok == token.CASE || p.tok == token.DEFAULT { + cases.Push(p.parseTypeCaseClause()); } - rbrace := P.expect(token.RBRACE); - P.opt_semi = true; + rbrace := p.expect(token.RBRACE); + p.opt_semi = true; body := &ast.BlockStmt{lbrace, asStmtList(cases), rbrace}; return &ast.TypeSwitchStmt{pos, s1, s2, body}; } @@ -1397,79 +1397,79 @@ func (P *parser) parseSwitchStmt() ast.Stmt { } -func (P *parser) parseCommClause() *ast.CommClause { - if P.trace { - defer un(trace(P, "CommClause")); +func (p *parser) parseCommClause() *ast.CommClause { + if p.trace { + defer un(trace(p, "CommClause")); } // CommCase - loc := P.pos; + pos := p.pos; var tok token.Token; var lhs, rhs ast.Expr; - if P.tok == token.CASE { - P.next(); - if P.tok == token.ARROW { + if p.tok == token.CASE { + p.next(); + if p.tok == token.ARROW { // RecvExpr without assignment - rhs = P.parseExpression(1); + rhs = p.parseExpression(1); } else { // SendExpr or RecvExpr - rhs = P.parseExpression(1); - if P.tok == token.ASSIGN || P.tok == token.DEFINE { + rhs = p.parseExpression(1); + if p.tok == token.ASSIGN || p.tok == token.DEFINE { // RecvExpr with assignment - tok = P.tok; - P.next(); + tok = p.tok; + p.next(); lhs = rhs; - if P.tok == token.ARROW { - rhs = P.parseExpression(1); + if p.tok == token.ARROW { + rhs = p.parseExpression(1); } else { - P.expect(token.ARROW); // use expect() error handling + p.expect(token.ARROW); // use expect() error handling } } // else SendExpr } } else { - P.expect(token.DEFAULT); + p.expect(token.DEFAULT); } - colon := P.expect(token.COLON); - body := P.parseStatementList(); + colon := p.expect(token.COLON); + body := p.parseStatementList(); - return &ast.CommClause{loc, tok, lhs, rhs, colon, body}; + return &ast.CommClause{pos, tok, lhs, rhs, colon, body}; } -func (P *parser) parseSelectStmt() *ast.SelectStmt { - if P.trace { - defer un(trace(P, "SelectStmt")); +func (p *parser) parseSelectStmt() *ast.SelectStmt { + if p.trace { + defer un(trace(p, "SelectStmt")); } - pos := P.expect(token.SELECT); - lbrace := P.expect(token.LBRACE); + pos := p.expect(token.SELECT); + lbrace := p.expect(token.LBRACE); cases := vector.New(0); - for P.tok == token.CASE || P.tok == token.DEFAULT { - cases.Push(P.parseCommClause()); + for p.tok == token.CASE || p.tok == token.DEFAULT { + cases.Push(p.parseCommClause()); } - rbrace := P.expect(token.RBRACE); - P.opt_semi = true; + rbrace := p.expect(token.RBRACE); + p.opt_semi = true; body := &ast.BlockStmt{lbrace, asStmtList(cases), rbrace}; return &ast.SelectStmt{pos, body}; } -func (P *parser) parseForStmt() ast.Stmt { - if P.trace { - defer un(trace(P, "ForStmt")); +func (p *parser) parseForStmt() ast.Stmt { + if p.trace { + defer un(trace(p, "ForStmt")); } - pos := P.expect(token.FOR); - s1, s2, s3 := P.parseControlClause(true); - body := P.parseBlockStmt(); + pos := p.expect(token.FOR); + s1, s2, s3 := p.parseControlClause(true); + body := p.parseBlockStmt(); if as, is_as := s2.(*ast.AssignStmt); is_as { // possibly a for statement with a range clause; check assignment operator if as.Tok != token.ASSIGN && as.Tok != token.DEFINE { - P.error(as.TokPos, "'=' or ':=' expected"); + p.error(as.TokPos, "'=' or ':=' expected"); return &ast.BadStmt{pos}; } // check lhs @@ -1481,24 +1481,24 @@ func (P *parser) parseForStmt() ast.Stmt { case 1: key = as.Lhs[0]; default: - P.error(as.Lhs[0].Pos(), "expected 1 or 2 expressions"); + p.error(as.Lhs[0].Pos(), "expected 1 or 2 expressions"); return &ast.BadStmt{pos}; } // check rhs if len(as.Rhs) != 1 { - P.error(as.Rhs[0].Pos(), "expected 1 expressions"); + p.error(as.Rhs[0].Pos(), "expected 1 expressions"); return &ast.BadStmt{pos}; } if rhs, is_unary := as.Rhs[0].(*ast.UnaryExpr); is_unary && rhs.Op == token.RANGE { // rhs is range expression; check lhs return &ast.RangeStmt{pos, key, value, as.TokPos, as.Tok, rhs.X, body} } else { - P.error(s2.Pos(), "range clause expected"); + p.error(s2.Pos(), "range clause expected"); return &ast.BadStmt{pos}; } } else { // regular for statement - return &ast.ForStmt{pos, s1, P.asExpr(s2), s3, body}; + return &ast.ForStmt{pos, s1, p.asExpr(s2), s3, body}; } unreachable(); @@ -1506,128 +1506,128 @@ func (P *parser) parseForStmt() ast.Stmt { } -func (P *parser) parseStatement() ast.Stmt { - if P.trace { - defer un(trace(P, "Statement")); +func (p *parser) parseStatement() ast.Stmt { + if p.trace { + defer un(trace(p, "Statement")); } - switch P.tok { + switch p.tok { case token.CONST, token.TYPE, token.VAR: - return &ast.DeclStmt{P.parseDeclaration()}; + return &ast.DeclStmt{p.parseDeclaration()}; case // tokens that may start a top-level expression token.IDENT, token.INT, token.FLOAT, token.CHAR, token.STRING, token.FUNC, token.LPAREN, // operand token.LBRACK, token.STRUCT, // composite type token.MUL, token.AND, token.ARROW: // unary operators - return P.parseSimpleStmt(); + return p.parseSimpleStmt(); case token.GO: - return P.parseGoStmt(); + return p.parseGoStmt(); case token.DEFER: - return P.parseDeferStmt(); + return p.parseDeferStmt(); case token.RETURN: - return P.parseReturnStmt(); + return p.parseReturnStmt(); case token.BREAK, token.CONTINUE, token.GOTO, token.FALLTHROUGH: - return P.parseBranchStmt(P.tok); + return p.parseBranchStmt(p.tok); case token.LBRACE: - return P.parseBlockStmt(); + return p.parseBlockStmt(); case token.IF: - return P.parseIfStmt(); + return p.parseIfStmt(); case token.FOR: - return P.parseForStmt(); + return p.parseForStmt(); case token.SWITCH: - return P.parseSwitchStmt(); + return p.parseSwitchStmt(); case token.SELECT: - return P.parseSelectStmt(); + return p.parseSelectStmt(); case token.SEMICOLON, token.RBRACE: // don't consume the ";", it is the separator following the empty statement - return &ast.EmptyStmt{P.pos}; + return &ast.EmptyStmt{p.pos}; } // no statement found - P.error(P.pos, "statement expected"); - return &ast.BadStmt{P.pos}; + p.error(p.pos, "statement expected"); + return &ast.BadStmt{p.pos}; } // ---------------------------------------------------------------------------- // Declarations -func (P *parser) parseImportSpec(pos token.Position, doc ast.Comments) *ast.ImportDecl { - if P.trace { - defer un(trace(P, "ImportSpec")); +func (p *parser) parseImportSpec(pos token.Position, doc ast.Comments) *ast.ImportDecl { + if p.trace { + defer un(trace(p, "ImportSpec")); } var ident *ast.Ident; - if P.tok == token.PERIOD { - P.error(P.pos, `"import ." not yet handled properly`); - P.next(); - } else if P.tok == token.IDENT { - ident = P.parseIdent(); + if p.tok == token.PERIOD { + p.error(p.pos, `"import ." not yet handled properly`); + p.next(); + } else if p.tok == token.IDENT { + ident = p.parseIdent(); } var path []*ast.StringLit; - if P.tok == token.STRING { - path = P.parseStringList(nil); + if p.tok == token.STRING { + path = p.parseStringList(nil); } else { - P.expect(token.STRING); // use expect() error handling + p.expect(token.STRING); // use expect() error handling } return &ast.ImportDecl{doc, pos, ident, path}; } -func (P *parser) parseConstSpec(pos token.Position, doc ast.Comments) *ast.ConstDecl { - if P.trace { - defer un(trace(P, "ConstSpec")); +func (p *parser) parseConstSpec(pos token.Position, doc ast.Comments) *ast.ConstDecl { + if p.trace { + defer un(trace(p, "ConstSpec")); } - names := P.parseIdentList(nil); - typ := P.tryType(); + names := p.parseIdentList(nil); + typ := p.tryType(); var values []ast.Expr; - if typ != nil || P.tok == token.ASSIGN { - P.expect(token.ASSIGN); - values = P.parseExpressionList(); + if typ != nil || p.tok == token.ASSIGN { + p.expect(token.ASSIGN); + values = p.parseExpressionList(); } return &ast.ConstDecl{doc, pos, names, typ, values}; } -func (P *parser) parseTypeSpec(pos token.Position, doc ast.Comments) *ast.TypeDecl { - if P.trace { - defer un(trace(P, "TypeSpec")); +func (p *parser) parseTypeSpec(pos token.Position, doc ast.Comments) *ast.TypeDecl { + if p.trace { + defer un(trace(p, "TypeSpec")); } - ident := P.parseIdent(); - typ := P.parseType(); + ident := p.parseIdent(); + typ := p.parseType(); return &ast.TypeDecl{doc, pos, ident, typ}; } -func (P *parser) parseVarSpec(pos token.Position, doc ast.Comments) *ast.VarDecl { - if P.trace { - defer un(trace(P, "VarSpec")); +func (p *parser) parseVarSpec(pos token.Position, doc ast.Comments) *ast.VarDecl { + if p.trace { + defer un(trace(p, "VarSpec")); } - names := P.parseIdentList(nil); - typ := P.tryType(); + names := p.parseIdentList(nil); + typ := p.tryType(); var values []ast.Expr; - if typ == nil || P.tok == token.ASSIGN { - P.expect(token.ASSIGN); - values = P.parseExpressionList(); + if typ == nil || p.tok == token.ASSIGN { + p.expect(token.ASSIGN); + values = p.parseExpressionList(); } return &ast.VarDecl{doc, pos, names, typ, values}; } -func (P *parser) parseSpec(pos token.Position, doc ast.Comments, keyword int) ast.Decl { +func (p *parser) parseSpec(pos token.Position, doc ast.Comments, keyword int) ast.Decl { switch keyword { - case token.IMPORT: return P.parseImportSpec(pos, doc); - case token.CONST: return P.parseConstSpec(pos, doc); - case token.TYPE: return P.parseTypeSpec(pos, doc); - case token.VAR: return P.parseVarSpec(pos, doc); + case token.IMPORT: return p.parseImportSpec(pos, doc); + case token.CONST: return p.parseConstSpec(pos, doc); + case token.TYPE: return p.parseTypeSpec(pos, doc); + case token.VAR: return p.parseVarSpec(pos, doc); } unreachable(); @@ -1635,27 +1635,27 @@ func (P *parser) parseSpec(pos token.Position, doc ast.Comments, keyword int) as } -func (P *parser) parseDecl(keyword int) ast.Decl { - if P.trace { - defer un(trace(P, "Decl")); +func (p *parser) parseDecl(keyword int) ast.Decl { + if p.trace { + defer un(trace(p, "Decl")); } - doc := P.getDoc(); - pos := P.expect(keyword); - if P.tok == token.LPAREN { - lparen := P.pos; - P.next(); + doc := p.getDoc(); + pos := p.expect(keyword); + if p.tok == token.LPAREN { + lparen := p.pos; + p.next(); list := vector.New(0); - for P.tok != token.RPAREN && P.tok != token.EOF { - list.Push(P.parseSpec(nopos, nil, keyword)); - if P.tok == token.SEMICOLON { - P.next(); + for p.tok != token.RPAREN && p.tok != token.EOF { + list.Push(p.parseSpec(nopos, nil, keyword)); + if p.tok == token.SEMICOLON { + p.next(); } else { break; } } - rparen := P.expect(token.RPAREN); - P.opt_semi = true; + rparen := p.expect(token.RPAREN); + p.opt_semi = true; // convert vector decls := make([]ast.Decl, list.Len()); @@ -1666,7 +1666,7 @@ func (P *parser) parseDecl(keyword int) ast.Decl { return &ast.DeclList{doc, pos, keyword, lparen, decls, rparen}; } - return P.parseSpec(pos, doc, keyword); + return p.parseSpec(pos, doc, keyword); } @@ -1679,53 +1679,53 @@ func (P *parser) parseDecl(keyword int) ast.Decl { // func (recv) ident (params) type // func (recv) ident (params) (results) -func (P *parser) parseFunctionDecl() *ast.FuncDecl { - if P.trace { - defer un(trace(P, "FunctionDecl")); +func (p *parser) parseFunctionDecl() *ast.FuncDecl { + if p.trace { + defer un(trace(p, "FunctionDecl")); } - doc := P.getDoc(); - pos := P.expect(token.FUNC); + doc := p.getDoc(); + pos := p.expect(token.FUNC); var recv *ast.Field; - if P.tok == token.LPAREN { - loc := P.pos; - tmp := P.parseParameters(true); + if p.tok == token.LPAREN { + pos := p.pos; + tmp := p.parseParameters(true); if len(tmp) == 1 { recv = tmp[0]; } else { - P.error(loc, "must have exactly one receiver"); + p.error(pos, "must have exactly one receiver"); } } - ident := P.parseIdent(); - params, results := P.parseSignature(); + ident := p.parseIdent(); + params, results := p.parseSignature(); var body *ast.BlockStmt; - if P.tok == token.LBRACE { - body = P.parseBlockStmt(); + if p.tok == token.LBRACE { + body = p.parseBlockStmt(); } return &ast.FuncDecl{doc, recv, ident, &ast.FunctionType{pos, params, results}, body}; } -func (P *parser) parseDeclaration() ast.Decl { - if P.trace { - defer un(trace(P, "Declaration")); +func (p *parser) parseDeclaration() ast.Decl { + if p.trace { + defer un(trace(p, "Declaration")); } - switch P.tok { + switch p.tok { case token.CONST, token.TYPE, token.VAR: - return P.parseDecl(P.tok); + return p.parseDecl(p.tok); case token.FUNC: - return P.parseFunctionDecl(); + return p.parseFunctionDecl(); } - loc := P.pos; - P.error(loc, "declaration expected"); - P.next(); // make progress - return &ast.BadDecl{loc}; + pos := p.pos; + p.error(pos, "declaration expected"); + p.next(); // make progress + return &ast.BadDecl{pos}; } @@ -1741,19 +1741,19 @@ const ( ) -func (P *parser) parsePackage(mode Mode) *ast.Package { - if P.trace { - defer un(trace(P, "Program")); +func (p *parser) parsePackage(mode Mode) *ast.Package { + if p.trace { + defer un(trace(p, "Program")); } // package clause - comment := P.getDoc(); - pos := P.expect(token.PACKAGE); - name := P.parseIdent(); - if P.tok == token.SEMICOLON { + comment := p.getDoc(); + pos := p.expect(token.PACKAGE); + name := p.parseIdent(); + if p.tok == token.SEMICOLON { // common error - P.error(P.pos, "extra semicolon"); - P.next(); + p.error(p.pos, "extra semicolon"); + p.next(); } @@ -1761,19 +1761,19 @@ func (P *parser) parsePackage(mode Mode) *ast.Package { if mode <= ParseImportDeclsOnly { // import decls list := vector.New(0); - for P.tok == token.IMPORT { - list.Push(P.parseDecl(token.IMPORT)); - if P.tok == token.SEMICOLON { - P.next(); + for p.tok == token.IMPORT { + list.Push(p.parseDecl(token.IMPORT)); + if p.tok == token.SEMICOLON { + p.next(); } } if mode <= ParseEntirePackage { // rest of package body - for P.tok != token.EOF { - list.Push(P.parseDeclaration()); - if P.tok == token.SEMICOLON { - P.next(); + for p.tok != token.EOF { + list.Push(p.parseDeclaration()); + if p.tok == token.SEMICOLON { + p.next(); } } } @@ -1786,12 +1786,9 @@ func (P *parser) parsePackage(mode Mode) *ast.Package { } // convert comments list - comments := make([]*ast.Comment, P.comments.Len()); - for i := 0; i < P.comments.Len(); i++ { - c := P.comments.At(i); - if c != nil { - comments[i] = c.(*ast.Comment); - } + comments := make([]*ast.Comment, p.comments.Len()); + for i := 0; i < p.comments.Len(); i++ { + comments[i] = p.comments.At(i).(*ast.Comment); } return &ast.Package{comment, pos, name, decls, comments}; @@ -1802,19 +1799,25 @@ func (P *parser) parsePackage(mode Mode) *ast.Package { // Parsing of entire programs. // Parse invokes the Go parser. It calls the scanner's Scan method repeatedly -// to obtain the token sequence corresponding to the source code. The sequence -// is parsed according to Go syntax and the corresponding abstract syntax tree -// is constructed. The error handler err will be used to report syntax errors. +// to obtain a token sequence which is parsed according to Go syntax. If an +// error handler is provided (err != nil), it is invoked for each syntax error +// encountered. // -// If no syntax errors were encountered (i.e., if the error handler was never -// called), the result is a correct AST. If errors were encountered, the AST -// may only be constructed partially, with ast.BadX nodes representing the -// fragments of source code that contained syntax errors. +// Parse returns an AST and the number of syntax errors encountered. If the +// error count is 0, the result is the correct AST for the token sequence +// returned by the scanner (*). If the error count is > 0, the AST may only +// be constructed partially, with ast.BadX nodes representing the fragments +// of source code that contained syntax errors. // // The amount of source text parsed can be controlled with the mode parameter. // The flags parameter controls optional parser functionality such as tracing. // -func Parse(scanner Scanner, err ErrorHandler, mode Mode, flags uint) *ast.Package { +// (*) Note that a scanner may find lexical syntax errors but still return +// a legal token sequence. To be sure there are no syntax errors in the +// source (and not just the token sequence corresponding to the source) +// both the parser and scanner error count must be 0. +// +func Parse(scanner Scanner, err ErrorHandler, mode Mode, flags uint) (*ast.Package, int) { // initialize parser state var p parser; p.scanner = scanner; @@ -1824,5 +1827,5 @@ func Parse(scanner Scanner, err ErrorHandler, mode Mode, flags uint) *ast.Packag p.next(); // parse program - return p.parsePackage(mode); + return p.parsePackage(mode), p.errorCount; } -- 2.48.1