From c6ffc40dab430ed137c0f56001129d6d8b4a8a33 Mon Sep 17 00:00:00 2001 From: dalance Date: Sun, 21 Jul 2019 15:04:51 +0900 Subject: [PATCH] Add Extra struct / Rename sv-parser-derive to sv-parser-macro --- .gitignore | 2 +- Cargo.toml | 2 +- README.md | 3 + src/ast.rs | 2 +- src/parser.rs | 10 +- .../procedural_blocks_and_assignments.rs | 16 ++++ .../module_parameter_declarations.rs | 70 ++++++++++++++ .../declarations/net_and_variable_types.rs | 57 +++++++++-- src/parser/declarations/type_declarations.rs | 70 ++++++++++++++ src/parser/expressions/expressions.rs | 8 +- src/parser/expressions/primaries.rs | 9 ++ src/parser/utils.rs | 95 +++++++------------ .../Cargo.toml | 4 +- .../src/lib.rs | 15 ++- 14 files changed, 275 insertions(+), 88 deletions(-) rename {sv-parser-derive => sv-parser-macro}/Cargo.toml (64%) rename {sv-parser-derive => sv-parser-macro}/src/lib.rs (94%) diff --git a/.gitignore b/.gitignore index 5562a0e..db2cfe7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ /target -/sv-parser-derive/target +/sv-parser-macro/target **/*.rs.bk Cargo.lock diff --git a/Cargo.toml b/Cargo.toml index 7ec6ac4..7b8c78e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/README.md b/README.md index 1128bee..af0df44 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/src/ast.rs b/src/ast.rs index 07f4750..704f898 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -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::*; diff --git a/src/parser.rs b/src/parser.rs index 48d380d..261d65a 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -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 { diff --git a/src/parser/behavioral_statements/procedural_blocks_and_assignments.rs b/src/parser/behavioral_statements/procedural_blocks_and_assignments.rs index 507ef96..5ee9e99 100644 --- a/src/parser/behavioral_statements/procedural_blocks_and_assignments.rs +++ b/src/parser/behavioral_statements/procedural_blocks_and_assignments.rs @@ -359,3 +359,19 @@ pub fn variable_assignment(s: Span) -> IResult { 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(_))) + ); + } +} diff --git a/src/parser/declarations/module_parameter_declarations.rs b/src/parser/declarations/module_parameter_declarations.rs index ac61b13..b37d3b2 100644 --- a/src/parser/declarations/module_parameter_declarations.rs +++ b/src/parser/declarations/module_parameter_declarations.rs @@ -128,3 +128,73 @@ pub fn specparam_declaration(s: Span) -> IResult { }, )) } + +// ----------------------------------------------------------------------------- + +#[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((_, _)) + ); + } +} diff --git a/src/parser/declarations/net_and_variable_types.rs b/src/parser/declarations/net_and_variable_types.rs index db2b4b9..f9b6295 100644 --- a/src/parser/declarations/net_and_variable_types.rs +++ b/src/parser/declarations/net_and_variable_types.rs @@ -22,7 +22,7 @@ pub enum DataType<'a> { Vector(DataTypeVector<'a>), Atom(DataTypeAtom<'a>), NonIntegerType(NonIntegerType<'a>), - Union(Box>), + StructUnion(Box>), 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>)>, @@ -301,12 +301,12 @@ pub struct TypeReferenceDataType<'a> { pub fn casting_type(s: Span) -> IResult { 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 { 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 { } #[parser] -pub fn data_type_union(s: Span) -> IResult { +pub fn data_type_struct_union(s: Span) -> IResult { 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 { 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(_))) + ); + } +} diff --git a/src/parser/declarations/type_declarations.rs b/src/parser/declarations/type_declarations.rs index 7c09a71..06e93d5 100644 --- a/src/parser/declarations/type_declarations.rs +++ b/src/parser/declarations/type_declarations.rs @@ -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(_))) + ); } } diff --git a/src/parser/expressions/expressions.rs b/src/parser/expressions/expressions.rs index e73ea28..4e207e5 100644 --- a/src/parser/expressions/expressions.rs +++ b/src/parser/expressions/expressions.rs @@ -325,12 +325,12 @@ pub fn conditional_expression(s: Span) -> IResult { #[parser] pub fn constant_expression(s: Span) -> IResult { 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 { #[parser] pub fn expression(s: Span) -> IResult { 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 { map(tagged_union_expression, |x| { Expression::TaggedUnionExpression(Box::new(x)) }), + map(primary, |x| Expression::Primary(Box::new(x))), ))(s) } diff --git a/src/parser/expressions/primaries.rs b/src/parser/expressions/primaries.rs index 6db419f..a1db990 100644 --- a/src/parser/expressions/primaries.rs +++ b/src/parser/expressions/primaries.rs @@ -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((_, _))); + } } diff --git a/src/parser/utils.rs b/src/parser/utils.rs index 0f259ce..1d18d23 100644 --- a/src/parser/utils.rs +++ b/src/parser/utils.rs @@ -317,15 +317,8 @@ where pub fn symbol<'a>(t: &'a str) -> impl Fn(Span<'a>) -> IResult, 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, Symbol<' pub fn keyword<'a>(t: &'a str) -> impl Fn(Span<'a>) -> IResult, 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, 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, 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, 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, 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) diff --git a/sv-parser-derive/Cargo.toml b/sv-parser-macro/Cargo.toml similarity index 64% rename from sv-parser-derive/Cargo.toml rename to sv-parser-macro/Cargo.toml index b4d8b85..d627b2c 100644 --- a/sv-parser-derive/Cargo.toml +++ b/sv-parser-macro/Cargo.toml @@ -1,11 +1,9 @@ [package] -name = "sv-parser-derive" +name = "sv-parser-macro" version = "0.1.0" authors = ["dalance "] edition = "2018" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [lib] proc-macro = true diff --git a/sv-parser-derive/src/lib.rs b/sv-parser-macro/src/lib.rs similarity index 94% rename from sv-parser-derive/src/lib.rs rename to sv-parser-macro/src/lib.rs index f5a732a..d0aaa58 100644 --- a/sv-parser-derive/src/lib.rs +++ b/sv-parser-macro/src/lib.rs @@ -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 } });