ast: Add metadata attributes on Items
TODO: decide what other places attributes belong
This commit is contained in:
parent
9806e95247
commit
325498ac8b
@ -8,7 +8,11 @@ Visibility = "pub"? ;
|
|||||||
File = Item* EOI ;
|
File = Item* EOI ;
|
||||||
|
|
||||||
|
|
||||||
Item = Visibility ItemKind ;
|
Attrs = ('#' '[' (Meta ',') Meta? ']')* ;
|
||||||
|
Meta = Identifier ('=' Literal | '(' (Literal ',')* Literal? ')')? ;
|
||||||
|
|
||||||
|
|
||||||
|
Item = Attrs* Visibility ItemKind ;
|
||||||
ItemKind = Const | Static | Module
|
ItemKind = Const | Static | Module
|
||||||
| Function | Struct | Enum
|
| Function | Struct | Enum
|
||||||
| Alias | Impl ;
|
| Alias | Impl ;
|
||||||
|
@ -32,11 +32,31 @@ pub struct File {
|
|||||||
pub items: Vec<Item>,
|
pub items: Vec<Item>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Metadata decorators
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Attrs {
|
||||||
|
pub meta: Vec<Meta>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Meta {
|
||||||
|
pub name: Identifier,
|
||||||
|
pub kind: MetaKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum MetaKind {
|
||||||
|
Plain,
|
||||||
|
Equals(Literal),
|
||||||
|
Func(Vec<Literal>),
|
||||||
|
}
|
||||||
|
|
||||||
// Items
|
// Items
|
||||||
/// Stores an [ItemKind] and associated metadata
|
/// Stores an [ItemKind] and associated metadata
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct Item {
|
pub struct Item {
|
||||||
pub extents: Span,
|
pub extents: Span,
|
||||||
|
pub attrs: Attrs,
|
||||||
pub vis: Visibility,
|
pub vis: Visibility,
|
||||||
pub kind: ItemKind,
|
pub kind: ItemKind,
|
||||||
}
|
}
|
||||||
|
@ -77,10 +77,39 @@ mod display {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for Attrs {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let Self { meta } = self;
|
||||||
|
if meta.is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
"#".fmt(f)?;
|
||||||
|
delimit(separate(meta, ", "), INLINE_SQUARE)(f)?;
|
||||||
|
"\n".fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Display for Meta {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let Self { name, kind } = self;
|
||||||
|
write!(f, "{name}{kind}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Display for MetaKind {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
MetaKind::Plain => Ok(()),
|
||||||
|
MetaKind::Equals(v) => write!(f, " = {v}"),
|
||||||
|
MetaKind::Func(args) => delimit(separate(args, ", "), INLINE_PARENS)(f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for Item {
|
impl Display for Item {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
self.vis.fmt(f)?;
|
let Self { extents: _, attrs, vis, kind } = self;
|
||||||
match &self.kind {
|
attrs.fmt(f)?;
|
||||||
|
vis.fmt(f)?;
|
||||||
|
match kind {
|
||||||
ItemKind::Alias(v) => v.fmt(f),
|
ItemKind::Alias(v) => v.fmt(f),
|
||||||
ItemKind::Const(v) => v.fmt(f),
|
ItemKind::Const(v) => v.fmt(f),
|
||||||
ItemKind::Static(v) => v.fmt(f),
|
ItemKind::Static(v) => v.fmt(f),
|
||||||
|
@ -68,6 +68,9 @@ pub mod error {
|
|||||||
pub enum Parsing {
|
pub enum Parsing {
|
||||||
File,
|
File,
|
||||||
|
|
||||||
|
Attrs,
|
||||||
|
Meta,
|
||||||
|
|
||||||
Item,
|
Item,
|
||||||
Visibility,
|
Visibility,
|
||||||
Mutability,
|
Mutability,
|
||||||
@ -161,6 +164,10 @@ pub mod error {
|
|||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Parsing::File => "a file",
|
Parsing::File => "a file",
|
||||||
|
|
||||||
|
Parsing::Attrs => "an attribute-set",
|
||||||
|
Parsing::Meta => "an attribute",
|
||||||
|
|
||||||
Parsing::Item => "an item",
|
Parsing::Item => "an item",
|
||||||
Parsing::Visibility => "a visibility qualifier",
|
Parsing::Visibility => "a visibility qualifier",
|
||||||
Parsing::Mutability => "a mutability qualifier",
|
Parsing::Mutability => "a mutability qualifier",
|
||||||
@ -371,7 +378,8 @@ fn rep<'t, T>(
|
|||||||
|
|
||||||
/// Expands to a pattern which matches item-like [Token] [Type]s
|
/// Expands to a pattern which matches item-like [Token] [Type]s
|
||||||
macro item_like() {
|
macro item_like() {
|
||||||
Type::Keyword(
|
Type::Hash
|
||||||
|
| Type::Keyword(
|
||||||
Keyword::Pub
|
Keyword::Pub
|
||||||
| Keyword::Type
|
| Keyword::Type
|
||||||
| Keyword::Const
|
| Keyword::Const
|
||||||
@ -406,6 +414,7 @@ impl<'t> Parser<'t> {
|
|||||||
let start = self.loc();
|
let start = self.loc();
|
||||||
Ok(Item {
|
Ok(Item {
|
||||||
vis: self.visibility()?,
|
vis: self.visibility()?,
|
||||||
|
attrs: self.attributes()?,
|
||||||
kind: self.itemkind()?,
|
kind: self.itemkind()?,
|
||||||
extents: Span(start, self.loc()),
|
extents: Span(start, self.loc()),
|
||||||
})
|
})
|
||||||
@ -464,6 +473,41 @@ impl<'t> Parser<'t> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Attribute parsing
|
||||||
|
impl<'t> Parser<'t> {
|
||||||
|
/// Parses an [attribute set](Attrs)
|
||||||
|
pub fn attributes(&mut self) -> PResult<Attrs> {
|
||||||
|
if self.match_type(Type::Hash, Parsing::Attrs).is_err() {
|
||||||
|
return Ok(Attrs { meta: vec![] });
|
||||||
|
}
|
||||||
|
let meta = delim(
|
||||||
|
sep(Self::meta, Type::Comma, BRACKETS.1, Parsing::Attrs),
|
||||||
|
BRACKETS,
|
||||||
|
Parsing::Attrs,
|
||||||
|
);
|
||||||
|
Ok(Attrs { meta: meta(self)? })
|
||||||
|
}
|
||||||
|
pub fn meta(&mut self) -> PResult<Meta> {
|
||||||
|
Ok(Meta { name: self.identifier()?, kind: self.meta_kind()? })
|
||||||
|
}
|
||||||
|
pub fn meta_kind(&mut self) -> PResult<MetaKind> {
|
||||||
|
const PARSING: Parsing = Parsing::Meta;
|
||||||
|
let lit_tuple = delim(
|
||||||
|
sep(Self::literal, Type::Comma, PARENS.1, PARSING),
|
||||||
|
PARENS,
|
||||||
|
PARSING,
|
||||||
|
);
|
||||||
|
Ok(match self.peek_type(PARSING) {
|
||||||
|
Ok(Type::Eq) => {
|
||||||
|
self.consume_peeked();
|
||||||
|
MetaKind::Equals(self.literal()?)
|
||||||
|
}
|
||||||
|
Ok(Type::LParen) => MetaKind::Func(lit_tuple(self)?),
|
||||||
|
_ => MetaKind::Plain,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Item parsing
|
/// Item parsing
|
||||||
impl<'t> Parser<'t> {
|
impl<'t> Parser<'t> {
|
||||||
/// Parses an [ItemKind]
|
/// Parses an [ItemKind]
|
||||||
|
Loading…
Reference in New Issue
Block a user