From: Robert Griesemer Date: Sat, 25 Mar 2017 01:03:17 +0000 (-0700) Subject: cmd/compile/internal/syntax: remove need for missing_statement (fixed TODO) X-Git-Tag: go1.9beta1~975 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=783f166e659558414d846d16bbe65e6fe9c7099b;p=gostls13.git cmd/compile/internal/syntax: remove need for missing_statement (fixed TODO) Now that we have consistent use of xOrNil parse methods, we don't need a special missing_statement singleton to distinguish between missing actually statements and other errors (which have returned nil before). For #19663. Change-Id: I8364f1441bdf8dd966bcd6d8219b2a42d6b88abd Reviewed-on: https://go-review.googlesource.com/38656 Run-TryBot: Robert Griesemer TryBot-Result: Gobot Gobot Reviewed-by: Matthew Dempsky --- diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index 840648683a..e55a2219d6 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -1494,8 +1494,6 @@ func (p *parser) bad() *BadExpr { var ImplicitOne = &BasicLit{Value: "1"} // SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl . -// -// simpleStmt may return missing_stmt if labelOk is set. func (p *parser) simpleStmt(lhs Expr, rangeOk bool) SimpleStmt { if trace { defer p.trace("simpleStmt")() @@ -1627,7 +1625,7 @@ func (p *parser) newAssignStmt(pos src.Pos, op Operator, lhs, rhs Expr) *AssignS return a } -func (p *parser) labeledStmt(label *Name) Stmt { +func (p *parser) labeledStmtOrNil(label *Name) Stmt { if trace { defer p.trace("labeledStmt")() } @@ -1638,17 +1636,25 @@ func (p *parser) labeledStmt(label *Name) Stmt { p.want(_Colon) - if p.tok != _Rbrace && p.tok != _EOF { - s.Stmt = p.stmt() - if s.Stmt == missing_stmt { - // report error at line of ':' token - p.syntax_error_at(label.Pos(), "missing statement after label") - // we are already at the end of the labeled statement - no need to advance - return missing_stmt - } + if p.tok == _Rbrace { + // We expect a statement (incl. an empty statement), which must be + // terminated by a semicolon. Because semicolons may be omitted before + // an _Rbrace, seeing an _Rbrace implies an empty statement. + e := new(EmptyStmt) + e.pos = p.pos() + s.Stmt = e + return s } - return s + s.Stmt = p.stmtOrNil() + if s.Stmt != nil { + return s + } + + // report error at line of ':' token + p.syntax_error_at(s.pos, "missing statement after label") + // we are already at the end of the labeled statement - no need to advance + return nil // avoids follow-on errors (see e.g., fixedbugs/bug274.go) } func (p *parser) blockStmt(context string) *BlockStmt { @@ -1922,17 +1928,12 @@ func (p *parser) commClause() *CommClause { return c } -// TODO(gri) find a better solution -var missing_stmt Stmt = new(EmptyStmt) // = nod(OXXX, nil, nil) - // Statement = // Declaration | LabeledStmt | SimpleStmt | // GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt | // FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt | // DeferStmt . -// -// stmt may return missing_stmt. -func (p *parser) stmt() Stmt { +func (p *parser) stmtOrNil() Stmt { if trace { defer p.trace("stmt " + p.tok.String())() } @@ -1942,7 +1943,7 @@ func (p *parser) stmt() Stmt { if p.tok == _Name { lhs := p.exprList() if label, ok := lhs.(*Name); ok && p.tok == _Colon { - return p.labeledStmt(label) + return p.labeledStmtOrNil(label) } return p.simpleStmt(lhs, false) } @@ -2026,7 +2027,7 @@ func (p *parser) stmt() Stmt { return s } - return missing_stmt + return nil } // StatementList = { Statement ";" } . @@ -2036,8 +2037,8 @@ func (p *parser) stmtList() (l []Stmt) { } for p.tok != _EOF && p.tok != _Rbrace && p.tok != _Case && p.tok != _Default { - s := p.stmt() - if s == missing_stmt { + s := p.stmtOrNil() + if s == nil { break } l = append(l, s)