use crate::lossless::{Error, ErrorInfo, Makefile, ParseError, PositionedParseError, Rule};
use rowan::ast::AstNode;
use rowan::{GreenNode, SyntaxNode};
use std::marker::PhantomData;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Parse<T> {
green: GreenNode,
errors: Vec<ErrorInfo>,
positioned_errors: Vec<PositionedParseError>,
_ty: PhantomData<T>,
}
impl<T> Parse<T> {
pub fn new(
green: GreenNode,
errors: Vec<ErrorInfo>,
positioned_errors: Vec<PositionedParseError>,
) -> Self {
Parse {
green,
errors,
positioned_errors,
_ty: PhantomData,
}
}
pub fn green(&self) -> &GreenNode {
&self.green
}
pub fn errors(&self) -> &[ErrorInfo] {
&self.errors
}
pub fn positioned_errors(&self) -> &[PositionedParseError] {
&self.positioned_errors
}
pub fn ok(&self) -> bool {
self.errors.is_empty()
}
pub fn to_result(self) -> Result<T, Error>
where
T: AstNode<Language = crate::lossless::Lang>,
{
if self.errors.is_empty() {
let node = SyntaxNode::new_root_mut(self.green);
Ok(T::cast(node).expect("root node has wrong type"))
} else {
Err(Error::Parse(ParseError {
errors: self.errors,
}))
}
}
pub fn tree(&self) -> T
where
T: AstNode<Language = crate::lossless::Lang>,
{
let node = SyntaxNode::new_root_mut(self.green.clone());
T::cast(node).expect("root node has wrong type")
}
pub fn syntax_node(&self) -> SyntaxNode<crate::lossless::Lang> {
SyntaxNode::new_root(self.green.clone())
}
}
unsafe impl<T> Send for Parse<T> {}
unsafe impl<T> Sync for Parse<T> {}
impl Parse<Makefile> {
pub fn parse_makefile(text: &str) -> Self {
let parsed = crate::lossless::parse(text, None);
Parse::new(parsed.green_node, parsed.errors, parsed.positioned_errors)
}
}
impl Parse<Rule> {
pub fn parse_rule(text: &str) -> Self {
let parsed = crate::lossless::parse(text, None);
Parse::new(parsed.green_node, parsed.errors, parsed.positioned_errors)
}
pub fn to_rule_result(self) -> Result<Rule, Error> {
if !self.errors.is_empty() {
return Err(Error::Parse(ParseError {
errors: self.errors,
}));
}
let makefile =
Makefile::cast(SyntaxNode::new_root_mut(self.green)).expect("root node has wrong type");
let rules: Vec<_> = makefile.rules().collect();
if rules.len() == 1 {
Ok(rules.into_iter().next().unwrap())
} else {
Err(Error::Parse(ParseError {
errors: vec![ErrorInfo {
message: "expected a single rule".to_string(),
line: 1,
context: "".to_string(),
}],
}))
}
}
}