Attribute parsing and ast
This commit is contained in:
+22
-11
@@ -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>),
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user