Working parser for attributes
This commit is contained in:
@@ -78,7 +78,6 @@ pub enum TopLevelKind {
|
|||||||
return_type: TypeExpr,
|
return_type: TypeExpr,
|
||||||
body: Block,
|
body: Block,
|
||||||
},
|
},
|
||||||
EOI,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ meta_list = {
|
|||||||
meta ~ ("," ~ meta)* ~ ","?
|
meta ~ ("," ~ meta)* ~ ","?
|
||||||
}
|
}
|
||||||
|
|
||||||
top_level = { attribute* ~ (import | function_decl | struct_decl) }
|
attributes = { attribute* }
|
||||||
|
|
||||||
|
top_level = { attributes ~ (import | function_decl | struct_decl) }
|
||||||
|
|
||||||
import = { sharp ~ "include" ~ "<" ~ static_path ~ ">" }
|
import = { sharp ~ "include" ~ "<" ~ static_path ~ ">" }
|
||||||
|
|
||||||
|
|||||||
+56
-19
@@ -18,8 +18,10 @@ 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 pair.as_rule() != Rule::EOI {
|
||||||
statements.push(TopLevel::from(pair));
|
statements.push(TopLevel::from(pair));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(statements)
|
Ok(statements)
|
||||||
}
|
}
|
||||||
@@ -120,36 +122,73 @@ impl From<pest::iterators::Pair<'_, Rule>> for ParamList {
|
|||||||
|
|
||||||
impl From<pest::iterators::Pair<'_, Rule>> for Attribute {
|
impl From<pest::iterators::Pair<'_, Rule>> for Attribute {
|
||||||
fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self {
|
fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self {
|
||||||
let rule = pair.as_rule();
|
match pair.as_rule() {
|
||||||
|
Rule::attribute => {
|
||||||
// If we start at the top-level #[...], dive into the meta_item
|
// unwrap #[ ... ]
|
||||||
if rule == Rule::attribute {
|
Attribute::from(pair.into_inner().next().unwrap())
|
||||||
return Attribute::from(pair.into_inner().next().unwrap());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rule::meta => {
|
||||||
let mut inner = pair.into_inner();
|
let mut inner = pair.into_inner();
|
||||||
|
|
||||||
|
// first item is always the path
|
||||||
let path = StaticPath::from(inner.next().unwrap());
|
let path = StaticPath::from(inner.next().unwrap());
|
||||||
|
|
||||||
let kind = match rule {
|
// check what comes next
|
||||||
_ => unimplemented!("{:?}", rule),
|
match inner.next() {
|
||||||
};
|
None => {
|
||||||
|
// #[path]
|
||||||
|
Attribute::Path(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(next) => match next.as_rule() {
|
||||||
|
Rule::primary => {
|
||||||
|
// #[path = literal]
|
||||||
|
Attribute::NameValue {
|
||||||
|
path,
|
||||||
|
value: Literal::from(next),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rule::meta_list => {
|
||||||
|
// #[path(...)]
|
||||||
|
let items = next.into_inner().map(Attribute::from).collect();
|
||||||
|
|
||||||
|
Attribute::List { path, items }
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => unreachable!("unexpected rule in meta: {:?}", next.as_rule()),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rule::meta_list => {
|
||||||
|
// This case usually won't be hit directly,
|
||||||
|
// but it's nice to keep it safe if reused
|
||||||
|
let items = pair.into_inner().map(Attribute::from).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// NOTE: this shouldn't normally construct an Attribute alone
|
||||||
|
// but you can panic or wrap depending on your design
|
||||||
|
panic!("meta_list should be handled inside meta: {:?}", items);
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => unreachable!("unexpected rule: {:?}", pair.as_rule()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<pest::iterators::Pair<'_, Rule>> for TopLevel {
|
impl From<pest::iterators::Pair<'_, Rule>> for TopLevel {
|
||||||
fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self {
|
fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self {
|
||||||
let mut inner = pair.into_inner();
|
let mut inner = pair.into_inner();
|
||||||
let mut attributes = Vec::new();
|
|
||||||
|
|
||||||
while inner
|
let attributes = inner
|
||||||
.peek()
|
.next()
|
||||||
.map(|v| v.as_rule() == Rule::attribute)
|
.unwrap()
|
||||||
.unwrap_or_default()
|
.into_inner()
|
||||||
{
|
.map(Attribute::from)
|
||||||
attributes.push(Attribute::from(inner.next().unwrap()));
|
.collect::<Vec<_>>();
|
||||||
}
|
|
||||||
|
|
||||||
TopLevel(inner.next().unwrap().into(), attributes)
|
TopLevel(TopLevelKind::from(inner.next().unwrap()), attributes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,8 +253,6 @@ impl From<pest::iterators::Pair<'_, Rule>> for TopLevelKind {
|
|||||||
fields,
|
fields,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rule::EOI => TopLevelKind::EOI,
|
|
||||||
_ => unimplemented!("{rule:#?}"),
|
_ => unimplemented!("{rule:#?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -285,7 +285,6 @@ impl ToRust for TopLevelKind {
|
|||||||
cg.indent -= 1;
|
cg.indent -= 1;
|
||||||
cg.addln("}\n");
|
cg.addln("}\n");
|
||||||
}
|
}
|
||||||
Self::EOI => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user