From 678bafeaa214cf33342b28e76b77c0f1e264671f Mon Sep 17 00:00:00 2001 From: Alessandro Arzilli Date: Fri, 7 Dec 2018 17:28:35 +0100 Subject: Add while statement and allow recursion (#39) Adds a flag, AllowRecursion, that enables while statements and recursive functions. --- syntax/grammar.txt | 4 +++- syntax/parse.go | 14 ++++++++++++++ syntax/scan.go | 3 ++- syntax/syntax.go | 14 ++++++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) (limited to 'syntax') diff --git a/syntax/grammar.txt b/syntax/grammar.txt index 8c90272..c3ad159 100644 --- a/syntax/grammar.txt +++ b/syntax/grammar.txt @@ -4,7 +4,7 @@ Grammar of Starlark File = {Statement | newline} eof . -Statement = DefStmt | IfStmt | ForStmt | SimpleStmt . +Statement = DefStmt | IfStmt | ForStmt | WhileStmt | SimpleStmt . DefStmt = 'def' identifier '(' [Parameters [',']] ')' ':' Suite . @@ -16,6 +16,8 @@ IfStmt = 'if' Test ':' Suite {'elif' Test ':' Suite} ['else' ':' Suite] . ForStmt = 'for' LoopVariables 'in' Expression ':' Suite . +WhileStmt = 'while' Test ':' Suite . + Suite = [newline indent {Statement} outdent] | SimpleStmt . SimpleStmt = SmallStmt {';' SmallStmt} [';'] '\n' . diff --git a/syntax/parse.go b/syntax/parse.go index 6bc12b3..08a40e3 100644 --- a/syntax/parse.go +++ b/syntax/parse.go @@ -111,6 +111,8 @@ func (p *parser) parseStmt(stmts []Stmt) []Stmt { return append(stmts, p.parseIfStmt()) } else if p.tok == FOR { return append(stmts, p.parseForStmt()) + } else if p.tok == WHILE { + return append(stmts, p.parseWhileStmt()) } return p.parseSimpleStmt(stmts) } @@ -182,6 +184,18 @@ func (p *parser) parseForStmt() Stmt { } } +func (p *parser) parseWhileStmt() Stmt { + whilepos := p.nextToken() // consume WHILE + cond := p.parseTest() + p.consume(COLON) + body := p.parseSuite() + return &WhileStmt{ + While: whilepos, + Cond: cond, + Body: body, + } +} + // Equivalent to 'exprlist' production in Python grammar. // // loop_variables = primary_with_suffix (COMMA primary_with_suffix)* COMMA? diff --git a/syntax/scan.go b/syntax/scan.go index 37bd38e..695a120 100644 --- a/syntax/scan.go +++ b/syntax/scan.go @@ -95,6 +95,7 @@ const ( OR PASS RETURN + WHILE maxToken ) @@ -996,6 +997,7 @@ var keywordToken = map[string]Token{ "or": OR, "pass": PASS, "return": RETURN, + "while": WHILE, // reserved words: "as": ILLEGAL, @@ -1011,7 +1013,6 @@ var keywordToken = map[string]Token{ "nonlocal": ILLEGAL, "raise": ILLEGAL, "try": ILLEGAL, - "while": ILLEGAL, "with": ILLEGAL, "yield": ILLEGAL, } diff --git a/syntax/syntax.go b/syntax/syntax.go index 29b22de..c4f64c0 100644 --- a/syntax/syntax.go +++ b/syntax/syntax.go @@ -95,6 +95,7 @@ func (*BranchStmt) stmt() {} func (*DefStmt) stmt() {} func (*ExprStmt) stmt() {} func (*ForStmt) stmt() {} +func (*WhileStmt) stmt() {} func (*IfStmt) stmt() {} func (*LoadStmt) stmt() {} func (*ReturnStmt) stmt() {} @@ -351,6 +352,19 @@ func (x *ForStmt) Span() (start, end Position) { return x.For, end } +// A WhileStmt represents a while loop: while X: Body. +type WhileStmt struct { + commentsRef + While Position + Cond Expr + Body []Stmt +} + +func (x *WhileStmt) Span() (start, end Position) { + _, end = x.Body[len(x.Body)-1].Span() + return x.While, end +} + // A ForClause represents a for clause in a list comprehension: for Vars in X. type ForClause struct { commentsRef -- cgit v1.2.3