Implement if
This commit is contained in:
parent
8c9756b6d2
commit
7b6fc89fb7
@ -1,6 +1,6 @@
|
|||||||
use std::{collections::HashMap, fmt::Display};
|
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)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
@ -40,16 +40,16 @@ impl Interpreter {
|
|||||||
self.resolve_expr(expr);
|
self.resolve_expr(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Statement::Loop(lop) => {
|
Statement::Loop(looop) => {
|
||||||
// loop runs as long condition != 0
|
// loop runs as long condition != 0
|
||||||
loop {
|
loop {
|
||||||
if matches!(self.resolve_expr(lop.condition.clone()), Value::I64(0)) {
|
if matches!(self.resolve_expr(looop.condition.clone()), Value::I64(0)) {
|
||||||
break;
|
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());
|
self.resolve_expr(adv.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,6 +59,14 @@ impl Interpreter {
|
|||||||
let result = self.resolve_expr(expr);
|
let result = self.resolve_expr(expr);
|
||||||
println!("{}", result);
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,12 @@ pub enum Token {
|
|||||||
/// Print keyword (print)
|
/// Print keyword (print)
|
||||||
Print,
|
Print,
|
||||||
|
|
||||||
|
/// If keyword (if)
|
||||||
|
If,
|
||||||
|
|
||||||
|
/// Else keyword (else)
|
||||||
|
Else,
|
||||||
|
|
||||||
/// Left Parenthesis ('(')
|
/// Left Parenthesis ('(')
|
||||||
LParen,
|
LParen,
|
||||||
|
|
||||||
@ -204,6 +210,8 @@ impl<'a> Lexer<'a> {
|
|||||||
let token = match ident.as_str() {
|
let token = match ident.as_str() {
|
||||||
"loop" => Token::Loop,
|
"loop" => Token::Loop,
|
||||||
"print" => Token::Print,
|
"print" => Token::Print,
|
||||||
|
"if" => Token::If,
|
||||||
|
"else" => Token::Else,
|
||||||
_ => Token::Ident(ident),
|
_ => Token::Ident(ident),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -92,13 +92,24 @@ pub struct Loop {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub enum Statement {
|
pub struct If {
|
||||||
Expr(Expression),
|
/// The condition
|
||||||
Loop(Loop),
|
pub condition: Expression,
|
||||||
Print(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)]
|
#[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 struct Ast {
|
||||||
pub prog: Vec<Statement>
|
pub prog: Vec<Statement>
|
||||||
}
|
}
|
||||||
@ -124,7 +135,6 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
}
|
}
|
||||||
Token::EoF => break,
|
Token::EoF => break,
|
||||||
Token::RBraces => {
|
Token::RBraces => {
|
||||||
self.next();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,6 +166,8 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
Statement::Print(expr)
|
Statement::Print(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Token::If => Statement::If(self.parse_if()),
|
||||||
|
|
||||||
// If it is not a loop, try to lex as an expression
|
// If it is not a loop, try to lex as an expression
|
||||||
_ => {
|
_ => {
|
||||||
let stmt = Statement::Expr(self.parse_expr());
|
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 {
|
fn parse_if(&mut self) -> If {
|
||||||
// if i % 3 == 0 | i % 5 == 0 {
|
if !matches!(self.next(), Token::If) {
|
||||||
// sum = sum + i;
|
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 {
|
fn parse_loop(&mut self) -> Loop {
|
||||||
if !matches!(self.next(), Token::Loop) {
|
if !matches!(self.next(), Token::Loop) {
|
||||||
@ -204,6 +246,10 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
|||||||
_ => panic!("Error lexing loop: Expected ';' or '{{'")
|
_ => panic!("Error lexing loop: Expected ';' or '{{'")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !matches!(self.next(), Token::RBraces) {
|
||||||
|
panic!("Error lexing loop: Expected '}}'")
|
||||||
|
}
|
||||||
|
|
||||||
Loop { condition, advancement, body }
|
Loop { condition, advancement, body }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user