diff --git a/src/root/nom_parser/parse.rs b/src/root/nom_parser/parse.rs index 02d62b8..fe45bc7 100644 --- a/src/root/nom_parser/parse.rs +++ b/src/root/nom_parser/parse.rs @@ -8,8 +8,8 @@ use std::rc::Rc; pub type Span<'a> = LocatedSpan<&'a str, &'a Rc>; -pub type ParseResult<'a, I = Span<'a>, O = Span<'a>, E = TypeErrorTree<'a>> = IResult; -pub type TypeErrorTree<'a> = GenericErrorTree< +pub type ParseResult<'a, I = Span<'a>, O = Span<'a>, E = ErrorTree<'a>> = IResult; +pub type ErrorTree<'a> = GenericErrorTree< Span<'a>, &'static str, &'static str, diff --git a/src/root/nom_parser/parse_function.rs b/src/root/nom_parser/parse_function.rs index 1af7652..469062e 100644 --- a/src/root/nom_parser/parse_function.rs +++ b/src/root/nom_parser/parse_function.rs @@ -4,7 +4,7 @@ use nom::Parser; use nom_supreme::tag::complete::tag; use substring::Substring; -use crate::root::nom_parser::parse::{Location, ParseResult, Span, TypeErrorTree}; +use crate::root::nom_parser::parse::{Location, ParseResult, Span, ErrorTree}; use crate::root::nom_parser::parse_blocks::{braced_section, bracketed_section}; use crate::root::nom_parser::parse_function::parse_line::{parse_lines, LineTokens}; use crate::root::nom_parser::parse_name::{parse_full_name, parse_simple_name, NameToken}; @@ -51,7 +51,7 @@ pub fn parse_function(s: Span) -> ParseResult { let (s, _) = multispace0(s)?; - let (s, return_type) = if let Ok((s, _)) = tag::<_, _, TypeErrorTree>("->")(s) { + let (s, return_type) = if let Ok((s, _)) = tag::<_, _, ErrorTree>("->")(s) { let (s, _) = multispace0(s)?; let (s, return_type) = parse_full_name(s)?; (multispace0(s)?.0, Some(return_type)) diff --git a/src/root/nom_parser/parse_function/base.rs b/src/root/nom_parser/parse_function/base.rs index ad2fb53..fdd78c3 100644 --- a/src/root/nom_parser/parse_function/base.rs +++ b/src/root/nom_parser/parse_function/base.rs @@ -1,5 +1,6 @@ use crate::root::nom_parser::parse::Location; -use crate::root::nom_parser::parse_function::parse_evaluable::{EvaluableToken, OperatorTokens}; +use crate::root::nom_parser::parse_function::parse_evaluable::{EvaluableToken}; +use crate::root::nom_parser::parse_function::parse_operator::OperatorTokens; #[derive(Debug)] struct AssignmentOperatorToken { diff --git a/src/root/nom_parser/parse_function/parse_evaluable.rs b/src/root/nom_parser/parse_function/parse_evaluable.rs index b67ea08..26f04e0 100644 --- a/src/root/nom_parser/parse_function/parse_evaluable.rs +++ b/src/root/nom_parser/parse_function/parse_evaluable.rs @@ -1,29 +1,29 @@ -use nom::character::complete::multispace0; +use either::Either; +use nom::branch::alt; +use nom::character::complete::{char, multispace0}; +use nom_supreme::error::GenericErrorTree; use crate::root::ast::operators::Operator; -use crate::root::nom_parser::parse::{Location, ParseResult, Span}; +use crate::root::nom_parser::parse::{ErrorTree, Location, ParseResult, Span}; use crate::root::nom_parser::parse_blocks::braced_section; use crate::root::nom_parser::parse_function::FunctionToken; -use crate::root::nom_parser::parse_function::parse_operator::OperatorToken; -use crate::root::nom_parser::parse_name::NameToken; +use crate::root::nom_parser::parse_function::parse_operator::{OperatorToken, parse_operator}; +use crate::root::nom_parser::parse_name::{NameToken, parse_full_name}; use crate::root::nom_parser::parse_parameters::Parameters; #[derive(Debug)] pub struct EvaluableToken { location: Location, - tokens: EvaluableTokens, + token: EvaluableTokens, } #[derive(Debug)] enum EvaluableTokens { Name(NameToken), Literal(LiteralTokens), - FunctionCall(NameToken, Parameters), InfixOperator(Box, OperatorToken, Box), PrefixOperator(OperatorToken, Box), } - - #[derive(Debug)] enum LiteralTokens { Bool(bool), @@ -33,7 +33,7 @@ enum LiteralTokens { #[derive(Debug)] enum TempEvaluableTokens { EvaluableToken(EvaluableToken), - Operator(Operator) + Operator(OperatorToken) } pub fn parse_evaluable(s: Span, semicolon_terminated: bool) -> ParseResult { @@ -44,17 +44,128 @@ pub fn parse_evaluable(s: Span, semicolon_terminated: bool) -> ParseResult(';')(ns) { + s = ns; + break; + } + } + + if ns.is_empty() { + // Fail if semicolon required but ns is empty + if semicolon_terminated { + // ! Intentional failure + char(';')(ns)?; + unreachable!(); + } + + s = ns; + break; + } + let ns = if let Ok((ns, _)) = braced_section(s) { let (ns, evaluable) = parse_evaluable(ns, false)?; evaluables.push(TempEvaluableTokens::EvaluableToken(evaluable)); ns } else { - todo!() + let (ns, token) = alt(( + |x| parse_operator(x).map(|(s, t)| (s, TempEvaluableTokens::Operator(t))), + |x| parse_full_name(x) + .map(|(s, t)| + ( + s, + TempEvaluableTokens::EvaluableToken( + EvaluableToken { + location: Location::from_span(x), + token: EvaluableTokens::Name( + t + ) + } + ) + ) + ) + ))(ns)?; + evaluables.push(token); + ns }; s = ns; } + // * Process prefix operators + 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; + + while enumerated_slice.len() > 0 { + let operator = if base.is_some() { + match &enumerated_slice[0] { + (p, TempEvaluableTokens::Operator(_)) => { + enumerated_slice = &enumerated_slice[1..]; + Some(*p) + } + (_, TempEvaluableTokens::EvaluableToken(_)) => { + // ? Expected infix connecting operator + todo!() + } + } + } else { + None + }; + + let value = match &enumerated_slice[0] { + (p, TempEvaluableTokens::EvaluableToken(_)) => { + enumerated_slice = &enumerated_slice[1..]; + TempOperation::Value(*p) + } + (_, TempEvaluableTokens::Operator(_)) => { + let (new_slice, value) = match parse_prefix(enumerated_slice) { + Ok(r) => { + r + } + Err(_) => { todo!() } + }; + enumerated_slice = new_slice; + value + } + }; + + if base.is_none() { + base = Some(value); + } + else { + after.push((operator.unwrap(), value)); + } + } + todo!() } + +enum TempOperation { + Infix(Box, usize, Box), + Prefix(usize, Box), + Value(usize) +} + +fn parse_prefix(section: &[(usize, TempEvaluableTokens)]) -> ParseResult<&[(usize, TempEvaluableTokens)], TempOperation> { + let operator = section[0].0; + + 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, Box::new(operand)))) +} \ No newline at end of file diff --git a/src/root/nom_parser/parse_function/parse_if.rs b/src/root/nom_parser/parse_function/parse_if.rs index fb560c2..cc3f300 100644 --- a/src/root/nom_parser/parse_function/parse_if.rs +++ b/src/root/nom_parser/parse_function/parse_if.rs @@ -2,7 +2,7 @@ use nom::character::complete::{multispace0, multispace1}; use nom::sequence::Tuple; use nom_supreme::tag::complete::tag; -use crate::root::nom_parser::parse::{Location, ParseResult, Span, TypeErrorTree}; +use crate::root::nom_parser::parse::{Location, ParseResult, Span, ErrorTree}; use crate::root::nom_parser::parse_blocks::bracketed_section; use crate::root::nom_parser::parse_function::parse_evaluable::{EvaluableToken, parse_evaluable}; use crate::root::nom_parser::parse_function::parse_line::{LineTestFn, LineTokens, parse_lines}; @@ -40,7 +40,7 @@ pub fn parse_if(s: Span) -> ParseResult { if ns.is_empty() { break; } - let ns = if let Ok((ns, _)) = tag::<_, _, TypeErrorTree>("else")(ns) { + let ns = if let Ok((ns, _)) = tag::<_, _, ErrorTree>("else")(ns) { ns } else { @@ -48,7 +48,7 @@ pub fn parse_if(s: Span) -> ParseResult { break; }; - let (ns, condition) = if let Ok((ns, _)) = (multispace1::<_, TypeErrorTree>, tag("if")).parse(ns) { + let (ns, condition) = if let Ok((ns, _)) = (multispace1::<_, ErrorTree>, tag("if")).parse(ns) { let (ns, _) = multispace0(ns)?; let (ns, content) = bracketed_section(ns)?; let (_, condition) = parse_evaluable(content, false)?; diff --git a/src/root/nom_parser/parse_function/parse_initialisation.rs b/src/root/nom_parser/parse_function/parse_initialisation.rs index 6d1892b..ae04a52 100644 --- a/src/root/nom_parser/parse_function/parse_initialisation.rs +++ b/src/root/nom_parser/parse_function/parse_initialisation.rs @@ -1,4 +1,4 @@ -use crate::root::nom_parser::parse::{Location, ParseResult, Span, TypeErrorTree}; +use crate::root::nom_parser::parse::{Location, ParseResult, Span, ErrorTree}; use crate::root::nom_parser::parse_function::parse_break::parse_break; use crate::root::nom_parser::parse_function::parse_evaluable::{parse_evaluable, EvaluableToken}; use crate::root::nom_parser::parse_function::parse_line::{LineTestFn, LineTokens}; diff --git a/src/root/nom_parser/parse_function/parse_line.rs b/src/root/nom_parser/parse_function/parse_line.rs index 9c47a77..80314b8 100644 --- a/src/root/nom_parser/parse_function/parse_line.rs +++ b/src/root/nom_parser/parse_function/parse_line.rs @@ -1,4 +1,4 @@ -use crate::root::nom_parser::parse::{ParseResult, Span}; +use crate::root::nom_parser::parse::{ErrorTree, ParseResult, Span}; use crate::root::nom_parser::parse_function::base::AssignmentToken; use crate::root::nom_parser::parse_function::parse_break::{test_parse_break, BreakToken}; use crate::root::nom_parser::parse_function::parse_evaluable::{parse_evaluable, EvaluableToken}; @@ -56,6 +56,6 @@ pub fn parse_line(s: Span) -> ParseResult { parser(s) } else { // ? Default case is evaluable - parse_evaluable(s, true).map(|(s, e)| (s, LineTokens::NoOp(e))) + parse_evaluable(s, true).map(|(s, e)| (s, LineTokens::NoOp(e))).map_err(|e| todo!()) } } diff --git a/src/root/nom_parser/parse_function/parse_operator.rs b/src/root/nom_parser/parse_function/parse_operator.rs index babc38a..6d73a21 100644 --- a/src/root/nom_parser/parse_function/parse_operator.rs +++ b/src/root/nom_parser/parse_function/parse_operator.rs @@ -1,14 +1,16 @@ -use nom::branch::alt; -use nom::bytes::complete::tag; use nom::Err::Error; +use nom::error::{ErrorKind, ParseError}; use nom::Parser; use nom_supreme::error::GenericErrorTree; -use crate::root::nom_parser::parse::{Location, ParseResult, Span}; +use nom_supreme::tag::complete::tag; +use nom_supreme::tag::TagError; +use crate::root::nom_parser::parse::{Location, ParseResult, Span, ErrorTree}; -const OPERATOR_MAPS: [(&str, OperatorTokens); 3] = [ - ("+", OperatorTokens::Add), - ("-", OperatorTokens::Subtract), - ("!", OperatorTokens::Not) + +const OPERATOR_MAPS: [(&str, OperatorTokens, bool); 3] = [ + ("+", OperatorTokens::Add, true), + ("-", OperatorTokens::Subtract, true), + ("!", OperatorTokens::Not, false) ]; #[derive(Debug)] @@ -25,12 +27,15 @@ pub enum OperatorTokens { } pub fn parse_operator(s: Span) -> ParseResult { - for (operator, token) in OPERATOR_MAPS { - if let Ok((s, x)) = tag(operator)(s) { + for (operator, token, _) in OPERATOR_MAPS { + if let Ok((s, x)) = tag::<_, _, ErrorTree>(operator)(s) { return Ok((s, OperatorToken { location: Location::from_span(x), operator: token })) } } - - todo!() + Err(Error( + GenericErrorTree::Alt( + OPERATOR_MAPS.iter().map(|(t, _, _)| GenericErrorTree::from_tag(s, *t)).collect() + ) + )) } diff --git a/src/root/nom_parser/parse_function/parse_return.rs b/src/root/nom_parser/parse_function/parse_return.rs index 40f96e9..3756d3c 100644 --- a/src/root/nom_parser/parse_function/parse_return.rs +++ b/src/root/nom_parser/parse_function/parse_return.rs @@ -2,7 +2,7 @@ use nom::character::complete::multispace1; use nom::sequence::Tuple; use nom_supreme::tag::complete::tag; -use crate::root::nom_parser::parse::{Location, ParseResult, Span}; +use crate::root::nom_parser::parse::{ErrorTree, Location, ParseResult, Span}; use crate::root::nom_parser::parse_function::parse_evaluable::{parse_evaluable, EvaluableToken}; use crate::root::nom_parser::parse_function::parse_line::{LineTestFn, LineTokens}; diff --git a/src/root/nom_parser/parse_function/parse_while.rs b/src/root/nom_parser/parse_function/parse_while.rs index b236e24..4afc031 100644 --- a/src/root/nom_parser/parse_function/parse_while.rs +++ b/src/root/nom_parser/parse_function/parse_while.rs @@ -3,7 +3,7 @@ use nom::sequence::Tuple; use nom::Parser; use nom_supreme::tag::complete::tag; -use crate::root::nom_parser::parse::{Location, ParseResult, Span, TypeErrorTree}; +use crate::root::nom_parser::parse::{Location, ParseResult, Span, ErrorTree}; use crate::root::nom_parser::parse_blocks::bracketed_section; use crate::root::nom_parser::parse_function::parse_evaluable::{parse_evaluable, EvaluableToken}; use crate::root::nom_parser::parse_function::parse_line::{parse_lines, LineTestFn, LineTokens}; diff --git a/src/root/nom_parser/parse_name.rs b/src/root/nom_parser/parse_name.rs index 8301c2a..f91b30e 100644 --- a/src/root/nom_parser/parse_name.rs +++ b/src/root/nom_parser/parse_name.rs @@ -1,4 +1,4 @@ -use crate::root::nom_parser::parse::{Location, ParseResult, Span, TypeErrorTree}; +use crate::root::nom_parser::parse::{Location, ParseResult, Span, ErrorTree}; use crate::root::nom_parser::parse_function::parse_evaluable::EvaluableToken; use nom::bytes::complete::take_till; use nom::Err::Error; @@ -19,6 +19,7 @@ pub struct NameToken { function_call: Option>, } + pub fn parse_full_name(s: Span) -> ParseResult { // TODO: Handle function calls @@ -66,7 +67,7 @@ pub fn parse_simple_name(s: Span) -> ParseResult { if let Some(first) = s.chars().next() { if first.is_ascii_digit() { - return Err(Error(TypeErrorTree::Base { + return Err(Error(ErrorTree::Base { location: s, kind: BaseErrorKind::Expected(Expectation::Space), })); @@ -74,7 +75,7 @@ pub fn parse_simple_name(s: Span) -> ParseResult { } if n.is_empty() { - Err(Error(TypeErrorTree::Base { + Err(Error(ErrorTree::Base { location: s, kind: BaseErrorKind::Expected(Expectation::Alpha), })) diff --git a/src/root/nom_parser/parse_struct.rs b/src/root/nom_parser/parse_struct.rs index ecde23f..079573f 100644 --- a/src/root/nom_parser/parse_struct.rs +++ b/src/root/nom_parser/parse_struct.rs @@ -1,4 +1,4 @@ -use crate::root::nom_parser::parse::{Location, ParseResult, Span, TypeErrorTree}; +use crate::root::nom_parser::parse::{Location, ParseResult, Span, ErrorTree}; use crate::root::nom_parser::parse_blocks::braced_section; use crate::root::nom_parser::parse_name::{parse_simple_name, NameToken}; use crate::root::nom_parser::parse_parameters::{parse_parameters, Parameters}; diff --git a/src/root/nom_parser/parse_util.rs b/src/root/nom_parser/parse_util.rs index 8f80b23..67fe2f5 100644 --- a/src/root/nom_parser/parse_util.rs +++ b/src/root/nom_parser/parse_util.rs @@ -1,4 +1,4 @@ -use crate::root::nom_parser::parse::{ParseResult, Span, TypeErrorTree}; +use crate::root::nom_parser::parse::{ParseResult, Span, ErrorTree}; use crate::root::nom_parser::parse_comments; use nom::bytes::complete::{take_till, take_while}; use nom::error::ParseError;