use crate::Node;
use crate::error::E;
use crate::parser::{IParser, RsHtmlParser, Rule};
use crate::position::Position;
use pest::error::Error;
use pest::iterators::{Pair, Pairs};
use std::iter::Peekable;
pub struct RustExprParser;
impl IParser for RustExprParser {
fn parse(parser: &mut RsHtmlParser, pair: Pair<Rule>) -> Result<Node, Box<Error<Rule>>> {
let pair_span = pair.as_span();
let position = Position::from(&pair);
let mut inner_pairs = pair.into_inner().peekable();
let mut clauses: Vec<(String, Position, Vec<Node>)> = Vec::new();
let consume_whitespaces = |inner_p: &mut Peekable<Pairs<Rule>>| {
while let Some(p) = inner_p.peek() {
if p.as_rule() == Rule::WHITESPACE {
inner_p.next();
} else {
break;
}
}
};
while inner_pairs.peek().is_some() {
let head_pair = inner_pairs
.next_if(|p| p.as_rule() == Rule::rust_expr_head)
.ok_or(
E::mes(format!(
"Internal Error: rust_expr expected a head, found {:?}",
inner_pairs.peek().map(|p| p.as_rule())
))
.span(pair_span),
)?;
let head_position = Position::from(&head_pair);
let head = head_pair.as_str().trim().to_string();
consume_whitespaces(&mut inner_pairs);
let template_pair = inner_pairs
.next_if(|p| p.as_rule() == Rule::inner_template)
.ok_or(
E::mes(format!(
"Internal Error: rust_expr missing inner_template for head: '{head}'"
))
.span(pair_span),
)?;
let body_nodes = parser.build_nodes_from_pairs(template_pair.into_inner())?;
clauses.push((head.clone(), head_position, body_nodes));
consume_whitespaces(&mut inner_pairs);
}
if clauses.is_empty() {
return Err(E::mes("Internal Error: rust_expr parsed with no clauses").span(pair_span));
}
Ok(Node::RustExpr(clauses, position))
}
}