Fix for latest syn changes

This commit is contained in:
Andrey Tkachenko 2018-10-12 15:23:31 +04:00
parent f5ce2c9564
commit 8e67c1a054
7 changed files with 140 additions and 114 deletions

View File

@ -1,4 +1,4 @@
#![feature(proc_macro_non_items)]
#![feature(proc_macro_hygiene)]
#![allow(dead_code)]
#[macro_use]

View File

@ -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

View 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>
}
}

View File

@ -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 {

View File

@ -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()
}

View File

@ -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()?))
}
}
}

View File

@ -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"))
}
}
}