Skip to content

Commit

Permalink
Continued nom parser implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert Lucas committed Apr 9, 2024
1 parent 45f21ea commit daa0399
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 28 deletions.
2 changes: 1 addition & 1 deletion src/root/nom_parser/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub type ErrorTree<'a> = GenericErrorTree<
Box<dyn std::error::Error + Send + Sync + 'static>,
>;

#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct Location {
path: Rc<PathBuf>,
offset: usize,
Expand Down
103 changes: 81 additions & 22 deletions src/root/nom_parser/parse_function/parse_evaluable.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use b_box::b;
use either::Either;
use nom::branch::alt;
use nom::character::complete::{char, multispace0};
Expand Down Expand Up @@ -93,20 +94,47 @@ pub fn parse_evaluable(s: Span, semicolon_terminated: bool) -> ParseResult<Span,
s = ns;
}

// * Process prefix operators
enum TempOperation {
Infix(Box<TempOperation>, OperatorToken, Box<TempOperation>),
Prefix(OperatorToken, Box<TempOperation>),
Value(usize)
}

fn parse_prefix(section: &[(usize, TempEvaluableTokens)]) -> ParseResult<&[(usize, TempEvaluableTokens)], TempOperation> {
let TempEvaluableTokens::Operator(operator) = &section[0].1 else { panic!() };

if section.len() < 2 {
todo!()
}

let (remaining, operand) = match &section[1] {
(p, TempEvaluableTokens::EvaluableToken(_)) => {
(&section[2..], TempOperation::Value(*p))
}
(_, TempEvaluableTokens::Operator(_)) => {
parse_prefix(&section[1..])?
}
};

Ok((remaining, TempOperation::Prefix(operator.clone(), Box::new(operand))))
}

let enumerated: Vec<(usize, TempEvaluableTokens)> = evaluables.into_iter().enumerate().collect();

let mut base = None;
let mut after = Vec::new();

let mut enumerated_slice: &[(usize, TempEvaluableTokens)] = &enumerated;

let mut operator_priority = Vec::new();

while enumerated_slice.len() > 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
Expand Down Expand Up @@ -138,34 +166,65 @@ pub fn parse_evaluable(s: Span, semicolon_terminated: bool) -> ParseResult<Span,
base = Some(value);
}
else {
after.push((operator.unwrap(), value));
after.push(Some((operator.unwrap(), value)));
}
}

todo!()
}
operator_priority.sort();

enum TempOperation {
Infix(Box<TempOperation>, usize, Box<TempOperation>),
Prefix(usize, Box<TempOperation>),
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 &section[1] {
(p, TempEvaluableTokens::EvaluableToken(_)) => {
(&section[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<Option<TempEvaluableTokens>>) -> EvaluableToken {
fn not_operator(te: TempEvaluableTokens) -> EvaluableToken {
match te {
TempEvaluableTokens::EvaluableToken(e) => {e}
TempEvaluableTokens::Operator(_) => {panic!()}
}
}
(_, TempEvaluableTokens::Operator(_)) => {
parse_prefix(&section[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)))
}
50 changes: 45 additions & 5 deletions src/root/nom_parser/parse_function/parse_operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Span, OperatorToken> {
for (operator, token, _) in OPERATOR_MAPS {
if let Ok((s, x)) = tag::<_, _, ErrorTree>(operator)(s) {
Expand Down

0 comments on commit daa0399

Please sign in to comment.