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 090518b commit 45f21ea
Show file tree
Hide file tree
Showing 13 changed files with 157 additions and 39 deletions.
4 changes: 2 additions & 2 deletions src/root/nom_parser/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use std::rc::Rc;

pub type Span<'a> = LocatedSpan<&'a str, &'a Rc<PathBuf>>;

pub type ParseResult<'a, I = Span<'a>, O = Span<'a>, E = TypeErrorTree<'a>> = IResult<I, O, E>;
pub type TypeErrorTree<'a> = GenericErrorTree<
pub type ParseResult<'a, I = Span<'a>, O = Span<'a>, E = ErrorTree<'a>> = IResult<I, O, E>;
pub type ErrorTree<'a> = GenericErrorTree<
Span<'a>,
&'static str,
&'static str,
Expand Down
4 changes: 2 additions & 2 deletions src/root/nom_parser/parse_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -51,7 +51,7 @@ pub fn parse_function(s: Span) -> ParseResult<Span, FunctionToken> {

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))
Expand Down
3 changes: 2 additions & 1 deletion src/root/nom_parser/parse_function/base.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
131 changes: 121 additions & 10 deletions src/root/nom_parser/parse_function/parse_evaluable.rs
Original file line number Diff line number Diff line change
@@ -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<EvaluableToken>, OperatorToken, Box<EvaluableToken>),
PrefixOperator(OperatorToken, Box<EvaluableToken>),
}



#[derive(Debug)]
enum LiteralTokens {
Bool(bool),
Expand All @@ -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<Span, EvaluableToken> {
Expand All @@ -44,17 +44,128 @@ pub fn parse_evaluable(s: Span, semicolon_terminated: bool) -> ParseResult<Span,
loop {
let (ns, _) = multispace0(s)?;

if semicolon_terminated {
if let Ok((ns, _)) = char::<_, ErrorTree>(';')(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<TempOperation>, usize, Box<TempOperation>),
Prefix(usize, Box<TempOperation>),
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 &section[1] {
(p, TempEvaluableTokens::EvaluableToken(_)) => {
(&section[2..], TempOperation::Value(*p))
}
(_, TempEvaluableTokens::Operator(_)) => {
parse_prefix(&section[1..])?
}
};

Ok((remaining, TempOperation::Prefix(operator, Box::new(operand))))
}
6 changes: 3 additions & 3 deletions src/root/nom_parser/parse_function/parse_if.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -40,15 +40,15 @@ pub fn parse_if(s: Span) -> ParseResult<Span, IfToken> {

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 {
s = ns;
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)?;
Expand Down
2 changes: 1 addition & 1 deletion src/root/nom_parser/parse_function/parse_initialisation.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down
4 changes: 2 additions & 2 deletions src/root/nom_parser/parse_function/parse_line.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -56,6 +56,6 @@ pub fn parse_line(s: Span) -> ParseResult<Span, LineTokens> {
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!())
}
}
27 changes: 16 additions & 11 deletions src/root/nom_parser/parse_function/parse_operator.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand All @@ -25,12 +27,15 @@ pub enum OperatorTokens {
}

pub fn parse_operator(s: Span) -> ParseResult<Span, OperatorToken> {
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()
)
))
}
2 changes: 1 addition & 1 deletion src/root/nom_parser/parse_function/parse_return.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down
2 changes: 1 addition & 1 deletion src/root/nom_parser/parse_function/parse_while.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
7 changes: 4 additions & 3 deletions src/root/nom_parser/parse_name.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -19,6 +19,7 @@ pub struct NameToken {
function_call: Option<Vec<EvaluableToken>>,
}


pub fn parse_full_name(s: Span) -> ParseResult<Span, NameToken> {
// TODO: Handle function calls

Expand Down Expand Up @@ -66,15 +67,15 @@ 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),
}));
}
}

if n.is_empty() {
Err(Error(TypeErrorTree::Base {
Err(Error(ErrorTree::Base {
location: s,
kind: BaseErrorKind::Expected(Expectation::Alpha),
}))
Expand Down
2 changes: 1 addition & 1 deletion src/root/nom_parser/parse_struct.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down
2 changes: 1 addition & 1 deletion src/root/nom_parser/parse_util.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down

0 comments on commit 45f21ea

Please sign in to comment.