Fix for latest syn changes
This commit is contained in:
parent
f5ce2c9564
commit
8e67c1a054
@ -1,4 +1,4 @@
|
||||
#![feature(proc_macro_non_items)]
|
||||
#![feature(proc_macro_hygiene)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
#[macro_use]
|
||||
|
@ -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
|
||||
proc-macro = true
|
||||
|
15
maple-macro/examples/test1.rs
Normal file
15
maple-macro/examples/test1.rs
Normal file
@ -0,0 +1,15 @@
|
||||
#![feature(proc_macro_hygiene)]
|
||||
use maple_macro::view;
|
||||
|
||||
fn main() {
|
||||
view! {
|
||||
<test dasdasd="string">
|
||||
<div dasdasd=4.6>
|
||||
"dasdasdasdasdas"
|
||||
{ 1 + 1 }
|
||||
{ ... test() }
|
||||
</div>
|
||||
<div />
|
||||
</test>
|
||||
}
|
||||
}
|
@ -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<Self> {
|
||||
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<Self> {
|
||||
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 {
|
||||
|
@ -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()
|
||||
}
|
@ -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<Self> {
|
||||
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::<Token![...]>()?;
|
||||
let expr = content.parse::<syn::Expr>()?;
|
||||
|
||||
Node::Embed(expr)
|
||||
} else {
|
||||
let expr = content.parse::<syn::Expr>()?;
|
||||
|
||||
Node::Expr(expr)
|
||||
})
|
||||
} else {
|
||||
Ok(Node::Tag(input.parse()?))
|
||||
}
|
||||
}
|
||||
}
|
@ -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<Node>
|
||||
}
|
||||
|
||||
impl Tag {
|
||||
pub fn new(open: TypePath, close: Option<TypePath>, attrs: Vec<Attribute>, body: Vec<Node>) -> Result<Self, String> {
|
||||
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<Self> {
|
||||
let mut attrs: Vec<Attribute> = Vec::new();
|
||||
let mut children: Vec<Node> = Vec::new();
|
||||
let mut open_path: TypePath;
|
||||
let mut close_path: TypePath;
|
||||
|
||||
// parsing opening "<"
|
||||
input.parse::<Token![<]>()?;
|
||||
|
||||
// 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::<Token![/]>()?;
|
||||
input.parse::<Token![>]>()?;
|
||||
|
||||
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::<Token![>]>()?;
|
||||
|
||||
// parsing children
|
||||
while !(input.peek(Token![<]) && input.peek2(Token![/])) {
|
||||
children.push(input.parse()?);
|
||||
}
|
||||
|
||||
// parsing closing "</{tag path}>"
|
||||
input.parse::<Token![<]>()?;
|
||||
input.parse::<Token![/]>()?;
|
||||
close_path = input.parse()?;
|
||||
input.parse::<Token![>]>()?;
|
||||
}
|
||||
|
||||
if close_path == open_path {
|
||||
Ok(Tag {
|
||||
path: open_path,
|
||||
attributes: attrs,
|
||||
body: children,
|
||||
})
|
||||
} else {
|
||||
Err(input.error("open and close paths shoud match"))
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user