ask-dracula-rs/src/parse.rs

146 lines
2.8 KiB
Rust
Raw Normal View History

2019-11-02 02:13:45 +01:00
use nom::
{
IResult,
sequence::{delimited, pair, preceded, terminated, tuple},
combinator::{map, recognize},
2019-11-02 02:13:45 +01:00
branch::alt,
bytes::complete::tag,
};
use foliage::parse::whitespace0;
pub fn recognize_and_keep<I: Clone + nom::Offset + nom::Slice<std::ops::RangeTo<usize>>, O, E: nom::error::ParseError<I>, F>(parser: F) -> impl Fn(I) -> IResult<I, (I, O), E>
where
F: Fn(I) -> IResult<I, O, E>,
{
move |input: I|
{
let i = input.clone();
match parser(i)
{
Ok((i, result)) =>
{
let index = input.offset(&i);
Ok((i, (input.slice(..index), result)))
},
Err(e) => Err(e),
}
}
}
2019-11-02 02:13:45 +01:00
fn statement_kind(i: &str) -> IResult<&str, crate::project::StatementKind>
{
let foo = delimited
(
whitespace0,
2019-11-02 02:13:45 +01:00
alt
((
map
(
tag("axiom:"),
|_| crate::project::StatementKind::Axiom,
),
map
(
tag("lemma:"),
|_| crate::project::StatementKind::Lemma,
),
map
(
tag("conjecture:"),
|_| crate::project::StatementKind::Conjecture,
),
)),
whitespace0,
2019-11-02 02:13:45 +01:00
)(i);
foo
}
fn statement(i: &str) -> IResult<&str, (crate::project::StatementKind, foliage::Formula)>
{
terminated
(
pair
(
statement_kind,
foliage::formula,
),
preceded
2019-11-02 02:13:45 +01:00
(
whitespace0,
2019-11-02 02:13:45 +01:00
tag("."),
),
)(i)
}
fn statement_enclosed_by_whitespace(i: &str) -> IResult<&str, (&str, (&str, (crate::project::StatementKind, foliage::Formula)), &str)>
{
tuple
((
recognize(whitespace0),
recognize_and_keep(statement),
recognize(whitespace0),
))(i)
}
2019-11-02 02:13:45 +01:00
pub fn project(i: &str) -> IResult<&str, crate::Project>
{
let mut statement_input = i.clone();
let mut blocks = Vec::new();
2019-11-02 02:13:45 +01:00
loop
{
let i_ = statement_input.clone();
match statement_enclosed_by_whitespace(i_)
2019-11-02 02:13:45 +01:00
{
Ok((i, (whitespace_before, (statement_original_text, (statement_kind, formula)), whitespace_after))) =>
2019-11-02 02:13:45 +01:00
{
// Iteration must always consume input (to prevent infinite loops)
if i == statement_input
{
return Err(nom::Err::Error(nom::error::ParseError::from_error_kind(statement_input, nom::error::ErrorKind::Many0)));
}
if !whitespace_before.is_empty()
{
blocks.push(crate::project::Block::Whitespace(whitespace_before));
}
let statement = crate::project::Statement
{
kind: statement_kind,
original_text: statement_original_text,
formula,
};
blocks.push(crate::project::Block::Statement(statement));
if !whitespace_after.is_empty()
{
blocks.push(crate::project::Block::Whitespace(whitespace_after));
}
2019-11-02 02:13:45 +01:00
statement_input = i;
},
Err(nom::Err::Error(_)) => break,
Err(e) => return Err(e),
}
}
let i = statement_input;
// Verify that the whole file has been parsed
if i != ""
{
return Err(nom::Err::Error(nom::error::ParseError::from_error_kind(statement_input, nom::error::ErrorKind::Many0)));
}
let project = crate::Project
{
blocks,
2019-11-02 02:13:45 +01:00
};
Ok((i, project))
}