Restructured code

pull/2/head
Mark 2023-03-27 09:47:02 -07:00
parent ca35c8d9e9
commit 1794042514
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
8 changed files with 140 additions and 122 deletions

View File

@ -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<usize>) -> &'a mut Token {
@ -15,9 +13,9 @@ fn get_at_coords<'a>(g: &'a mut Token, coords: &Vec<usize>) -> &'a mut Token {
}
pub fn p_evaluate(
pub fn evaluate(
mut g: Token,
) -> Result<Token, (LineLocation, ParserError)> {
) -> Result<Token, ()> {
let mut coords: Vec<usize> = Vec::with_capacity(16);
coords.push(0);

View File

@ -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",

View File

@ -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}
};

View File

@ -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

84
src/parser/mod.rs Normal file
View File

@ -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;
}

View File

@ -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.

View File

@ -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,

View File

@ -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<Token, (LineLocation, ParserError)> {
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;
}