Add custom derive

This commit is contained in:
dalance 2019-07-11 16:43:33 +09:00
parent 07265d153e
commit fe008b3bad
11 changed files with 277 additions and 42 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
/target /target
/node_derive/target
**/*.rs.bk **/*.rs.bk
Cargo.lock Cargo.lock

View File

@ -14,3 +14,4 @@ edition = "2018"
nom = "5.0.0" nom = "5.0.0"
nom_locate = { git = "https://github.com/fflorent/nom_locate" } nom_locate = { git = "https://github.com/fflorent/nom_locate" }
str-concat = "*" str-concat = "*"
node_derive = { path = "./node_derive" }

View File

@ -54,7 +54,7 @@ A parser library for System Verilog.
| behavioral_statements | case_statements | | | | | behavioral_statements | case_statements | | | |
| behavioral_statements | patterns | | | | | behavioral_statements | patterns | | | |
| behavioral_statements | looping_statements | | | | | behavioral_statements | looping_statements | | | |
| behavioral_statements | subroutine_call_statements | | | | | behavioral_statements | subroutine_call_statements | x | x | |
| behavioral_statements | assertion_statements | | | | | behavioral_statements | assertion_statements | | | |
| behavioral_statements | clocking_block | | | | | behavioral_statements | clocking_block | | | |
| behavioral_statements | randsequence | | | | | behavioral_statements | randsequence | | | |

14
node_derive/Cargo.toml Normal file
View File

@ -0,0 +1,14 @@
[package]
name = "node_derive"
version = "0.1.0"
authors = ["dalance <dalance@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
proc-macro = true
[dependencies]
syn = "0.14.4"
quote = "0.6.3"

110
node_derive/src/lib.rs Normal file
View File

@ -0,0 +1,110 @@
#![recursion_limit = "128"]
extern crate proc_macro;
use crate::proc_macro::TokenStream;
use quote::quote;
use syn;
#[proc_macro_derive(Node)]
pub fn node_derive(input: TokenStream) -> TokenStream {
let ast = syn::parse(input).unwrap();
impl_node(&ast)
}
fn impl_node(ast: &syn::DeriveInput) -> TokenStream {
let name = &ast.ident;
let next = match ast.data {
syn::Data::Enum(ref data) => {
let mut items = quote! {};
for v in &data.variants {
let ident = &v.ident;
let item = quote! {
#name::#ident(x) => { let ret: AnyNode<'a> = x.into(); vec![ret] },
};
items = quote! {
#items
#item
};
}
quote! {
match self {
#items
}
}
}
_ => {
quote! {
vec![]
}
}
};
let gen = quote! {
impl<'a> Node<'a> for #name<'a> {
fn test(&'a self) -> String {
format!("{}", stringify!(#name))
}
fn next(&'a self) -> Vec<AnyNode<'a>> {
#next
}
}
impl<'a> From<&'a #name<'a>> for AnyNode<'a> {
fn from(x: &'a #name<'a>) -> Self {
AnyNode::#name(x)
}
}
impl<'a> IntoIterator for &'a #name<'a> {
type Item = AnyNode<'a>;
type IntoIter = Iter<'a>;
fn into_iter(self) -> Self::IntoIter {
let node: AnyNode<'a> = self.into();
Iter { next: vec![node] }
}
}
};
gen.into()
}
#[proc_macro_derive(AnyNode)]
pub fn any_node_derive(input: TokenStream) -> TokenStream {
let ast = syn::parse(input).unwrap();
impl_any_node(&ast)
}
fn impl_any_node(ast: &syn::DeriveInput) -> TokenStream {
let ref data = match ast.data {
syn::Data::Enum(ref data) => data,
_ => unreachable!(),
};
let mut items = quote! {};
for v in &data.variants {
let ident = &v.ident;
let item = quote! {
AnyNode::#ident(x) => x.next(),
};
items = quote! {
#items
#item
};
}
let name = &ast.ident;
let gen = quote! {
impl<'a> #name<'a> {
fn next(&self) -> Vec<AnyNode<'a>> {
match self {
#items
}
}
}
};
gen.into()
}

View File

@ -1,2 +1,3 @@
#![recursion_limit = "128"] #![recursion_limit = "128"]
pub mod node;
pub mod parser; pub mod parser;

74
src/node.rs Normal file
View File

