Skip to content

Commit

Permalink
Fix invalid parser error in range-based loops
Browse files Browse the repository at this point in the history
  • Loading branch information
5nord committed Oct 25, 2024
1 parent 1f34a6d commit 461ef7a
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 69 deletions.
3 changes: 1 addition & 2 deletions ttcn3/printer/printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 1 addition & 3 deletions ttcn3/scopes.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 1 addition & 3 deletions ttcn3/syntax/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
43 changes: 8 additions & 35 deletions ttcn3/syntax/nodes_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

71 changes: 46 additions & 25 deletions ttcn3/syntax/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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)
Expand All @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion ttcn3/syntax/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}`},
Expand Down

0 comments on commit 461ef7a

Please sign in to comment.