aboutsummaryrefslogtreecommitdiff
path: root/syntax
diff options
context:
space:
mode:
authorAlessandro Arzilli <alessandro.arzilli@gmail.com>2018-12-07 17:28:35 +0100
committeralandonovan <adonovan@google.com>2018-12-07 11:28:35 -0500
commit678bafeaa214cf33342b28e76b77c0f1e264671f (patch)
treee238dd59443cb8ec3df6453c71101cd945853aab /syntax
parentd0a402bd6a104746d6256a517e57ce1adde31b45 (diff)
downloadstarlark-go-678bafeaa214cf33342b28e76b77c0f1e264671f.tar.gz
Add while statement and allow recursion (#39)
Adds a flag, AllowRecursion, that enables while statements and recursive functions.
Diffstat (limited to 'syntax')
-rw-r--r--syntax/grammar.txt4
-rw-r--r--syntax/parse.go14
-rw-r--r--syntax/scan.go3
-rw-r--r--syntax/syntax.go14
4 files changed, 33 insertions, 2 deletions
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