@ -0,0 +1,74 @@
use crate::parser::*;
use node_derive::AnyNode;
pub trait Node<'a> {
fn test(&'a self) -> String;
fn next(&'a self) -> Vec<AnyNode<'a>>;
}
impl<'a> Node<'a> for Span<'a> {
fn test(&'a self) -> String {
String::from("")
}
fn next(&'a self) -> Vec<AnyNode<'a>> {
vec![]
}
}
impl<'a> From<&'a Span<'a>> for AnyNode<'a> {
fn from(x: &'a Span<'a>) -> Self {
AnyNode::Span(x)
}
}
#[derive(Debug, Clone, AnyNode)]
pub enum AnyNode<'a> {
Span(&'a Span<'a>),
Symbol(&'a Symbol<'a>),
WhiteSpace(&'a WhiteSpace<'a>),
Comment(&'a Comment<'a>),
Number(&'a Number<'a>),
IntegralNumber(&'a IntegralNumber<'a>),
DecimalNumber(&'a DecimalNumber<'a>),
DecimalNumberBaseUnsigned(&'a DecimalNumberBaseUnsigned<'a>),
DecimalNumberBaseXNumber(&'a DecimalNumberBaseXNumber<'a>),
DecimalNumberBaseZNumber(&'a DecimalNumberBaseZNumber<'a>),
BinaryNumber(&'a BinaryNumber<'a>),
OctalNumber(&'a OctalNumber<'a>),
HexNumber(&'a HexNumber<'a>),
Sign(&'a Sign<'a>),
Size(&'a Size<'a>),
NonZeroUnsignedNumber(&'a NonZeroUnsignedNumber<'a>),
RealNumber(&'a RealNumber<'a>),
RealNumberFloating(&'a RealNumberFloating<'a>),
FixedPointNumber(&'a FixedPointNumber<'a>),
Exp(&'a Exp<'a>),
UnsignedNumber(&'a UnsignedNumber<'a>),
BinaryValue(&'a BinaryValue<'a>),
OctalValue(&'a OctalValue<'a>),
HexValue(&'a HexValue<'a>),
DecimalBase(&'a DecimalBase<'a>),
BinaryBase(&'a BinaryBase<'a>),
OctalBase(&'a OctalBase<'a>),
HexBase(&'a HexBase<'a>),
XNumber(&'a XNumber<'a>),
ZNumber(&'a ZNumber<'a>),
UnbasedUnsizedLiteral(&'a UnbasedUnsizedLiteral<'a>),
}
pub struct Iter<'a> {
pub(crate) next: Vec<AnyNode<'a>>,
}
impl<'a> Iterator for Iter<'a> {
type Item = AnyNode<'a>;
fn next(&mut self) -> Option<Self::Item> {
let ret = self.next.pop();
if let Some(x) = ret.clone() {
let mut x = x.next();
self.next.append(&mut x);
}
ret
}
}

View File

