Skip to content

Commit

Permalink
Improved block parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert-M-Lucas committed Jul 25, 2024
1 parent 7c7b983 commit 312c99c
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 52 deletions.
17 changes: 11 additions & 6 deletions .idea/workspace.xml

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

2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
pub mod root;
// pub mod root;
129 changes: 105 additions & 24 deletions src/root/parser/parse_blocks.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,62 @@
use std::path::PathBuf;
use std::rc::Rc;
use itertools::Itertools;
use crate::root::parser::parse::{ErrorTree, ParseResult, Span};
use nom::character::complete::{anychar, char as nchar};
use nom::Err::Error;
use nom::error::ParseError;
use nom::error::{ErrorKind, ParseError};
use nom::{InputTake, Offset};
use nom::bytes::complete::{tag, take_until};
use nom_locate::LocatedSpan;
use crate::root::parser::parse_util::discard_ignored;

// ! BROKEN

const DEFAULT_TERMINATORS: [(char, char, bool); 3] = [
('{', '}', true),
('(', ')', true),
('"', '"', false)
pub struct Terminator {
pub opening: char,
pub closing: char,
pub allow_recursive: bool,
pub escape_char: Option<char>
}

pub const BRACE_TERMINATOR: Terminator = Terminator {
opening: '{',
closing: '}',
allow_recursive: true,
escape_char: None,
};

pub const BRACKET_TERMINATOR: Terminator = Terminator {
opening: '(',
closing: ')',
allow_recursive: true,
escape_char: None,
};

pub const STRING_TERMINATOR: Terminator = Terminator {
opening: '"',
closing: '"',
allow_recursive: false,
escape_char: Some('\\'),
};

pub const DEFAULT_TERMINATORS: [Terminator; 3] = [
BRACE_TERMINATOR,
BRACKET_TERMINATOR,
STRING_TERMINATOR
];

pub fn default_section(s: Span, section_char: char) -> ParseResult {
let x = section(
pub fn parse_terminator_default_set<'a, 'b>(s: Span<'a>, terminator: &'b Terminator) -> ParseResult<'a> {
parse_terminator(
s,
DEFAULT_TERMINATORS.iter().find_position(|(c, _, _)| *c == section_char).unwrap().0,
terminator,
&DEFAULT_TERMINATORS
);
// println!("----------\n{:?}\n**{}\n\n**{}\n\n**{}", section_char, s.fragment(), x.as_ref().unwrap().0.fragment(), x.as_ref().unwrap().1.fragment());
x
)
}

pub fn section<'a>(s: Span<'a>, terminator: usize, all_terminators: &[(char, char, bool)]) -> ParseResult<'a> {
let (initial_span, _) = nchar(all_terminators[terminator].0)(s)?;
pub fn parse_terminator<'a, 'b, 'c>(s: Span<'a>, terminator: &'b Terminator, all_terminators: &'c [Terminator]) -> ParseResult<'a> {
let (initial_span, _) = nchar(terminator.opening)(s)?;

let allow_subsections = all_terminators[terminator].2;
let allow_subsections = terminator.allow_recursive;

let mut depth = 0;

