use super::node;
use crate::ast::source::*;
use crate::error::{Result, Span};
use crate::parser::Rule;
use pest::iterators::Pair;
pub fn build_component_def(pair: Pair<Rule>) -> Result<ComponentDef> {
let span = Span::from_pair(&pair);
let mut inner = pair.into_inner();
let name = inner.next().unwrap().as_str().to_string();
let mut next = inner.next().unwrap();
let interface = if next.as_rule() == Rule::component_params {
let interf = build_interface(next)?;
next = inner.next().unwrap();
interf
} else {
ComponentInterface::None
};
let mut body = Vec::new();
for item_pair in next.into_inner() {
body.push(node::build_node_item(item_pair)?);
}
Ok(ComponentDef { name, interface, body, span })
}
fn build_interface(pair: Pair<Rule>) -> Result<ComponentInterface> {
let inner = match pair.into_inner().next() {
Some(p) => p,
None => return Ok(ComponentInterface::None),
};
match inner.as_rule() {
Rule::any_params => {
let ident = inner
.into_inner()
.find(|p| p.as_rule() == Rule::snake_ident)
.expect("Grammar guaranteed a snake_ident in any_params")
.as_str()
.to_string();
Ok(ComponentInterface::Loose(ident))
}
Rule::named_params => {
let mut params = Vec::new();
for item in inner.into_inner() {
params.push(build_param_item(item)?);
}
Ok(ComponentInterface::Strict(params))
}
_ => unreachable!(),
}
}
fn build_param_item(pair: Pair<Rule>) -> Result<Parameter> {
let mut inner = pair.into_inner();
let name = inner.next().unwrap().as_str().to_string();
let mut type_hint = None;
let mut is_optional = false;
for part in inner {
match part.as_rule() {
Rule::type_hint => type_hint = Some(part.as_str().to_string()),
_ if part.as_str() == "?" => is_optional = true,
_ => {}
}
}
Ok(Parameter { name, type_hint, is_optional })
}