diff --git a/Cargo.lock b/Cargo.lock index 4acd214..32b6e44 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,6 +56,12 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "autocfg" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" + [[package]] name = "b-box" version = "0.1.0" @@ -309,6 +315,15 @@ dependencies = [ "syn 2.0.53", ] +[[package]] +name = "substring" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ee6433ecef213b2e72f587ef64a2f5943e7cd16fbd82dbe8bc07486c534c86" +dependencies = [ + "autocfg", +] + [[package]] name = "syn" version = "1.0.109" @@ -409,6 +424,7 @@ dependencies = [ "same-file", "strum", "strum_macros", + "substring", "thiserror", "unique-type-id", "walkdir", diff --git a/Cargo.toml b/Cargo.toml index 68ae409..073f030 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ color-print = "0.3.5" nom = "7.1.3" nom_locate = "4.2.0" nom-supreme = "0.8.0" +substring = "1.4.5" [profile.release] opt-level = 3 diff --git a/src/root/nom_parser/parse_function.rs b/src/root/nom_parser/parse_function.rs index 83ec293..8778635 100644 --- a/src/root/nom_parser/parse_function.rs +++ b/src/root/nom_parser/parse_function.rs @@ -3,12 +3,14 @@ mod parse_line; mod parse_break; pub(crate) mod parse_evaluable; mod parse_return; +mod parse_initialisation; 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 substring::Substring; 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; @@ -30,7 +32,7 @@ pub struct FunctionToken { } pub fn test_parse_function<'a>(s: Span) -> ParseResult> { - if s.len() >= 2 && &s[..2] == "fn" { + if s.len() >= 2 && s.substring(0, 2) == "fn" { Ok((s, |x| parse_function(x).map(|(s, f)| (s, TopLevelTokens::Function(f))))) } else { diff --git a/src/root/nom_parser/parse_function/base.rs b/src/root/nom_parser/parse_function/base.rs index 887d886..613abe6 100644 --- a/src/root/nom_parser/parse_function/base.rs +++ b/src/root/nom_parser/parse_function/base.rs @@ -2,14 +2,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_line::LineTokens; -#[derive(Debug)] -pub struct InitialisationToken { - location: Location, - name: String, - type_name: String, - value: EvaluableToken -} - #[derive(Debug)] struct AssignmentOperatorToken { location: Location, diff --git a/src/root/nom_parser/parse_function/parse_break.rs b/src/root/nom_parser/parse_function/parse_break.rs index 69cc49d..e99440f 100644 --- a/src/root/nom_parser/parse_function/parse_break.rs +++ b/src/root/nom_parser/parse_function/parse_break.rs @@ -1,6 +1,12 @@ use nom::character::complete::char; +use nom::Err::Error; +use nom_supreme::error::{BaseErrorKind, Expectation}; use nom_supreme::tag::complete::tag; -use crate::root::nom_parser::parse::{Location, ParseResult, Span}; +use substring::Substring; +use crate::root::nom_parser::parse::{Location, ParseResult, Span, TypeErrorTree}; +use crate::root::nom_parser::parse_function::parse_line::{LineTestFn, LineTokens}; +use crate::root::nom_parser::parse_struct::parse_struct; +use crate::root::nom_parser::parse_toplevel::{ToplevelTestFn, TopLevelTokens}; use crate::root::nom_parser::parse_util::discard_ignored; #[derive(Debug)] @@ -8,6 +14,22 @@ pub struct BreakToken { location: Location, } +pub fn test_parse_break<'a>(s: Span) -> ParseResult> { + if s.len() >= 5 && s.substring(0, 5) == "break" { + Ok((s, |x| parse_break(x).map(|(s, b)| (s, LineTokens::Break(b))))) + } + else { + Err(Error( + TypeErrorTree::Base { + location: s, + kind: BaseErrorKind::Expected( + Expectation::Tag("break") + ), + } + )) + } +} + pub fn parse_break(s: Span) -> ParseResult { let (s, l) = tag("break")(s)?; let (s, _) = discard_ignored(s); diff --git a/src/root/nom_parser/parse_function/parse_initialisation.rs b/src/root/nom_parser/parse_function/parse_initialisation.rs new file mode 100644 index 0000000..ec59c41 --- /dev/null +++ b/src/root/nom_parser/parse_function/parse_initialisation.rs @@ -0,0 +1,56 @@ +use nom::character::complete::char; +use nom::Err::Error; +use nom_supreme::error::{BaseErrorKind, Expectation}; +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_function::parse_evaluable::{EvaluableToken, parse_evaluable}; +use crate::root::nom_parser::parse_function::parse_line::{LineTestFn, LineTokens}; +use crate::root::nom_parser::parse_name::{NameToken, parse_full_name, parse_simple_name}; +use crate::root::nom_parser::parse_util::{discard_ignored, require_ignored}; + + +#[derive(Debug)] +pub struct InitialisationToken { + location: Location, + name: String, + type_name: NameToken, + value: EvaluableToken +} + +pub fn test_parse_initialisation<'a>(s: Span) -> ParseResult> { + if s.len() >= 3 && s.substring(0, 3) == "let" { + Ok((s, |x| parse_initialisation(x).map(|(s, i)| (s, LineTokens::Initialisation(i))))) + } + else { + Err(Error( + TypeErrorTree::Base { + location: s, + kind: BaseErrorKind::Expected( + Expectation::Tag("let") + ), + } + )) + } +} + +pub fn parse_initialisation(s: Span) -> ParseResult { + let (s, l) = tag("let")(s)?; + let (s, _) = require_ignored(s)?; + let (s, name) = parse_simple_name(s)?; + let (s, _) = discard_ignored(s); + let (s, _) = char(':')(s)?; + let (s, _) = discard_ignored(s); + let (s, type_name) = parse_full_name(s)?; + let (s, _) = discard_ignored(s); + let (s, _) = char('=')(s)?; + let (s, _) = discard_ignored(s); + let (s, value) = parse_evaluable(s, true)?; + + Ok((s, InitialisationToken { + location: Location::from_span(l), + name: name.to_string(), + type_name, + value, + })) +} diff --git a/src/root/nom_parser/parse_function/parse_line.rs b/src/root/nom_parser/parse_function/parse_line.rs index 6e1f7cb..0c54ecd 100644 --- a/src/root/nom_parser/parse_function/parse_line.rs +++ b/src/root/nom_parser/parse_function/parse_line.rs @@ -1,10 +1,11 @@ use nom::branch::alt; use nom::Parser; -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::{ParseResult, Span}; +use crate::root::nom_parser::parse_function::base::{AssignmentToken, IfToken, WhileToken}; +use crate::root::nom_parser::parse_function::parse_break::{BreakToken, test_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}; +use crate::root::nom_parser::parse_function::parse_initialisation::{InitialisationToken, test_parse_initialisation}; +use crate::root::nom_parser::parse_function::parse_return::{ReturnToken, test_parse_return}; #[derive(Debug)] pub enum LineTokens { @@ -17,11 +18,16 @@ pub enum LineTokens { NoOp(EvaluableToken) } +pub type LineTestFn<'a> = fn(Span<'a>) -> ParseResult, LineTokens>; pub fn parse_line(s: Span) -> ParseResult { - 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) + if let Ok((s, parser)) = alt(( + test_parse_break, + test_parse_return, + test_parse_initialisation, + )).parse(s) { + parser(s) + } + else { // ? Default case is evaluable + parse_evaluable(s, true).map(|(s, e)| (s, LineTokens::NoOp(e))) + } } diff --git a/src/root/nom_parser/parse_function/parse_return.rs b/src/root/nom_parser/parse_function/parse_return.rs index 7f6a770..760b295 100644 --- a/src/root/nom_parser/parse_function/parse_return.rs +++ b/src/root/nom_parser/parse_function/parse_return.rs @@ -1,7 +1,12 @@ use nom::character::complete::char; +use nom::Err::Error; +use nom_supreme::error::{BaseErrorKind, Expectation}; use nom_supreme::tag::complete::tag; -use crate::root::nom_parser::parse::{Location, ParseResult, Span}; +use substring::Substring; +use crate::root::nom_parser::parse::{Location, ParseResult, Span, TypeErrorTree}; +use crate::root::nom_parser::parse_function::parse_break::parse_break; use crate::root::nom_parser::parse_function::parse_evaluable::{EvaluableToken, parse_evaluable}; +use crate::root::nom_parser::parse_function::parse_line::{LineTestFn, LineTokens}; use crate::root::nom_parser::parse_util::{discard_ignored, require_ignored}; #[derive(Debug)] @@ -10,6 +15,22 @@ pub struct ReturnToken { return_value: EvaluableToken } +pub fn test_parse_return<'a>(s: Span) -> ParseResult> { + if s.len() >= 6 && s.substring(0, 6) == "return" { + Ok((s, |x| parse_return(x).map(|(s, r)| (s, LineTokens::Return(r))))) + } + else { + Err(Error( + TypeErrorTree::Base { + location: s, + kind: BaseErrorKind::Expected( + Expectation::Tag("return") + ), + } + )) + } +} + pub fn parse_return(s: Span) -> ParseResult { let (s, l) = tag("return")(s)?; let (s, _) = require_ignored(s)?; diff --git a/src/root/nom_parser/parse_impl.rs b/src/root/nom_parser/parse_impl.rs index 8ca3a20..817e483 100644 --- a/src/root/nom_parser/parse_impl.rs +++ b/src/root/nom_parser/parse_impl.rs @@ -2,6 +2,7 @@ use nom::Err::Error; use nom::Parser; use nom_supreme::error::{BaseErrorKind, Expectation}; 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_blocks::braced_section; use crate::root::nom_parser::parse_function::{FunctionToken, parse_function}; @@ -19,7 +20,7 @@ pub struct ImplToken { } pub fn test_parse_impl<'a>(s: Span) -> ParseResult> { - if s.len() >= 4 && &s[..4] == "impl" { + if s.len() >= 4 && s.substring(0, 4) == "impl" { Ok((s, |x| parse_impl(x).map(|(s, i)| (s, TopLevelTokens::Impl(i))))) } else { diff --git a/src/root/nom_parser/parse_struct.rs b/src/root/nom_parser/parse_struct.rs index fbc5fdc..e8557f6 100644 --- a/src/root/nom_parser/parse_struct.rs +++ b/src/root/nom_parser/parse_struct.rs @@ -2,6 +2,7 @@ use nom::Err::Error; use nom_supreme::tag::complete::tag; use nom::Parser; use nom_supreme::error::{BaseErrorKind, Expectation}; +use substring::Substring; 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}; @@ -17,7 +18,7 @@ pub struct StructToken { } pub fn test_parse_struct<'a>(s: Span) -> ParseResult> { - if s.len() >= 6 && &s[..6] == "struct" { + if s.len() >= 6 && s.substring(0, 6) == "struct" { Ok((s, |x| parse_struct(x).map(|(s, st)| (s, TopLevelTokens::Struct(st))))) } else {