diff --git a/interpreter.go b/interpreter.go index e13b78a..397d48a 100644 --- a/interpreter.go +++ b/interpreter.go @@ -231,7 +231,6 @@ func (i *Interpreter) visitWhileStmt(w *WhileStmt) { } w.body.accept(i) - } } diff --git a/parser.go b/parser.go index ddfb879..55bb54c 100644 --- a/parser.go +++ b/parser.go @@ -69,6 +69,7 @@ func (p *Parser) varDecl() Stmt { // statement -> exprStmt // // | whileStmt +// | forStmt // | printStmt // | blockStmt // | breakStmt @@ -95,6 +96,10 @@ func (p *Parser) statement() Stmt { return p.whileStmt() } + if p.match(FOR) { + return p.forStmt() + } + if p.match(BREAK) { return p.breakStmt() } @@ -171,6 +176,60 @@ func (p *Parser) whileStmt() Stmt { return &WhileStmt{cond, body} } +// for -> "for" ( "(" ( varDecl | exprStmt | ";" ) expression? ";" expression ")" )? statement +func (p *Parser) forStmt() Stmt { + + if p.check(LEFT_BRACE) { + return &WhileStmt{&Literal{true}, p.statement()} + } + + p.consume(LEFT_PAREN, "Expect '(' after 'for'.") + + var init Stmt + + if p.match(SEMICOLON) { + init = nil + } else if p.match(VAR) { + init = p.varDecl() + } else { + init = p.exprStmt() + } + + var cond Expr + + if !p.check(SEMICOLON) { + cond = p.expression() + } + + p.consume(SEMICOLON, "Expect ';' after for loop condition;") + + var incr Expr + + if !p.check(RIGHT_PAREN) { + incr = p.expression() + } + + p.consume(RIGHT_PAREN, "Expect ')' after for clauses;") + + var body = p.statement() + + if incr != nil { + body = &BlockStmt{[]Stmt{body, &ExprStmt{incr}}} + } + + if cond == nil { + cond = &Literal{true} + } + + body = &WhileStmt{cond, body} + + if init != nil { + body = &BlockStmt{[]Stmt{init, body}} + } + + return body +} + // env -> "env" ";" func (p *Parser) envStmt() Stmt { p.consume(SEMICOLON, "Expect ';' after 'env'.") diff --git a/tests/for.lox b/tests/for.lox new file mode 100644 index 0000000..91a53fc --- /dev/null +++ b/tests/for.lox @@ -0,0 +1,36 @@ + +print "full form -------------------------"; +for (var i = 0; i < 100; i = i + 20) print i; + +print "without init ----------------------"; +var n = 100; +for (;n > 0; n = n - 20) print n; + +print "only cond -----------------------"; + +var i = 1; +for (;i < 100;) { + print i; + i = i + 10; +} + +print "inf ---------------------------"; + +var b = 0; +for { + print b; + b = b + 5; + if (b > 10) break; + + print "after break"; +} + +print "fibonachi ------------------------"; +var temp; +var first = 0; + +for (var second = 1; first < 10000; second = temp + second) { + print first; + temp = first; + first = second; +} \ No newline at end of file diff --git a/tests/while.lox b/tests/while.lox index 232e666..6a9c17a 100644 --- a/tests/while.lox +++ b/tests/while.lox @@ -13,16 +13,23 @@ var iterator = 100; { while (iterator < 100) { { - print iterator; - iterator = iterator + 2; + { + print iterator; + iterator = iterator + 2; - if (iterator > 50) { - break; + if (iterator > 50) break; + + print "shoud not be printed after 50"; } - print "shoud not be printed after 50"; + print "OUTER also shoud not be printed after 50"; + } } } +while (iterator < 100) iterator = iterator + 2; + + + print iterator; \ No newline at end of file