From 8e67c1a0540ceea8efaf792c52032ee86b8c7f39 Mon Sep 17 00:00:00 2001 From: Andrey Tkachenko Date: Fri, 12 Oct 2018 15:23:31 +0400 Subject: [PATCH] Fix for latest syn changes --- maple-examples/examples/simple.rs | 2 +- maple-macro/Cargo.toml | 3 +- maple-macro/examples/test1.rs | 15 +++++ maple-macro/src/attribute.rs | 51 +++++++++-------- maple-macro/src/lib.rs | 40 +++++++------- maple-macro/src/node.rs | 52 +++++++++--------- maple-macro/src/tag.rs | 91 ++++++++++++++++--------------- 7 files changed, 140 insertions(+), 114 deletions(-) create mode 100644 maple-macro/examples/test1.rs diff --git a/maple-examples/examples/simple.rs b/maple-examples/examples/simple.rs index b320c96..fad12c8 100644 --- a/maple-examples/examples/simple.rs +++ b/maple-examples/examples/simple.rs @@ -1,4 +1,4 @@ -#![feature(proc_macro_non_items)] +#![feature(proc_macro_hygiene)] #![allow(dead_code)] #[macro_use] diff --git a/maple-macro/Cargo.toml b/maple-macro/Cargo.toml index 273c9c4..d238736 100644 --- a/maple-macro/Cargo.toml +++ b/maple-macro/Cargo.toml @@ -11,6 +11,7 @@ syn = {version = "*", features=["full", "extra-traits"]} quote = "*" proc-macro2 = {version = "*", features=["nightly", "proc-macro"]} maple-core = { path="../maple-core" } +nom = "4.1.0" [lib] -proc-macro = true \ No newline at end of file +proc-macro = true diff --git a/maple-macro/examples/test1.rs b/maple-macro/examples/test1.rs new file mode 100644 index 0000000..caef185 --- /dev/null +++ b/maple-macro/examples/test1.rs @@ -0,0 +1,15 @@ +#![feature(proc_macro_hygiene)] +use maple_macro::view; + +fn main() { + view! { + +
+ "dasdasdasdasdas" + { 1 + 1 } + { ... test() } +
+
+ + } +} \ No newline at end of file diff --git a/maple-macro/src/attribute.rs b/maple-macro/src/attribute.rs index 767176f..b8d2a70 100644 --- a/maple-macro/src/attribute.rs +++ b/maple-macro/src/attribute.rs @@ -1,39 +1,42 @@ -use syn::{Expr, ExprLit, Ident}; -use syn::synom::Synom; +use syn::parse::{Parse, ParseStream, Result}; use quote::ToTokens; #[derive(Debug)] crate struct Attribute { - pub name: Ident, + pub name: syn::Ident, + eq: Token![=], pub value: AttributeValue } -impl Synom for Attribute { - named!(parse -> Self, do_parse!( - name: syn!(Ident) >> - punct!(=) >> - value: syn!(AttributeValue) >> - - (Attribute { name, value }) - )); +impl Parse for Attribute { + fn parse(input: ParseStream) -> Result { + Ok(Self { + name: input.parse()?, + eq: input.parse()?, + value: input.parse()?, + }) + } } #[derive(Debug)] -crate enum AttributeValue { - Expr(Expr), - Literal(ExprLit) +pub enum AttributeValue { + Expr(syn::Expr), + Literal(syn::Lit) } -impl Synom for AttributeValue { - named!(parse -> Self, do_parse!( - value: alt!( - syn!(ExprLit) => { |d| AttributeValue::Literal(d) } - | - braces!(syn!(Expr)) => { |d| AttributeValue::Expr(d.1) } - ) >> - - (value) - )); +impl Parse for AttributeValue { + fn parse(input: ParseStream) -> Result { + if input.peek(syn::Lit) { + Ok(AttributeValue::Literal(input.parse()?)) + } else if input.peek(syn::token::Brace) { + let content; + braced!(content in input); + + Ok(AttributeValue::Expr(content.parse()?)) + } else { + Err(input.error("Expected a literal or { expression }")) + } + } } impl ToTokens for AttributeValue { diff --git a/maple-macro/src/lib.rs b/maple-macro/src/lib.rs index c9d15fd..3d8a366 100644 --- a/maple-macro/src/lib.rs +++ b/maple-macro/src/lib.rs @@ -1,3 +1,4 @@ + #![feature(crate_visibility_modifier)] mod attribute; mod node; @@ -8,16 +9,15 @@ extern crate syn; #[macro_use] extern crate quote; +extern crate proc_macro; -use proc_macro::{TokenStream}; -use syn::synom::Synom; +use self::proc_macro::{TokenStream}; use syn::{TypePath, Ident, Expr}; -use syn::buffer::{TokenBuffer}; -// use syn::parsers::{named, do_parse, punct, syn, call, alt, braces, many0}; use quote::*; use self::node::Node; use self::attribute::{Attribute, AttributeValue}; +use self::tag::Tag; fn visit_attribute(ident: &Ident, attr: &Attribute, _ctx: &TypePath) -> impl ToTokens { let attr_name = &attr.name; @@ -110,25 +110,25 @@ fn visit_node(parent: &str, idx: &mut u32, node: &Node, stream: &mut proc_macro2 #[proc_macro] pub fn view(input: TokenStream) -> TokenStream { - let buffer = TokenBuffer::new(input); - let cursor = buffer.begin(); - let res = Node::parse(cursor); + let toks = match syn::parse(input) { + Ok(root) => { + let mut output = proc_macro2::TokenStream::new(); + let mut thread = proc_macro2::TokenStream::new(); - let mut output = proc_macro2::TokenStream::new(); - let mut thread = proc_macro2::TokenStream::new(); - let mut idx = 0; + let mut idx = 0; - match res { - Ok((root, _)) => visit_node("default", &mut idx, &root, &mut output, &mut thread), - Err(err) => panic!("Error: {:?}", err) + visit_node("default", &mut idx, &root, &mut output, &mut thread); + + quote! {{ + let ctx_default = DefaultContext; + #output + #thread + p0 + }} + } + + Err(err) => err.to_compile_error() }; - let toks = quote! {{ - let ctx_default = DefaultContext; - #output - #thread - p0 - }}; - toks.into() } \ No newline at end of file diff --git a/maple-macro/src/node.rs b/maple-macro/src/node.rs index b064911..81c0848 100644 --- a/maple-macro/src/node.rs +++ b/maple-macro/src/node.rs @@ -1,34 +1,36 @@ -use syn::synom::Synom; -use syn::{LitStr, Expr}; -use crate::tag::Tag; +use syn::parse::{Parse, ParseStream, Result}; +use quote::ToTokens; +use crate::tag::Tag; #[derive(Debug)] crate enum Node { Tag(Tag), - Text(LitStr), - Expr(Expr), - Embed(Expr) + Text(syn::LitStr), + Expr(syn::Expr), + Embed(syn::Expr) } -impl Synom for Node { - named!(parse -> Self, do_parse!( - value: alt!( - syn!(Tag) => { |tag| Node::Tag(tag) } - | - braces!( - do_parse!( - punct!(.) >> - punct!(.) >> - punct!(.) >> - tt: syn!(Expr) >> (tt) - )) => { |d| Node::Embed(d.1) } - | - braces!(syn!(Expr)) => { |d| Node::Expr(d.1) } - | - syn!(LitStr) => { |_str| Node::Text(_str) } - ) >> +impl Parse for Node { + fn parse(input: ParseStream) -> Result { + if input.peek(syn::LitStr) { + Ok(Node::Text(input.parse()?)) + } else if input.peek(syn::token::Brace) { + let content; + braced!(content in input); - (value) - )); + Ok(if content.peek(Token![...]) { + content.parse::()?; + let expr = content.parse::()?; + + Node::Embed(expr) + } else { + let expr = content.parse::()?; + + Node::Expr(expr) + }) + } else { + Ok(Node::Tag(input.parse()?)) + } + } } \ No newline at end of file diff --git a/maple-macro/src/tag.rs b/maple-macro/src/tag.rs index 46bfca5..eeb965f 100644 --- a/maple-macro/src/tag.rs +++ b/maple-macro/src/tag.rs @@ -1,7 +1,7 @@ use crate::attribute::Attribute; use crate::node::Node; use syn::TypePath; -use syn::synom::Synom; +use syn::parse::{Parse, ParseStream, Result}; #[derive(Debug)] crate struct Tag { @@ -10,49 +10,54 @@ crate struct Tag { pub body: Vec } -impl Tag { - pub fn new(open: TypePath, close: Option, attrs: Vec, body: Vec) -> Result { - if let Some(close_ref) = &close { - if &open != close_ref { - return Err(format!("Open({}) and closing({}) tags are not matching!", quote!{#open}, quote!{#close_ref})) - } +impl Parse for Tag { + fn parse(input: ParseStream) -> Result { + let mut attrs: Vec = Vec::new(); + let mut children: Vec = Vec::new(); + let mut open_path: TypePath; + let mut close_path: TypePath; + + // parsing opening "<" + input.parse::()?; + + // parsing tag name + open_path = input.parse()?; + + // parsing attributes + while input.peek(syn::Ident) { + attrs.push(input.parse()?); } - Ok(Tag { - path: open, - attributes: attrs, - body - }) - } -} + if input.peek(Token![/]) && input.peek2(Token![>]) { + // parsing closing "/>" + input.parse::()?; + input.parse::]>()?; -impl Synom for Tag { - named!(parse -> Self, do_parse!( - t: alt!( - do_parse!( - punct!(<) >> - open: syn!(TypePath) >> - attrs: many0!(syn!(Attribute)) >> - punct!(>) >> - body: many0!(syn!(Node)) >> - punct!(<) >> punct!(/) >> - close: syn!(TypePath) >> - punct!(>) >> - - (match Tag::new(open, Some(close), attrs, body) { - Ok(v) => v, - Err(e) => panic!("{:?}", e) - }) - ) => {|x|x} - | - do_parse!( - punct!(<) >> - open: syn!(TypePath) >> - attrs: many0!(syn!(Attribute)) >> - punct!(/) >> - punct!(>) >> - (Tag::new(open, None, attrs, vec![]).unwrap()) - ) => {|x|x} - ) >> (t) - )); + close_path = open_path.clone(); + } else { + // parsing closing ">" + input.parse::]>()?; + + // parsing children + while !(input.peek(Token![<]) && input.peek2(Token![/])) { + children.push(input.parse()?); + } + + // parsing closing "" + input.parse::()?; + input.parse::()?; + close_path = input.parse()?; + input.parse::]>()?; + } + + if close_path == open_path { + Ok(Tag { + path: open_path, + attributes: attrs, + body: children, + }) + } else { + Err(input.error("open and close paths shoud match")) + } + } } \ No newline at end of file