use super::ParserError as RustreParseError;
use rowan_nom::*;
use crate::lexer::Token::{self, *};
type Lang = crate::LustreLang;
type Children = rowan_nom::Children<Lang, super::ParserError>;
type Input<'slice, 'src> = rowan_nom::Input<'slice, 'src, Lang>;
type IResult<'slice, 'src, E = super::ParserError> =
rowan_nom::IResult<'slice, 'src, Lang, super::ParserError, E>;
type RootIResult<'slice, 'src, E = super::ParserError> =
rowan_nom::RootIResult<'slice, 'src, Lang, super::ParserError, E>;
pub fn many_delimited<'slice, 'src: 'slice, IE: RowanNomError<Lang>>(
mut left: impl nom::Parser<Input<'slice, 'src>, Children, IE>,
mut repeat: impl nom::Parser<Input<'slice, 'src>, Children, IE>,
mut separator: impl nom::Parser<Input<'slice, 'src>, Children, IE>,
mut right: impl nom::Parser<Input<'slice, 'src>, Children, IE>,
) -> impl FnMut(Input<'slice, 'src>) -> IResult<'slice, 'src, IE> {
use std::ops::ControlFlow;
fn preceded_with_junk<'slice, 'src: 'slice, IE: RowanNomError<Lang>>(
mut parser: impl nom::Parser<Input<'slice, 'src>, Children, IE>,
mut right: impl nom::Parser<Input<'slice, 'src>, Children, IE>,
) -> impl FnMut(
Input<'slice, 'src>,
) -> nom::IResult<Input<'slice, 'src>, ControlFlow<Children, Children>, IE> {
move |mut input| {
let mut children = Children::empty();
loop {
if let Ok((input, new_children)) = right.parse(input.clone()) {
break Ok((input, ControlFlow::Break(children + new_children)));
} else if let Ok((input, new_children)) = parser.parse(input.clone()) {
break Ok((input, ControlFlow::Continue(children + new_children)));
} else if let Ok((new_input, new_children)) =
t_any::<_, _, DummyError>(input.clone())
{
input = new_input;
children += new_children.into_node(Error);
let err = super::ParserError::from_message("many_preceded is skipping");
children += Children::from_err(err);
} else {
break Err(nom::Err::Error(IE::from_unexpected_eof(input.src_pos())));
}
}
}
}
macro_rules! preceded_with_junk {
($parser:expr, $input:expr, &mut $children:ident) => {
match preceded_with_junk(|i| $parser.parse(i), |i| right.parse(i))($input)? {
(input, ControlFlow::Break(new_children)) => {
return Ok((input, $children + new_children));
}
(input, ControlFlow::Continue(new_children)) => {
$children += new_children;
input
}
}
};
}
move |input| {
let (input, mut children) = left.parse(input)?;
let mut input = preceded_with_junk!(repeat, input, &mut children);
loop {
input = preceded_with_junk!(separator, input, &mut children);
input = preceded_with_junk!(repeat, input, &mut children);
}
}
}
pub fn parse_program<'slice, 'src>(input: Input<'slice, 'src>) -> RootIResult<'slice, 'src> {
root_node(
Root,
many_delimited(success, parse_top_level_decl, success, eof),
)(input)
}
pub fn parse_include<'slice, 'src>(input: Input<'slice, 'src>) -> IResult<'slice, 'src> {
node(IncludeStatement, join((t(Include), fallible(t(Str)))))(input)
}
pub fn parse_top_level_decl<'slice, 'src>(input: Input<'slice, 'src>) -> IResult<'slice, 'src> {
alt((
parse_include,
constant_decl::parse_const_decl,
type_decl::parse_type_decl,
ext_nodes::parse_ext_node_decl,
nodes::parse_node_decl,
model::parse_model_decl,
package::parse_pack_decl,
package::parse_pack_eq,
))(input)
}
pub mod package;
pub mod model;
pub mod ident;
pub mod nodes;
pub mod constant_decl;
pub mod type_decl;
pub fn parse_type<'slice, 'src>(input: Input<'slice, 'src>) -> IResult<'slice, 'src> {
node(
TypeNode,
join((
alt((t(Int), t(Bool), t(Real), ident::parse_lv6_id_ref)),
parse_type_hat,
)),
)(input)
}
fn parse_type_hat<'slice, 'src>(input: Input<'slice, 'src>) -> IResult<'slice, 'src> {
opt(join((
t(Hat),
expect(expression::parse_expression, "expected expression"),
)))(input)
}
pub mod ext_nodes;
pub mod static_rules;
pub mod body;
pub mod left;
pub mod expression;
pub mod merge;
fn parse_predef_op_t<'slice, 'src: 'slice, P>(
mut t: impl FnMut(Token) -> P,
) -> impl FnMut(Input<'slice, 'src>) -> IResult<'slice, 'src>
where
P: nom::Parser<Input<'slice, 'src>, Children, super::ParserError>,
{
move |input| {
alt((
t(Not),
t(FBy),
t(Pre),
t(Current),
t(Arrow),
t(And),
t(Or),
t(Xor),
t(Impl),
t(Equal),
t(Neq),
t(Lt),
t(Lte),
t(Gt),
t(Gte),
t(Div),
t(Mod),
t(Minus),
t(Plus),
t(Slash),
t(Star),
t(If),
))(input)
}
}
pub fn parse_predef_op<'slice, 'src>(input: Input<'slice, 'src>) -> IResult<'slice, 'src> {
node(PredefOp, parse_predef_op_t(t))(input)
}
pub mod expression_by_names;
pub fn parse_constant<'slice, 'src>(input: Input<'slice, 'src>) -> IResult<'slice, 'src> {
node(ConstantNode, alt((t(True), t(False), t(IConst), t(RConst))))(input)
}