diff --git a/enterprise-macros/src/ast.rs b/enterprise-macros/src/ast.rs index 40f9994..c131e65 100644 --- a/enterprise-macros/src/ast.rs +++ b/enterprise-macros/src/ast.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + #[derive(Debug)] pub enum Toplevel { Use(Use), @@ -10,11 +12,23 @@ pub struct Use(pub Vec); #[derive(Debug)] pub struct Component { pub name: String, + pub body: Vec, } #[derive(Debug)] pub enum ComponentBody { Constructor(), - View(), + View(Rsx), Fn(), } + +#[derive(Debug)] +pub enum Rsx { + Tag { + tag: String, + attrs: HashMap, + inner: Vec, + }, + CodeSegment(String), + Text(String), +} \ No newline at end of file diff --git a/enterprise-macros/src/parser.lalrpop b/enterprise-macros/src/parser.lalrpop index b267de1..7258f14 100644 --- a/enterprise-macros/src/parser.lalrpop +++ b/enterprise-macros/src/parser.lalrpop @@ -1,4 +1,5 @@ use std::iter::FromIterator; +use std::collections::HashMap; use proc_macro2::{Ident, Punct, TokenTree, Delimiter, TokenStream, Group, Spacing, Literal}; @@ -22,6 +23,7 @@ Component: Component = { "component" > => { Component { name: name.to_string(), + body, } } }; @@ -30,8 +32,8 @@ ComponentBody: ComponentBody = { "constructor" "(" ")" BraceGrouper => { ComponentBody::Constructor() }, - "view" BraceGrouper => { - ComponentBody::View() + "view" > => { + ComponentBody::View(rsx) }, "fn" Ident "(" Delim ")" BraceGrouper => { ComponentBody::Fn() @@ -44,6 +46,29 @@ Arg: () = { Ident ":" Ident => {}, }; +Rsx: Rsx = { + "<" "/" ">" => { Rsx::Tag { tag: tag.to_string(), attrs, inner: Vec::new(), } }, + "<" ">" "<" "/" ">" => { + assert_eq!(tag, closeTag, "Tags {} and {} do not match.", tag, closeTag); + Rsx::Tag { tag: tag.to_string(), attrs, inner } + }, + BraceGrouper => { Rsx::CodeSegment(<>.to_string()) }, + AnyText => { Rsx::Text(<>) }, +}; + +Attrs: HashMap = { + (AttrLhs "=" BraceGrouper)* => { + <>.into_iter() + .map(|(lhs, _, rhs)| (lhs.to_string(), rhs.to_string())) + .collect() + } +}; + +AttrLhs: String = { + ":" => format!("{}:{}", a, b), + Ident => <>.to_string(), +}; + // pub ArbitraryBlocks: Vec = AnyToken*; @@ -58,6 +83,12 @@ BraceGrouper: TokenTree = { "{" "}" => TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::from_iter(b.into_iter()))), }; +AnyText: String = { + Ident => <>.to_string(), + Punct => <>.to_string(), + Literal => <>.to_string(), +}; + AnyToken: TokenTree = { Grouper => <>, @@ -70,6 +101,10 @@ AnyToken: TokenTree = { ":" => TokenTree::Punct(Punct::new(':', Spacing::Alone)), ";" => TokenTree::Punct(Punct::new(';', Spacing::Alone)), "," => TokenTree::Punct(Punct::new(',', Spacing::Alone)), + "<" => TokenTree::Punct(Punct::new('<', Spacing::Alone)), + ">" => TokenTree::Punct(Punct::new('>', Spacing::Alone)), + "/" => TokenTree::Punct(Punct::new('/', Spacing::Alone)), + "=" => TokenTree::Punct(Punct::new('=', Spacing::Alone)), Ident => TokenTree::Ident(<>), Punct => TokenTree::Punct(<>), @@ -115,6 +150,10 @@ extern { ")" => TokenType::Punct(')', _), "[" => TokenType::Punct('[', _), "]" => TokenType::Punct(']', _), + "<" => TokenType::Punct('<', _), + ">" => TokenType::Punct('>', _), + "/" => TokenType::Punct('/', _), + "=" => TokenType::Punct('=', _), Punct => TokenType::Punct(_, ), Ident => TokenType::Ident(),