Implement for loop
This commit is contained in:
parent
ffdce64df8
commit
e62121c75b
@ -23,6 +23,7 @@
|
||||
- [x] Else statement
|
||||
- [ ] Line comments `//`
|
||||
- [x] Strings
|
||||
- [x] For loops `for X; Y; Z { ... }`
|
||||
- [ ] IO Intrinsics
|
||||
- [x] Print
|
||||
- [ ] ReadLine
|
||||
|
||||
@ -49,6 +49,28 @@ impl Interpreter {
|
||||
let result = self.resolve_expr(rhs);
|
||||
self.vartable.insert(name.clone(), result);
|
||||
}
|
||||
Stmt::For(init, condition, advance, body) => {
|
||||
// Execute initital let instruction
|
||||
let init_val = self.resolve_expr(&init.1);
|
||||
self.vartable.insert(init.0.clone(), init_val);
|
||||
|
||||
loop {
|
||||
// Check condition
|
||||
match self.resolve_expr(condition) {
|
||||
Value::I64(val) if val == 0 => break,
|
||||
Value::I64(_) => (),
|
||||
|
||||
Value::Str(text) if text.is_empty() => break,
|
||||
Value::Str(_) => (),
|
||||
}
|
||||
|
||||
// Execute loop body
|
||||
self.run(body);
|
||||
|
||||
// Execute advancement
|
||||
self.resolve_expr(advance);
|
||||
}
|
||||
}
|
||||
Stmt::While(condition, body) => {
|
||||
loop {
|
||||
// Check condition
|
||||
|
||||
@ -37,6 +37,9 @@ pub enum Token {
|
||||
/// While (while)
|
||||
While,
|
||||
|
||||
/// For (for)
|
||||
For,
|
||||
|
||||
/// If (if)
|
||||
If,
|
||||
|
||||
@ -246,6 +249,7 @@ impl<'a> Lexer<'a> {
|
||||
"while" => tokens.push(Token::While),
|
||||
"if" => tokens.push(Token::If),
|
||||
"else" => tokens.push(Token::Else),
|
||||
"for" => tokens.push(Token::For),
|
||||
_ => tokens.push(Token::Ident(ident)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,6 +74,7 @@ pub enum Stmt {
|
||||
Expr(Expr),
|
||||
Let(String, Expr),
|
||||
While(Expr, Ast),
|
||||
For((String, Expr), Expr, Expr, Ast),
|
||||
If(Expr, Ast, Ast),
|
||||
DbgPrint(Expr),
|
||||
Print(Expr),
|
||||
@ -112,9 +113,11 @@ expr = expr_bor
|
||||
stmt_expr = expr
|
||||
stmt_let = "let" IDENT "=" expr
|
||||
stmt_while = "while" expr "{" (stmt)* "}"
|
||||
stmt_for = "for" stmt_let ";" expr ";" expr "{" (stmt)* "}"
|
||||
stmt_if = "if" expr "{" (stmt)* "}" ( "else" "{" (stmt)* "}" )
|
||||
stmt_dbgprint = "$" expr
|
||||
stmt = stmt_expr | stmt_let | stmt_while | stmt_if | stmt_dbgprint
|
||||
stmt_dbgprint = "$$" expr
|
||||
stmt_print = "$" expr
|
||||
stmt = stmt_expr | stmt_let | stmt_while | stmt_for | stmt_if | stmt_dbgprint | stmt_print
|
||||
*/
|
||||
|
||||
struct Parser<T: Iterator<Item = Token>> {
|
||||
@ -142,6 +145,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
||||
Token::Let => self.parse_let_stmt(),
|
||||
Token::While => self.parse_while(),
|
||||
Token::If => self.parse_if(),
|
||||
Token::For => self.parse_for(),
|
||||
Token::Dollar => {
|
||||
self.next();
|
||||
Stmt::Print(self.parse_expr())
|
||||
@ -160,6 +164,41 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
||||
Ast { prog }
|
||||
}
|
||||
|
||||
fn parse_for(&mut self) -> Stmt {
|
||||
if !matches!(self.next(), Token::For) {
|
||||
panic!("Error parsing for: Expected for token");
|
||||
}
|
||||
|
||||
let init = match self.parse_let_stmt() {
|
||||
Stmt::Let(name, rhs) => (name, rhs),
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
if !matches!(self.next(), Token::Semicolon) {
|
||||
panic!("Error parsing for: Expected semicolon token");
|
||||
}
|
||||
|
||||
let condition = self.parse_expr();
|
||||
|
||||
if !matches!(self.next(), Token::Semicolon) {
|
||||
panic!("Error parsing for: Expected semicolon token");
|
||||
}
|
||||
|
||||
let advance = self.parse_expr();
|
||||
|
||||
if !matches!(self.next(), Token::LBrace) {
|
||||
panic!("Error parsing for: Expected '{{' token");
|
||||
}
|
||||
|
||||
let body = self.parse();
|
||||
|
||||
if !matches!(self.next(), Token::RBrace) {
|
||||
panic!("Error parsing for: Expected '}}' token");
|
||||
}
|
||||
|
||||
Stmt::For(init, condition, advance, body)
|
||||
}
|
||||
|
||||
fn parse_if(&mut self) -> Stmt {
|
||||
if !matches!(self.next(), Token::If) {
|
||||
panic!("Error parsing if: Expected if token");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user