From 1794042514b54cba29f6295bdd745e315019d794 Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 27 Mar 2023 09:47:02 -0700 Subject: [PATCH] Restructured code --- src/{parser => }/evaluate.rs | 8 +-- src/main.rs | 33 +++++++++-- src/parser/find_subs.rs | 7 ++- src/parser/groupify.rs | 7 ++- src/parser/mod.rs | 84 ++++++++++++++++++++++++++ src/parser/tokenize.rs | 6 +- src/parser/treeify.rs | 7 ++- src/{parser.rs => tokens.rs} | 110 +++-------------------------------- 8 files changed, 140 insertions(+), 122 deletions(-) rename src/{parser => }/evaluate.rs (88%) create mode 100644 src/parser/mod.rs rename src/{parser.rs => tokens.rs} (76%) diff --git a/src/parser/evaluate.rs b/src/evaluate.rs similarity index 88% rename from src/parser/evaluate.rs rename to src/evaluate.rs index a49a4b6..defff4b 100644 --- a/src/parser/evaluate.rs +++ b/src/evaluate.rs @@ -1,6 +1,4 @@ -use crate::parser::Token; -use crate::parser::LineLocation; -use crate::parser::ParserError; +use crate::tokens::Token; #[inline(always)] fn get_at_coords<'a>(g: &'a mut Token, coords: &Vec) -> &'a mut Token { @@ -15,9 +13,9 @@ fn get_at_coords<'a>(g: &'a mut Token, coords: &Vec) -> &'a mut Token { } -pub fn p_evaluate( +pub fn evaluate( mut g: Token, -) -> Result { +) -> Result { let mut coords: Vec = Vec::with_capacity(16); coords.push(0); diff --git a/src/main.rs b/src/main.rs index 408ff4a..4008eae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,11 +6,14 @@ use termion::raw::IntoRawMode; use termion::raw::RawTerminal; use termion::{color, style}; +pub mod tokens; mod parser; mod promptbuffer; +mod evaluate; + +use crate::tokens::Token; use crate::promptbuffer::PromptBuffer; -use crate::parser::Token; //use crate::parser::ParserError; //use crate::parser::LineLocation; @@ -79,6 +82,17 @@ fn draw_line( return Ok(()); } +/* + +#[cfg(debug_assertions)] +RawTerminal::suspend_raw_mode(&stdout)?; +#[cfg(debug_assertions)] +write!(stdout, "\n")?; + +#[cfg(debug_assertions)] +RawTerminal::activate_raw_mode(&stdout)?; +*/ + fn main() -> Result<(), std::io::Error> { let mut stdout = stdout().into_raw_mode().unwrap(); @@ -106,16 +120,25 @@ fn main() -> Result<(), std::io::Error> { match q { '\n' => { let s = pb.enter(); - if s == "" { write!(stdout, "\r\n")?; break; } + write!(stdout, "\r\n")?; + if s == "" { break; } + #[cfg(debug_assertions)] RawTerminal::suspend_raw_mode(&stdout)?; - write!(stdout, "\n")?; - let g = parser::evaluate(&s); + let g = parser::parse(&s); + #[cfg(debug_assertions)] RawTerminal::activate_raw_mode(&stdout)?; match g { Ok(g) => { + #[cfg(debug_assertions)] + RawTerminal::suspend_raw_mode(&stdout)?; + let g = evaluate::evaluate(g).unwrap(); let n = g.eval(); + #[cfg(debug_assertions)] + RawTerminal::activate_raw_mode(&stdout)?; + + if let Token::Number(_, v) = n { write!( stdout, "\r\n {}{}={} {v}{}\r\n\n", @@ -126,6 +149,8 @@ fn main() -> Result<(), std::io::Error> { )?; } else { panic!(); } }, + + // Show parse error Err((l, e)) => { write!( stdout, "{}{}{} {}{}\r\n", diff --git a/src/parser/find_subs.rs b/src/parser/find_subs.rs index ceed468..e034e94 100644 --- a/src/parser/find_subs.rs +++ b/src/parser/find_subs.rs @@ -1,8 +1,8 @@ use std::collections::VecDeque; -use crate::parser::Operator; -use crate::parser::Token; -use crate::parser::LineLocation; +use crate::tokens::Token; +use crate::tokens::Operator; +use crate::tokens::LineLocation; pub fn p_find_subs( @@ -60,6 +60,7 @@ pub fn p_find_subs( "chi" => {Some("χ")}, "psi" => {Some("ψ")}, "omega" => {Some("ω")}, + "sqrt" => {Some("√")}, _ => {None} }; diff --git a/src/parser/groupify.rs b/src/parser/groupify.rs index 7d7f4e3..033397a 100644 --- a/src/parser/groupify.rs +++ b/src/parser/groupify.rs @@ -1,9 +1,10 @@ use std::collections::VecDeque; -use crate::parser::Token; -use crate::parser::LineLocation; +use crate::tokens::Token; +use crate::tokens::Operator; +use crate::tokens::LineLocation; + use crate::parser::ParserError; -use crate::parser::Operator; /// Looks backwards at the elements of g. /// - Inserts ImplicitMultiply diff --git a/src/parser/mod.rs b/src/parser/mod.rs new file mode 100644 index 0000000..4def6b0 --- /dev/null +++ b/src/parser/mod.rs @@ -0,0 +1,84 @@ +mod tokenize; +mod treeify; +mod groupify; +mod find_subs; + + +use crate::parser::tokenize::p_tokenize; +use crate::parser::groupify::p_groupify; +use crate::parser::treeify::p_treeify; +use crate::parser::find_subs::p_find_subs; + +use crate::tokens; + +/// Types of parser errors. +/// If we cannot parse a string, one of these is returned. +#[derive(Debug)] +pub enum ParserError { + //MissingCloseParen, + ExtraCloseParen, + EmptyGroup, + Syntax, + Undefined(String), + BadNumber +} + +impl ParserError { + pub fn to_message(&self) -> String { + match self { + //ParserError::MissingCloseParen => { + // String::from("This group is never closed") + //}, + ParserError::ExtraCloseParen => { + String::from("Extra close parenthesis") + }, + ParserError::EmptyGroup => { + String::from("Groups can't be empty") + }, + ParserError::Syntax => { + String::from("Syntax") + }, + ParserError::Undefined(s) => { + format!("\"{s}\" isn't defined") + }, + ParserError::BadNumber => { + String::from("Invalid number") + } + } + } +} + + + +pub fn parse( + s: &String +) -> Result< + tokens::Token, + (tokens::LineLocation, ParserError) +> { + + let tokens = p_tokenize(s); + let (_, tokens) = p_find_subs(tokens); + let mut g = p_groupify(tokens)?; + g = p_treeify(g)?; + + return Ok(g); +} + + +pub fn substitute(s: &String) -> String{ + if s == "" { return s.clone() } + let mut new_s = s.clone(); + + let tokens = p_tokenize(s); + let (subs, _) = p_find_subs(tokens); + + for r in subs.iter() { + new_s.replace_range( + r.0.pos..r.0.pos+r.0.len, + &r.1[..] + ) + } + + return new_s; +} \ No newline at end of file diff --git a/src/parser/tokenize.rs b/src/parser/tokenize.rs index 2f50de0..bb5833a 100644 --- a/src/parser/tokenize.rs +++ b/src/parser/tokenize.rs @@ -1,8 +1,8 @@ use std::collections::VecDeque; -use crate::parser::Token; -use crate::parser::LineLocation; -use crate::parser::Operator; +use crate::tokens::Token; +use crate::tokens::Operator; +use crate::tokens::LineLocation; /// Updates the length of a Token's LineLocation. /// Run whenever a token is finished. diff --git a/src/parser/treeify.rs b/src/parser/treeify.rs index f9e3a91..a762ac3 100644 --- a/src/parser/treeify.rs +++ b/src/parser/treeify.rs @@ -1,9 +1,10 @@ use std::collections::VecDeque; -use crate::parser::Token; -use crate::parser::LineLocation; +use crate::tokens::Token; +use crate::tokens::Operator; +use crate::tokens::LineLocation; + use crate::parser::ParserError; -use crate::parser::Operator; fn treeify_binary( i: usize, diff --git a/src/parser.rs b/src/tokens.rs similarity index 76% rename from src/parser.rs rename to src/tokens.rs index ec198f0..1697734 100644 --- a/src/parser.rs +++ b/src/tokens.rs @@ -1,23 +1,19 @@ -mod tokenize; -mod treeify; -mod groupify; -mod evaluate; -mod find_subs; - -use crate::parser::tokenize::p_tokenize; -use crate::parser::groupify::p_groupify; -use crate::parser::treeify::p_treeify; -use crate::parser::evaluate::p_evaluate; -use crate::parser::find_subs::p_find_subs; - use std::collections::VecDeque; +/// Specifies the location of a token in an input string. +/// Used to locate ParserErrors. +#[derive(Debug)] +#[derive(Copy, Clone)] +pub struct LineLocation { + pub pos: usize, + pub len: usize +} + /// Tokens represent logical objects in an expession. /// /// Tokens starting with `Pre*` are intermediate tokens, and /// will never show up in a fully-parsed expression tree. - #[derive(Debug)] pub enum Token { @@ -310,91 +306,3 @@ impl Operator { } } } - -/// Specifies the location of a token in an input string. -/// Used to locate ParserErrors. -#[derive(Debug)] -#[derive(Copy, Clone)] -pub struct LineLocation { - pub pos: usize, - pub len: usize -} - -/// Types of parser errors. -/// If we cannot parse a string, one of these is returned. -#[derive(Debug)] -pub enum ParserError { - //MissingCloseParen, - ExtraCloseParen, - EmptyGroup, - Syntax, - Undefined(String), - BadNumber -} - -impl ParserError { - pub fn to_message(&self) -> String { - match self { - //ParserError::MissingCloseParen => { - // String::from("This group is never closed") - //}, - ParserError::ExtraCloseParen => { - String::from("Extra close parenthesis") - }, - ParserError::EmptyGroup => { - String::from("Groups can't be empty") - }, - ParserError::Syntax => { - String::from("Syntax") - }, - ParserError::Undefined(s) => { - format!("\"{s}\" isn't defined") - }, - ParserError::BadNumber => { - String::from("Invalid number") - } - } - } -} - - -/// Parse a user string. This is the only method that should be used -/// outside this module. -/// -/// # Arguments: -/// `s`: the string to parse. Must be trimmed. -/// -/// # Returns: -/// - `Err(LineLocation, ParserError)` if we couldn't parse this string. -/// `LineLocation` specifies *where* the error is, and `ParserError` specifies -/// *what* the error is. -/// -/// - `Ok(Token)` otherwise, where `Token` is the top of an expression tree. -pub fn evaluate(s: &String) -> Result { - - let tokens = p_tokenize(s); - let (_, tokens) = p_find_subs(tokens); - let mut g = p_groupify(tokens)?; - g = p_treeify(g)?; - g = p_evaluate(g)?; - - return Ok(g); -} - - -pub fn substitute(s: &String) -> String{ - if s == "" { return s.clone() } - let mut new_s = s.clone(); - - let tokens = p_tokenize(s); - let (subs, _) = p_find_subs(tokens); - - for r in subs.iter() { - new_s.replace_range( - r.0.pos..r.0.pos+r.0.len, - &r.1[..] - ) - } - - return new_s; -} \ No newline at end of file