Implement if

This commit is contained in:
Daniel M 2022-02-02 16:19:46 +01:00
parent 8c9756b6d2
commit 7b6fc89fb7
3 changed files with 77 additions and 15 deletions

View File

@ -1,6 +1,6 @@
use std::{collections::HashMap, fmt::Display};
use crate::{parser::{Expression, BinOpType, UnOpType, Ast, Statement, parse}, lexer::lex};
use crate::{parser::{Expression, BinOpType, UnOpType, Ast, Statement, parse, If}, lexer::lex};
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Value {
@ -40,16 +40,16 @@ impl Interpreter {
self.resolve_expr(expr);
}
Statement::Loop(lop) => {
Statement::Loop(looop) => {
// loop runs as long condition != 0
loop {
if matches!(self.resolve_expr(lop.condition.clone()), Value::I64(0)) {
if matches!(self.resolve_expr(looop.condition.clone()), Value::I64(0)) {
break;
}
self.run(lop.body.clone());
self.run(looop.body.clone());
if let Some(adv) = &lop.advancement {
if let Some(adv) = &looop.advancement {
self.resolve_expr(adv.clone());
}
}
@ -59,6 +59,14 @@ impl Interpreter {
let result = self.resolve_expr(expr);
println!("{}", result);
}
Statement::If(If {condition, body_true, body_false}) => {
if matches!(self.resolve_expr(condition.clone()), Value::I64(0)) {
self.run(body_false.clone());
} else {
self.run(body_true.clone());
}
}
}
}

View File

@ -16,6 +16,12 @@ pub enum Token {
/// Print keyword (print)
Print,
/// If keyword (if)
If,
/// Else keyword (else)
Else,
/// Left Parenthesis ('(')
LParen,
@ -204,6 +210,8 @@ impl<'a> Lexer<'a> {
let token = match ident.as_str() {
"loop" => Token::Loop,
"print" => Token::Print,
"if" => Token::If,
"else" => Token::Else,
_ => Token::Ident(ident),
};

View File

@ -92,13 +92,24 @@ pub struct Loop {
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Statement {
Expr(Expression),
Loop(Loop),
Print(Expression),
pub struct If {
/// The condition
pub condition: Expression,
/// The body that is executed when condition is true
pub body_true: Ast,
/// The if body that is executed when the condition is false
pub body_false: Ast,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Statement {
Expr(Expression),
Loop(Loop),
If(If),
Print(Expression),
}
#[derive(Debug, PartialEq, Eq, Clone, Default)]
pub struct Ast {
pub prog: Vec<Statement>
}
@ -124,7 +135,6 @@ impl<T: Iterator<Item = Token>> Parser<T> {
}
Token::EoF => break,
Token::RBraces => {
self.next();
break;
}
@ -156,6 +166,8 @@ impl<T: Iterator<Item = Token>> Parser<T> {
Statement::Print(expr)
}
Token::If => Statement::If(self.parse_if()),
// If it is not a loop, try to lex as an expression
_ => {
let stmt = Statement::Expr(self.parse_expr());
@ -170,11 +182,41 @@ impl<T: Iterator<Item = Token>> Parser<T> {
}
}
// loop i < 1_000; i = i +1 {
// if i % 3 == 0 | i % 5 == 0 {
// sum = sum + i;
// }
// }
fn parse_if(&mut self) -> If {
if !matches!(self.next(), Token::If) {
panic!("Error lexing if: Expected if token");
}
let condition = self.parse_expr();
if !matches!(self.next(), Token::LBraces) {
panic!("Error lexing if: Expected '{{'")
}
let body_true = self.parse();
if !matches!(self.next(), Token::RBraces) {
panic!("Error lexing if: Expected '}}'")
}
let mut body_false = Ast::default();
if matches!(self.peek(), Token::Else) {
self.next();
if !matches!(self.next(), Token::LBraces) {
panic!("Error lexing if: Expected '{{'")
}
body_false = self.parse();
if !matches!(self.next(), Token::RBraces) {
panic!("Error lexing if: Expected '}}'")
}
}
If { condition, body_true, body_false }
}
fn parse_loop(&mut self) -> Loop {
if !matches!(self.next(), Token::Loop) {
@ -204,6 +246,10 @@ impl<T: Iterator<Item = Token>> Parser<T> {
_ => panic!("Error lexing loop: Expected ';' or '{{'")
}
if !matches!(self.next(), Token::RBraces) {
panic!("Error lexing loop: Expected '}}'")
}
Loop { condition, advancement, body }
}