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)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -11,6 +11,7 @@ syn = {version = "*", features=["full", "extra-traits"]}
|
|||||||
quote = "*"
|
quote = "*"
|
||||||
proc-macro2 = {version = "*", features=["nightly", "proc-macro"]}
|
proc-macro2 = {version = "*", features=["nightly", "proc-macro"]}
|
||||||
maple-core = { path="../maple-core" }
|
maple-core = { path="../maple-core" }
|
||||||
|
nom = "4.1.0"
|
||||||
|
|
||||||
[lib]
|
[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::parse::{Parse, ParseStream, Result};
|
||||||
use syn::synom::Synom;
|
|
||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
crate struct Attribute {
|
crate struct Attribute {
|
||||||
pub name: Ident,
|
pub name: syn::Ident,
|
||||||
|
eq: Token![=],
|
||||||
pub value: AttributeValue
|
pub value: AttributeValue
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Synom for Attribute {
|
impl Parse for Attribute {
|
||||||
named!(parse -> Self, do_parse!(
|
fn parse(input: ParseStream) -> Result<Self> {
|
||||||
name: syn!(Ident) >>
|
Ok(Self {
|
||||||
punct!(=) >>
|
name: input.parse()?,
|
||||||
value: syn!(AttributeValue) >>
|
eq: input.parse()?,
|
||||||
|
value: input.parse()?,
|
||||||
(Attribute { name, value })
|
})
|
||||||
));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
crate enum AttributeValue {
|
pub enum AttributeValue {
|
||||||
Expr(Expr),
|
Expr(syn::Expr),
|
||||||
Literal(ExprLit)
|
Literal(syn::Lit)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Synom for AttributeValue {
|
impl Parse for AttributeValue {
|
||||||
named!(parse -> Self, do_parse!(
|
fn parse(input: ParseStream) -> Result<Self> {
|
||||||
value: alt!(
|
if input.peek(syn::Lit) {
|
||||||
syn!(ExprLit) => { |d| AttributeValue::Literal(d) }
|
Ok(AttributeValue::Literal(input.parse()?))
|
||||||
|
|
} else if input.peek(syn::token::Brace) {
|
||||||
braces!(syn!(Expr)) => { |d| AttributeValue::Expr(d.1) }
|
let content;
|
||||||
) >>
|
braced!(content in input);
|
||||||
|
|
||||||
(value)
|
Ok(AttributeValue::Expr(content.parse()?))
|
||||||
));
|
} else {
|
||||||
|
Err(input.error("Expected a literal or { expression }"))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToTokens for AttributeValue {
|
impl ToTokens for AttributeValue {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#![feature(crate_visibility_modifier)]
|
||||||
|
|
||||||
mod attribute;
|
mod attribute;
|
||||||
mod node;
|
mod node;
|
||||||
@ -8,16 +9,15 @@ extern crate syn;
|
|||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate quote;
|
extern crate quote;
|
||||||
|
extern crate proc_macro;
|
||||||
|
|
||||||
use proc_macro::{TokenStream};
|
use self::proc_macro::{TokenStream};
|
||||||
use syn::synom::Synom;
|
|
||||||
use syn::{TypePath, Ident, Expr};
|
use syn::{TypePath, Ident, Expr};
|
||||||
use syn::buffer::{TokenBuffer};
|
|
||||||
// use syn::parsers::{named, do_parse, punct, syn, call, alt, braces, many0};
|
|
||||||
use quote::*;
|
use quote::*;
|
||||||
|
|
||||||
use self::node::Node;
|
use self::node::Node;
|
||||||
use self::attribute::{Attribute, AttributeValue};
|
use self::attribute::{Attribute, AttributeValue};
|
||||||
|
use self::tag::Tag;
|
||||||
|
|
||||||
fn visit_attribute(ident: &Ident, attr: &Attribute, _ctx: &TypePath) -> impl ToTokens {
|
fn visit_attribute(ident: &Ident, attr: &Attribute, _ctx: &TypePath) -> impl ToTokens {
|
||||||
let attr_name = &attr.name;
|
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]
|
#[proc_macro]
|
||||||
pub fn view(input: TokenStream) -> TokenStream {
|
pub fn view(input: TokenStream) -> TokenStream {
|
||||||
let buffer = TokenBuffer::new(input);
|
let toks = match syn::parse(input) {
|
||||||
let cursor = buffer.begin();
|
Ok(root) => {
|
||||||
let res = Node::parse(cursor);
|
let mut output = proc_macro2::TokenStream::new();
|
||||||
|
let mut thread = proc_macro2::TokenStream::new();
|
||||||
|
|
||||||
let mut output = proc_macro2::TokenStream::new();
|
let mut idx = 0;
|
||||||
let mut thread = proc_macro2::TokenStream::new();
|
|
||||||
let mut idx = 0;
|
|
||||||
|
|
||||||
match res {
|
visit_node("default", &mut idx, &root, &mut output, &mut thread);
|
||||||
Ok((root, _)) => visit_node("default", &mut idx, &root, &mut output, &mut thread),
|
|
||||||
Err(err) => panic!("Error: {:?}", err)
|
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()
|
toks.into()
|
||||||
}
|
}
|
@ -1,34 +1,36 @@
|
|||||||
use syn::synom::Synom;
|
use syn::parse::{Parse, ParseStream, Result};
|
||||||
use syn::{LitStr, Expr};
|
use quote::ToTokens;
|
||||||
use crate::tag::Tag;
|
|
||||||
|
|
||||||
|
use crate::tag::Tag;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
crate enum Node {
|
crate enum Node {
|
||||||
Tag(Tag),
|
Tag(Tag),
|
||||||
Text(LitStr),
|
Text(syn::LitStr),
|
||||||
Expr(Expr),
|
Expr(syn::Expr),
|
||||||
Embed(Expr)
|
Embed(syn::Expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Synom for Node {
|
impl Parse for Node {
|
||||||
named!(parse -> Self, do_parse!(
|
fn parse(input: ParseStream) -> Result<Self> {
|
||||||
value: alt!(
|
if input.peek(syn::LitStr) {
|
||||||
syn!(Tag) => { |tag| Node::Tag(tag) }
|
Ok(Node::Text(input.parse()?))
|
||||||
|
|
} else if input.peek(syn::token::Brace) {
|
||||||
braces!(
|
let content;
|
||||||
do_parse!(
|
braced!(content in input);
|
||||||
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) }
|
|
||||||
) >>
|
|
||||||
|
|
||||||
(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::attribute::Attribute;
|
||||||
use crate::node::Node;
|
use crate::node::Node;
|
||||||
use syn::TypePath;
|
use syn::TypePath;
|
||||||
use syn::synom::Synom;
|
use syn::parse::{Parse, ParseStream, Result};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
crate struct Tag {
|
crate struct Tag {
|
||||||
@ -10,49 +10,54 @@ crate struct Tag {
|
|||||||
pub body: Vec<Node>
|
pub body: Vec<Node>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tag {
|
impl Parse for Tag {
|
||||||
pub fn new(open: TypePath, close: Option<TypePath>, attrs: Vec<Attribute>, body: Vec<Node>) -> Result<Self, String> {
|
fn parse(input: ParseStream) -> Result<Self> {
|
||||||
if let Some(close_ref) = &close {
|
let mut attrs: Vec<Attribute> = Vec::new();
|
||||||
if &open != close_ref {
|
let mut children: Vec<Node> = Vec::new();
|
||||||
return Err(format!("Open({}) and closing({}) tags are not matching!", quote!{#open}, quote!{#close_ref}))
|
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 {
|
if input.peek(Token![/]) && input.peek2(Token![>]) {
|
||||||
path: open,
|
// parsing closing "/>"
|
||||||
attributes: attrs,
|
input.parse::<Token![/]>()?;
|
||||||
body
|
input.parse::<Token![>]>()?;
|
||||||
})
|
|
||||||
|
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"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|
||||||
));
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user