From daa0399e7e1fb9e57fc74865a8f4899fbe121b05 Mon Sep 17 00:00:00 2001 From: Robert Lucas Date: Tue, 9 Apr 2024 19:23:48 +0100 Subject: [PATCH] Continued nom parser implementation --- src/root/nom_parser/parse.rs | 2 +- .../parse_function/parse_evaluable.rs | 103 ++++++++++++++---- .../parse_function/parse_operator.rs | 50 ++++++++- 3 files changed, 127 insertions(+), 28 deletions(-) diff --git a/src/root/nom_parser/parse.rs b/src/root/nom_parser/parse.rs index fe45bc7..f573ad0 100644 --- a/src/root/nom_parser/parse.rs +++ b/src/root/nom_parser/parse.rs @@ -16,7 +16,7 @@ pub type ErrorTree<'a> = GenericErrorTree< Box, >; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Location { path: Rc, offset: usize, diff --git a/src/root/nom_parser/parse_function/parse_evaluable.rs b/src/root/nom_parser/parse_function/parse_evaluable.rs index 26f04e0..b197123 100644 --- a/src/root/nom_parser/parse_function/parse_evaluable.rs +++ b/src/root/nom_parser/parse_function/parse_evaluable.rs @@ -1,3 +1,4 @@ +use b_box::b; use either::Either; use nom::branch::alt; use nom::character::complete::{char, multispace0}; @@ -93,7 +94,31 @@ pub fn parse_evaluable(s: Span, semicolon_terminated: bool) -> ParseResult, OperatorToken, Box), + Prefix(OperatorToken, Box), + Value(usize) + } + + fn parse_prefix(section: &[(usize, TempEvaluableTokens)]) -> ParseResult<&[(usize, TempEvaluableTokens)], TempOperation> { + let TempEvaluableTokens::Operator(operator) = §ion[0].1 else { panic!() }; + + if section.len() < 2 { + todo!() + } + + let (remaining, operand) = match §ion[1] { + (p, TempEvaluableTokens::EvaluableToken(_)) => { + (§ion[2..], TempOperation::Value(*p)) + } + (_, TempEvaluableTokens::Operator(_)) => { + parse_prefix(§ion[1..])? + } + }; + + Ok((remaining, TempOperation::Prefix(operator.clone(), Box::new(operand)))) + } + let enumerated: Vec<(usize, TempEvaluableTokens)> = evaluables.into_iter().enumerate().collect(); let mut base = None; @@ -101,12 +126,15 @@ pub fn parse_evaluable(s: Span, semicolon_terminated: bool) -> ParseResult 0 { let operator = if base.is_some() { match &enumerated_slice[0] { - (p, TempEvaluableTokens::Operator(_)) => { + (_, TempEvaluableTokens::Operator(op)) => { + operator_priority.push(op.get_priority_t()); enumerated_slice = &enumerated_slice[1..]; - Some(*p) + Some(op.clone()) } (_, TempEvaluableTokens::EvaluableToken(_)) => { // ? Expected infix connecting operator @@ -138,34 +166,65 @@ pub fn parse_evaluable(s: Span, semicolon_terminated: bool) -> ParseResult, usize, Box), - Prefix(usize, Box), - Value(usize) -} + for priority in operator_priority { + for (pos, (op, _)) in after.iter().map(|x| x.as_ref().unwrap()).enumerate() { + if op.get_priority_t() != priority { continue; } -fn parse_prefix(section: &[(usize, TempEvaluableTokens)]) -> ParseResult<&[(usize, TempEvaluableTokens)], TempOperation> { - let operator = section[0].0; + if pos == 0 { + let (op, rhs) = after.remove(pos).unwrap(); + base = Some(TempOperation::Infix(b!(base.unwrap()), op, b!(rhs))) + } + else { + let (op, rhs) = after.remove(pos).unwrap(); + let (lop, base) = after[pos-1].take().unwrap(); + after[pos-1] = Some((lop, TempOperation::Infix(b!(base), op, b!(rhs)))); + } - if section.len() < 2 { - todo!() + break; + } } - let (remaining, operand) = match §ion[1] { - (p, TempEvaluableTokens::EvaluableToken(_)) => { - (§ion[2..], TempOperation::Value(*p)) + debug_assert!(after.is_empty()); + + let mut evaluables: Vec<_> = evaluables.into_iter().map(|e| Some(e)).collect(); + + + fn recursively_convert_temp(base: TempOperation, evaluables: &mut Vec>) -> EvaluableToken { + fn not_operator(te: TempEvaluableTokens) -> EvaluableToken { + match te { + TempEvaluableTokens::EvaluableToken(e) => {e} + TempEvaluableTokens::Operator(_) => {panic!()} + } } - (_, TempEvaluableTokens::Operator(_)) => { - parse_prefix(§ion[1..])? + + match base { + TempOperation::Infix(lhs, op, rhs) => { + let lhs = recursively_convert_temp(lhs.into(), evaluables); + EvaluableToken { + location: lhs.location.clone(), + token: EvaluableTokens::InfixOperator( + b!(lhs), + op, + b!(recursively_convert_temp(rhs.into(), evaluables)) + ), + } + + } + TempOperation::Prefix(_, _) => { + + } + TempOperation::Value(p) => { + not_operator(evaluables[p].take().unwrap()) + + } } - }; + } - Ok((remaining, TempOperation::Prefix(operator, Box::new(operand)))) + Ok((s, recursively_convert_temp(base.unwrap(), &mut evaluables))) } \ No newline at end of file diff --git a/src/root/nom_parser/parse_function/parse_operator.rs b/src/root/nom_parser/parse_function/parse_operator.rs index 6d73a21..7462fbb 100644 --- a/src/root/nom_parser/parse_function/parse_operator.rs +++ b/src/root/nom_parser/parse_function/parse_operator.rs @@ -8,24 +8,64 @@ use crate::root::nom_parser::parse::{Location, ParseResult, Span, ErrorTree}; const OPERATOR_MAPS: [(&str, OperatorTokens, bool); 3] = [ - ("+", OperatorTokens::Add, true), - ("-", OperatorTokens::Subtract, true), - ("!", OperatorTokens::Not, false) + ("+", OperatorTokens::Add, false), + ("-", OperatorTokens::Subtract, false), + ("!", OperatorTokens::Not, true) ]; -#[derive(Debug)] + +// TODO: Implement functionally +pub fn is_prefix_op(operator: &OperatorTokens) -> bool { + for (_, op, prefix) in &OPERATOR_MAPS { + if operator == op { + return *prefix; + } + } + panic!() +} + +pub fn get_priority(operator: &OperatorTokens) -> usize { + for (p, (_, op, _)) in OPERATOR_MAPS.iter().enumerate() { + if operator == op { + return p; + } + } + panic!() +} + +#[derive(Debug, Clone)] pub struct OperatorToken { location: Location, operator: OperatorTokens, } -#[derive(Debug)] +impl OperatorToken { + pub fn is_prefix_opt_t(&self) -> bool { + is_prefix_op(&self.operator) + } + + pub fn get_priority_t(&self) -> usize { + get_priority(&self.operator) + } +} + +#[derive(Debug, Eq, PartialEq, Clone)] pub enum OperatorTokens { Add, Subtract, Not } +impl OperatorTokens { + pub fn is_prefix_opt_t(&self) -> bool { + is_prefix_op(&self) + } + + pub fn get_priority_t(&self) -> usize { + get_priority(&self) + } +} + pub fn parse_operator(s: Span) -> ParseResult { for (operator, token, _) in OPERATOR_MAPS { if let Ok((s, x)) = tag::<_, _, ErrorTree>(operator)(s) {