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
+22 -11
View File
@@ -20,22 +20,20 @@ pub enum TypePostfix {
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub struct Attribute { pub struct Attribute {
pub path: StaticPath, pub path: StaticPath,
pub args: Vec<AttributeArg>, pub kind: MetaItemKind,
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub enum AttributeArg { pub enum MetaItemKind {
Named(String, Literal), Word,
Positional(Literal), NameValue(Literal),
List(Vec<NestedMetaItem>),
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub enum Literal { pub enum NestedMetaItem {
String(String), Literal(Literal),
Int(i64), MetaItem(Attribute),
Float(f64),
Bool(bool),
Tuple(Vec<Expression>),
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
@@ -67,7 +65,10 @@ pub enum BinaryOp {
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub enum TopLevel { pub struct TopLevel(pub TopLevelKind, pub Vec<Attribute>);
#[derive(Debug, Clone, Serialize)]
pub enum TopLevelKind {
Include(StaticPath), Include(StaticPath),
StructDecl { StructDecl {
export: bool, export: bool,
@@ -81,6 +82,7 @@ pub enum TopLevel {
return_type: TypeExpr, return_type: TypeExpr,
body: Block, body: Block,
}, },
EOI,
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
@@ -166,3 +168,12 @@ pub enum Expression {
postfixes: Vec<Postfix>, postfixes: Vec<Postfix>,
}, },
} }
#[derive(Debug, Clone, Serialize)]
pub enum Literal {
String(String),
Int(i64),
Float(f64),
Bool(bool),
Tuple(Vec<Expression>),
}
+1 -1
View File
@@ -37,7 +37,7 @@ structured_style = { identifier ~ "(" ~ pair ~ ("," ~ pair)* ~ ","? ~ ")" }
pair = { identifier ~ "=" ~ primary } pair = { identifier ~ "=" ~ primary }
top_level = _{ attribute* ~ (import | function_decl | struct_decl) } top_level = { attribute* ~ (import | function_decl | struct_decl) }
import = { sharp ~ "include" ~ "<" ~ static_path ~ ">" } import = { sharp ~ "include" ~ "<" ~ static_path ~ ">" }
+91 -12
View File
@@ -18,9 +18,7 @@ pub fn parse(source: &str) -> Result<Vec<TopLevel>, ParseError> {
let mut statements = vec![]; let mut statements = vec![];
for pair in pairs.next().unwrap().into_inner() { for pair in pairs.next().unwrap().into_inner() {
if let Ok(stmt) = TopLevel::try_from(pair) { statements.push(TopLevel::from(pair));
statements.push(stmt);
}
} }
Ok(statements) Ok(statements)
@@ -120,14 +118,79 @@ impl From<pest::iterators::Pair<'_, Rule>> for ParamList {
} }
} }
impl TryFrom<pest::iterators::Pair<'_, Rule>> for TopLevel { impl From<pest::iterators::Pair<'_, Rule>> for Attribute {
type Error = (); fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self {
fn try_from(pair: pest::iterators::Pair<Rule>) -> Result<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 rule = pair.as_rule();
let mut inner = pair.into_inner(); let mut inner = pair.into_inner();
match rule { match rule {
Rule::import => Ok(TopLevel::Include(StaticPath::from(inner.next().unwrap()))), Rule::import => TopLevelKind::Include(StaticPath::from(inner.next().unwrap())),
Rule::function_decl => { Rule::function_decl => {
let export = if let Some(first) = inner.peek() { 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()); let body = Block::from(inner.next().unwrap());
Ok(TopLevel::FunctionDecl { TopLevelKind::FunctionDecl {
export, export,
name, name,
params, params,
return_type, return_type,
body, body,
}) }
} }
Rule::struct_decl => { Rule::struct_decl => {
@@ -176,14 +239,14 @@ impl TryFrom<pest::iterators::Pair<'_, Rule>> for TopLevel {
let fields_pair = inner.next().unwrap(); let fields_pair = inner.next().unwrap();
let fields = FieldList::from(fields_pair); let fields = FieldList::from(fields_pair);
Ok(TopLevel::StructDecl { TopLevelKind::StructDecl {
export, export,
name, name,
fields, fields,
}) }
} }
Rule::EOI => Err(()), Rule::EOI => TopLevelKind::EOI,
_ => unimplemented!("{rule:#?}"), _ => 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 { impl From<pest::iterators::Pair<'_, Rule>> for Expression {
fn from(pair: pest::iterators::Pair<Rule>) -> Self { fn from(pair: pest::iterators::Pair<Rule>) -> Self {
let rule = pair.as_rule(); let rule = pair.as_rule();