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