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 6f111ed commit 9c4722b
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 23 deletions.
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion src/root/nom_parser/parse_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -30,7 +32,7 @@ pub struct FunctionToken {
}

pub fn test_parse_function<'a>(s: Span) -> ParseResult<Span, ToplevelTestFn<'a>> {
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 {
Expand Down
8 changes: 0 additions & 8 deletions src/root/nom_parser/parse_function/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
24 changes: 23 additions & 1 deletion src/root/nom_parser/parse_function/parse_break.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,35 @@
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)]
pub struct BreakToken {
location: Location,
}

pub fn test_parse_break<'a>(s: Span) -> ParseResult<Span, LineTestFn<'a>> {
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<Span, BreakToken> {
let (s, l) = tag("break")(s)?;
let (s, _) = discard_ignored(s);
Expand Down
56 changes: 56 additions & 0 deletions src/root/nom_parser/parse_function/parse_initialisation.rs
Original file line number Diff line number Diff line change
@@ -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<Span, LineTestFn<'a>> {
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<Span, InitialisationToken> {
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,
}))
}
26 changes: 16 additions & 10 deletions src/root/nom_parser/parse_function/parse_line.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -17,11 +18,16 @@ pub enum LineTokens {
NoOp(EvaluableToken)
}

pub type LineTestFn<'a> = fn(Span<'a>) -> ParseResult<Span<'a>, 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)
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)))
}
}
23 changes: 22 additions & 1 deletion src/root/nom_parser/parse_function/parse_return.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand All @@ -10,6 +15,22 @@ pub struct ReturnToken {
return_value: EvaluableToken
}

pub fn test_parse_return<'a>(s: Span) -> ParseResult<Span, LineTestFn<'a>> {
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<Span, ReturnToken> {
let (s, l) = tag("return")(s)?;
let (s, _) = require_ignored(s)?;
Expand Down
3 changes: 2 additions & 1 deletion src/root/nom_parser/parse_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -19,7 +20,7 @@ pub struct ImplToken {
}

pub fn test_parse_impl<'a>(s: Span) -> ParseResult<Span, ToplevelTestFn<'a>> {
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 {
Expand Down
3 changes: 2 additions & 1 deletion src/root/nom_parser/parse_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -17,7 +18,7 @@ pub struct StructToken {
}

pub fn test_parse_struct<'a>(s: Span) -> ParseResult<Span, ToplevelTestFn<'a>> {
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 {
Expand Down

0 comments on commit 9c4722b

Please sign in to comment.