Add Extra struct / Rename sv-parser-derive to sv-parser-macro

This commit is contained in:
dalance 2019-07-21 15:04:51 +09:00
parent 368a1479aa
commit c6ffc40dab
14 changed files with 275 additions and 88 deletions

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
/target
/sv-parser-derive/target
/sv-parser-macro/target
**/*.rs.bk
Cargo.lock

View File

@ -19,7 +19,7 @@ trace = []
nom = "5.0.0"
nom_locate = { git = "https://github.com/fflorent/nom_locate" }
str-concat = "*"
sv-parser-derive = { path = "./sv-parser-derive" }
sv-parser-macro = { path = "./sv-parser-macro" }
[build-dependencies]
walkdir = "2"

View File

@ -76,3 +76,6 @@ A parser library for System Verilog.
| general | attributes | x | x | x |
| general | comments | x | x | x |
| general | identifiers | x | x | x |
## Test
6.25

View File

@ -2,4 +2,4 @@ pub mod any_node;
pub mod node;
pub use any_node::*;
pub use node::*;
pub use sv_parser_derive::*;
pub use sv_parser_macro::*;

View File

@ -22,7 +22,15 @@ pub use specify_section::*;
pub use udp_declaration_and_instantiation::*;
pub const RECURSIVE_FLAG_WORDS: usize = 1;
pub type Span<'a> = nom_locate::LocatedSpanEx<&'a str, [u128; RECURSIVE_FLAG_WORDS]>;
#[derive(Copy, Clone, Default, Debug, PartialEq)]
pub struct Extra {
#[cfg(feature = "trace")]
pub depth: usize,
pub recursive_flag: [u128; RECURSIVE_FLAG_WORDS],
}
pub type Span<'a> = nom_locate::LocatedSpanEx<&'a str, Extra>;
mod thread_context {

View File

@ -359,3 +359,19 @@ pub fn variable_assignment(s: Span) -> IResult<Span, VariableAssignment> {
let (s, c) = expression(s)?;
Ok((s, VariableAssignment { nodes: (a, b, c) }))
}
// -----------------------------------------------------------------------------
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_blocking_assignment() {
parser_test!(
blocking_assignment,
"idest = new [3] (isrc)",
Ok((_, BlockingAssignment::NonrangeVariable(_)))
);
}
}

View File

@ -128,3 +128,73 @@ pub fn specparam_declaration(s: Span) -> IResult<Span, SpecparamDeclaration> {
},
))
}
// -----------------------------------------------------------------------------
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_local_parameter_declaration() {
parser_test!(
local_parameter_declaration,
"localparam byte colon1 = \":\" ",
Ok((_, LocalParameterDeclaration::Param(_)))
);
}
#[test]
fn test_parameter_declaration() {
parser_test!(
parameter_declaration,
"parameter logic flag = 1 ",
Ok((_, ParameterDeclaration::Param(_)))
);
parser_test!(
parameter_declaration,
"parameter e = 25, f = 9 ",
Ok((_, ParameterDeclaration::Param(_)))
);
parser_test!(
parameter_declaration,
"parameter byte_size = 8, byte_mask = byte_size - 1",
Ok((_, ParameterDeclaration::Param(_)))
);
parser_test!(
parameter_declaration,
"parameter signed [3:0] mux_selector = 0",
Ok((_, ParameterDeclaration::Param(_)))
);
parser_test!(
parameter_declaration,
"parameter real r1 = 3.5e17",
Ok((_, ParameterDeclaration::Param(_)))
);
parser_test!(
parameter_declaration,
"parameter logic [31:0] P1 [3:0] = '{ 1, 2, 3, 4 } ",
Ok((_, ParameterDeclaration::Param(_)))
);
parser_test!(
parameter_declaration,
"parameter r2 = $ ",
Ok((_, ParameterDeclaration::Param(_)))
);
parser_test!(
parameter_declaration,
"parameter type p2 = shortint ",
Ok((_, ParameterDeclaration::Type(_)))
);
}
#[test]
fn test_specparam_declaration() {
parser_test!(specparam_declaration, "specparam delay = 10 ; ", Ok((_, _)));
parser_test!(
specparam_declaration,
"specparam tRise_clk_q = 150, tFall_clk_q = 200;",
Ok((_, _))
);
}
}

View File

@ -22,7 +22,7 @@ pub enum DataType<'a> {
Vector(DataTypeVector<'a>),
Atom(DataTypeAtom<'a>),
NonIntegerType(NonIntegerType<'a>),
Union(Box<DataTypeUnion<'a>>),
StructUnion(Box<DataTypeStructUnion<'a>>),
Enum(DataTypeEnum<'a>),
String(Keyword<'a>),
Chandle(Keyword<'a>),
@ -49,7 +49,7 @@ pub struct DataTypeAtom<'a> {
}
#[derive(Debug, Node)]
pub struct DataTypeUnion<'a> {
pub struct DataTypeStructUnion<'a> {
pub nodes: (
StructUnion<'a>,
Option<(Packed<'a>, Option<Signing<'a>>)>,
@ -301,12 +301,12 @@ pub struct TypeReferenceDataType<'a> {
pub fn casting_type(s: Span) -> IResult<Span, CastingType> {
alt((
map(simple_type, |x| CastingType::SimpleType(Box::new(x))),
map(constant_primary, |x| {
CastingType::ConstantPrimary(Box::new(x))
}),
map(signing, |x| CastingType::Signing(Box::new(x))),
map(keyword("string"), |x| CastingType::String(x)),
map(keyword("const"), |x| CastingType::Const(x)),
map(constant_primary, |x| {
CastingType::ConstantPrimary(Box::new(x))
}),
))(s)
}
@ -316,7 +316,7 @@ pub fn data_type(s: Span) -> IResult<Span, DataType> {
data_type_vector,
data_type_atom,
map(non_integer_type, |x| DataType::NonIntegerType(x)),
data_type_union,
data_type_struct_union,
data_type_enum,
map(keyword("string"), |x| DataType::String(x)),
map(keyword("chandle"), |x| DataType::Chandle(x)),
@ -347,14 +347,14 @@ pub fn data_type_atom(s: Span) -> IResult<Span, DataType> {
}
#[parser]
pub fn data_type_union(s: Span) -> IResult<Span, DataType> {
pub fn data_type_struct_union(s: Span) -> IResult<Span, DataType> {
let (s, a) = struct_union(s)?;
let (s, b) = opt(pair(packed, opt(signing)))(s)?;
let (s, c) = brace(pair(struct_union_member, many0(struct_union_member)))(s)?;
let (s, d) = many0(packed_dimension)(s)?;
Ok((
s,
DataType::Union(Box::new(DataTypeUnion {
DataType::StructUnion(Box::new(DataTypeStructUnion {
nodes: (a, b, c, d),
})),
))
@ -674,3 +674,44 @@ pub fn type_reference_data_type(s: Span) -> IResult<Span, TypeReference> {
TypeReference::DataType(TypeReferenceDataType { nodes: (a, b) }),
))
}
// -----------------------------------------------------------------------------
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_data_type() {
parser_test!(
data_type,
"struct { bit [7:0] opcode; bit [23:0] addr; }",
Ok((_, DataType::StructUnion(_)))
);
parser_test!(
data_type,
"struct packed signed { int a; shortint b; byte c; bit [7:0] d; }",
Ok((_, DataType::StructUnion(_)))
);
parser_test!(
data_type,
"union { int i; shortreal f; } ",
Ok((_, DataType::StructUnion(_)))
);
parser_test!(
data_type,
"struct { bit isfloat; union { int i; shortreal f; } n; }",
Ok((_, DataType::StructUnion(_)))
);
parser_test!(
data_type,
"union packed { s_atmcell acell; bit [423:0] bit_slice; bit [52:0][7:0] byte_slice; }",
Ok((_, DataType::StructUnion(_)))
);
parser_test!(
data_type,
"union tagged { void Invalid; int Valid; }",
Ok((_, DataType::StructUnion(_)))
);
}
}

View File

@ -785,5 +785,75 @@ mod tests {
"typedef C::T c_t;",
Ok((_, DataDeclaration::TypeDeclaration(_)))
);
parser_test!(
data_declaration,
"enum {red, yellow, green} light1, light2;",
Ok((_, DataDeclaration::Variable(_)))
);
parser_test!(
data_declaration,
"enum bit [1:0] {IDLE, XX='x, S1=2'b01, S2=2'b10} state, next;",
Ok((_, DataDeclaration::Variable(_)))
);
parser_test!(
data_declaration,
"enum integer {IDLE, XX='x, S1='b01, S2='b10} state, next;",
Ok((_, DataDeclaration::Variable(_)))
);
parser_test!(
data_declaration,
"enum integer {IDLE, XX='x, S1='b01, S2='b10} state, next;",
Ok((_, DataDeclaration::Variable(_)))
);
parser_test!(
data_declaration,
"enum {bronze=3, silver, gold} medal;",
Ok((_, DataDeclaration::Variable(_)))
);
parser_test!(
data_declaration,
"enum {a=3, b=7, c} alphabet;",
Ok((_, DataDeclaration::Variable(_)))
);
parser_test!(
data_declaration,
"enum bit [3:0] {bronze='h3, silver, gold='h5} medal2;",
Ok((_, DataDeclaration::Variable(_)))
);
parser_test!(
data_declaration,
"integer i_array[*];",
Ok((_, DataDeclaration::Variable(_)))
);
parser_test!(
data_declaration,
"bit [20:0] array_b[string];",
Ok((_, DataDeclaration::Variable(_)))
);
parser_test!(
data_declaration,
"event ev_array[myClass];",
Ok((_, DataDeclaration::Variable(_)))
);
parser_test!(
data_declaration,
"int array_name [*];",
Ok((_, DataDeclaration::Variable(_)))
);
parser_test!(
data_declaration,
"int array_name1 [ integer ];",
Ok((_, DataDeclaration::Variable(_)))
);
parser_test!(
data_declaration,
"int a[int] = '{default:1};",
Ok((_, DataDeclaration::Variable(_)))
);
parser_test!(
data_declaration,
"byte q1[$];",
Ok((_, DataDeclaration::Variable(_)))
);
}
}

View File

@ -325,12 +325,12 @@ pub fn conditional_expression(s: Span) -> IResult<Span, ConditionalExpression> {
#[parser]
pub fn constant_expression(s: Span) -> IResult<Span, ConstantExpression> {
alt((
map(constant_primary, |x| {
ConstantExpression::ConstantPrimary(Box::new(x))
}),
constant_expression_unary,
constant_expression_binary,
constant_expression_ternary,
map(constant_primary, |x| {
ConstantExpression::ConstantPrimary(Box::new(x))
}),
))(s)
}
@ -467,7 +467,6 @@ pub fn constant_indexed_range(s: Span) -> IResult<Span, ConstantIndexedRange> {
#[parser]
pub fn expression(s: Span) -> IResult<Span, Expression> {
alt((
map(primary, |x| Expression::Primary(Box::new(x))),
expression_unary,
map(inc_or_dec_expression, |x| {
Expression::IncOrDecExpression(Box::new(x))
@ -483,6 +482,7 @@ pub fn expression(s: Span) -> IResult<Span, Expression> {
map(tagged_union_expression, |x| {
Expression::TaggedUnionExpression(Box::new(x))
}),
map(primary, |x| Expression::Primary(Box::new(x))),
))(s)
}

View File

@ -653,4 +653,13 @@ mod tests {
parser_test!(primary, "$", Ok((_, Primary::Dollar(_))));
parser_test!(primary, "null ", Ok((_, Primary::Null(_))));
}
#[test]
fn test_cast() {
parser_test!(cast, "int'(2.0 * 3.0)", Ok((_, _)));
parser_test!(cast, "shortint'({8'hFA,8'hCE}) ", Ok((_, _)));
parser_test!(cast, "signed'(x)", Ok((_, _)));
parser_test!(cast, "const'(x)", Ok((_, _)));
parser_test!(cast, "type_t'(x)", Ok((_, _)));
}
}

View File

@ -317,15 +317,8 @@ where
pub fn symbol<'a>(t: &'a str) -> impl Fn(Span<'a>) -> IResult<Span<'a>, Symbol<'a>> {
move |s: Span<'a>| {
if cfg!(feature = "trace") {
println!(
"{:<64} : {:<4},{:>032x} : {}",
format!("symbol(\"{}\")", t),
s.offset,
s.extra[0],
s.fragment
);
}
#[cfg(feature = "trace")]
let s = trace(s, &format!("symbol(\"{}\")", t));
let (s, x) = map(ws(tag(t.clone())), |x| Symbol { nodes: x })(s)?;
Ok((clear_recursive_flags(s), x))
}
@ -333,15 +326,8 @@ pub fn symbol<'a>(t: &'a str) -> impl Fn(Span<'a>) -> IResult<Span<'a>, Symbol<'
pub fn keyword<'a>(t: &'a str) -> impl Fn(Span<'a>) -> IResult<Span<'a>, Keyword<'a>> {
move |s: Span<'a>| {
if cfg!(feature = "trace") {
println!(
"{:<64} : {:<4},{:>032x} : {}",
format!("keyword(\"{}\")", t),
s.offset,
s.extra[0],
s.fragment
);
}
#[cfg(feature = "trace")]
let s = trace(s, &format!("keyword(\"{}\")", t));
let (s, x) = map(ws(terminated(tag(t.clone()), peek(none_of(AZ09_)))), |x| {
Keyword { nodes: x }
})(s)?;
@ -354,12 +340,8 @@ where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
if cfg!(feature = "trace") {
println!(
"{:<64} : {:<4},{:>032x} : {}",
"paren", s.offset, s.extra[0], s.fragment
);
}
#[cfg(feature = "trace")]
let s = trace(s, "paren");
let (s, a) = symbol("(")(s)?;
let (s, b) = f(s)?;
let (s, c) = symbol(")")(s)?;
@ -372,12 +354,8 @@ where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
if cfg!(feature = "trace") {
println!(
"{:<64} : {:<4},{:>032x} : {}",
"bracket", s.offset, s.extra[0], s.fragment
);
}
#[cfg(feature = "trace")]
let s = trace(s, "bracket");
let (s, a) = symbol("[")(s)?;
let (s, b) = f(s)?;
let (s, c) = symbol("]")(s)?;
@ -390,12 +368,8 @@ where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
if cfg!(feature = "trace") {
println!(
"{:<64} : {:<4},{:>032x} : {}",
"brace", s.offset, s.extra[0], s.fragment
);
}
#[cfg(feature = "trace")]
let s = trace(s, "brace");
let (s, a) = symbol("{")(s)?;
let (s, b) = f(s)?;
let (s, c) = symbol("}")(s)?;
@ -410,12 +384,8 @@ where
F: Fn(Span<'a>) -> IResult<Span<'a>, O>,
{
move |s: Span<'a>| {
if cfg!(feature = "trace") {
println!(
"{:<64} : {:<4},{:>032x} : {}",
"apostrophe_brace", s.offset, s.extra[0], s.fragment
);
}
#[cfg(feature = "trace")]
let s = trace(s, "apostrophe_brace");
let (s, a) = symbol("'{")(s)?;
let (s, b) = f(s)?;
let (s, c) = symbol("}")(s)?;
@ -522,33 +492,25 @@ pub fn check_recursive_flag(s: Span, id: usize) -> bool {
let upper = id / 128;
let lower = id % 128;
((s.extra[upper] >> lower) & 1) == 1
((s.extra.recursive_flag[upper] >> lower) & 1) == 1
}
pub fn set_recursive_flag(s: Span, id: usize, bit: bool) -> Span {
pub fn set_recursive_flag(mut s: Span, id: usize, bit: bool) -> Span {
let upper = id / 128;
let lower = id % 128;
let val = if bit { 1u128 << lower } else { 0u128 };
let mask = !(1u128 << lower);
let mut extra = s.extra;
extra[upper] = (extra[upper] & mask) | val;
Span {
offset: s.offset,
line: s.line,
fragment: s.fragment,
extra,
}
let mut recursive_flag = s.extra.recursive_flag;
recursive_flag[upper] = (recursive_flag[upper] & mask) | val;
s.extra.recursive_flag = recursive_flag;
s
}
pub fn clear_recursive_flags(s: Span) -> Span {
Span {
offset: s.offset,
line: s.line,
fragment: s.fragment,
extra: [0; RECURSIVE_FLAG_WORDS],
}
pub fn clear_recursive_flags(mut s: Span) -> Span {
s.extra.recursive_flag = [0; RECURSIVE_FLAG_WORDS];
s
}
pub fn is_keyword(s: &Span) -> bool {
@ -560,12 +522,25 @@ pub fn is_keyword(s: &Span) -> bool {
false
}
#[cfg(feature = "trace")]
pub fn trace<'a>(mut s: Span<'a>, name: &str) -> Span<'a> {
println!(
"{:<128} : {:<4},{:>032x} : {}",
format!("{}{}", " ".repeat(s.extra.depth), name),
s.offset,
s.extra.recursive_flag[0],
s.fragment
);
s.extra.depth += 1;
s
}
// -----------------------------------------------------------------------------
#[cfg(test)]
macro_rules! parser_test {
( $x:expr, $y:expr, $z:pat ) => {
let ret = all_consuming($x)(Span::new_extra($y, [0; RECURSIVE_FLAG_WORDS]));
let ret = all_consuming($x)(Span::new_extra($y, Extra::default()));
if let $z = ret {
} else {
assert!(false, "{:?}", ret)

View File

@ -1,11 +1,9 @@
[package]
name = "sv-parser-derive"
name = "sv-parser-macro"
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

View File

@ -180,9 +180,8 @@ fn impl_parser_trace(item: &ItemFn) -> TokenStream {
let ident = &item.ident;
let gen = quote! {
if cfg!(feature = "trace") {
println!("{:<64} : {:<4},{:>032x} : {}", stringify!(#ident), s.offset, s.extra[0], s.fragment);
}
#[cfg(feature = "trace")]
let s = trace(s, stringify!(#ident));
};
gen.into()
}
@ -198,9 +197,8 @@ fn impl_parser_check_recursive_flag(item: &ItemFn) -> TokenStream {
return false
}
}) {
if cfg!(feature = "trace") {
println!("{:<64} : loop detect", stringify!(#ident));
}
#[cfg(feature = "trace")]
println!("{:<128} : loop detect", format!("{}{}", " ".repeat(s.extra.depth), stringify!(#ident)));
return Err(nom::Err::Error(nom::error::make_error(s, nom::error::ErrorKind::Fix)));
}
};
@ -215,9 +213,8 @@ fn impl_parser_set_recursive_flag(item: &ItemFn) -> TokenStream {
if let Some(i) = p.borrow_mut().get(stringify!(#ident)) {
set_recursive_flag(s, i, true)
} else {
if cfg!(feature = "trace") {
println!("{:<64} : allocate failed", stringify!(#ident));
}
#[cfg(feature = "trace")]
println!("{:<128} : allocate failed", format!("{}{}", " ".repeat(s.extra.depth), stringify!(#ident)));
s
}
});