parser changed to reflect new semicolon rules

R=rsc
https://golang.org/cl/175046
This commit is contained in:
Robert Griesemer 2009-12-11 15:31:24 -08:00
parent b9b89f56ad
commit 97a08f7a81
2 changed files with 167 additions and 229 deletions

View File

@ -56,7 +56,6 @@ type parser struct {
lit []byte; // token literal
// Non-syntactic parser control
optSemi bool; // true if semicolon separator is optional in statement list
exprLev int; // < 0: in control clause, >= 0: in expression
// Scopes
@ -68,10 +67,11 @@ type parser struct {
// scannerMode returns the scanner mode bits given the parser's mode bits.
func scannerMode(mode uint) uint {
var m uint = scanner.InsertSemis;
if mode&ParseComments != 0 {
return scanner.ScanComments
m |= scanner.ScanComments
}
return 0;
return m;
}
@ -133,10 +133,8 @@ func (p *parser) next0() {
}
p.pos, p.tok, p.lit = p.scanner.Scan();
p.optSemi = false;
}
// Consume a comment and return it and the line on which it ends.
func (p *parser) consumeComment() (comment *ast.Comment, endline int) {
// /*-style comments may end on a different line than where they start.
@ -163,7 +161,7 @@ func (p *parser) consumeComment() (comment *ast.Comment, endline int) {
// a comment group.
//
func (p *parser) consumeCommentGroup() int {
list := new(vector.Vector);
var list vector.Vector;
endline := p.pos.Line;
for p.tok == token.COMMENT && endline+1 >= p.pos.Line {
var comment *ast.Comment;
@ -262,6 +260,13 @@ func (p *parser) expect(tok token.Token) token.Position {
}
func (p *parser) expectSemi() {
if p.tok != token.RPAREN && p.tok != token.RBRACE {
p.expect(token.SEMICOLON)
}
}
// ----------------------------------------------------------------------------
// Scope support
@ -308,7 +313,7 @@ func (p *parser) parseIdentList() []*ast.Ident {
defer un(trace(p, "IdentList"))
}
list := new(vector.Vector);
var list vector.Vector;
list.Push(p.parseIdent());
for p.tok == token.COMMA {
p.next();
@ -325,25 +330,28 @@ func (p *parser) parseIdentList() []*ast.Ident {
}
func makeExprList(list *vector.Vector) []ast.Expr {
exprs := make([]ast.Expr, list.Len());
for i := 0; i < list.Len(); i++ {
exprs[i] = list.At(i).(ast.Expr)
}
return exprs;
}
func (p *parser) parseExprList() []ast.Expr {
if p.trace {
defer un(trace(p, "ExpressionList"))
}
list := new(vector.Vector);
var list vector.Vector;
list.Push(p.parseExpr());
for p.tok == token.COMMA {
p.next();
list.Push(p.parseExpr());
}
// convert list
exprs := make([]ast.Expr, list.Len());
for i := 0; i < list.Len(); i++ {
exprs[i] = list.At(i).(ast.Expr)
}
return exprs;
return makeExprList(&list);
}
@ -435,15 +443,14 @@ func (p *parser) parseFieldDecl() *ast.Field {
doc := p.leadComment;
// a list of identifiers looks like a list of type names
list := new(vector.Vector);
var list vector.Vector;
for {
// TODO(gri): do not allow ()'s here
list.Push(p.parseType());
if p.tok == token.COMMA {
p.next()
} else {
if p.tok != token.COMMA {
break
}
p.next();
}
// if we had a list of identifiers, it must be followed by a type
@ -452,14 +459,16 @@ func (p *parser) parseFieldDecl() *ast.Field {
// optional tag
var tag []*ast.BasicLit;
if p.tok == token.STRING {
tag = p.parseStringList(nil)
x := &ast.BasicLit{p.pos, p.tok, p.lit};
p.next();
tag = []*ast.BasicLit{x};
}
// analyze case
var idents []*ast.Ident;
if typ != nil {
// IdentifierList Type
idents = p.makeIdentList(list)
idents = p.makeIdentList(&list)
} else {
// Type (anonymous field)
if list.Len() == 1 {
@ -471,7 +480,9 @@ func (p *parser) parseFieldDecl() *ast.Field {
}
}
return &ast.Field{doc, idents, typ, tag, nil};
p.expectSemi();
return &ast.Field{doc, idents, typ, tag, p.lineComment};
}
@ -482,17 +493,11 @@ func (p *parser) parseStructType() *ast.StructType {
pos := p.expect(token.STRUCT);
lbrace := p.expect(token.LBRACE);
list := new(vector.Vector);
var list vector.Vector;
for p.tok == token.IDENT || p.tok == token.MUL {
f := p.parseFieldDecl();
if p.tok != token.RBRACE {
p.expect(token.SEMICOLON)
}
f.Comment = p.lineComment;
list.Push(f);
list.Push(p.parseFieldDecl())
}
rbrace := p.expect(token.RBRACE);
p.optSemi = true;
// convert vector
fields := make([]*ast.Field, list.Len());
@ -547,21 +552,20 @@ func (p *parser) parseParameterDecl(ellipsisOk bool) (*vector.Vector, ast.Expr)
}
// a list of identifiers looks like a list of type names
list := new(vector.Vector);
var list vector.Vector;
for {
// TODO(gri): do not allow ()'s here
list.Push(p.parseParameterType(ellipsisOk));
if p.tok == token.COMMA {
p.next()
} else {
if p.tok != token.COMMA {
break
}
p.next();
}
// if we had a list of identifiers, it must be followed by a type
typ := p.tryParameterType(ellipsisOk);
return list, typ;
return &list, typ;
}
@ -576,12 +580,18 @@ func (p *parser) parseParameterList(ellipsisOk bool) []*ast.Field {
idents := p.makeIdentList(list);
list.Resize(0, 0);
list.Push(&ast.Field{nil, idents, typ, nil, nil});
if p.tok == token.COMMA {
p.next()
}
for p.tok == token.COMMA {
p.next();
for p.tok != token.RPAREN && p.tok != token.EOF {
idents := p.parseIdentList();
typ := p.parseParameterType(ellipsisOk);
list.Push(&ast.Field{nil, idents, typ, nil, nil});
if p.tok != token.COMMA {
break
}
p.next();
}
} else {
@ -680,8 +690,9 @@ func (p *parser) parseMethodSpec() *ast.Field {
// embedded interface
typ = x
}
p.expectSemi();
return &ast.Field{doc, idents, typ, nil, nil};
return &ast.Field{doc, idents, typ, nil, p.lineComment};
}
@ -692,17 +703,11 @@ func (p *parser) parseInterfaceType() *ast.InterfaceType {
pos := p.expect(token.INTERFACE);
lbrace := p.expect(token.LBRACE);
list := new(vector.Vector);
var list vector.Vector;
for p.tok == token.IDENT {
m := p.parseMethodSpec();
if p.tok != token.RBRACE {
p.expect(token.SEMICOLON)
}
m.Comment = p.lineComment;
list.Push(m);
list.Push(p.parseMethodSpec())
}
rbrace := p.expect(token.RBRACE);
p.optSemi = true;
// convert vector
methods := make([]*ast.Field, list.Len());
@ -804,28 +809,16 @@ func (p *parser) parseStmtList() []ast.Stmt {
defer un(trace(p, "StatementList"))
}
list := new(vector.Vector);
expectSemi := false;
var list vector.Vector;
for p.tok != token.CASE && p.tok != token.DEFAULT && p.tok != token.RBRACE && p.tok != token.EOF {
if expectSemi {
p.expect(token.SEMICOLON);
expectSemi = false;
}
list.Push(p.parseStmt());
if p.tok == token.SEMICOLON {
p.next()
} else if p.optSemi {
p.optSemi = false // "consume" optional semicolon
} else {
expectSemi = true
}
list.Push(p.parseStmt())
}
return makeStmtList(list);
return makeStmtList(&list);
}
func (p *parser) parseBlockStmt(idents []*ast.Ident) *ast.BlockStmt {
func (p *parser) parseBlockStmt() *ast.BlockStmt {
if p.trace {
defer un(trace(p, "BlockStmt"))
}
@ -835,7 +828,6 @@ func (p *parser) parseBlockStmt(idents []*ast.Ident) *ast.BlockStmt {
lbrace := p.expect(token.LBRACE);
list := p.parseStmtList();
rbrace := p.expect(token.RBRACE);
p.optSemi = true;
return &ast.BlockStmt{lbrace, list, rbrace};
}
@ -844,31 +836,6 @@ func (p *parser) parseBlockStmt(idents []*ast.Ident) *ast.BlockStmt {
// ----------------------------------------------------------------------------
// Expressions
func (p *parser) parseStringList(x *ast.BasicLit) []*ast.BasicLit {
if p.trace {
defer un(trace(p, "StringList"))
}
list := new(vector.Vector);
if x != nil {
list.Push(x)
}
for p.tok == token.STRING {
list.Push(&ast.BasicLit{p.pos, token.STRING, p.lit});
p.next();
}
// convert list
strings := make([]*ast.BasicLit, list.Len());
for i := 0; i < list.Len(); i++ {
strings[i] = list.At(i).(*ast.BasicLit)
}
return strings;
}
func (p *parser) parseFuncTypeOrLit() ast.Expr {
if p.trace {
defer un(trace(p, "FuncTypeOrLit"))
@ -881,8 +848,7 @@ func (p *parser) parseFuncTypeOrLit() ast.Expr {
}
p.exprLev++;
body := p.parseBlockStmt(nil);
p.optSemi = false; // function body requires separating ";"
body := p.parseBlockStmt();
p.exprLev--;
return &ast.FuncLit{typ, body};
@ -904,9 +870,6 @@ func (p *parser) parseOperand() ast.Expr {
case token.INT, token.FLOAT, token.CHAR, token.STRING:
x := &ast.BasicLit{p.pos, p.tok, p.lit};
p.next();
if p.tok == token.STRING && p.tok == token.STRING {
return &ast.StringList{p.parseStringList(x)}
}
return x;
case token.LPAREN:
@ -993,14 +956,18 @@ func (p *parser) parseCallOrConversion(fun ast.Expr) *ast.CallExpr {
lparen := p.expect(token.LPAREN);
p.exprLev++;
var args []ast.Expr;
if p.tok != token.RPAREN {
args = p.parseExprList()
var list vector.Vector;
for p.tok != token.RPAREN && p.tok != token.EOF {
list.Push(p.parseExpr());
if p.tok != token.COMMA {
break
}
p.next();
}
p.exprLev--;
rparen := p.expect(token.RPAREN);
return &ast.CallExpr{fun, lparen, args, rparen};
return &ast.CallExpr{fun, lparen, makeExprList(&list), rparen};
}
@ -1025,23 +992,16 @@ func (p *parser) parseElementList() []ast.Expr {
defer un(trace(p, "ElementList"))
}
list := new(vector.Vector);
var list vector.Vector;
for p.tok != token.RBRACE && p.tok != token.EOF {
list.Push(p.parseElement());
if p.tok == token.COMMA {
p.next()
} else {
if p.tok != token.COMMA {
break
}
p.next();
}
// convert list
elts := make([]ast.Expr, list.Len());
for i := 0; i < list.Len(); i++ {
elts[i] = list.At(i).(ast.Expr)
}
return elts;
return makeExprList(&list);
}
@ -1250,7 +1210,6 @@ func (p *parser) parseExpr() ast.Expr {
// ----------------------------------------------------------------------------
// Statements
func (p *parser) parseSimpleStmt(labelOk bool) ast.Stmt {
if p.trace {
defer un(trace(p, "SimpleStmt"))
@ -1319,10 +1278,12 @@ func (p *parser) parseGoStmt() ast.Stmt {
pos := p.expect(token.GO);
call := p.parseCallExpr();
if call != nil {
return &ast.GoStmt{pos, call}
p.expectSemi();
if call == nil {
return &ast.BadStmt{pos}
}
return &ast.BadStmt{pos};
return &ast.GoStmt{pos, call};
}
@ -1333,10 +1294,12 @@ func (p *parser) parseDeferStmt() ast.Stmt {
pos := p.expect(token.DEFER);
call := p.parseCallExpr();
if call != nil {
return &ast.DeferStmt{pos, call}
p.expectSemi();
if call == nil {
return &ast.BadStmt{pos}
}
return &ast.BadStmt{pos};
return &ast.DeferStmt{pos, call};
}
@ -1348,9 +1311,10 @@ func (p *parser) parseReturnStmt() *ast.ReturnStmt {
pos := p.pos;
p.expect(token.RETURN);
var x []ast.Expr;
if p.tok != token.SEMICOLON && p.tok != token.CASE && p.tok != token.DEFAULT && p.tok != token.RBRACE {
if p.tok != token.SEMICOLON && p.tok != token.RBRACE {
x = p.parseExprList()
}
p.expectSemi();
return &ast.ReturnStmt{pos, x};
}
@ -1366,6 +1330,7 @@ func (p *parser) parseBranchStmt(tok token.Token) *ast.BranchStmt {
if tok != token.FALLTHROUGH && p.tok == token.IDENT {
s.Label = p.parseIdent()
}
p.expectSemi();
return s;
}
@ -1398,7 +1363,7 @@ func (p *parser) parseControlClause(isForStmt bool) (s1, s2, s3 ast.Stmt) {
}
if isForStmt {
// for statements have a 3rd section
p.expect(token.SEMICOLON);
p.expectSemi();
if p.tok != token.LBRACE {
s3 = p.parseSimpleStmt(false)
}
@ -1424,11 +1389,13 @@ func (p *parser) parseIfStmt() *ast.IfStmt {
pos := p.expect(token.IF);
s1, s2, _ := p.parseControlClause(false);
body := p.parseBlockStmt(nil);
body := p.parseBlockStmt();
var else_ ast.Stmt;
if p.tok == token.ELSE {
p.next();
else_ = p.parseStmt();
} else {
p.expectSemi()
}
return &ast.IfStmt{pos, s1, p.makeExpr(s2), body, else_};
@ -1465,20 +1432,14 @@ func (p *parser) parseTypeList() []ast.Expr {
defer un(trace(p, "TypeList"))
}
list := new(vector.Vector);
var list vector.Vector;
list.Push(p.parseType());
for p.tok == token.COMMA {
p.next();
list.Push(p.parseType());
}
// convert list
exprs := make([]ast.Expr, list.Len());
for i := 0; i < list.Len(); i++ {
exprs[i] = list.At(i).(ast.Expr)
}
return exprs;
return makeExprList(&list);
}
@ -1534,26 +1495,26 @@ func (p *parser) parseSwitchStmt() ast.Stmt {
if isExprSwitch(s2) {
lbrace := p.expect(token.LBRACE);
cases := new(vector.Vector);
var cases vector.Vector;
for p.tok == token.CASE || p.tok == token.DEFAULT {
cases.Push(p.parseCaseClause())
}
rbrace := p.expect(token.RBRACE);
p.optSemi = true;
body := &ast.BlockStmt{lbrace, makeStmtList(cases), rbrace};
body := &ast.BlockStmt{lbrace, makeStmtList(&cases), rbrace};
p.expectSemi();
return &ast.SwitchStmt{pos, s1, p.makeExpr(s2), body};
}
// type switch
// TODO(gri): do all the checks!
lbrace := p.expect(token.LBRACE);
cases := new(vector.Vector);
var cases vector.Vector;
for p.tok == token.CASE || p.tok == token.DEFAULT {
cases.Push(p.parseTypeCaseClause())
}
rbrace := p.expect(token.RBRACE);
p.optSemi = true;
body := &ast.BlockStmt{lbrace, makeStmtList(cases), rbrace};
p.expectSemi();
body := &ast.BlockStmt{lbrace, makeStmtList(&cases), rbrace};
return &ast.TypeSwitchStmt{pos, s1, s2, body};
}
@ -1609,13 +1570,13 @@ func (p *parser) parseSelectStmt() *ast.SelectStmt {
pos := p.expect(token.SELECT);
lbrace := p.expect(token.LBRACE);
cases := new(vector.Vector);
var cases vector.Vector;
for p.tok == token.CASE || p.tok == token.DEFAULT {
cases.Push(p.parseCommClause())
}
rbrace := p.expect(token.RBRACE);
p.optSemi = true;
body := &ast.BlockStmt{lbrace, makeStmtList(cases), rbrace};
p.expectSemi();
body := &ast.BlockStmt{lbrace, makeStmtList(&cases), rbrace};
return &ast.SelectStmt{pos, body};
}
@ -1631,7 +1592,8 @@ func (p *parser) parseForStmt() ast.Stmt {
pos := p.expect(token.FOR);
s1, s2, s3 := p.parseControlClause(true);
body := p.parseBlockStmt(nil);
body := p.parseBlockStmt();
p.expectSemi();
if as, isAssign := s2.(*ast.AssignStmt); isAssign {
// possibly a for statement with a range clause; check assignment operator
@ -1673,70 +1635,69 @@ func (p *parser) parseForStmt() ast.Stmt {
}
func (p *parser) parseStmt() ast.Stmt {
func (p *parser) parseStmt() (s ast.Stmt) {
if p.trace {
defer un(trace(p, "Statement"))
}
switch p.tok {
case token.CONST, token.TYPE, token.VAR:
decl, _ := p.parseDecl(false); // do not consume trailing semicolon
return &ast.DeclStmt{decl};
s = &ast.DeclStmt{p.parseDecl()}
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, token.ADD, token.SUB, token.XOR: // unary operators
return p.parseSimpleStmt(true)
s = p.parseSimpleStmt(true);
// because of the required look-ahead, labeled statements are
// parsed by parseSimpleStmt - don't expect a semicolon after
// them
if _, isLabeledStmt := s.(*ast.LabeledStmt); !isLabeledStmt {
p.expectSemi()
}
case token.GO:
return p.parseGoStmt()
s = p.parseGoStmt()
case token.DEFER:
return p.parseDeferStmt()
s = p.parseDeferStmt()
case token.RETURN:
return p.parseReturnStmt()
s = p.parseReturnStmt()
case token.BREAK, token.CONTINUE, token.GOTO, token.FALLTHROUGH:
return p.parseBranchStmt(p.tok)
s = p.parseBranchStmt(p.tok)
case token.LBRACE:
return p.parseBlockStmt(nil)
s = p.parseBlockStmt();
p.expectSemi();
case token.IF:
return p.parseIfStmt()
s = p.parseIfStmt()
case token.SWITCH:
return p.parseSwitchStmt()
s = p.parseSwitchStmt()
case token.SELECT:
return p.parseSelectStmt()
s = p.parseSelectStmt()
case token.FOR:
return p.parseForStmt()
case token.SEMICOLON, token.RBRACE:
// don't consume the ";", it is the separator following the empty statement
return &ast.EmptyStmt{p.pos}
s = p.parseForStmt()
case token.SEMICOLON:
p.next();
fallthrough;
case token.RBRACE:
// a semicolon may be omitted before a closing "}"
s = &ast.EmptyStmt{p.pos}
default:
// no statement found
p.errorExpected(p.pos, "statement");
p.next(); // make progress
s = &ast.BadStmt{p.pos};
}
// no statement found
p.errorExpected(p.pos, "statement");
p.next(); // make progress
return &ast.BadStmt{p.pos};
return;
}
// ----------------------------------------------------------------------------
// Declarations
type parseSpecFunction func(p *parser, doc *ast.CommentGroup, getSemi bool) (spec ast.Spec, gotSemi bool)
type parseSpecFunction func(p *parser, doc *ast.CommentGroup) ast.Spec
// Consume semicolon if there is one and getSemi is set, and get any line comment.
// Return the comment if any and indicate if a semicolon was consumed.
//
func (p *parser) parseComment(getSemi bool) (comment *ast.CommentGroup, gotSemi bool) {
if getSemi && p.tok == token.SEMICOLON {
p.next();
gotSemi = true;
}
return p.lineComment, gotSemi;
}
func parseImportSpec(p *parser, doc *ast.CommentGroup, getSemi bool) (spec ast.Spec, gotSemi bool) {
func parseImportSpec(p *parser, doc *ast.CommentGroup) ast.Spec {
if p.trace {
defer un(trace(p, "ImportSpec"))
}
@ -1751,18 +1712,19 @@ func parseImportSpec(p *parser, doc *ast.CommentGroup, getSemi bool) (spec ast.S
var path []*ast.BasicLit;
if p.tok == token.STRING {
path = p.parseStringList(nil)
x := &ast.BasicLit{p.pos, p.tok, p.lit};
p.next();
path = []*ast.BasicLit{x};
} else {
p.expect(token.STRING) // use expect() error handling
}
p.expectSemi();
comment, gotSemi := p.parseComment(getSemi);
return &ast.ImportSpec{doc, ident, path, comment}, gotSemi;
return &ast.ImportSpec{doc, ident, path, p.lineComment};
}
func parseConstSpec(p *parser, doc *ast.CommentGroup, getSemi bool) (spec ast.Spec, gotSemi bool) {
func parseConstSpec(p *parser, doc *ast.CommentGroup) ast.Spec {
if p.trace {
defer un(trace(p, "ConstSpec"))
}
@ -1774,26 +1736,26 @@ func parseConstSpec(p *parser, doc *ast.CommentGroup, getSemi bool) (spec ast.Sp
p.expect(token.ASSIGN);
values = p.parseExprList();
}
comment, gotSemi := p.parseComment(getSemi);
p.expectSemi();
return &ast.ValueSpec{doc, idents, typ, values, comment}, gotSemi;
return &ast.ValueSpec{doc, idents, typ, values, p.lineComment};
}
func parseTypeSpec(p *parser, doc *ast.CommentGroup, getSemi bool) (spec ast.Spec, gotSemi bool) {
func parseTypeSpec(p *parser, doc *ast.CommentGroup) ast.Spec {
if p.trace {
defer un(trace(p, "TypeSpec"))
}
ident := p.parseIdent();
typ := p.parseType();
comment, gotSemi := p.parseComment(getSemi);
p.expectSemi();
return &ast.TypeSpec{doc, ident, typ, comment}, gotSemi;
return &ast.TypeSpec{doc, ident, typ, p.lineComment};
}
func parseVarSpec(p *parser, doc *ast.CommentGroup, getSemi bool) (spec ast.Spec, gotSemi bool) {
func parseVarSpec(p *parser, doc *ast.CommentGroup) ast.Spec {
if p.trace {
defer un(trace(p, "VarSpec"))
}
@ -1805,13 +1767,13 @@ func parseVarSpec(p *parser, doc *ast.CommentGroup, getSemi bool) (spec ast.Spec
p.expect(token.ASSIGN);
values = p.parseExprList();
}
comment, gotSemi := p.parseComment(getSemi);
p.expectSemi();
return &ast.ValueSpec{doc, idents, typ, values, comment}, gotSemi;
return &ast.ValueSpec{doc, idents, typ, values, p.lineComment};
}
func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction, getSemi bool) (decl *ast.GenDecl, gotSemi bool) {
func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.GenDecl {
if p.trace {
defer un(trace(p, keyword.String()+"Decl"))
}
@ -1819,30 +1781,17 @@ func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction, getSemi
doc := p.leadComment;
pos := p.expect(keyword);
var lparen, rparen token.Position;
list := new(vector.Vector);
var list vector.Vector;
if p.tok == token.LPAREN {
lparen = p.pos;
p.next();
for p.tok != token.RPAREN && p.tok != token.EOF {
doc := p.leadComment;
spec, semi := f(p, doc, true); // consume semicolon if any
list.Push(spec);
if !semi {
break
}
list.Push(f(p, p.leadComment))
}
rparen = p.expect(token.RPAREN);
if getSemi && p.tok == token.SEMICOLON {
p.next();
gotSemi = true;
} else {
p.optSemi = true
}
p.expectSemi();
} else {
spec, semi := f(p, nil, getSemi);
list.Push(spec);
gotSemi = semi;
list.Push(f(p, nil))
}
// convert vector
@ -1851,7 +1800,7 @@ func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction, getSemi
specs[i] = list.At(i).(ast.Spec)
}
return &ast.GenDecl{doc, pos, keyword, lparen, specs, rparen}, gotSemi;
return &ast.GenDecl{doc, pos, keyword, lparen, specs, rparen};
}
@ -1902,14 +1851,15 @@ func (p *parser) parseFunctionDecl() *ast.FuncDecl {
var body *ast.BlockStmt;
if p.tok == token.LBRACE {
body = p.parseBlockStmt(nil)
body = p.parseBlockStmt()
}
p.expectSemi();
return &ast.FuncDecl{doc, recv, ident, &ast.FuncType{pos, params, results}, body};
}
func (p *parser) parseDecl(getSemi bool) (decl ast.Decl, gotSemi bool) {
func (p *parser) parseDecl() ast.Decl {
if p.trace {
defer un(trace(p, "Declaration"))
}
@ -1926,20 +1876,17 @@ func (p *parser) parseDecl(getSemi bool) (decl ast.Decl, gotSemi bool) {
f = parseVarSpec
case token.FUNC:
decl = p.parseFunctionDecl();
_, gotSemi := p.parseComment(getSemi);
return decl, gotSemi;
return p.parseFunctionDecl()
default:
pos := p.pos;
p.errorExpected(pos, "declaration");
decl = &ast.BadDecl{pos};
gotSemi = getSemi && p.tok == token.SEMICOLON;
decl := &ast.BadDecl{pos};
p.next(); // make progress in any case
return decl, gotSemi;
return decl;
}
return p.parseGenDecl(p.tok, f, getSemi);
return p.parseGenDecl(p.tok, f);
}
@ -1948,10 +1895,9 @@ func (p *parser) parseDeclList() []ast.Decl {
defer un(trace(p, "DeclList"))
}
list := new(vector.Vector);
var list vector.Vector;
for p.tok != token.EOF {
decl, _ := p.parseDecl(true); // consume optional semicolon
list.Push(decl);
list.Push(p.parseDecl())
}
// convert vector
@ -1979,13 +1925,7 @@ func (p *parser) parseFile() *ast.File {
doc := p.leadComment;
pos := p.expect(token.PACKAGE);
ident := p.parseIdent();
// Common error: semicolon after package clause.
// Accept and report it for better error synchronization.
if p.tok == token.SEMICOLON {
p.Error(p.pos, "expected declaration, found ';'");
p.next();
}
p.expectSemi();
var decls []ast.Decl;
@ -1994,17 +1934,15 @@ func (p *parser) parseFile() *ast.File {
if p.ErrorCount() == 0 && p.mode&PackageClauseOnly == 0 {
// import decls
list := new(vector.Vector);
var list vector.Vector;
for p.tok == token.IMPORT {
decl, _ := p.parseGenDecl(token.IMPORT, parseImportSpec, true); // consume optional semicolon
list.Push(decl);
list.Push(p.parseGenDecl(token.IMPORT, parseImportSpec))
}
if p.mode&ImportsOnly == 0 {
// rest of package body
for p.tok != token.EOF {
decl, _ := p.parseDecl(true); // consume optional semicolon
list.Push(decl);
list.Push(p.parseDecl())
}
}

View File

@ -29,9 +29,9 @@ func TestParseIllegalInputs(t *testing.T) {
var validPrograms = []interface{}{
`package main`,
`package main import "fmt" func main() { fmt.Println("Hello, World!") }`,
`package main func main() { if f(T{}) {} }`,
`package main;`,
`package main; import "fmt"; func main() { fmt.Println("Hello, World!") }` + "\n",
`package main; func main() { if f(T{}) {} }` + "\n",
}