Expand All @@ -40,7 +69,7 @@ pub fn section<'a>(s: Span<'a>, terminator: usize, all_terminators: &[(char, cha
break;
}

if let Ok((ns, _)) = nchar::<_, ErrorTree>(all_terminators[terminator].1)(s) {
if let Ok((ns, _)) = nchar::<_, ErrorTree>(terminator.closing)(s) {
if depth == 0 {
return Ok((ns, initial_span.take_split(initial_span.offset(&s)).1));
} else {
Expand All @@ -50,22 +79,20 @@ pub fn section<'a>(s: Span<'a>, terminator: usize, all_terminators: &[(char, cha
}
}

if let Ok((ns, _)) = nchar::<_, ErrorTree>(all_terminators[terminator].0)(s) {
if let Ok((ns, _)) = nchar::<_, ErrorTree>(terminator.opening)(s) {
s = ns;
depth += 1;
continue;
}

if allow_subsections {
for (pos, t) in all_terminators.iter().enumerate() {
if pos == terminator { continue; }

if let Ok(_) = nchar::<_, ErrorTree>(t.0)(s) {
s = section(s, pos, all_terminators)?.0;
for t in all_terminators {
if let Ok(_) = nchar::<_, ErrorTree>(t.opening)(s) {
s = parse_terminator(s, t, all_terminators)?.0;
continue 'main;
}

if let Ok(_) = nchar::<_, ErrorTree>(t.1)(s) {
if let Ok(_) = nchar::<_, ErrorTree>(t.closing)(s) {
// Unopened section closed
todo!()
}
Expand All @@ -75,7 +102,61 @@ pub fn section<'a>(s: Span<'a>, terminator: usize, all_terminators: &[(char, cha
}
}

Err(Error(ErrorTree::from_char(s, all_terminators[terminator].1)))
Err(nom::Err::Error(ErrorTree::from_char(s, terminator.closing)))
}

pub fn take_until_or_end_smart<'a>(s: Span<'a>, until: &str) -> ParseResult<'a> {
let original = s.clone();
let mut s = s;
while !s.is_empty() {
if let Ok((ns, _)) = tag::<&str, LocatedSpan<&str, &Rc<PathBuf>>, ErrorTree>(until)(s) {
s = ns;
break;
}

let c = s.chars().next().unwrap();

for t in &DEFAULT_TERMINATORS {
if t.opening == c {
s = parse_terminator_default_set(s, t)?.0;
continue;
}
}

s = s.take_split(1).0;
}

let offset = original.offset(&s);

Ok(original.take_split(offset))
}

pub fn take_until_smart<'a>(s: Span<'a>, until: &str) -> ParseResult<'a> {
let original = s.clone();
let mut s = s;
loop {
if s.is_empty() {
return Err(nom::Err::Error(ErrorTree::from_error_kind(original, ErrorKind::TakeUntil)));
}

if let Ok((ns, _)) = tag::<&str, LocatedSpan<&str, &Rc<PathBuf>>, ErrorTree>(until)(s) {
s = ns;
break;
}

let c = s.chars().next().unwrap();

for t in &DEFAULT_TERMINATORS {
if t.opening == c {
s = parse_terminator_default_set(s, t)?.0;
continue;
}
}

s = s.take_split(1).0;
}

let offset = original.offset(&s);

Ok(original.take_split(offset))
}
6 changes: 3 additions & 3 deletions src/root/parser/parse_function.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::parser::parse::{ErrorTree, Location, ParseResult, Span};
use crate::root::parser::parse_blocks::default_section;
use crate::root::parser::parse_blocks::{BRACE_TERMINATOR, BRACKET_TERMINATOR, parse_terminator_default_set};
use crate::root::parser::parse_function::parse_evaluable::{FullNameWithIndirectionToken, parse_full_name};
use crate::root::parser::parse_function::parse_line::{LineTokens, parse_lines};
use crate::root::parser::parse_name::{parse_simple_name, SimpleNameToken};
Expand Down Expand Up @@ -55,7 +55,7 @@ pub fn parse_function<'a, 'b>(s: Span<'a>, allow_self: Option<&'b SimpleNameToke
// Some(s.as_str())
// } else { None };

let (s, contents) = default_section(s, '(')?;
let (s, contents) = parse_terminator_default_set(s, &BRACKET_TERMINATOR)?;
let (_, (parameters, has_self)) = parse_parameters(contents, allow_self)?;

let (s, _) = discard_ignored(s)?;
Expand All @@ -69,7 +69,7 @@ pub fn parse_function<'a, 'b>(s: Span<'a>, allow_self: Option<&'b SimpleNameToke
(s, None)
};

let (s, contents) = default_section(s, '{')?;
let (s, contents) = parse_terminator_default_set(s, &BRACE_TERMINATOR)?;

let end_location = Location::from_span_end(&contents);

Expand Down
6 changes: 3 additions & 3 deletions src/root/parser/parse_function/parse_evaluable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use nom::bytes::complete::tag;
use nom::character::complete::char;
use crate::root::parser::parse_arguments::parse_arguments;
use crate::root::parser::parse_name::{SimpleNameToken, parse_simple_name};
use crate::root::parser::parse_blocks::default_section;
use crate::root::parser::parse_blocks::{BRACE_TERMINATOR, BRACKET_TERMINATOR, parse_terminator_default_set};
use crate::root::parser::parse_function::parse_struct_init::{parse_struct_init, StructInitToken};
use crate::root::parser::parse_struct::StructToken;
use crate::root::parser::parse_util::discard_ignored;
Expand Down Expand Up @@ -223,7 +223,7 @@ pub fn parse_evaluable<'a, 'b>(s: Span<'a>, containing_class: Option<&'b SimpleN
}

// Recursively parse bracketed sections
let ns = if let Ok((ns, inner)) = default_section(s, '(') {
let ns = if let Ok((ns, inner)) = parse_terminator_default_set(s, &BRACKET_TERMINATOR) {
let (_, evaluable) = parse_evaluable(inner, containing_class, false)?;
evaluables.push(TempEvaluableTokensOne::EvaluableToken(evaluable));
ns
Expand Down Expand Up @@ -252,7 +252,7 @@ pub fn parse_evaluable<'a, 'b>(s: Span<'a>, containing_class: Option<&'b SimpleN
let (x, section) = parse_simple_name(x)?;

Ok(if char::<Span, ErrorTree>('(')(x).is_ok() {
let (x, arguments) = default_section(x, '(')?;
let (x, arguments) = parse_terminator_default_set(x, &BRACKET_TERMINATOR)?;
let (_, arguments) = parse_arguments(arguments, containing_class)?;
(x, match kind {
Kind::Static => TempEvaluableTokensOne::StaticFunctionCall(section, arguments),
Expand Down
10 changes: 5 additions & 5 deletions src/root/parser/parse_function/parse_if.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use nom::sequence::Tuple;
use nom_supreme::tag::complete::tag;

use crate::root::parser::parse::{ErrorTree, Location, ParseResult, Span};
use crate::root::parser::parse_blocks::default_section;
use crate::root::parser::parse_blocks::{BRACE_TERMINATOR, BRACKET_TERMINATOR, parse_terminator_default_set};
use crate::root::parser::parse_function::parse_evaluable::{parse_evaluable, EvaluableToken};
use crate::root::parser::parse_function::parse_line::{parse_lines, LineTestFn, LineTokens};
use crate::root::parser::parse_name::SimpleNameToken;
Expand All @@ -28,10 +28,10 @@ pub fn test_parse_if<'a, 'b>(s: Span<'a>) -> ParseResult<Span, LineTestFn<'a, 'b
pub fn parse_if<'a, 'b>(s: Span<'a>, containing_class: Option<&'b SimpleNameToken>) -> ParseResult<'a, Span<'a>, IfToken> {
let (s, l) = tag("if")(s)?;
let (s, _) = discard_ignored(s)?;
let (s, content) = default_section(s, '(')?;
let (s, content) = parse_terminator_default_set(s, &BRACKET_TERMINATOR)?;
let (_, if_condition) = parse_evaluable(content, containing_class,false)?;
let (s, _) = discard_ignored(s)?;
let (s, contents) = default_section(s, '{')?;
let (s, contents) = parse_terminator_default_set(s, &BRACE_TERMINATOR)?;
let (_, if_contents) = parse_lines(contents, containing_class)?;

let mut elifs = Vec::new();
Expand All @@ -54,7 +54,7 @@ pub fn parse_if<'a, 'b>(s: Span<'a>, containing_class: Option<&'b SimpleNameToke
let (ns, condition) =
if let Ok((ns, _)) = (require_ignored, tag("if")).parse(ns) {
let (ns, _) = discard_ignored(ns)?;
let (ns, content) = default_section(ns, '(')?;
let (ns, content) = parse_terminator_default_set(ns, &BRACKET_TERMINATOR)?;
let (_, condition) = parse_evaluable(content, containing_class, false)?;
(ns, Some(condition))
} else {
Expand All @@ -63,7 +63,7 @@ pub fn parse_if<'a, 'b>(s: Span<'a>, containing_class: Option<&'b SimpleNameToke

let (ns, _) = discard_ignored(ns)?;

let (ns, contents) = default_section(ns, '{')?;
let (ns, contents) = parse_terminator_default_set(ns, &BRACE_TERMINATOR)?;
let (_, contents) = parse_lines(contents, containing_class)?;

// ? Handle else if
Expand Down
4 changes: 2 additions & 2 deletions src/root/parser/parse_function/parse_struct_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use nom::bytes::complete::{tag, take_till};
use nom::bytes::streaming::take_until;
use nom::character::streaming::char;
use crate::root::parser::parse::{Location, ParseResult, Span};
use crate::root::parser::parse_blocks::default_section;
use crate::root::parser::parse_blocks::{BRACE_TERMINATOR, parse_terminator_default_set};
use crate::root::parser::parse_function::parse_evaluable::{EvaluableToken, EvaluableTokens, FullNameToken, FullNameWithIndirectionToken, parse_evaluable, parse_full_name};
use crate::root::parser::parse_function::parse_literal::{LiteralToken, LiteralTokens};
use crate::root::parser::parse_name::{parse_simple_name, SimpleNameToken};
Expand All @@ -27,7 +27,7 @@ pub fn parse_struct_init<'a, 'b>(s: Span<'a>, containing_class: Option<&'b Simpl

let (s, _) = discard_ignored(s)?;

let (remaining, in_braces) = default_section( s,'{')?;
let (remaining, in_braces) = parse_terminator_default_set(s, &BRACE_TERMINATOR)?;

let mut contents = Vec::new();

Expand Down
6 changes: 3 additions & 3 deletions src/root/parser/parse_function/parse_while.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 crate::root::parser::parse::{Location, ParseResult, Span};
use crate::root::parser::parse_blocks::default_section;
use crate::root::parser::parse_blocks::{BRACE_TERMINATOR, BRACKET_TERMINATOR, parse_terminator_default_set};
use crate::root::parser::parse_function::parse_evaluable::{parse_evaluable, EvaluableToken,};
use crate::root::parser::parse_function::parse_line::{parse_lines, LineTestFn, LineTokens};
use crate::root::parser::parse_name::SimpleNameToken;
Expand All @@ -29,10 +29,10 @@ pub fn test_parse_while<'a, 'b>(s: Span<'a>) -> ParseResult<Span, LineTestFn<'a,
pub fn parse_while<'a, 'b>(s: Span<'a>, containing_class: Option<&'b SimpleNameToken>) -> ParseResult<'a, Span<'a>, WhileToken> {
let (s, l) = tag("while")(s)?;
let (s, _) = discard_ignored(s)?;
let (s, content) = default_section(s, '(')?;
let (s, content) = parse_terminator_default_set(s, &BRACKET_TERMINATOR)?;
let (_, condition) = parse_evaluable(content, containing_class, false)?;
let (s, _) = discard_ignored(s)?;
let (s, contents) = default_section(s, '{')?;
let (s, contents) = parse_terminator_default_set(s, &BRACE_TERMINATOR)?;

let (_, lines) = parse_lines(contents, containing_class)?;

Expand Down
5 changes: 2 additions & 3 deletions src/root/parser/parse_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ use derive_getters::{Dissolve, Getters};
use nom::sequence::Tuple;
use nom::Parser;
use nom_supreme::tag::complete::tag;

use crate::root::parser::parse::{Location, ParseResult, Span};
use crate::root::parser::parse_blocks::default_section;
use crate::root::parser::parse_blocks::{BRACE_TERMINATOR, parse_terminator_default_set};
use crate::root::parser::parse_function::{FunctionToken, parse_function};
use crate::root::parser::parse_name::{parse_simple_name, SimpleNameToken};
use crate::root::parser::parse_toplevel::{ToplevelTestFn, TopLevelTokens};
Expand Down Expand Up @@ -33,7 +32,7 @@ pub fn parse_impl(s: Span) -> ParseResult<Span, ImplToken> {
let (s, _) = require_ignored(s)?;
let (s, name) = parse_simple_name(s)?;
let (s, _) = discard_ignored(s)?;
let (s, contents) = default_section(s, '{')?;
let (s, contents) = parse_terminator_default_set(s, &BRACE_TERMINATOR)?;

let mut functions = Vec::new();

Expand Down
4 changes: 2 additions & 2 deletions src/root/parser/parse_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use derive_getters::{Dissolve, Getters};
use nom::sequence::Tuple;
use nom::Parser;
use nom_supreme::tag::complete::tag;
use crate::root::parser::parse_blocks::default_section;
use crate::root::parser::parse_blocks::{BRACE_TERMINATOR, parse_terminator_default_set};
use crate::root::parser::parse_name::{parse_simple_name, SimpleNameToken};
use crate::root::parser::parse_util::{discard_ignored, require_ignored};
use crate::root::shared::common::TypeID;
Expand Down Expand Up @@ -39,7 +39,7 @@ pub fn parse_struct(s: Span) -> ParseResult<Span, StructToken> {
let (s, _) = require_ignored(s)?;
let (s, name) = parse_simple_name(s)?;
let (s, _) = discard_ignored(s)?;
let (s, contents) = default_section(s, '{')?;
let (s, contents) = parse_terminator_default_set(s, &BRACE_TERMINATOR)?;
let (_, (parameters, _)) = parse_parameters(contents, None)?;

Ok((
Expand Down

0 comments on commit 312c99c

Please sign in to comment.