// checkExprOrType checks that x is an expression or a type // (and not a raw type such as [...]T). // func (p *parser) checkExprOrType(x ast.Expr) ast.Expr { switch t := unparen(x).(type) { case *ast.ParenExpr: panic("unreachable") case *ast.UnaryExpr: if t.Op == token.RANGE { // the range operator is only allowed at the top of a for statement p.errorExpected(x.Pos(), "expression") x = &ast.BadExpr{x.Pos(), x.End()} } case *ast.ArrayType: if len, isEllipsis := t.Len.(*ast.Ellipsis); isEllipsis { p.error(len.Pos(), "expected array length, found '...'") x = &ast.BadExpr{x.Pos(), x.End()} } } // all other nodes are expressions or types return x }
// checkExpr checks that x is an expression (and not a type). func (p *parser) checkExpr(x ast.Expr) ast.Expr { switch t := unparen(x).(type) { case *ast.BadExpr: case *ast.Ident: case *ast.BasicLit: case *ast.FuncLit: case *ast.CompositeLit: case *ast.ParenExpr: panic("unreachable") case *ast.SelectorExpr: case *ast.IndexExpr: case *ast.SliceExpr: case *ast.TypeAssertExpr: if t.Type == nil { // the form X.(type) is only allowed in type switch expressions p.errorExpected(x.Pos(), "expression") x = &ast.BadExpr{x.Pos(), x.End()} } case *ast.CallExpr: case *ast.StarExpr: case *ast.UnaryExpr: if t.Op == token.RANGE { // the range operator is only allowed at the top of a for statement p.errorExpected(x.Pos(), "expression") x = &ast.BadExpr{x.Pos(), x.End()} } case *ast.BinaryExpr: default: // all other nodes are not proper expressions p.errorExpected(x.Pos(), "expression") x = &ast.BadExpr{x.Pos(), x.End()} } return x }
func (p *parser) parseCommClause() *ast.CommClause { if p.trace { defer un(trace(p, "CommClause")) } // CommCase pos := p.pos var comm ast.Stmt if p.tok == token.CASE { p.next() lhs := p.parseExprList() if p.tok == token.ARROW { // 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 { // RecvStmt pos := p.pos tok := p.tok var rhs ast.Expr if p.tok == token.ASSIGN || p.tok == token.DEFINE { // 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() 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 { p.expect(token.DEFAULT) } colon := p.expect(token.COLON) body := p.parseStmtList() return &ast.CommClause{pos, comm, colon, body} }