use anyhow::{anyhow, Error};
use pest::Parser;
use crate::{
builder::builder::{Builder, MetaBuilder},
lang::{builder_tree::BuilderTree, parse_main_line::LineResult, state::State},
};
use super::{InnerLangParser, Pairs, Rule};
pub(crate) fn build<MB, B>(
state: &State,
tree: &mut BuilderTree<B>,
r: LineResult,
meta_builder: &MB,
start_index: usize,
) -> Result<(), anyhow::Error>
where
MB: MetaBuilder<Item = B>,
B: Builder,
{
let (def, _emp) = state.default_types();
let (name, arg) = if def.is_empty() || r.define_canceled{
let mut p = InnerLangParser::parse(Rule::content, &r.content)
.map_err(|_| anyhow!("preceding space is not allowed in this context"))?;
parse_content(p.next().unwrap().into_inner())?
} else {
let full = format!("{def} {}", r.content);
let mut p = InnerLangParser::parse(Rule::content, &full)
.map_err(|_| anyhow!("preceding space is not allowed in this context"))?;
parse_content(p.next().unwrap().into_inner())?
};
let mut builder = meta_builder.build(name, arg).map_err(Error::msg)?;
let params = r.params;
for param in params {
let p = InnerLangParser::parse(Rule::param, ¶m).expect("unreachable");
let (name, val) = parse_param(p)?;
builder.set_param(name, val).map_err(Error::msg)?;
}
tree.add(builder, state.indent_level(), start_index)
.expect("unreachable");
Ok(())
}
pub(crate) fn build_empty_line_item<MB, B>(
state: &State,
tree: &mut BuilderTree<B>,
meta_builder: &MB,
start_index: usize,
) -> Result<(), Error>
where
MB: MetaBuilder<Item = B>,
{
let (_def, emp) = state.default_types();
if emp.is_empty() {
return Ok(());
}
let mut p = InnerLangParser::parse(Rule::content, emp)
.map_err(|_| anyhow!("preceding space is not allowed in this context"))?;
let (name, arg) = parse_content(p.next().unwrap().into_inner())?;
let builder = meta_builder.build(name, arg).map_err(Error::msg)?;
tree.add(builder, state.indent_level(), start_index)
.expect("unreachable");
Ok(())
}
fn parse_content(pairs: Pairs) -> Result<(String, String), Error> {
let mut name = String::new();
let mut text = String::new();
for pair in pairs {
match pair.as_rule() {
Rule::name => name = pair.as_str().to_string(),
Rule::text => text = pair.as_str().to_string(),
Rule::EOI => {}
_ => {
return Err(anyhow!("{:#?}", pair));
}
}
}
Ok((name, text))
}
fn parse_param(mut pairs: Pairs) -> Result<(String, String), Error> {
parse_content(pairs.next().unwrap().into_inner())
}