Skip to content

Commit

Permalink
BUG: fixed unexpected decimal error and empty calculation errors
Browse files Browse the repository at this point in the history
  • Loading branch information
keplerHaloxx committed Aug 21, 2024
1 parent 553d6e6 commit 4f1ce14
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 26 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## A simple math interpreter
Currently supports `PLUS`, `MINUS`, `MULTIPLY`, `DIVIDE`, `POWER`

I'd like to add functions such as `sin(x)` into the interpreter but this code is messy and all over the place. Maybe one day when I learn more I can redo this project.
70 changes: 49 additions & 21 deletions src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,33 @@ use crate::{
};

const DIGITS: &str = ".0123456789";
const LETTERS: &str = "abcdefghijklmnopqrstuvwxyz";

pub struct Lexer {
source: String,
pub struct Lexer<I: Iterator<Item = char> + Clone> {
// source: String,
iter: Peekable<I>,
}

impl Lexer {
pub fn new(source: String) -> Self {
Self { source }
impl<I: Iterator<Item = char> + Clone> Lexer<I> {
pub fn new(source: I) -> Self {
Self {
// source,
iter: source.peekable(),
}
}

pub fn tokenize(&self) -> Result<Vec<Token>, ErrorReason> {
pub fn tokenize(&mut self) -> Result<Vec<Token>, ErrorReason> {
let mut tokens: Vec<Token> = Vec::new();
let mut chars = self
.source
.chars()
.filter(|c| !c.is_whitespace())
.peekable();

while let Some(&current) = chars.peek() {
// Best solution i could find to making sure it doesn't skip

// Best solution i could find to making sure it doesn't skip
while let Some(&current) = self.iter.peek() {
if current.is_ascii_whitespace() {
self.iter.next();
continue;
}

if DIGITS.contains(current) {
tokens.push(self.generate_number(&mut chars)?);
tokens.push(self.generate_number()?);
} else {
let token = match current {
'+' => Token::new(TokenKind::Plus, None),
Expand All @@ -37,44 +42,67 @@ impl Lexer {
'^' => Token::new(TokenKind::Power, None),
'(' => Token::new(TokenKind::LParen, None),
')' => Token::new(TokenKind::RParen, None),
// 'a'..='z' => {}
_ => Token::new(
TokenKind::Unknown,
Some(TokenValue::StrValue(current.to_string())),
),
};
tokens.push(token);
chars.next();
self.iter.next();
}
}

Ok(tokens)
}

fn generate_number<I>(&self, chars: &mut Peekable<I>) -> Result<Token, ErrorReason>
fn read_function(&mut self) -> Token {
// TODO: read the parameters of function
// bruh i cant figure this out rn i do later
let mut name = String::new();

while let Some(&current) = self.iter.peek() {
if LETTERS.contains(current) {
name.push(current);
}

if current == '(' {
self.iter.next(); // Consume '('

}
self.iter.next();
}
Token::new(TokenKind::Function, Some(TokenValue::FuncParams(name, 0))) // change params later
}

fn generate_number(&mut self) -> Result<Token, ErrorReason>
where
I: Iterator<Item = char>,
{
let mut decimal_point_counter = 0;
let mut number = String::new();

while let Some(&current) = chars.peek() {
while let Some(&current) = self.iter.peek() {
if current == '.' {
decimal_point_counter += 1;
if decimal_point_counter > 1 {
return Err(ErrorReason::Error("Too many decimal points".into()));
}
}
number.push(current);
chars.next();
self.iter.next();

// Peek the next character and check if it's valid for a number
if let Some(&next_char) = chars.peek() {
if let Some(&next_char) = self.iter.peek() {
if !DIGITS.contains(next_char) {
if number.trim() == "." {
return Err(ErrorReason::Error("Random decimal place found ".into()));
return Err(ErrorReason::Error("Invalid sequence".into()));
}
break;
}
} else {
// this is PROBABLY the error but i cbf actually finding the bugs
return Err(ErrorReason::Error("Invalid sequence".into()));
}
}

Expand Down
17 changes: 12 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::io::{stdin, stdout, Write};
use colored::Colorize;
use errors::{ErrorReason, ParserError};
use lexer::Lexer;
use parser::Parser;
use parser::{ASTNode, Parser};
use token::{Token, TokenKind, TokenValue};

/// Prompts user for input and returns trimmed result
Expand All @@ -30,7 +30,7 @@ fn main() {
loop {
let input = prompt_input("> ");

let lexer = Lexer::new(input);
let mut lexer = Lexer::new(input.chars());
let tokens_result = lexer.tokenize();
if let Err(err) = tokens_result {
println!("{}", err);
Expand All @@ -43,16 +43,23 @@ fn main() {
for err in token_errors {
println!(
"{}",
ParserError::new(ErrorReason::Error(format!("Invalid sequence: '{}'", err)))
.description
ParserError::new(ErrorReason::Error(format!(
"Invalid sequence: '{}'",
err
)))
.description
);
}
println!();
} else {
pretty_print_tokens(tokens.clone());
let mut parser = Parser::new(tokens.into_iter());
let result = parser.parse_expr();
println!("{:?}", result);
// println!("{:?}", result);
if result.is_err() {
println!("{}", result.unwrap_err().description);
continue;
}
println!(
"{} {}",
"RESULT:".bright_green(),
Expand Down
1 change: 1 addition & 0 deletions src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub enum TokenKind {

#[derive(Debug, PartialEq, Clone)]
pub enum TokenValue {
FuncParams(String, u8), // function_name, num_of_params
StrValue(String),
NumValue(f64),
None,
Expand Down

0 comments on commit 4f1ce14

Please sign in to comment.