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 7, 2024
1 parent 487b1ac commit 6f111ed
Show file tree
Hide file tree
Showing 10 changed files with 204 additions and 22 deletions.
5 changes: 1 addition & 4 deletions parse_test.why
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
struct A {
a: A::B.C
}

structs
3 changes: 2 additions & 1 deletion src/root/nom_parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ mod parse_comments;
mod parse_blocks;
mod parse_parameters;
mod parse_name;
mod parse_arguments;
mod parse_arguments;
mod soft_alt;
23 changes: 21 additions & 2 deletions src/root/nom_parser/parse_function.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
pub mod base;
mod parse_line;
mod parse_break;
mod parse_evaluable;
pub(crate) mod parse_evaluable;
mod parse_return;

use nom::character::complete::char;
use nom::Err::Error;
use nom_supreme::tag::complete::tag;
use nom::Parser;
use nom_supreme::error::{BaseErrorKind, Expectation};
use crate::root::nom_parser::parse::{Location, ParseResult, Span, TypeErrorTree};
use crate::root::nom_parser::parse_blocks::{braced_section, bracketed_section};
use parse_line::parse_line;
use crate::root::nom_parser::parse_function::parse_line::LineTokens;
use crate::root::nom_parser::parse_impl::parse_impl;
use crate::root::nom_parser::parse_name::{NameToken, parse_full_name, parse_simple_name};
use crate::root::nom_parser::parse_parameters::{Parameters, parse_parameters};
use crate::root::nom_parser::parse_struct::StructToken;
use crate::root::nom_parser::parse_toplevel::TopLevelTokens;
use crate::root::nom_parser::parse_toplevel::{ToplevelTestFn, TopLevelTokens};
use crate::root::nom_parser::parse_util::{discard_ignored, require_ignored};

#[derive(Debug)]
Expand All @@ -26,6 +29,22 @@ pub struct FunctionToken {
lines: Vec<LineTokens>
}

pub fn test_parse_function<'a>(s: Span) -> ParseResult<Span, ToplevelTestFn<'a>> {
if s.len() >= 2 && &s[..2] == "fn" {
Ok((s, |x| parse_function(x).map(|(s, f)| (s, TopLevelTokens::Function(f)))))
}
else {
Err(Error(
TypeErrorTree::Base {
location: s,
kind: BaseErrorKind::Expected(
Expectation::Tag("fn")
),
}
))
}
}