@ -8,26 +8,42 @@ use nom::IResult;
#[derive(Debug)] #[derive(Debug)]
pub enum SubroutineCallStatement<'a> { pub enum SubroutineCallStatement<'a> {
SubroutineCall(SubroutineCall<'a>), SubroutineCall((SubroutineCall<'a>, Symbol<'a>)),
FunctionSubroutineCall(FunctionSubroutineCall<'a>), Function(SubroutineCallStatementFunction<'a>),
}
#[derive(Debug)]
pub struct SubroutineCallStatementFunction<'a> {
pub nodes: (
Symbol<'a>,
Symbol<'a>,
Paren<'a, FunctionSubroutineCall<'a>>,
Symbol<'a>,
),
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
pub fn subroutine_call_statement(s: Span) -> IResult<Span, SubroutineCallStatement> { pub fn subroutine_call_statement(s: Span) -> IResult<Span, SubroutineCallStatement> {
alt(( alt((
map(terminated(subroutine_call, symbol(";")), |x| { map(pair(subroutine_call, symbol(";")), |x| {
SubroutineCallStatement::SubroutineCall(x) SubroutineCallStatement::SubroutineCall(x)
}), }),
map( subroutine_call_statement_function,
delimited(
triple(symbol("void"), symbol("'"), symbol("(")),
function_subroutine_call,
pair(symbol(")"), symbol(";")),
),
|x| SubroutineCallStatement::FunctionSubroutineCall(x),
),
))(s) ))(s)
} }
pub fn subroutine_call_statement_function(s: Span) -> IResult<Span, SubroutineCallStatement> {
let (s, a) = symbol("void")(s)?;
let (s, b) = symbol("'")(s)?;
let (s, c) = paren2(function_subroutine_call)(s)?;
let (s, d) = symbol(";")(s)?;
Ok((
s,
SubroutineCallStatement::Function(SubroutineCallStatementFunction {
nodes: (a, b, c, d),
}),
))
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@ -1,4 +1,6 @@
use crate::node::*;
use crate::parser::*; use crate::parser::*;
use node_derive::Node;
use nom::branch::*; use nom::branch::*;
use nom::bytes::complete::*; use nom::bytes::complete::*;
use nom::character::complete::*; use nom::character::complete::*;
@ -9,13 +11,13 @@ use nom::IResult;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#[derive(Debug)] #[derive(Debug, Node)]
pub enum Number<'a> { pub enum Number<'a> {
IntegralNumber(IntegralNumber<'a>), IntegralNumber(IntegralNumber<'a>),
RealNumber(RealNumber<'a>), RealNumber(RealNumber<'a>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub enum IntegralNumber<'a> { pub enum IntegralNumber<'a> {
DecimalNumber(DecimalNumber<'a>), DecimalNumber(DecimalNumber<'a>),
OctalNumber(OctalNumber<'a>), OctalNumber(OctalNumber<'a>),
@ -23,7 +25,7 @@ pub enum IntegralNumber<'a> {
HexNumber(HexNumber<'a>), HexNumber(HexNumber<'a>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub enum DecimalNumber<'a> { pub enum DecimalNumber<'a> {
UnsignedNumber(UnsignedNumber<'a>), UnsignedNumber(UnsignedNumber<'a>),
BaseUnsigned(DecimalNumberBaseUnsigned<'a>), BaseUnsigned(DecimalNumberBaseUnsigned<'a>),
@ -31,59 +33,59 @@ pub enum DecimalNumber<'a> {
BaseZNumber(DecimalNumberBaseZNumber<'a>), BaseZNumber(DecimalNumberBaseZNumber<'a>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct DecimalNumberBaseUnsigned<'a> { pub struct DecimalNumberBaseUnsigned<'a> {
pub nodes: (Option<Size<'a>>, DecimalBase<'a>, UnsignedNumber<'a>), pub nodes: (Option<Size<'a>>, DecimalBase<'a>, UnsignedNumber<'a>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct DecimalNumberBaseXNumber<'a> { pub struct DecimalNumberBaseXNumber<'a> {
pub nodes: (Option<Size<'a>>, DecimalBase<'a>, XNumber<'a>), pub nodes: (Option<Size<'a>>, DecimalBase<'a>, XNumber<'a>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct DecimalNumberBaseZNumber<'a> { pub struct DecimalNumberBaseZNumber<'a> {
pub nodes: (Option<Size<'a>>, DecimalBase<'a>, ZNumber<'a>), pub nodes: (Option<Size<'a>>, DecimalBase<'a>, ZNumber<'a>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct BinaryNumber<'a> { pub struct BinaryNumber<'a> {
pub nodes: (Option<Size<'a>>, BinaryBase<'a>, BinaryValue<'a>), pub nodes: (Option<Size<'a>>, BinaryBase<'a>, BinaryValue<'a>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct OctalNumber<'a> { pub struct OctalNumber<'a> {
pub nodes: (Option<Size<'a>>, OctalBase<'a>, OctalValue<'a>), pub nodes: (Option<Size<'a>>, OctalBase<'a>, OctalValue<'a>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct HexNumber<'a> { pub struct HexNumber<'a> {
pub nodes: (Option<Size<'a>>, HexBase<'a>, HexValue<'a>), pub nodes: (Option<Size<'a>>, HexBase<'a>, HexValue<'a>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub enum Sign<'a> { pub enum Sign<'a> {
Plus(Symbol<'a>), Plus(Symbol<'a>),
Minus(Symbol<'a>), Minus(Symbol<'a>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct Size<'a> { pub struct Size<'a> {
pub nodes: (NonZeroUnsignedNumber<'a>,), pub nodes: (NonZeroUnsignedNumber<'a>,),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct NonZeroUnsignedNumber<'a> { pub struct NonZeroUnsignedNumber<'a> {
pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>), pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub enum RealNumber<'a> { pub enum RealNumber<'a> {
FixedPointNumber(FixedPointNumber<'a>), FixedPointNumber(FixedPointNumber<'a>),
Floating(RealNumberFloating<'a>), Floating(RealNumberFloating<'a>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct RealNumberFloating<'a> { pub struct RealNumberFloating<'a> {
pub nodes: ( pub nodes: (
UnsignedNumber<'a>, UnsignedNumber<'a>,
@ -94,67 +96,67 @@ pub struct RealNumberFloating<'a> {
), ),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct FixedPointNumber<'a> { pub struct FixedPointNumber<'a> {
pub nodes: (UnsignedNumber<'a>, Symbol<'a>, UnsignedNumber<'a>), pub nodes: (UnsignedNumber<'a>, Symbol<'a>, UnsignedNumber<'a>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct Exp<'a> { pub struct Exp<'a> {
pub nodes: (Symbol<'a>,), pub nodes: (Symbol<'a>,),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct UnsignedNumber<'a> { pub struct UnsignedNumber<'a> {
pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>), pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct BinaryValue<'a> { pub struct BinaryValue<'a> {
pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>), pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct OctalValue<'a> { pub struct OctalValue<'a> {
pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>), pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct HexValue<'a> { pub struct HexValue<'a> {
pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>), pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct DecimalBase<'a> { pub struct DecimalBase<'a> {
pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>), pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct BinaryBase<'a> { pub struct BinaryBase<'a> {
pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>), pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct OctalBase<'a> { pub struct OctalBase<'a> {
pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>), pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct HexBase<'a> { pub struct HexBase<'a> {
pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>), pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct XNumber<'a> { pub struct XNumber<'a> {
pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>), pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct ZNumber<'a> { pub struct ZNumber<'a> {
pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>), pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub struct UnbasedUnsizedLiteral<'a> { pub struct UnbasedUnsizedLiteral<'a> {
pub nodes: (Symbol<'a>,), pub nodes: (Symbol<'a>,),
} }
@ -547,4 +549,16 @@ mod tests {
parser_test!(unbased_unsized_literal, "'x", Ok((_, _))); parser_test!(unbased_unsized_literal, "'x", Ok((_, _)));
parser_test!(unbased_unsized_literal, "'z", Ok((_, _))); parser_test!(unbased_unsized_literal, "'z", Ok((_, _)));
} }
#[test]
fn test_node() {
if let Ok((_, x)) = all_consuming(number)(Span::new_extra("10", 0)) {
//assert_eq!(x.test(), "aaaa");
//let y: AnyNode = (&x).into();
for a in &x {
dbg!(a);
//assert_eq!(format!("{:?}", a), "aaa");
}
}
}
} }

View File

@ -1,11 +1,13 @@
use crate::node::*;
use crate::parser::*; use crate::parser::*;
use node_derive::Node;
use nom::branch::*; use nom::branch::*;
use nom::bytes::complete::*; use nom::bytes::complete::*;
use nom::IResult; use nom::IResult;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#[derive(Debug)] #[derive(Debug, Node)]
pub struct Comment<'a> { pub struct Comment<'a> {
nodes: (Span<'a>,), nodes: (Span<'a>,),
} }

View File

@ -1,4 +1,6 @@
use crate::node::*;
use crate::parser::*; use crate::parser::*;
use node_derive::Node;
use nom::branch::*; use nom::branch::*;
use nom::bytes::complete::*; use nom::bytes::complete::*;
use nom::character::complete::*; use nom::character::complete::*;
@ -9,12 +11,12 @@ use nom::{Err, IResult};
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#[derive(Debug)] #[derive(Debug, Node)]
pub struct Symbol<'a> { pub struct Symbol<'a> {
pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>), pub nodes: (Span<'a>, Vec<WhiteSpace<'a>>),
} }
#[derive(Debug)] #[derive(Debug, Node)]
pub enum WhiteSpace<'a> { pub enum WhiteSpace<'a> {
Space(Span<'a>), Space(Span<'a>),
Comment(Comment<'a>), Comment(Comment<'a>),