about summary refs log tree commit diff
path: root/pkg/lang/parser/stmts.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/lang/parser/stmts.go')
-rw-r--r--pkg/lang/parser/stmts.go66
1 files changed, 64 insertions, 2 deletions
diff --git a/pkg/lang/parser/stmts.go b/pkg/lang/parser/stmts.go
index 4b1077e..2a32906 100644
--- a/pkg/lang/parser/stmts.go
+++ b/pkg/lang/parser/stmts.go
@@ -18,6 +18,8 @@ func (p *Parser) parseStmt() (ast.Stmt, error) {
 		return p.parseVarDeclStmt()
 	case token.KwIf:
 		return p.parseIfStmt()
+	case token.KwFor:
+		return p.parseForStmt()
 	case token.KwTry:
 		return p.parseTryStmt()
 	case token.KwReturn:
@@ -192,7 +194,6 @@ func (p *Parser) parseIfStmt() (ast.Stmt, error) {
 		})
 	}
 
-
 	if p.peek().Kind == token.KwElse {
 		elseTok, err := p.expect(token.KwElse)
 		if err != nil {
@@ -205,7 +206,7 @@ func (p *Parser) parseIfStmt() (ast.Stmt, error) {
 		}
 
 		conds = append(conds, ast.CondNode{
-			At: elseTok.At,
+			At:   elseTok.At,
 			Cond: ast.Expr{},
 			Then: elseThen,
 		})
@@ -220,6 +221,67 @@ func (p *Parser) parseIfStmt() (ast.Stmt, error) {
 	}, nil
 }
 
+func (p *Parser) parseForStmt() (ast.Stmt, error) {
+	// ForStmt = ForCondStmt | ForInStmt
+	// ForCondStmt = "for" Expr? Block
+	// ForInStmt = "for" Ident "in" Expr Block
+
+	forTok, err := p.expect(token.KwFor)
+	if err != nil {
+		return ast.Stmt{}, err
+	}
+
+	expr, err := p.parseExpr()
+	if err != nil {
+		return ast.Stmt{}, err
+	}
+
+	// ForInStmt
+	if expr.Kind == ast.ExprKindIdent && p.peek().Kind == token.KwIn {
+		_, err := p.expect(token.KwIn)
+		if err != nil {
+			return ast.Stmt{}, err
+		}
+
+		collection, err := p.parseExpr()
+		if err != nil {
+			return ast.Stmt{}, err
+		}
+
+		do, err := p.parseBlock()
+		if err != nil {
+			return ast.Stmt{}, err
+		}
+
+		return ast.Stmt{
+			At:   forTok.At,
+			Kind: ast.StmtKindForIn,
+			Value: ast.StmtForIn{
+				Name:       expr.Value.(ast.ExprIdent).Value,
+				Collection: collection,
+				Do:         do,
+			},
+		}, nil
+	}
+
+	// ForCondStmt
+	cond := expr
+
+	do, err := p.parseBlock()
+	if err != nil {
+		return ast.Stmt{}, err
+	}
+
+	return ast.Stmt{
+		At:   forTok.At,
+		Kind: ast.StmtKindForCond,
+		Value: ast.StmtForCond{
+			Cond: cond,
+			Do:   do,
+		},
+	}, nil
+}
+
 func (p *Parser) parseTryStmt() (ast.Stmt, error) {
 	// TryStmt = "try" Block "catch" Ident ("finally" Block)?