pub fn parse_function(s: Span) -> ParseResult<Span, FunctionToken> {
let location = Location::from_span(s);
let (s, _) = tag("fn").parse(s)?;
Expand Down
4 changes: 2 additions & 2 deletions src/root/nom_parser/parse_function/parse_evaluable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ enum EvaluableTokens {
Name(NameToken),
Literal(LiteralTokens),
FunctionCall(NameToken, Parameters),
InfixOperator(EvaluableToken, OperatorToken, EvaluableToken),
PrefixOperator(OperatorToken, EvaluableToken)
InfixOperator(Box<EvaluableToken>, OperatorToken, Box<EvaluableToken>),
PrefixOperator(OperatorToken, Box<EvaluableToken>)
}

#[derive(Debug)]
Expand Down
2 changes: 2 additions & 0 deletions src/root/nom_parser/parse_function/parse_line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::root::nom_parser::parse::{Location, ParseResult, Span};
use crate::root::nom_parser::parse_function::base::{AssignmentToken, IfToken, InitialisationToken, WhileToken};
use crate::root::nom_parser::parse_function::parse_break::{BreakToken, parse_break};
use crate::root::nom_parser::parse_function::parse_evaluable::{EvaluableToken, parse_evaluable};
use crate::root::nom_parser::parse_function::parse_return::{parse_return, ReturnToken};

#[derive(Debug)]
pub enum LineTokens {
Expand All @@ -19,6 +20,7 @@ pub enum LineTokens {
pub fn parse_line(s: Span) -> ParseResult<Span, LineTokens> {
alt((
|x| parse_break(x).map(|(s, b)| (s, LineTokens::Break(b))),
|x| parse_return(x).map(|(s, r)| (s, LineTokens::Return(r))),
|x| parse_evaluable(x, true).map(|(s, e)| (s, LineTokens::NoOp(e))),
))
.parse(s)
Expand Down
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 @@ -10,7 +10,7 @@ pub struct ReturnToken {
return_value: EvaluableToken
}

pub fn parse_break(s: Span) -> ParseResult<Span, ReturnToken> {
pub fn parse_return(s: Span) -> ParseResult<Span, ReturnToken> {
let (s, l) = tag("return")(s)?;
let (s, _) = require_ignored(s)?;
let (s, value) = parse_evaluable(s, true)?;
Expand Down
23 changes: 20 additions & 3 deletions src/root/nom_parser/parse_impl.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use nom::Err::Error;
use nom::Parser;
use nom_supreme::error::{BaseErrorKind, Expectation};
use nom_supreme::tag::complete::tag;
use crate::root::nom_parser::parse::{Location, ParseResult, Span};
use crate::root::nom_parser::parse::{Location, ParseResult, Span, TypeErrorTree};
use crate::root::nom_parser::parse_blocks::braced_section;
use crate::root::nom_parser::parse_function::{FunctionToken, parse_function};
use crate::root::nom_parser::parse_name::parse_simple_name;
use crate::root::nom_parser::parse_parameters::parse_parameters;
use crate::root::nom_parser::parse_struct::StructToken;
use crate::root::nom_parser::parse_toplevel::TopLevelTokens;
use crate::root::nom_parser::parse_struct::{parse_struct, StructToken};
use crate::root::nom_parser::parse_toplevel::{ToplevelTestFn, TopLevelTokens};
use crate::root::nom_parser::parse_util::{discard_ignored, require_ignored};

#[derive(Debug)]
Expand All @@ -16,6 +18,21 @@ pub struct ImplToken {
functions: Vec<FunctionToken>
}

pub fn test_parse_impl<'a>(s: Span) -> ParseResult<Span, ToplevelTestFn<'a>> {
if s.len() >= 4 && &s[..4] == "impl" {
Ok((s, |x| parse_impl(x).map(|(s, i)| (s, TopLevelTokens::Impl(i)))))
}
else {
Err(Error(
TypeErrorTree::Base {
location: s,
kind: BaseErrorKind::Expected(
Expectation::Tag("impl")
),
}
))
}
}
pub fn parse_impl(s: Span) -> ParseResult<Span, ImplToken> {
let location = Location::from_span(s);
let (s, _) = tag("impl").parse(s)?;
Expand Down
22 changes: 20 additions & 2 deletions src/root/nom_parser/parse_struct.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use nom::Err::Error;
use nom_supreme::tag::complete::tag;
use nom::Parser;
use crate::root::nom_parser::parse::{Location, ParseResult, Span};
use nom_supreme::error::{BaseErrorKind, Expectation};
use crate::root::nom_parser::parse::{Location, ParseResult, Span, TypeErrorTree};
use crate::root::nom_parser::parse_blocks::braced_section;
use crate::root::nom_parser::parse_name::{NameToken, parse_simple_name};
use crate::root::nom_parser::parse_parameters::{Parameters, parse_parameters};
use crate::root::nom_parser::parse_toplevel::TopLevelTokens;
use crate::root::nom_parser::parse_toplevel::{ToplevelTestFn, TopLevelTokens};
use crate::root::nom_parser::parse_util::{discard_ignored, require_ignored};

#[derive(Debug)]
Expand All @@ -14,6 +16,22 @@ pub struct StructToken {
attributes: Parameters
}

pub fn test_parse_struct<'a>(s: Span) -> ParseResult<Span, ToplevelTestFn<'a>> {
if s.len() >= 6 && &s[..6] == "struct" {
Ok((s, |x| parse_struct(x).map(|(s, st)| (s, TopLevelTokens::Struct(st)))))
}
else {
Err(Error(
TypeErrorTree::Base {
location: s,
kind: BaseErrorKind::Expected(
Expectation::Tag("struct")
),
}
))
}
}

pub fn parse_struct(s: Span) -> ParseResult<Span, StructToken> {
let location = Location::from_span(s);
let (s, _) = tag("struct").parse(s)?;
Expand Down
18 changes: 11 additions & 7 deletions src/root/nom_parser/parse_toplevel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use nom::branch::alt;
use nom::Parser;
use crate::root::nom_parser::parse::{ParseResult, Span};
use crate::root::nom_parser::{parse_util};
use crate::root::nom_parser::parse_function::{FunctionToken, parse_function};
use crate::root::nom_parser::parse_impl::{ImplToken, parse_impl};
use crate::root::nom_parser::parse_struct::{parse_struct, StructToken};
use crate::root::nom_parser::parse_function::{FunctionToken, parse_function, test_parse_function};
use crate::root::nom_parser::parse_impl::{ImplToken, parse_impl, test_parse_impl};
use crate::root::nom_parser::parse_struct::{parse_struct, StructToken, test_parse_struct};

#[derive(Debug)]
pub enum TopLevelTokens {
Expand All @@ -13,6 +13,8 @@ pub enum TopLevelTokens {
Function(FunctionToken),
}

pub type ToplevelTestFn<'a> = fn(Span<'a>) -> ParseResult<Span<'a>, TopLevelTokens>;

pub fn parse_toplevel(s: Span) -> ParseResult<Span, Vec<TopLevelTokens>> {
let mut s = s;
let mut tokens = Vec::new();
Expand All @@ -25,13 +27,15 @@ pub fn parse_toplevel(s: Span) -> ParseResult<Span, Vec<TopLevelTokens>> {
return Ok((ns, tokens))
}

let (ns, token) = alt((
|x| parse_impl(x).map(|(s, i)| (s, TopLevelTokens::Impl(i))),
|x| parse_function(x).map(|(s, f)| (s, TopLevelTokens::Function(f))),
|x| parse_struct(x).map(|(s, st)| (s, TopLevelTokens::Struct(st))),
let (ns, parse_fn) = alt((
test_parse_struct,
test_parse_impl,
test_parse_function
))
.parse(ns)?;

let (ns, token) = parse_fn(ns)?;

tokens.push(token);

s = ns;
Expand Down
124 changes: 124 additions & 0 deletions src/root/nom_parser/soft_alt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// use nom::error::ParseError;
// use nom::{IResult, Parser};
//
// pub trait Alt<I, O, E> {
// /// Tests each parser in the tuple and returns the result of the first one that succeeds
// fn choice(&mut self, input: I) -> IResult<I, O, E>;
// }
//
// /// Tests a list of parsers one by one until one succeeds.
// ///
// /// It takes as argument a tuple of parsers. There is a maximum of 21
// /// parsers. If you need more, it is possible to nest them in other `alt` calls,
// /// like this: `alt(parser_a, alt(parser_b, parser_c))`
// ///
// /// ```rust
// /// # use nom::error_position;
// /// # use nom::{Err,error::ErrorKind, Needed, IResult};
// /// use nom::character::complete::{alpha1, digit1};
// /// use nom::branch::alt;
// /// # fn main() {
// /// fn parser(input: &str) -> IResult<&str, &str> {
// /// alt((alpha1, digit1))(input)
// /// };
// ///
// /// // the first parser, alpha1, recognizes the input
// /// assert_eq!(parser("abc"), Ok(("", "abc")));
// ///
// /// // the first parser returns an error, so alt tries the second one
// /// assert_eq!(parser("123456"), Ok(("", "123456")));
// ///
// /// // both parsers failed, and with the default error type, alt will return the last error
// /// assert_eq!(parser(" "), Err(Err::Error(error_position!(" ", ErrorKind::Digit))));
// /// # }
// /// ```
// ///
// /// With a custom error type, it is possible to have alt return the error of the parser
// /// that went the farthest in the input data
// pub fn alt<I: Clone, O, E: ParseError<I>, List: nom::branch::Alt<I, O, E>>(
// mut l: List,
// ) -> impl FnMut(I) -> IResult<I, O, E> {
// move |i: I| l.choice(i)
// }
//
// macro_rules! alt_trait(
// ($first:ident $second:ident $($id: ident)+) => (
// alt_trait!(__impl $first $second; $($id)+);
// );
// (__impl $($current:ident)*; $head:ident $($id: ident)+) => (
// alt_trait_impl!($($current)*);
//
// alt_trait!(__impl $($current)* $head; $($id)+);
// );
// (__impl $($current:ident)*; $head:ident) => (
// alt_trait_impl!($($current)*);
// alt_trait_impl!($($current)* $head);
// );
// );
//
// macro_rules! alt_trait_impl(
// ($($id:ident)+) => (
// impl<
// Input: Clone, Output, Error: ParseError<Input>,
// $($id: Parser<Input, Output, Error>),+
// > Alt<Input, Output, Error> for ( $($id),+ ) {
//
// fn choice(&mut self, input: Input) -> IResult<Input, Output, Error> {
// match self.0.parse(input.clone()) {
// Err(Err::Error(e)) => alt_trait_inner!(1, self, input, e, $($id)+),
// res => res,
// }
// }
// }
// );
// );
//
// macro_rules! alt_trait_inner(
// ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident $($id:ident)+) => (
// match $self.$it.parse($input.clone()) {
// Err(Err::Error(e)) => {
// let err = $err.or(e);
// succ!($it, alt_trait_inner!($self, $input, err, $($id)+))
// }
// res => res,
// }
// );
// ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident) => (
// Err(Err::Error(Error::append($input, ErrorKind::Alt, $err)))
// );
// );
//
// alt_trait!(A B C D E F G H I J K L M N O P Q R S T U);
//
// // Manually implement Alt for (A,), the 1-tuple type
// impl<Input, Output, Error: ParseError<Input>, A: Parser<Input, Output, Error>>
// nom::branch::Alt<Input, Output, Error> for (A,)
// {
// fn choice(&mut self, input: Input) -> IResult<Input, Output, Error> {
// self.0.parse(input)
// }
// }
//
// macro_rules! succ (
// (0, $submac:ident ! ($($rest:tt)*)) => ($submac!(1, $($rest)*));
// (1, $submac:ident ! ($($rest:tt)*)) => ($submac!(2, $($rest)*));
// (2, $submac:ident ! ($($rest:tt)*)) => ($submac!(3, $($rest)*));
// (3, $submac:ident ! ($($rest:tt)*)) => ($submac!(4, $($rest)*));
// (4, $submac:ident ! ($($rest:tt)*)) => ($submac!(5, $($rest)*));
// (5, $submac:ident ! ($($rest:tt)*)) => ($submac!(6, $($rest)*));
// (6, $submac:ident ! ($($rest:tt)*)) => ($submac!(7, $($rest)*));
// (7, $submac:ident ! ($($rest:tt)*)) => ($submac!(8, $($rest)*));
// (8, $submac:ident ! ($($rest:tt)*)) => ($submac!(9, $($rest)*));
// (9, $submac:ident ! ($($rest:tt)*)) => ($submac!(10, $($rest)*));
// (10, $submac:ident ! ($($rest:tt)*)) => ($submac!(11, $($rest)*));
// (11, $submac:ident ! ($($rest:tt)*)) => ($submac!(12, $($rest)*));
// (12, $submac:ident ! ($($rest:tt)*)) => ($submac!(13, $($rest)*));
// (13, $submac:ident ! ($($rest:tt)*)) => ($submac!(14, $($rest)*));
// (14, $submac:ident ! ($($rest:tt)*)) => ($submac!(15, $($rest)*));
// (15, $submac:ident ! ($($rest:tt)*)) => ($submac!(16, $($rest)*));
// (16, $submac:ident ! ($($rest:tt)*)) => ($submac!(17, $($rest)*));
// (17, $submac:ident ! ($($rest:tt)*)) => ($submac!(18, $($rest)*));
// (18, $submac:ident ! ($($rest:tt)*)) => ($submac!(19, $($rest)*));
// (19, $submac:ident ! ($($rest:tt)*)) => ($submac!(20, $($rest)*));
// (20, $submac:ident ! ($($rest:tt)*)) => ($submac!(21, $($rest)*));
// );

0 comments on commit 6f111ed

Please sign in to comment.