treehouse/crates/treehouse-format/src/ast.rs

82 lines
2.3 KiB
Rust
Raw Normal View History

2023-08-18 13:25:20 +02:00
use std::ops::Range;
use crate::{
2023-08-18 20:58:07 +02:00
pull::{Attributes, BranchEvent, BranchKind, Parser},
2023-08-18 13:25:20 +02:00
ParseError, ParseErrorKind,
};
#[derive(Debug, Clone)]
pub struct Roots {
2024-01-18 22:46:57 +01:00
pub attributes: Option<Attributes>,
2023-08-18 13:25:20 +02:00
pub branches: Vec<Branch>,
}
impl Roots {
pub fn parse(parser: &mut Parser) -> Result<Self, ParseError> {
2024-01-18 22:46:57 +01:00
let attributes = parser.top_level_attributes()?;
2023-08-18 13:25:20 +02:00
let mut branches = vec![];
while let Some((branch, indent_level)) = Branch::parse_with_indent_level(parser)? {
if indent_level != 0 {
return Err(ParseErrorKind::RootIndentLevel.at(branch.kind_span));
}
branches.push(branch);
}
2024-01-18 22:46:57 +01:00
Ok(Self {
attributes,
branches,
})
2023-08-18 13:25:20 +02:00
}
}
#[derive(Debug, Clone)]
pub struct Branch {
2023-08-18 17:04:12 +02:00
pub indent_level: usize,
2023-08-18 20:58:07 +02:00
pub attributes: Option<Attributes>,
2023-08-18 13:25:20 +02:00
pub kind: BranchKind,
pub kind_span: Range<usize>,
pub content: Range<usize>,
pub children: Vec<Branch>,
}
impl From<BranchEvent> for Branch {
fn from(branch: BranchEvent) -> Self {
Self {
2023-08-18 17:04:12 +02:00
indent_level: branch.indent_level,
2023-08-18 13:25:20 +02:00
attributes: branch.attributes,
kind: branch.kind,
kind_span: branch.kind_span,
content: branch.content,
children: vec![],
}
}
}
impl Branch {
pub fn parse_with_indent_level(
parser: &mut Parser,
) -> Result<Option<(Self, usize)>, ParseError> {
if let Some(branch_event) = parser.next_branch()? {
let own_indent_level = branch_event.indent_level;
let mut branch = Branch::from(branch_event);
let children_indent_level = parser.peek_indent_level();
if children_indent_level > own_indent_level {
while parser.peek_indent_level() == children_indent_level {
if let Some(child) = Branch::parse(parser)? {
branch.children.push(child);
} else {
break;
}
}
}
Ok(Some((branch, own_indent_level)))
} else {
Ok(None)
}
}
pub fn parse(parser: &mut Parser) -> Result<Option<Self>, ParseError> {
Ok(Self::parse_with_indent_level(parser)?.map(|(branch, _)| branch))
}
}