brisk_it/component.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
//! Data structure created from parsing a declarative component.
use syn::{parse::Parse, Token};
/// Represents a property in a component.
///
/// ```
/// identifier: some+expression
/// ```
///
/// In which case, the `identifier` is stored in the `name` field, while `some+expression` is in `expr`.
#[derive(Debug)]
pub struct PropertyValue {
/// name of the property
pub name: syn::Ident,
#[allow(missing_docs)]
pub colon_token: Token![:],
/// Expression of the property
pub expr: syn::Expr,
}
/// Intermediary structure used for parsing
#[derive(Debug)]
enum ComponentContent {
Id(syn::Ident),
Property(PropertyValue),
Child(ComponentInput),
}
/// Represents a component
/// ```
/// Identifier
/// {
/// id: some_name
/// prop1: value1
/// Child
/// {
/// prop2: value2
/// }
/// }
/// ```
///
/// `Identifier` is stored in the `name` field, while `prop1/value1` are in the list of `properties`.
/// And `Child` is in the list of `children`.
#[derive(Debug)]
pub struct ComponentInput {
/// Name of the component
pub name: syn::Ident,
#[allow(missing_docs)]
pub brace_token: syn::token::Brace,
/// Identifier, used for storing in a variable
pub id: Option<syn::Ident>,
/// List of properties
pub properties: Vec<PropertyValue>,
/// List of children
pub children: Vec<ComponentInput>,
}
impl Parse for ComponentContent {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
if input.peek2(Token![:]) {
let lookahead1 = input.lookahead1();
if lookahead1.peek(syn::Ident) {
let name: syn::Ident = input.parse()?;
if name == "id" {
let _: Token![:] = input.parse()?;
let id: syn::Ident = input.parse()?;
Ok(ComponentContent::Id(id))
} else {
let colon_token: Token![:] = input.parse()?;
let expr: syn::Expr = input.parse()?;
Ok(ComponentContent::Property(PropertyValue {
name,
colon_token,
expr,
}))
}
} else {
Err(lookahead1.error())
}
} else {
Ok(Self::Child(ComponentInput::parse(input)?))
}
}
}
impl syn::parse::Parse for ComponentInput {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let name = input.parse::<syn::Ident>()?;
let unparsed_content;
let brace_token = syn::braced!(unparsed_content in input);
let content = unparsed_content.parse_terminated(ComponentContent::parse, Token![,])?;
let mut id = Default::default();
let mut properties: Vec<PropertyValue> = Default::default();
let mut children: Vec<ComponentInput> = Default::default();
for item in content {
match item {
ComponentContent::Id(idid) => id = Some(idid),
ComponentContent::Property(prop) => {
properties.push(prop);
}
ComponentContent::Child(child) => {
children.push(child);
}
}
}
Ok(Self {
name,
brace_token,
id,
properties,
children,
})
}
}