Commit 23c16cf2 authored by Robert Griesemer's avatar Robert Griesemer

go/ast, parser: condition in if statement is mandatory

As a result, parsing a "control clause" is now sufficiently
different for if, switch, and for statements that the code
is not factored out anymore. The code is a bit longer but
clearer in each individual case.

Reflect the changes in AST.

R=r, r2
CC=golang-dev
https://golang.org/cl/4173075
parent a1368a6a
...@@ -597,7 +597,7 @@ type ( ...@@ -597,7 +597,7 @@ type (
IfStmt struct { IfStmt struct {
If token.Pos // position of "if" keyword If token.Pos // position of "if" keyword
Init Stmt // initalization statement; or nil Init Stmt // initalization statement; or nil
Cond Expr // condition; or nil Cond Expr // condition
Body *BlockStmt Body *BlockStmt
Else Stmt // else branch; or nil Else Stmt // else branch; or nil
} }
......
...@@ -227,9 +227,7 @@ func Walk(v Visitor, node Node) { ...@@ -227,9 +227,7 @@ func Walk(v Visitor, node Node) {
if n.Init != nil { if n.Init != nil {
Walk(v, n.Init) Walk(v, n.Init)
} }
if n.Cond != nil { Walk(v, n.Cond)
Walk(v, n.Cond)
}
Walk(v, n.Body) Walk(v, n.Body)
if n.Else != nil { if n.Else != nil {
Walk(v, n.Else) Walk(v, n.Else)
......
...@@ -1327,44 +1327,29 @@ func (p *parser) makeExpr(s ast.Stmt) ast.Expr { ...@@ -1327,44 +1327,29 @@ func (p *parser) makeExpr(s ast.Stmt) ast.Expr {
} }
func (p *parser) parseControlClause(isForStmt bool) (s1, s2, s3 ast.Stmt) { func (p *parser) parseIfStmt() *ast.IfStmt {
if p.tok != token.LBRACE { if p.trace {
defer un(trace(p, "IfStmt"))
}
pos := p.expect(token.IF)
var s ast.Stmt
var x ast.Expr
{
prevLev := p.exprLev prevLev := p.exprLev
p.exprLev = -1 p.exprLev = -1
s = p.parseSimpleStmt(false)
if p.tok != token.SEMICOLON {
s1 = p.parseSimpleStmt(false)
}
if p.tok == token.SEMICOLON { if p.tok == token.SEMICOLON {
p.next() p.next()
if p.tok != token.LBRACE && p.tok != token.SEMICOLON { x = p.parseExpr()
s2 = p.parseSimpleStmt(false)
}
if isForStmt {
// for statements have a 3rd section
p.expectSemi()
if p.tok != token.LBRACE {
s3 = p.parseSimpleStmt(false)
}
}
} else { } else {
s1, s2 = nil, s1 x = p.makeExpr(s)
s = nil
} }
p.exprLev = prevLev p.exprLev = prevLev
} }
return s1, s2, s3
}
func (p *parser) parseIfStmt() *ast.IfStmt {
if p.trace {
defer un(trace(p, "IfStmt"))
}
pos := p.expect(token.IF)
s1, s2, _ := p.parseControlClause(false)
body := p.parseBlockStmt() body := p.parseBlockStmt()
var else_ ast.Stmt var else_ ast.Stmt
if p.tok == token.ELSE { if p.tok == token.ELSE {
...@@ -1374,7 +1359,7 @@ func (p *parser) parseIfStmt() *ast.IfStmt { ...@@ -1374,7 +1359,7 @@ func (p *parser) parseIfStmt() *ast.IfStmt {
p.expectSemi() p.expectSemi()
} }
return &ast.IfStmt{pos, s1, p.makeExpr(s2), body, else_} return &ast.IfStmt{pos, s, x, body, else_}
} }
...@@ -1457,7 +1442,22 @@ func (p *parser) parseSwitchStmt() ast.Stmt { ...@@ -1457,7 +1442,22 @@ func (p *parser) parseSwitchStmt() ast.Stmt {
} }
pos := p.expect(token.SWITCH) pos := p.expect(token.SWITCH)
s1, s2, _ := p.parseControlClause(false)
var s1, s2 ast.Stmt
if p.tok != token.LBRACE {
prevLev := p.exprLev
p.exprLev = -1
s2 = p.parseSimpleStmt(false)
if p.tok == token.SEMICOLON {
p.next()
s1 = s2
s2 = nil
if p.tok != token.LBRACE {
s2 = p.parseSimpleStmt(false)
}
}
p.exprLev = prevLev
}
if isExprSwitch(s2) { if isExprSwitch(s2) {
lbrace := p.expect(token.LBRACE) lbrace := p.expect(token.LBRACE)
...@@ -1575,7 +1575,31 @@ func (p *parser) parseForStmt() ast.Stmt { ...@@ -1575,7 +1575,31 @@ func (p *parser) parseForStmt() ast.Stmt {
} }
pos := p.expect(token.FOR) pos := p.expect(token.FOR)
s1, s2, s3 := p.parseControlClause(true)
var s1, s2, s3 ast.Stmt
if p.tok != token.LBRACE {
prevLev := p.exprLev
p.exprLev = -1
if p.tok != token.SEMICOLON {
s2 = p.parseSimpleStmt(false)
}
if p.tok == token.SEMICOLON {
p.next()
s1 = s2
s2 = nil
if p.tok != token.SEMICOLON {
s2 = p.parseSimpleStmt(false)
}
p.expectSemi()
if p.tok != token.LBRACE {
s3 = p.parseSimpleStmt(false)
}
}
p.exprLev = prevLev
}
body := p.parseBlockStmt() body := p.parseBlockStmt()
p.expectSemi() p.expectSemi()
......
...@@ -18,6 +18,7 @@ var illegalInputs = []interface{}{ ...@@ -18,6 +18,7 @@ var illegalInputs = []interface{}{
3.14, 3.14,
[]byte(nil), []byte(nil),
"foo!", "foo!",
`package p; func f() { if /* should have condition */ {} };`,
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment