diff --git a/ttcn3/printer/printer.go b/ttcn3/printer/printer.go index 6056f2ee..8e34a7e7 100644 --- a/ttcn3/printer/printer.go +++ b/ttcn3/printer/printer.go @@ -306,8 +306,7 @@ func (p *printer) print(values ...interface{}) { } p.print(n.Tok) p.print(n.LParen) - p.print(n.VarTok) - p.print(n.Var) + p.print(n.Init) p.print(n.InTok) p.print(n.Range) p.print(n.RParen) diff --git a/ttcn3/scopes.go b/ttcn3/scopes.go index a73b04a2..ca7a76cf 100644 --- a/ttcn3/scopes.go +++ b/ttcn3/scopes.go @@ -138,9 +138,7 @@ func NewScope(n syntax.Node, tree *Tree) *Scope { scp.add(n.Init) case *syntax.ForRangeStmt: - if (n.VarTok != nil) && (n.Var != nil) { - scp.Insert(n.Var, n.Var) - } + scp.add(n.Init) case *syntax.IfStmt: scp.add(n.Then) diff --git a/ttcn3/syntax/nodes.go b/ttcn3/syntax/nodes.go index aba8b4ba..b1eaf696 100644 --- a/ttcn3/syntax/nodes.go +++ b/ttcn3/syntax/nodes.go @@ -424,9 +424,7 @@ type ( ForRangeStmt struct { Tok Token LParen Token - VarTok Token - Type TypeSpec - Var *Ident + Init Stmt InTok Token Range Expr RParen Token diff --git a/ttcn3/syntax/nodes_gen.go b/ttcn3/syntax/nodes_gen.go index cd56c75d..f7c02492 100644 --- a/ttcn3/syntax/nodes_gen.go +++ b/ttcn3/syntax/nodes_gen.go @@ -2717,14 +2717,8 @@ func (n *ForRangeStmt) FirstTok() Token { case n.LParen != nil: return n.LParen - case n.VarTok != nil: - return n.VarTok - - case n.Type != nil: - return n.Type.FirstTok() - - case n.Var != nil: - return n.Var.FirstTok() + case n.Init != nil: + return n.Init.FirstTok() case n.InTok != nil: return n.InTok @@ -2758,14 +2752,8 @@ func (n *ForRangeStmt) LastTok() Token { case n.InTok != nil: return n.InTok - case n.Var != nil: - return n.Var.LastTok() - - case n.Type != nil: - return n.Type.LastTok() - - case n.VarTok != nil: - return n.VarTok + case n.Init != nil: + return n.Init.LastTok() case n.LParen != nil: return n.LParen @@ -2779,7 +2767,7 @@ func (n *ForRangeStmt) LastTok() Token { } func (n *ForRangeStmt) Children() []Node { - ret := make([]Node, 0, 9) + ret := make([]Node, 0, 7) if n.Tok != nil { ret = append(ret, n.Tok) @@ -2789,16 +2777,8 @@ func (n *ForRangeStmt) Children() []Node { ret = append(ret, n.LParen) } - if n.VarTok != nil { - ret = append(ret, n.VarTok) - } - - if n.Type != nil { - ret = append(ret, n.Type) - } - - if n.Var != nil { - ret = append(ret, n.Var) + if n.Init != nil { + ret = append(ret, n.Init) } if n.InTok != nil { @@ -2822,14 +2802,7 @@ func (n *ForRangeStmt) Children() []Node { func (n *ForRangeStmt) Inspect(f func(Node) bool) { - if c := n.Type; c != nil { - if f(c) { - c.Inspect(f) - } - f(nil) - } - - if c := n.Var; c != nil { + if c := n.Init; c != nil { if f(c) { c.Inspect(f) } diff --git a/ttcn3/syntax/parser.go b/ttcn3/syntax/parser.go index 3c57a10f..6ee030e0 100644 --- a/ttcn3/syntax/parser.go +++ b/ttcn3/syntax/parser.go @@ -2469,9 +2469,6 @@ func (p *parser) parseStmt() Stmt { case LBRACK: return p.parseAltGuard() case FOR: - if p.peek(4).Kind() == IN || p.peek(5).Kind() == IN || p.peek(6).Kind() == IN { - return p.parseForRangeLoop() - } return p.parseForLoop() case WHILE: return p.parseWhileLoop() @@ -2522,15 +2519,36 @@ func (p *parser) parseStmt() Stmt { } } -func (p *parser) parseForLoop() *ForStmt { - x := new(ForStmt) - x.Tok = p.consume() - x.LParen = p.expect(LPAREN) +func (p *parser) parseForLoop() Stmt { + forTok := p.consume() + lParen := p.expect(LPAREN) + + var init Stmt if p.tok == VAR { - x.Init = &DeclStmt{Decl: p.parseValueDecl()} + init = &DeclStmt{Decl: p.parseValueDecl()} } else { - x.Init = &ExprStmt{Expr: p.parseExpr()} + init = &ExprStmt{Expr: p.parseExpr()} + } + + if p.tok == IN { + if hasAssignment(init) { + p.error(p.peek(1), "unexpected token %s", p.tok) + } + x := new(ForRangeStmt) + x.Tok = forTok + x.LParen = lParen + x.Init = init + x.InTok = p.consume() + x.Range = p.parseExpr() + x.RParen = p.expect(RPAREN) + x.Body = p.parseBlockStmt() + return x } + + x := new(ForStmt) + x.Tok = forTok + x.LParen = lParen + x.Init = init x.InitSemi = p.expect(SEMICOLON) x.Cond = p.parseExpr() x.CondSemi = p.expect(SEMICOLON) @@ -2540,24 +2558,27 @@ func (p *parser) parseForLoop() *ForStmt { return x } -func (p *parser) parseForRangeLoop() *ForRangeStmt { - x := new(ForRangeStmt) - x.Tok = p.consume() - x.LParen = p.expect(LPAREN) - if p.tok == VAR { - x.VarTok = p.consume() - if p.peek(2).Kind() != IN { - x.Type = p.parseTypeSpec() +func hasAssignment(n Node) bool { + switch n := n.(type) { + case *DeclStmt: + return hasAssignment(n.Decl) + case *ExprStmt: + return hasAssignment(n.Expr) + case *ValueDecl: + for _, d := range n.Decls { + if d.AssignTok != nil { + return true + } } - x.Var = p.parseName() - } else { - x.Var = p.parseIdent() + return false + case *BinaryExpr: + if n.Op.Kind() == ASSIGN { + return true + } + return false + default: + return false } - x.InTok = p.expect(IN) - x.Range = p.parseExpr() - x.RParen = p.expect(RPAREN) - x.Body = p.parseBlockStmt() - return x } func (p *parser) parseWhileLoop() *WhileStmt { diff --git a/ttcn3/syntax/parser_test.go b/ttcn3/syntax/parser_test.go index 023b73e5..f2c070de 100644 --- a/ttcn3/syntax/parser_test.go +++ b/ttcn3/syntax/parser_test.go @@ -282,8 +282,9 @@ func TestStmts(t *testing.T) { {pass, `for (var int i := 0; i<23; i := i+1) {}`}, {pass, `for (i:=x; i<23; i:=i+1) {}`}, {pass, `for (x in {1,2,3}) {}`}, - {pass, `for (var x in a) {}`}, + {fail, `for (var x in a) {}`}, {pass, `for (var integer x in a) {}`}, + {pass, `for (var template integer x in a) {}`}, {pass, `while (23) {}`}, {pass, `do {} while (23);`}, {pass, `if (1) {}`},