OSDN Git Service

Update to current version of Go library (revision 94d654be2064).
[pf3gnuchains/gcc-fork.git] / libgo / go / go / parser / parser.go
index f1746e0..7c5843f 100644 (file)
@@ -1193,18 +1193,6 @@ func (p *parser) parseSimpleStmt(labelOk bool) ast.Stmt {
        x := p.parseExprList()
 
        switch p.tok {
-       case token.COLON:
-               // labeled statement
-               colon := p.pos
-               p.next()
-               if labelOk && len(x) == 1 {
-                       if label, isIdent := x[0].(*ast.Ident); isIdent {
-                               return &ast.LabeledStmt{label, colon, p.parseStmt()}
-                       }
-               }
-               p.error(x[0].Pos(), "illegal label declaration")
-               return &ast.BadStmt{x[0].Pos(), colon + 1}
-
        case
                token.DEFINE, token.ASSIGN, token.ADD_ASSIGN,
                token.SUB_ASSIGN, token.MUL_ASSIGN, token.QUO_ASSIGN,
@@ -1218,11 +1206,29 @@ func (p *parser) parseSimpleStmt(labelOk bool) ast.Stmt {
        }
 
        if len(x) > 1 {
-               p.error(x[0].Pos(), "only one expression allowed")
+               p.errorExpected(x[0].Pos(), "1 expression")
                // continue with first expression
        }
 
-       if p.tok == token.INC || p.tok == token.DEC {
+       switch p.tok {
+       case token.COLON:
+               // labeled statement
+               colon := p.pos
+               p.next()
+               if label, isIdent := x[0].(*ast.Ident); labelOk && isIdent {
+                       return &ast.LabeledStmt{label, colon, p.parseStmt()}
+               }
+               p.error(x[0].Pos(), "illegal label declaration")
+               return &ast.BadStmt{x[0].Pos(), colon + 1}
+
+       case token.ARROW:
+               // send statement
+               arrow := p.pos
+               p.next() // consume "<-"
+               y := p.parseExpr()
+               return &ast.SendStmt{x[0], arrow, y}
+
+       case token.INC, token.DEC:
                // increment or decrement
                s := &ast.IncDecStmt{x[0], p.pos, p.tok}
                p.next() // consume "++" or "--"
@@ -1321,44 +1327,34 @@ func (p *parser) makeExpr(s ast.Stmt) ast.Expr {
 }
 
 
-func (p *parser) parseControlClause(isForStmt bool) (s1, s2, s3 ast.Stmt) {
-       if p.tok != token.LBRACE {
+func (p *parser) parseIfStmt() *ast.IfStmt {
+       if p.trace {
+               defer un(trace(p, "IfStmt"))
+       }
+
+       pos := p.expect(token.IF)
+
+       var s ast.Stmt
+       var x ast.Expr
+       {
                prevLev := p.exprLev
                p.exprLev = -1
-
-               if p.tok != token.SEMICOLON {
-                       s1 = p.parseSimpleStmt(false)
-               }
                if p.tok == token.SEMICOLON {
                        p.next()
-                       if p.tok != token.LBRACE && p.tok != token.SEMICOLON {
-                               s2 = p.parseSimpleStmt(false)
-                       }
-                       if isForStmt {
-                               // for statements have a 3rd section
-                               p.expectSemi()
-                               if p.tok != token.LBRACE {
-                                       s3 = p.parseSimpleStmt(false)
-                               }
-                       }
+                       x = p.parseExpr()
                } else {
-                       s1, s2 = nil, s1
+                       s = p.parseSimpleStmt(false)
+                       if p.tok == token.SEMICOLON {
+                               p.next()
+                               x = p.parseExpr()
+                       } else {
+                               x = p.makeExpr(s)
+                               s = nil
+                       }
                }
-
                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()
        var else_ ast.Stmt
        if p.tok == token.ELSE {
@@ -1368,7 +1364,7 @@ func (p *parser) parseIfStmt() *ast.IfStmt {
                p.expectSemi()
        }
 
-       return &ast.IfStmt{pos, s1, p.makeExpr(s2), body, else_}
+       return &ast.IfStmt{pos, s, x, body, else_}
 }
 
 
@@ -1451,7 +1447,24 @@ func (p *parser) parseSwitchStmt() ast.Stmt {
        }
 
        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
+               if p.tok != token.SEMICOLON {
+                       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) {
                lbrace := p.expect(token.LBRACE)
@@ -1486,28 +1499,52 @@ func (p *parser) parseCommClause() *ast.CommClause {
 
        // CommCase
        pos := p.pos
-       var tok token.Token
-       var lhs, rhs ast.Expr
+       var comm ast.Stmt
        if p.tok == token.CASE {
                p.next()
+               lhs := p.parseExprList()
                if p.tok == token.ARROW {
-                       // RecvExpr without assignment
-                       rhs = p.parseExpr()
+                       // SendStmt
+                       if len(lhs) > 1 {
+                               p.errorExpected(lhs[0].Pos(), "1 expression")
+                               // continue with first expression
+                       }
+                       arrow := p.pos
+                       p.next()
+                       rhs := p.parseExpr()
+                       comm = &ast.SendStmt{lhs[0], arrow, rhs}
                } else {
-                       // SendExpr or RecvExpr
-                       rhs = p.parseExpr()
+                       // RecvStmt
+                       pos := p.pos
+                       tok := p.tok
+                       var rhs ast.Expr
                        if p.tok == token.ASSIGN || p.tok == token.DEFINE {
-                               // RecvExpr with assignment
-                               tok = p.tok
+                               // RecvStmt with assignment
+                               if len(lhs) > 2 {
+                                       p.errorExpected(lhs[0].Pos(), "1 or 2 expressions")
+                                       // continue with first two expressions
+                                       lhs = lhs[0:2]
+                               }
                                p.next()
-                               lhs = rhs
-                               if p.tok == token.ARROW {
-                                       rhs = p.parseExpr()
-                               } else {
-                                       p.expect(token.ARROW) // use expect() error handling
+                               rhs = p.parseExpr()
+                       } else {
+                               // rhs must be single receive operation
+                               if len(lhs) > 1 {
+                                       p.errorExpected(lhs[0].Pos(), "1 expression")
+                                       // continue with first expression
                                }
+                               rhs = lhs[0]
+                               lhs = nil // there is no lhs
+                       }
+                       if x, isUnary := rhs.(*ast.UnaryExpr); !isUnary || x.Op != token.ARROW {
+                               p.errorExpected(rhs.Pos(), "send or receive operation")
+                               rhs = &ast.BadExpr{rhs.Pos(), rhs.End()}
+                       }
+                       if lhs != nil {
+                               comm = &ast.AssignStmt{lhs, pos, tok, []ast.Expr{rhs}}
+                       } else {
+                               comm = &ast.ExprStmt{rhs}
                        }
-                       // else SendExpr
                }
        } else {
                p.expect(token.DEFAULT)
@@ -1516,7 +1553,7 @@ func (p *parser) parseCommClause() *ast.CommClause {
        colon := p.expect(token.COLON)
        body := p.parseStmtList()
 
-       return &ast.CommClause{pos, tok, lhs, rhs, colon, body}
+       return &ast.CommClause{pos, comm, colon, body}
 }
 
 
@@ -1545,7 +1582,29 @@ func (p *parser) parseForStmt() ast.Stmt {
        }
 
        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()
        p.expectSemi()
 
@@ -1568,7 +1627,7 @@ func (p *parser) parseForStmt() ast.Stmt {
                }
                // check rhs
                if len(as.Rhs) != 1 {
-                       p.errorExpected(as.Rhs[0].Pos(), "1 expressions")
+                       p.errorExpected(as.Rhs[0].Pos(), "1 expression")
                        return &ast.BadStmt{pos, body.End()}
                }
                if rhs, isUnary := as.Rhs[0].(*ast.UnaryExpr); isUnary && rhs.Op == token.RANGE {