mirror of
https://github.com/PaddiM8/kalker.git
synced 2025-02-02 01:49:12 +01:00
Implemented somewhat proper error handling for the interpreter. This involved removing the visitor.
This commit is contained in:
parent
1a56ddac45
commit
41a41629a5
@ -2,15 +2,15 @@ use std::mem;
|
|||||||
|
|
||||||
use crate::lexer::TokenKind;
|
use crate::lexer::TokenKind;
|
||||||
use crate::parser::{Expr, Stmt, Unit};
|
use crate::parser::{Expr, Stmt, Unit};
|
||||||
use crate::prelude::{self};
|
use crate::prelude;
|
||||||
use crate::{symbol_table::SymbolTable, visitor::Visitor};
|
use crate::symbol_table::SymbolTable;
|
||||||
|
|
||||||
pub struct Interpreter<'a> {
|
pub struct Context<'a> {
|
||||||
symbol_table: &'a mut SymbolTable,
|
symbol_table: &'a mut SymbolTable,
|
||||||
angle_unit: Unit,
|
angle_unit: Unit,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Interpreter<'a> {
|
impl<'a> Context<'a> {
|
||||||
pub fn new(angle_unit: Unit, symbol_table: &'a mut SymbolTable) -> Self {
|
pub fn new(angle_unit: Unit, symbol_table: &'a mut SymbolTable) -> Self {
|
||||||
for constant in prelude::CONSTANTS {
|
for constant in prelude::CONSTANTS {
|
||||||
symbol_table.insert(
|
symbol_table.insert(
|
||||||
@ -22,33 +22,33 @@ impl<'a> Interpreter<'a> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Interpreter {
|
Context {
|
||||||
angle_unit: angle_unit.clone(),
|
angle_unit: angle_unit.clone(),
|
||||||
symbol_table,
|
symbol_table,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn interpret(&mut self, statements: Vec<Stmt>) -> Option<f64> {
|
pub fn interpret(&mut self, statements: Vec<Stmt>) -> Result<Option<f64>, String> {
|
||||||
for (i, stmt) in statements.iter().enumerate() {
|
for (i, stmt) in statements.iter().enumerate() {
|
||||||
let value = self.visit_stmt(stmt);
|
let value = eval_stmt(self, stmt);
|
||||||
|
|
||||||
if i == statements.len() - 1 {
|
if i == statements.len() - 1 {
|
||||||
if let Stmt::Expr(_) = stmt {
|
if let Stmt::Expr(_) = stmt {
|
||||||
return Some(value);
|
return Ok(Some(value?));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return None;
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TokenKind {
|
impl TokenKind {
|
||||||
fn to_unit(&self) -> Unit {
|
fn to_unit(&self) -> Result<Unit, String> {
|
||||||
match self {
|
match self {
|
||||||
TokenKind::Deg => Unit::Degrees,
|
TokenKind::Deg => Ok(Unit::Degrees),
|
||||||
TokenKind::Rad => Unit::Radians,
|
TokenKind::Rad => Ok(Unit::Radians),
|
||||||
_ => panic!("Invalid unit."),
|
_ => Err(String::from("Invalid unit.")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,142 +60,145 @@ impl Unit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Visitor<f64, f64> for Interpreter<'a> {
|
fn eval_stmt(context: &mut Context, stmt: &Stmt) -> Result<f64, String> {
|
||||||
fn visit_stmt(&mut self, stmt: &Stmt) -> f64 {
|
match stmt {
|
||||||
match stmt {
|
Stmt::VarDecl(identifier, _) => eval_var_decl_stmt(context, stmt, identifier),
|
||||||
Stmt::VarDecl(identifier, _) => self.eval_var_decl_stmt(stmt, identifier),
|
Stmt::FnDecl(_, _, _) => eval_fn_decl_stmt(context),
|
||||||
Stmt::FnDecl(_, _, _) => self.eval_fn_decl_stmt(),
|
Stmt::Expr(expr) => eval_expr_stmt(context, &expr),
|
||||||
Stmt::Expr(expr) => self.eval_expr_stmt(&expr),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &Expr) -> f64 {
|
fn eval_var_decl_stmt(context: &mut Context, stmt: &Stmt, identifier: &str) -> Result<f64, String> {
|
||||||
match expr {
|
context.symbol_table.insert(&identifier, stmt.clone());
|
||||||
Expr::Binary(left, op, right) => self.eval_binary_expr(&left, op, &right),
|
Ok(0f64)
|
||||||
Expr::Unary(_, expr) => self.eval_unary_expr(expr),
|
}
|
||||||
Expr::Unit(expr, kind) => self.eval_unit_expr(expr, kind),
|
|
||||||
Expr::Var(identifier) => self.eval_var_expr(identifier),
|
fn eval_fn_decl_stmt(_: &mut Context) -> Result<f64, String> {
|
||||||
Expr::Literal(value) => self.eval_literal_expr(value),
|
Ok(0f64) // Nothing needs to happen here, since the parser will already have added the FnDecl's to the symbol table.
|
||||||
Expr::Group(expr) => self.eval_group_expr(&expr),
|
}
|
||||||
Expr::FnCall(identifier, expressions) => {
|
|
||||||
self.eval_fn_call_expr(identifier, expressions)
|
fn eval_expr_stmt(context: &mut Context, expr: &Expr) -> Result<f64, String> {
|
||||||
}
|
eval_expr(context, &expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eval_expr(context: &mut Context, expr: &Expr) -> Result<f64, String> {
|
||||||
|
match expr {
|
||||||
|
Expr::Binary(left, op, right) => eval_binary_expr(context, &left, op, &right),
|
||||||
|
Expr::Unary(_, expr) => eval_unary_expr(context, expr),
|
||||||
|
Expr::Unit(expr, kind) => eval_unit_expr(context, expr, kind),
|
||||||
|
Expr::Var(identifier) => eval_var_expr(context, identifier),
|
||||||
|
Expr::Literal(value) => eval_literal_expr(context, value),
|
||||||
|
Expr::Group(expr) => eval_group_expr(context, &expr),
|
||||||
|
Expr::FnCall(identifier, expressions) => {
|
||||||
|
eval_fn_call_expr(context, identifier, expressions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Interpreter<'a> {
|
fn eval_binary_expr(
|
||||||
fn eval_var_decl_stmt(&mut self, stmt: &Stmt, identifier: &str) -> f64 {
|
context: &mut Context,
|
||||||
self.symbol_table.insert(&identifier, stmt.clone());
|
left: &Expr,
|
||||||
0f64
|
op: &TokenKind,
|
||||||
|
right: &Expr,
|
||||||
|
) -> Result<f64, String> {
|
||||||
|
let left = eval_expr(context, &left)?;
|
||||||
|
let right = eval_expr(context, &right)?;
|
||||||
|
|
||||||
|
Ok(match op {
|
||||||
|
TokenKind::Plus => left + right,
|
||||||
|
TokenKind::Minus => left - right,
|
||||||
|
TokenKind::Star => left * right,
|
||||||
|
TokenKind::Slash => left / right,
|
||||||
|
TokenKind::Power => left.powf(right),
|
||||||
|
_ => 0f64,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eval_unary_expr(context: &mut Context, expr: &Expr) -> Result<f64, String> {
|
||||||
|
eval_expr(context, &expr).clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eval_unit_expr(context: &mut Context, expr: &Expr, kind: &TokenKind) -> Result<f64, String> {
|
||||||
|
let x = eval_expr(context, &expr);
|
||||||
|
let unit = kind.to_unit()?;
|
||||||
|
|
||||||
|
// Don't do any angle conversions if the defauly angle unit is the same as the unit kind
|
||||||
|
match unit {
|
||||||
|
Unit::Degrees | Unit::Radians => {
|
||||||
|
if context.angle_unit.compare(&unit) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_fn_decl_stmt(&mut self) -> f64 {
|
match unit {
|
||||||
0f64 // Nothing needs to happen here, since the parser will already have added the FnDecl's to the symbol table.
|
Unit::Degrees => Ok(x?.to_radians()),
|
||||||
}
|
Unit::Radians => Ok(x?.to_degrees()),
|
||||||
|
|
||||||
fn eval_expr_stmt(&mut self, expr: &Expr) -> f64 {
|
|
||||||
self.visit_expr(&expr)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Interpreter<'a> {
|
fn eval_var_expr(context: &mut Context, identifier: &str) -> Result<f64, String> {
|
||||||
fn eval_binary_expr(&mut self, left: &Expr, op: &TokenKind, right: &Expr) -> f64 {
|
let var_decl = context.symbol_table.get(identifier).cloned();
|
||||||
let left = self.visit_expr(&left);
|
match var_decl {
|
||||||
let right = self.visit_expr(&right);
|
Some(Stmt::VarDecl(_, expr)) => eval_expr(context, &expr),
|
||||||
|
_ => Err(String::from("Undefined variable.")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match op {
|
fn eval_literal_expr(_: &mut Context, value: &str) -> Result<f64, String> {
|
||||||
TokenKind::Plus => left + right,
|
match value.parse() {
|
||||||
TokenKind::Minus => left - right,
|
Ok(parsed_value) => Ok(parsed_value),
|
||||||
TokenKind::Star => left * right,
|
Err(_) => Err(String::from("Invalid number literal.")),
|
||||||
TokenKind::Slash => left / right,
|
}
|
||||||
TokenKind::Power => left.powf(right),
|
}
|
||||||
_ => 0f64,
|
|
||||||
|
fn eval_group_expr(context: &mut Context, expr: &Expr) -> Result<f64, String> {
|
||||||
|
eval_expr(context, expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eval_fn_call_expr(
|
||||||
|
context: &mut Context,
|
||||||
|
identifier: &str,
|
||||||
|
expressions: &Vec<Expr>,
|
||||||
|
) -> Result<f64, String> {
|
||||||
|
let prelude_func = match expressions.len() {
|
||||||
|
1 => {
|
||||||
|
let x = eval_expr(context, &expressions[0])?;
|
||||||
|
prelude::call_unary_func(identifier, x, &context.angle_unit)
|
||||||
}
|
}
|
||||||
}
|
2 => {
|
||||||
|
let x = eval_expr(context, &expressions[0])?;
|
||||||
fn eval_unary_expr(&mut self, expr: &Expr) -> f64 {
|
let y = eval_expr(context, &expressions[1])?;
|
||||||
self.visit_expr(&expr).clone()
|
prelude::call_binary_func(identifier, x, y, &context.angle_unit)
|
||||||
}
|
|
||||||
|
|
||||||
fn eval_unit_expr(&mut self, expr: &Expr, kind: &TokenKind) -> f64 {
|
|
||||||
let x = self.visit_expr(&expr);
|
|
||||||
|
|
||||||
// Don't do any angle conversions if the defauly angle unit is the same as the unit kind
|
|
||||||
if (kind.compare(&TokenKind::Deg) || kind.compare(&TokenKind::Rad))
|
|
||||||
&& self.angle_unit.compare(&kind.to_unit())
|
|
||||||
{
|
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
match kind {
|
if let Some(result) = prelude_func {
|
||||||
TokenKind::Deg => x.to_radians(),
|
return Ok(result);
|
||||||
TokenKind::Rad => x.to_degrees(),
|
|
||||||
_ => panic!("Invalid unit."),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_var_expr(&mut self, identifier: &str) -> f64 {
|
let stmt_definition = context
|
||||||
let value = self
|
.symbol_table
|
||||||
.symbol_table
|
.get(&format!("{}()", identifier))
|
||||||
.get(identifier)
|
.cloned();
|
||||||
.expect("Undefined variable.")
|
|
||||||
.clone();
|
|
||||||
if let Stmt::VarDecl(_, expr) = value {
|
|
||||||
return self.visit_expr(&expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
panic!("Unknown error.");
|
match stmt_definition {
|
||||||
}
|
Some(Stmt::FnDecl(_, arguments, fn_body)) => {
|
||||||
|
|
||||||
fn eval_literal_expr(&mut self, value: &str) -> f64 {
|
|
||||||
value.parse().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn eval_group_expr(&mut self, expr: &Expr) -> f64 {
|
|
||||||
self.visit_expr(expr)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn eval_fn_call_expr(&mut self, identifier: &str, expressions: &Vec<Expr>) -> f64 {
|
|
||||||
let prelude_func = match expressions.len() {
|
|
||||||
1 => {
|
|
||||||
let x = self.visit_expr(&expressions[0]);
|
|
||||||
prelude::call_unary_func(identifier, x, &self.angle_unit)
|
|
||||||
}
|
|
||||||
2 => {
|
|
||||||
let x = self.visit_expr(&expressions[0]);
|
|
||||||
let y = self.visit_expr(&expressions[1]);
|
|
||||||
prelude::call_binary_func(identifier, x, y, &self.angle_unit)
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(result) = prelude_func {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
let stmt = self
|
|
||||||
.symbol_table
|
|
||||||
.get(&format!("{}()", identifier))
|
|
||||||
.expect("Undefined function")
|
|
||||||
.clone();
|
|
||||||
|
|
||||||
if let Stmt::FnDecl(_, arguments, fn_body) = stmt {
|
|
||||||
if arguments.len() != expressions.len() {
|
if arguments.len() != expressions.len() {
|
||||||
panic!("Incorrect amount of arguments.");
|
return Err(String::from("Incorrect amount of arguments."));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise the arguments as their own variables.
|
// Initialise the arguments as their own variables.
|
||||||
for (i, argument) in arguments.iter().enumerate() {
|
for (i, argument) in arguments.iter().enumerate() {
|
||||||
self.visit_stmt(&Stmt::VarDecl(
|
eval_stmt(
|
||||||
argument.clone(),
|
context,
|
||||||
Box::new(expressions[i].clone()),
|
&Stmt::VarDecl(argument.clone(), Box::new(expressions[i].clone())),
|
||||||
));
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.visit_expr(&*fn_body);
|
return eval_expr(context, &*fn_body);
|
||||||
}
|
}
|
||||||
|
_ => Err(String::from("Undefined function.")),
|
||||||
panic!("Unexpected error.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
src/main.rs
14
src/main.rs
@ -5,14 +5,13 @@ mod lexer;
|
|||||||
mod parser;
|
mod parser;
|
||||||
mod prelude;
|
mod prelude;
|
||||||
mod symbol_table;
|
mod symbol_table;
|
||||||
mod visitor;
|
use parser::Unit;
|
||||||
use parser::{ParserContext, Unit};
|
|
||||||
|
|
||||||
use rustyline::error::ReadlineError;
|
use rustyline::error::ReadlineError;
|
||||||
use rustyline::Editor;
|
use rustyline::Editor;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut parser = ParserContext::new();
|
let mut parser = parser::Context::new();
|
||||||
|
|
||||||
// Command line argument input, execute it and exit.
|
// Command line argument input, execute it and exit.
|
||||||
if let Some(expr) = env::args().skip(1).next() {
|
if let Some(expr) = env::args().skip(1).next() {
|
||||||
@ -37,7 +36,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_repl(parser: &mut ParserContext, input: &str) {
|
fn eval_repl(parser: &mut parser::Context, input: &str) {
|
||||||
match input {
|
match input {
|
||||||
"" => eprint!(""),
|
"" => eprint!(""),
|
||||||
"clear" => print!("\x1B[2J"),
|
"clear" => print!("\x1B[2J"),
|
||||||
@ -46,10 +45,11 @@ fn eval_repl(parser: &mut ParserContext, input: &str) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval(parser: &mut ParserContext, input: &str) {
|
fn eval(parser: &mut parser::Context, input: &str) {
|
||||||
match parser::parse(parser, input, get_angle_unit()) {
|
match parser::parse(parser, input, get_angle_unit()) {
|
||||||
Ok(result) => println!("{}", result),
|
Ok(Some(result)) => println!("{}", result),
|
||||||
Err(_) => println!("Invalid expression"),
|
Ok(None) => print!(""),
|
||||||
|
Err(err) => println!("{}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
interpreter::Interpreter,
|
interpreter,
|
||||||
lexer::{Lexer, Token, TokenKind},
|
lexer::{Lexer, Token, TokenKind},
|
||||||
symbol_table::SymbolTable,
|
symbol_table::SymbolTable,
|
||||||
};
|
};
|
||||||
@ -30,7 +30,7 @@ pub enum Unit {
|
|||||||
Degrees,
|
Degrees,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ParserContext {
|
pub struct Context {
|
||||||
//angle_unit: Unit,
|
//angle_unit: Unit,
|
||||||
tokens: Vec<Token>,
|
tokens: Vec<Token>,
|
||||||
pos: usize,
|
pos: usize,
|
||||||
@ -50,9 +50,9 @@ impl TokenKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParserContext {
|
impl Context {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
ParserContext {
|
Context {
|
||||||
tokens: Vec::new(),
|
tokens: Vec::new(),
|
||||||
pos: 0,
|
pos: 0,
|
||||||
symbol_table: SymbolTable::new(),
|
symbol_table: SymbolTable::new(),
|
||||||
@ -60,19 +60,20 @@ impl ParserContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(context: &mut ParserContext, input: &str, angle_unit: Unit) -> Result<f64, String> {
|
pub fn parse(context: &mut Context, input: &str, angle_unit: Unit) -> Result<Option<f64>, String> {
|
||||||
context.tokens = Lexer::lex(input);
|
context.tokens = Lexer::lex(input);
|
||||||
|
context.pos = 0;
|
||||||
|
|
||||||
let mut statements: Vec<Stmt> = Vec::new();
|
let mut statements: Vec<Stmt> = Vec::new();
|
||||||
while !is_at_end(context) {
|
while !is_at_end(context) {
|
||||||
statements.push(parse_stmt(context)?);
|
statements.push(parse_stmt(context)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut interpreter = Interpreter::new(angle_unit, &mut context.symbol_table);
|
let mut interpreter = interpreter::Context::new(angle_unit, &mut context.symbol_table);
|
||||||
Ok(interpreter.interpret(statements).unwrap())
|
interpreter.interpret(statements)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_stmt(context: &mut ParserContext) -> Result<Stmt, String> {
|
fn parse_stmt(context: &mut Context) -> Result<Stmt, String> {
|
||||||
if match_token(context, TokenKind::Identifier) {
|
if match_token(context, TokenKind::Identifier) {
|
||||||
return Ok(match peek_next(context).kind {
|
return Ok(match peek_next(context).kind {
|
||||||
TokenKind::Equals => parse_var_decl_stmt(context)?,
|
TokenKind::Equals => parse_var_decl_stmt(context)?,
|
||||||
@ -84,7 +85,7 @@ fn parse_stmt(context: &mut ParserContext) -> Result<Stmt, String> {
|
|||||||
Ok(Stmt::Expr(Box::new(parse_expr(context)?)))
|
Ok(Stmt::Expr(Box::new(parse_expr(context)?)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_identifier_stmt(context: &mut ParserContext) -> Result<Stmt, String> {
|
fn parse_identifier_stmt(context: &mut Context) -> Result<Stmt, String> {
|
||||||
let began_at = context.pos;
|
let began_at = context.pos;
|
||||||
let primary = parse_primary(context)?; // Since function declarations and function calls look the same at first, simply parse a "function call", and re-use the data.
|
let primary = parse_primary(context)?; // Since function declarations and function calls look the same at first, simply parse a "function call", and re-use the data.
|
||||||
|
|
||||||
@ -126,7 +127,7 @@ fn parse_identifier_stmt(context: &mut ParserContext) -> Result<Stmt, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_var_decl_stmt(context: &mut ParserContext) -> Result<Stmt, String> {
|
fn parse_var_decl_stmt(context: &mut Context) -> Result<Stmt, String> {
|
||||||
let identifier = advance(context).clone();
|
let identifier = advance(context).clone();
|
||||||
advance(context); // Equal sign
|
advance(context); // Equal sign
|
||||||
let expr = parse_expr(context)?;
|
let expr = parse_expr(context)?;
|
||||||
@ -134,11 +135,11 @@ fn parse_var_decl_stmt(context: &mut ParserContext) -> Result<Stmt, String> {
|
|||||||
Ok(Stmt::VarDecl(identifier.value, Box::new(expr)))
|
Ok(Stmt::VarDecl(identifier.value, Box::new(expr)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_expr(context: &mut ParserContext) -> Result<Expr, String> {
|
fn parse_expr(context: &mut Context) -> Result<Expr, String> {
|
||||||
Ok(parse_sum(context)?)
|
Ok(parse_sum(context)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_sum(context: &mut ParserContext) -> Result<Expr, String> {
|
fn parse_sum(context: &mut Context) -> Result<Expr, String> {
|
||||||
let mut left = parse_factor(context)?;
|
let mut left = parse_factor(context)?;
|
||||||
|
|
||||||
while match_token(context, TokenKind::Plus) || match_token(context, TokenKind::Minus) {
|
while match_token(context, TokenKind::Plus) || match_token(context, TokenKind::Minus) {
|
||||||
@ -152,7 +153,7 @@ fn parse_sum(context: &mut ParserContext) -> Result<Expr, String> {
|
|||||||
Ok(left)
|
Ok(left)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_factor(context: &mut ParserContext) -> Result<Expr, String> {
|
fn parse_factor(context: &mut Context) -> Result<Expr, String> {
|
||||||
let mut left = parse_unary(context)?;
|
let mut left = parse_unary(context)?;
|
||||||
|
|
||||||
while match_token(context, TokenKind::Star)
|
while match_token(context, TokenKind::Star)
|
||||||
@ -175,7 +176,7 @@ fn parse_factor(context: &mut ParserContext) -> Result<Expr, String> {
|
|||||||
Ok(left)
|
Ok(left)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_unary(context: &mut ParserContext) -> Result<Expr, String> {
|
fn parse_unary(context: &mut Context) -> Result<Expr, String> {
|
||||||
if match_token(context, TokenKind::Minus) {
|
if match_token(context, TokenKind::Minus) {
|
||||||
let op = advance(context).kind.clone();
|
let op = advance(context).kind.clone();
|
||||||
let expr = Box::new(parse_unary(context)?);
|
let expr = Box::new(parse_unary(context)?);
|
||||||
@ -185,7 +186,7 @@ fn parse_unary(context: &mut ParserContext) -> Result<Expr, String> {
|
|||||||
Ok(parse_exponent(context)?)
|
Ok(parse_exponent(context)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_exponent(context: &mut ParserContext) -> Result<Expr, String> {
|
fn parse_exponent(context: &mut Context) -> Result<Expr, String> {
|
||||||
let left = parse_primary(context)?;
|
let left = parse_primary(context)?;
|
||||||
|
|
||||||
if match_token(context, TokenKind::Power) {
|
if match_token(context, TokenKind::Power) {
|
||||||
@ -197,7 +198,7 @@ fn parse_exponent(context: &mut ParserContext) -> Result<Expr, String> {
|
|||||||
Ok(left)
|
Ok(left)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_primary(context: &mut ParserContext) -> Result<Expr, String> {
|
fn parse_primary(context: &mut Context) -> Result<Expr, String> {
|
||||||
let expr = match peek(context).kind {
|
let expr = match peek(context).kind {
|
||||||
TokenKind::OpenParenthesis => parse_group(context)?,
|
TokenKind::OpenParenthesis => parse_group(context)?,
|
||||||
TokenKind::Pipe => parse_abs(context)?,
|
TokenKind::Pipe => parse_abs(context)?,
|
||||||
@ -212,7 +213,7 @@ fn parse_primary(context: &mut ParserContext) -> Result<Expr, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_group(context: &mut ParserContext) -> Result<Expr, String> {
|
fn parse_group(context: &mut Context) -> Result<Expr, String> {
|
||||||
advance(context);
|
advance(context);
|
||||||
let group_expr = Expr::Group(Box::new(parse_expr(context)?));
|
let group_expr = Expr::Group(Box::new(parse_expr(context)?));
|
||||||
consume(context, TokenKind::ClosedParenthesis)?;
|
consume(context, TokenKind::ClosedParenthesis)?;
|
||||||
@ -220,7 +221,7 @@ fn parse_group(context: &mut ParserContext) -> Result<Expr, String> {
|
|||||||
Ok(group_expr)
|
Ok(group_expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_abs(context: &mut ParserContext) -> Result<Expr, String> {
|
fn parse_abs(context: &mut Context) -> Result<Expr, String> {
|
||||||
advance(context);
|
advance(context);
|
||||||
let group_expr = Expr::Group(Box::new(parse_expr(context)?));
|
let group_expr = Expr::Group(Box::new(parse_expr(context)?));
|
||||||
consume(context, TokenKind::Pipe)?;
|
consume(context, TokenKind::Pipe)?;
|
||||||
@ -228,7 +229,7 @@ fn parse_abs(context: &mut ParserContext) -> Result<Expr, String> {
|
|||||||
Ok(Expr::FnCall(String::from("abs"), vec![group_expr]))
|
Ok(Expr::FnCall(String::from("abs"), vec![group_expr]))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_identifier(context: &mut ParserContext) -> Result<Expr, String> {
|
fn parse_identifier(context: &mut Context) -> Result<Expr, String> {
|
||||||
let identifier = advance(context).clone();
|
let identifier = advance(context).clone();
|
||||||
|
|
||||||
// Eg. sqrt64
|
// Eg. sqrt64
|
||||||
@ -261,19 +262,19 @@ fn parse_identifier(context: &mut ParserContext) -> Result<Expr, String> {
|
|||||||
Ok(Expr::Var(identifier.value))
|
Ok(Expr::Var(identifier.value))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peek<'a>(context: &'a mut ParserContext) -> &'a Token {
|
fn peek<'a>(context: &'a mut Context) -> &'a Token {
|
||||||
&context.tokens[context.pos]
|
&context.tokens[context.pos]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peek_next<'a>(context: &'a mut ParserContext) -> &'a Token {
|
fn peek_next<'a>(context: &'a mut Context) -> &'a Token {
|
||||||
&context.tokens[context.pos + 1]
|
&context.tokens[context.pos + 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn previous<'a>(context: &'a mut ParserContext) -> &'a Token {
|
fn previous<'a>(context: &'a mut Context) -> &'a Token {
|
||||||
&context.tokens[context.pos - 1]
|
&context.tokens[context.pos - 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_token(context: &mut ParserContext, kind: TokenKind) -> bool {
|
fn match_token(context: &mut Context, kind: TokenKind) -> bool {
|
||||||
if is_at_end(context) {
|
if is_at_end(context) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -281,12 +282,12 @@ fn match_token(context: &mut ParserContext, kind: TokenKind) -> bool {
|
|||||||
peek(context).kind.compare(&kind)
|
peek(context).kind.compare(&kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn advance<'a>(context: &'a mut ParserContext) -> &'a Token {
|
fn advance<'a>(context: &'a mut Context) -> &'a Token {
|
||||||
context.pos += 1;
|
context.pos += 1;
|
||||||
previous(context)
|
previous(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consume<'a>(context: &'a mut ParserContext, kind: TokenKind) -> Result<&'a Token, String> {
|
fn consume<'a>(context: &'a mut Context, kind: TokenKind) -> Result<&'a Token, String> {
|
||||||
if match_token(context, kind) {
|
if match_token(context, kind) {
|
||||||
return Ok(advance(context));
|
return Ok(advance(context));
|
||||||
}
|
}
|
||||||
@ -294,6 +295,6 @@ fn consume<'a>(context: &'a mut ParserContext, kind: TokenKind) -> Result<&'a To
|
|||||||
Err("Unexpected token".into())
|
Err("Unexpected token".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_at_end(context: &mut ParserContext) -> bool {
|
fn is_at_end(context: &mut Context) -> bool {
|
||||||
context.pos >= context.tokens.len() || peek(context).kind.compare(&TokenKind::EOF)
|
context.pos >= context.tokens.len() || peek(context).kind.compare(&TokenKind::EOF)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
use crate::parser::{Expr, Stmt};
|
|
||||||
|
|
||||||
pub trait Visitor<T, U> {
|
|
||||||
fn visit_stmt(&mut self, stmt: &Stmt) -> T;
|
|
||||||
fn visit_expr(&mut self, expr: &Expr) -> U;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user