From c1671968096c7289ac42822b1154e46a865a69a6 Mon Sep 17 00:00:00 2001 From: Mark Date: Sat, 25 Mar 2023 20:10:31 -0700 Subject: [PATCH] Fixed syntax error location --- src/parser.rs | 20 ++++++++- src/parser/find_subs.rs | 96 +++++++++++++++++++++++++---------------- 2 files changed, 77 insertions(+), 39 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index ee79905..e3e59bc 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -83,8 +83,25 @@ impl Token { Token::Number(_l, _) | Token::Constant(_l, _, _) => panic!(), + _ => panic!() + } + } + #[inline(always)] + pub fn get_mut_line_location(&mut self) -> &mut LineLocation { + match self { + Token::PreNumber(l, _) | + Token::PreWord(l, _) | + Token::PreOperator(l, _) | + Token::PreGroupStart(l) | + Token::PreGroupEnd(l) | + Token::PreGroup(l, _) + => l, + // These have a line location, but we shouldn't ever need to get it. + Token::Number(_l, _) | + Token::Constant(_l, _, _) + => panic!(), _ => panic!() } } @@ -261,6 +278,7 @@ pub enum ParserError { 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)?; @@ -274,7 +292,7 @@ pub fn substitute(s: &String) -> String{ let mut new_s = s.clone(); let tokens = p_tokenize(s); - let subs = p_find_subs(tokens); + let (subs, _) = p_find_subs(tokens); for r in subs.iter() { new_s.replace_range( diff --git a/src/parser/find_subs.rs b/src/parser/find_subs.rs index 7a2e0ac..06ad1a8 100644 --- a/src/parser/find_subs.rs +++ b/src/parser/find_subs.rs @@ -7,60 +7,80 @@ use crate::parser::LineLocation; pub fn p_find_subs( mut g: VecDeque, -) -> Vec<(LineLocation, String)> { +) -> ( + Vec<(LineLocation, String)>, + VecDeque +) { + // Array of replacements let mut r: Vec<(LineLocation, String)> = Vec::with_capacity(8); + // New token array, with updated locations + let mut n: VecDeque = VecDeque::with_capacity(g.len()); + + let mut offset: usize = 0; + while g.len() > 0 { // Read in reverse. Very important! - let t = g.pop_back().unwrap(); + let mut t = g.pop_back().unwrap(); - match &t { - - Token::PreOperator(l, o) => { + let target: Option<&str> = match &mut t { + Token::PreOperator(_, o) => { match o { - Operator::Multiply => { r.push((l.clone(), String::from("×"))); }, - Operator::Divide => { r.push((l.clone(), String::from("÷"))); }, - _ => {} + Operator::Multiply => {Some("×")}, + Operator::Divide => {Some("÷")}, + _ => {None} } }, - Token::PreWord(l, s) => { + Token::PreWord(_, s) => { match &s[..] { - // Greek letters - "alpha" => { r.push((l.clone(), String::from("α"))); }, - "beta" => { r.push((l.clone(), String::from("β"))); }, - "gamma" => { r.push((l.clone(), String::from("γ"))); }, - "delta" => { r.push((l.clone(), String::from("δ"))); }, - "epsilon" => { r.push((l.clone(), String::from("ε"))); }, - "zeta" => { r.push((l.clone(), String::from("ζ"))); }, - "eta" => { r.push((l.clone(), String::from("η"))); }, - "theta" => { r.push((l.clone(), String::from("θ"))); }, - "iota" => { r.push((l.clone(), String::from("ι"))); }, - //"kappa" => { r.push((l.clone(), String::from("κ"))); }, - "lambda" => { r.push((l.clone(), String::from("λ"))); }, - "mu" => { r.push((l.clone(), String::from("μ"))); }, - "nu" => { r.push((l.clone(), String::from("ν"))); }, - "xi" => { r.push((l.clone(), String::from("ξ"))); }, - //"omicron" => { r.push((l.clone(), String::from("ο"))); }, - "pi" => { r.push((l.clone(), String::from("π"))); }, - "rho" => { r.push((l.clone(), String::from("ρ"))); }, - "sigma" => { r.push((l.clone(), String::from("σ"))); }, - "tau" => { r.push((l.clone(), String::from("τ"))); }, - //"upsilon" => { r.push((l.clone(), String::from("υ"))); }, - "phi" => { r.push((l.clone(), String::from("φ"))); }, - "chi" => { r.push((l.clone(), String::from("χ"))); }, - "psi" => { r.push((l.clone(), String::from("ψ"))); }, - "omega" => { r.push((l.clone(), String::from("ω"))); } + "alpha" => {Some("α")}, + "beta" => {Some("β")}, + "gamma" => {Some("γ")}, + "delta" => {Some("δ")}, + "epsilon" => {Some("ε")}, + "zeta" => {Some("ζ")}, + "eta" => {Some("η")}, + "theta" => {Some("θ")}, + "iota" => {Some("ι")}, + "kappa" => {Some("κ")}, + "lambda" => {Some("λ")}, + "mu" => {Some("μ")}, + "nu" => {Some("ν")}, + "xi" => {Some("ξ")}, + "omicron" => {Some("ο")}, + "pi" => {Some("π")}, + "rho" => {Some("ρ")}, + "sigma" => {Some("σ")}, + "tau" => {Some("τ")}, + "upsilon" => {Some("υ")}, + "phi" => {Some("φ")}, + "chi" => {Some("χ")}, + "psi" => {Some("ψ")}, + "omega" => {Some("ω")} - _ => {} + _ => {None} } + }, - } - _ => {} + _ => {None} + }; + + if target.is_none() { + // Even if nothing changed, we need to update token location + let l = t.get_mut_line_location(); + *l = LineLocation{pos: l.pos - offset, len: l.len}; + } else { + let target = target.unwrap(); + let l = t.get_mut_line_location(); + r.push((l.clone(), String::from(target))); + *l = LineLocation{ pos: l.pos - offset, len: target.chars().count()}; + offset += l.len - target.chars().count(); } + n.push_front(t); } - return r; + return (r, n); } \ No newline at end of file