mirror of https://github.com/rm-dr/daisy
Restructured code
parent
ca35c8d9e9
commit
1794042514
|
@ -1,6 +1,4 @@
|
||||||
use crate::parser::Token;
|
use crate::tokens::Token;
|
||||||
use crate::parser::LineLocation;
|
|
||||||
use crate::parser::ParserError;
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn get_at_coords<'a>(g: &'a mut Token, coords: &Vec<usize>) -> &'a mut Token {
|
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,
|
mut g: Token,
|
||||||
) -> Result<Token, (LineLocation, ParserError)> {
|
) -> Result<Token, ()> {
|
||||||
let mut coords: Vec<usize> = Vec::with_capacity(16);
|
let mut coords: Vec<usize> = Vec::with_capacity(16);
|
||||||
coords.push(0);
|
coords.push(0);
|
||||||
|
|
33
src/main.rs
33
src/main.rs
|
@ -6,11 +6,14 @@ use termion::raw::IntoRawMode;
|
||||||
use termion::raw::RawTerminal;
|
use termion::raw::RawTerminal;
|
||||||
use termion::{color, style};
|
use termion::{color, style};
|
||||||
|
|
||||||
|
pub mod tokens;
|
||||||
mod parser;
|
mod parser;
|
||||||
mod promptbuffer;
|
mod promptbuffer;
|
||||||
|
mod evaluate;
|
||||||
|
|
||||||
|
use crate::tokens::Token;
|
||||||
use crate::promptbuffer::PromptBuffer;
|
use crate::promptbuffer::PromptBuffer;
|
||||||
|
|
||||||
use crate::parser::Token;
|
|
||||||
//use crate::parser::ParserError;
|
//use crate::parser::ParserError;
|
||||||
//use crate::parser::LineLocation;
|
//use crate::parser::LineLocation;
|
||||||
|
|
||||||
|
@ -79,6 +82,17 @@ fn draw_line(
|
||||||
return Ok(());
|
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> {
|
fn main() -> Result<(), std::io::Error> {
|
||||||
let mut stdout = stdout().into_raw_mode().unwrap();
|
let mut stdout = stdout().into_raw_mode().unwrap();
|
||||||
|
|
||||||
|
@ -106,16 +120,25 @@ fn main() -> Result<(), std::io::Error> {
|
||||||
match q {
|
match q {
|
||||||
'\n' => {
|
'\n' => {
|
||||||
let s = pb.enter();
|
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)?;
|
RawTerminal::suspend_raw_mode(&stdout)?;
|
||||||
write!(stdout, "\n")?;
|
let g = parser::parse(&s);
|
||||||
let g = parser::evaluate(&s);
|
#[cfg(debug_assertions)]
|
||||||
RawTerminal::activate_raw_mode(&stdout)?;
|
RawTerminal::activate_raw_mode(&stdout)?;
|
||||||
|
|
||||||
match g {
|
match g {
|
||||||
Ok(g) => {
|
Ok(g) => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
RawTerminal::suspend_raw_mode(&stdout)?;
|
||||||
|
let g = evaluate::evaluate(g).unwrap();
|
||||||
let n = g.eval();
|
let n = g.eval();
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
RawTerminal::activate_raw_mode(&stdout)?;
|
||||||
|
|
||||||
|
|
||||||
if let Token::Number(_, v) = n {
|
if let Token::Number(_, v) = n {
|
||||||
write!(
|
write!(
|
||||||
stdout, "\r\n {}{}={} {v}{}\r\n\n",
|
stdout, "\r\n {}{}={} {v}{}\r\n\n",
|
||||||
|
@ -126,6 +149,8 @@ fn main() -> Result<(), std::io::Error> {
|
||||||
)?;
|
)?;
|
||||||
} else { panic!(); }
|
} else { panic!(); }
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Show parse error
|
||||||
Err((l, e)) => {
|
Err((l, e)) => {
|
||||||
write!(
|
write!(
|
||||||
stdout, "{}{}{} {}{}\r\n",
|
stdout, "{}{}{} {}{}\r\n",
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use crate::parser::Operator;
|
use crate::tokens::Token;
|
||||||
use crate::parser::Token;
|
use crate::tokens::Operator;
|
||||||
use crate::parser::LineLocation;
|
use crate::tokens::LineLocation;
|
||||||
|
|
||||||
|
|
||||||
pub fn p_find_subs(
|
pub fn p_find_subs(
|
||||||
|
@ -60,6 +60,7 @@ pub fn p_find_subs(
|
||||||
"chi" => {Some("χ")},
|
"chi" => {Some("χ")},
|
||||||
"psi" => {Some("ψ")},
|
"psi" => {Some("ψ")},
|
||||||
"omega" => {Some("ω")},
|
"omega" => {Some("ω")},
|
||||||
|
"sqrt" => {Some("√")},
|
||||||
|
|
||||||
_ => {None}
|
_ => {None}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use crate::parser::Token;
|
use crate::tokens::Token;
|
||||||
use crate::parser::LineLocation;
|
use crate::tokens::Operator;
|
||||||
|
use crate::tokens::LineLocation;
|
||||||
|
|
||||||
use crate::parser::ParserError;
|
use crate::parser::ParserError;
|
||||||
use crate::parser::Operator;
|
|
||||||
|
|
||||||
/// Looks backwards at the elements of g.
|
/// Looks backwards at the elements of g.
|
||||||
/// - Inserts ImplicitMultiply
|
/// - Inserts ImplicitMultiply
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use crate::parser::Token;
|
use crate::tokens::Token;
|
||||||
use crate::parser::LineLocation;
|
use crate::tokens::Operator;
|
||||||
use crate::parser::Operator;
|
use crate::tokens::LineLocation;
|
||||||
|
|
||||||
/// Updates the length of a Token's LineLocation.
|
/// Updates the length of a Token's LineLocation.
|
||||||
/// Run whenever a token is finished.
|
/// Run whenever a token is finished.
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use crate::parser::Token;
|
use crate::tokens::Token;
|
||||||
use crate::parser::LineLocation;
|
use crate::tokens::Operator;
|
||||||
|
use crate::tokens::LineLocation;
|
||||||
|
|
||||||
use crate::parser::ParserError;
|
use crate::parser::ParserError;
|
||||||
use crate::parser::Operator;
|
|
||||||
|
|
||||||
fn treeify_binary(
|
fn treeify_binary(
|
||||||
i: usize,
|
i: usize,
|
||||||
|
|
|
@ -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;
|
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 represent logical objects in an expession.
|
||||||
///
|
///
|
||||||
/// Tokens starting with `Pre*` are intermediate tokens, and
|
/// Tokens starting with `Pre*` are intermediate tokens, and
|
||||||
/// will never show up in a fully-parsed expression tree.
|
/// will never show up in a fully-parsed expression tree.
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Token {
|
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;
|
|
||||||
}
|
|
Loading…
Reference in New Issue