Attribute parsing and ast

This commit is contained in:
2026-05-05 03:17:33 +02:00
parent d9c20467a4
commit f4a14789c3
3 changed files with 114 additions and 24 deletions
+91 -12
View File
@@ -18,9 +18,7 @@ pub fn parse(source: &str) -> Result<Vec<TopLevel>, ParseError> {
let mut statements = vec![];
for pair in pairs.next().unwrap().into_inner() {
if let Ok(stmt) = TopLevel::try_from(pair) {
statements.push(stmt);
}
statements.push(TopLevel::from(pair));
}
Ok(statements)
@@ -120,14 +118,79 @@ impl From<pest::iterators::Pair<'_, Rule>> for ParamList {
}
}
impl TryFrom<pest::iterators::Pair<'_, Rule>> for TopLevel {
type Error = ();
fn try_from(pair: pest::iterators::Pair<Rule>) -> Result<Self, ()> {
impl From<pest::iterators::Pair<'_, Rule>> for Attribute {
fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self {
let rule = pair.as_rule();
// If we start at the top-level #[...], dive into the meta_item
if rule == Rule::attribute {
return Attribute::from(pair.into_inner().next().unwrap());
}
let mut inner = pair.into_inner();
// Every style starts with an identifier (the path)
let path = StaticPath::from(inner.next().expect("Path identifier expected"));
let kind = match rule {
Rule::simple_style => MetaItemKind::Word,
Rule::key_value_style | Rule::pair => {
let lit = Literal::from(inner.next().unwrap());
MetaItemKind::NameValue(lit)
}
Rule::list_style => {
// derive(Debug, Clone) -> NestedMetaItem::MetaItem(Attribute { path: "Debug", kind: Word })
let items = inner
.map(|p| {
NestedMetaItem::MetaItem(Attribute {
path: StaticPath::from(p),
kind: MetaItemKind::Word,
})
})
.collect();
MetaItemKind::List(items)
}
Rule::structured_style => {
// link(name = "readline") -> NestedMetaItem::MetaItem(Attribute { path: "name", kind: NameValue(...) })
let items = inner
.map(|p| NestedMetaItem::MetaItem(Attribute::from(p)))
.collect();
MetaItemKind::List(items)
}
_ => unreachable!("Unexpected rule: {:?}", rule),
};
Attribute { path, kind }
}
}
impl From<pest::iterators::Pair<'_, Rule>> for TopLevel {
fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self {
let mut inner = pair.into_inner();
let mut attributes = Vec::new();
while inner
.peek()
.map(|v| v.as_rule() == Rule::attribute)
.unwrap_or_default()
{
attributes.push(Attribute::from(inner.next().unwrap()));
}
TopLevel(inner.next().unwrap().into(), attributes)
}
}
impl From<pest::iterators::Pair<'_, Rule>> for TopLevelKind {
fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self {
let rule = pair.as_rule();
let mut inner = pair.into_inner();
match rule {
Rule::import => Ok(TopLevel::Include(StaticPath::from(inner.next().unwrap()))),
Rule::import => TopLevelKind::Include(StaticPath::from(inner.next().unwrap())),
Rule::function_decl => {
let export = if let Some(first) = inner.peek() {
@@ -152,13 +215,13 @@ impl TryFrom<pest::iterators::Pair<'_, Rule>> for TopLevel {
let body = Block::from(inner.next().unwrap());
Ok(TopLevel::FunctionDecl {
TopLevelKind::FunctionDecl {
export,
name,
params,
return_type,
body,
})
}
}
Rule::struct_decl => {
@@ -176,14 +239,14 @@ impl TryFrom<pest::iterators::Pair<'_, Rule>> for TopLevel {
let fields_pair = inner.next().unwrap();
let fields = FieldList::from(fields_pair);
Ok(TopLevel::StructDecl {
TopLevelKind::StructDecl {
export,
name,
fields,
})
}
}
Rule::EOI => Err(()),
Rule::EOI => TopLevelKind::EOI,
_ => unimplemented!("{rule:#?}"),
}
}
@@ -262,6 +325,22 @@ impl From<pest::iterators::Pair<'_, Rule>> for Statement {
}
}
impl From<pest::iterators::Pair<'_, Rule>> for Literal {
fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self {
let rule = pair.as_rule();
let inner = pair.clone().into_inner();
match rule {
Rule::integer => Literal::Int(pair.as_str().parse::<i64>().unwrap()),
Rule::float => Literal::Float(pair.as_str().parse::<f64>().unwrap()),
Rule::boolean => Literal::Bool(pair.as_str().parse::<bool>().unwrap()),
Rule::string_lit => Literal::String(inner.as_str().to_string()),
Rule::tuple => Literal::Tuple(inner.map(Expression::from).collect()),
_ => unimplemented!("{rule:#?}"),
}
}
}
impl From<pest::iterators::Pair<'_, Rule>> for Expression {
fn from(pair: pest::iterators::Pair<Rule>) -> Self {
let rule = pair.as_rule();