146 lines
2.8 KiB
Rust
146 lines
2.8 KiB
Rust
use nom::
|
|
{
|
|
IResult,
|
|
sequence::{delimited, pair, preceded, terminated, tuple},
|
|
combinator::{map, recognize},
|
|
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),
|
|
}
|
|
}
|
|
}
|
|
|
|
fn statement_kind(i: &str) -> IResult<&str, crate::project::StatementKind>
|
|
{
|
|
let foo = delimited
|
|
(
|
|
whitespace0,
|
|
alt
|
|
((
|
|
map
|
|
(
|
|
tag("axiom:"),
|
|
|_| crate::project::StatementKind::Axiom,
|
|
),
|
|
map
|
|
(
|
|
tag("lemma:"),
|
|
|_| crate::project::StatementKind::Lemma,
|
|
),
|
|
map
|
|
(
|
|
tag("conjecture:"),
|
|
|_| crate::project::StatementKind::Conjecture,
|
|
),
|
|
)),
|
|
whitespace0,
|
|
)(i);
|
|
|
|
foo
|
|
}
|
|
|
|
fn statement(i: &str) -> IResult<&str, (crate::project::StatementKind, foliage::Formula)>
|
|
{
|
|
terminated
|
|
(
|
|
pair
|
|
(
|
|
statement_kind,
|
|
foliage::formula,
|
|
),
|
|
preceded
|
|
(
|
|
whitespace0,
|
|
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)
|
|
}
|
|
|
|
pub fn project(i: &str) -> IResult<&str, crate::Project>
|
|
{
|
|
let mut statement_input = i.clone();
|
|
let mut blocks = Vec::new();
|
|
|
|
loop
|
|
{
|
|
let i_ = statement_input.clone();
|
|
match statement_enclosed_by_whitespace(i_)
|
|
{
|
|
Ok((i, (whitespace_before, (statement_original_text, (statement_kind, formula)), whitespace_after))) =>
|
|
{
|
|
// 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));
|
|
}
|
|
|
|
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,
|
|
};
|
|
|
|
Ok((i, project))
|
|
}
|