diff --git a/README.md b/README.md index a53904b..9c40931 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ A parser library for System Verilog. | 3 | x | x | 13 | x | | 23 | | | 33 | | | | 4 | x | x | 14 | x | | 24 | | | 34 | | | | 5 | x | x | 15 | x | | 25 | | | 35 | | | -| 6 | x | | 16 | x | | 26 | | | 36 | | | +| 6 | x | x | 16 | x | | 26 | | | 36 | | | | 7 | x | | 17 | | | 27 | | | 37 | | | | 8 | x | | 18 | | | 28 | | | 38 | | | | 9 | x | | 19 | | | 29 | | | 39 | | | diff --git a/sv-parser-parser/src/expressions/primaries.rs b/sv-parser-parser/src/expressions/primaries.rs index 05157a8..72a16fa 100644 --- a/sv-parser-parser/src/expressions/primaries.rs +++ b/sv-parser-parser/src/expressions/primaries.rs @@ -161,7 +161,13 @@ pub(crate) fn primary(s: Span) -> IResult { }), map(primary_literal, |x| Primary::PrimaryLiteral(Box::new(x))), map(cast, |x| Primary::Cast(Box::new(x))), - terminated(primary_hierarchical, peek(none_of("("))), + terminated( + primary_hierarchical, + peek(not(alt(( + map(one_of("(."), |_| ()), + map(keyword("with"), |_| ()), + )))), + ), map(empty_unpacked_array_concatenation, |x| { Primary::EmptyUnpackedArrayConcatenation(Box::new(x)) }), diff --git a/sv-parser-parser/src/expressions/subroutine_calls.rs b/sv-parser-parser/src/expressions/subroutine_calls.rs index 4eb91d6..520f737 100644 --- a/sv-parser-parser/src/expressions/subroutine_calls.rs +++ b/sv-parser-parser/src/expressions/subroutine_calls.rs @@ -68,12 +68,12 @@ pub(crate) fn system_tf_call_arg_expression(s: Span) -> IResult IResult { alt(( + subroutine_call_randomize, map(method_call, |x| SubroutineCall::MethodCall(Box::new(x))), map(tf_call, |x| SubroutineCall::TfCall(Box::new(x))), map(system_tf_call, |x| { SubroutineCall::SystemTfCall(Box::new(x)) }), - subroutine_call_randomize, ))(s) } @@ -152,10 +152,10 @@ pub(crate) fn method_call(s: Span) -> IResult { #[packrat_parser] pub(crate) fn method_call_body(s: Span) -> IResult { alt(( - method_call_body_user, map(built_in_method_call, |x| { MethodCallBody::BuiltInMethodCall(Box::new(x)) }), + method_call_body_user, ))(s) } @@ -237,13 +237,92 @@ pub(crate) fn variable_identifier_list_or_null( #[packrat_parser] pub(crate) fn method_call_root(s: Span) -> IResult { alt(( - map(primary, |x| MethodCallRoot::Primary(Box::new(x))), + map(primary_method_call_root, |x| { + MethodCallRoot::Primary(Box::new(x)) + }), map(implicit_class_handle, |x| { MethodCallRoot::ImplicitClassHandle(Box::new(x)) }), ))(s) } +#[tracable_parser] +#[packrat_parser] +pub(crate) fn primary_method_call_root(s: Span) -> IResult { + alt(( + map(keyword("this"), |x| Primary::This(Box::new(x))), + map(keyword("$"), |x| Primary::Dollar(Box::new(x))), + map(keyword("null"), |x| Primary::Null(Box::new(x))), + map(assignment_pattern_expression, |x| { + Primary::AssignmentPatternExpression(Box::new(x)) + }), + map(primary_literal, |x| Primary::PrimaryLiteral(Box::new(x))), + map(cast, |x| Primary::Cast(Box::new(x))), + terminated(primary_hierarchical_method_call_root, peek(none_of("("))), + map(empty_unpacked_array_concatenation, |x| { + Primary::EmptyUnpackedArrayConcatenation(Box::new(x)) + }), + primary_concatenation, + primary_multiple_concatenation, + map(function_subroutine_call, |x| { + Primary::FunctionSubroutineCall(Box::new(x)) + }), + map(let_expression, |x| Primary::LetExpression(Box::new(x))), + primary_mintypmax_expression, + map(streaming_concatenation, |x| { + Primary::StreamingConcatenation(Box::new(x)) + }), + map(sequence_method_call, |x| { + Primary::SequenceMethodCall(Box::new(x)) + }), + ))(s) +} + +#[tracable_parser] +#[packrat_parser] +pub(crate) fn primary_hierarchical_method_call_root(s: Span) -> IResult { + let (s, a) = opt(class_qualifier_or_package_scope)(s)?; + let (s, b) = hierarchical_identifier_method_call_root(s)?; + let (s, c) = select_method_call_root(s)?; + Ok(( + s, + Primary::Hierarchical(Box::new(PrimaryHierarchical { nodes: (a, b, c) })), + )) +} + +#[tracable_parser] +#[packrat_parser] +pub(crate) fn hierarchical_identifier_method_call_root( + s: Span, +) -> IResult { + let (s, a) = opt(root)(s)?; + let (s, b) = many0(terminated( + triple(identifier, constant_bit_select, symbol(".")), + peek(pair(identifier, symbol("."))), + ))(s)?; + let (s, c) = identifier(s)?; + Ok((s, HierarchicalIdentifier { nodes: (a, b, c) })) +} + +#[tracable_parser] +#[packrat_parser] +pub(crate) fn select_method_call_root(s: Span) -> IResult { + let (s, a) = opt(terminated( + triple( + many0(terminated( + triple(symbol("."), member_identifier, bit_select), + peek(triple(symbol("."), member_identifier, symbol("."))), + )), + symbol("."), + member_identifier, + ), + peek(symbol(".")), + ))(s)?; + let (s, b) = bit_select(s)?; + let (s, c) = opt(bracket(part_select_range))(s)?; + Ok((s, Select { nodes: (a, b, c) })) +} + #[tracable_parser] #[packrat_parser] pub(crate) fn array_method_name(s: Span) -> IResult { diff --git a/sv-parser-parser/src/general/identifiers.rs b/sv-parser-parser/src/general/identifiers.rs index 82df870..bf703c3 100644 --- a/sv-parser-parser/src/general/identifiers.rs +++ b/sv-parser-parser/src/general/identifiers.rs @@ -205,7 +205,10 @@ pub(crate) fn hierarchical_event_identifier(s: Span) -> IResult IResult { let (s, a) = opt(root)(s)?; - let (s, b) = many0(triple(identifier, constant_bit_select, symbol(".")))(s)?; + let (s, b) = many0(terminated( + triple(identifier, constant_bit_select, symbol(".")), + peek(identifier), + ))(s)?; let (s, c) = identifier(s)?; Ok((s, HierarchicalIdentifier { nodes: (a, b, c) })) } @@ -561,10 +564,10 @@ pub(crate) fn ps_or_hierarchical_tf_identifier( s: Span, ) -> IResult { alt(( - ps_or_hierarchical_tf_identifier_package_scope, map(hierarchical_tf_identifier, |x| { PsOrHierarchicalTfIdentifier::HierarchicalTfIdentifier(Box::new(x)) }), + ps_or_hierarchical_tf_identifier_package_scope, ))(s) } @@ -606,10 +609,13 @@ pub(crate) fn ps_parameter_identifier_scope(s: Span) -> IResult IResult { - let (s, a) = many0(triple( - generate_block_identifier, - opt(bracket(constant_expression)), - symbol("."), + let (s, a) = many0(terminated( + triple( + generate_block_identifier, + opt(bracket(constant_expression)), + symbol("."), + ), + peek(parameter_identifier), ))(s)?; let (s, b) = parameter_identifier(s)?; Ok(( diff --git a/sv-parser-parser/src/tests.rs b/sv-parser-parser/src/tests.rs index 26762f7..90b1270 100644 --- a/sv-parser-parser/src/tests.rs +++ b/sv-parser-parser/src/tests.rs @@ -1529,6 +1529,7 @@ mod spec { r##"localparam type T = type(bit[12:0]);"##, Ok((_, _)) ); + // TODO // What is addfixed_int/add_float? UDP? //test!( // many1(module_item), @@ -1616,26 +1617,31 @@ mod spec { dest_t b = dest_t'(a);"##, Ok((_, _)) ); - //test!( - // many1(module_item), - // r##"typedef struct { - // shortint address; - // logic [3:0] code; - // byte command [2]; - // } Control; + test!( + many1(module_item), + r##"typedef struct { + shortint address; + logic [3:0] code; + byte command [2]; + } Control; - // typedef bit Bits [36:1]; + typedef bit Bits [36:1]; - // Control p; - // Bits stream[$]; + Control p; + Bits stream[$]; - // stream.push_back(Bits'(p)); // append packet to unpacked queue of Bits - // Bits b; - // Control q; - // b = stream.pop_front(); // get packet (as Bits) from stream - // q = Control'(b); // convert packet bits back to a Control packet"##, - // Ok((_, _)) - //); + initial begin + stream.push_back(Bits'(p)); // append packet to unpacked queue of Bits + end + + initial begin + Bits b; + Control q; + b = stream.pop_front(); // get packet (as Bits) from stream + q = Control'(b); // convert packet bits back to a Control packet + end"##, + Ok((_, _)) + ); test!( many1(module_item), r##"typedef struct { @@ -1646,6 +1652,8 @@ mod spec { } Packet;"##, Ok((_, _)) ); + // TODO + // randomize can't take hierarchical identifier //test!( // many1(module_item), // r##"function Packet genPkt(); @@ -1665,15 +1673,19 @@ mod spec { channel = {channel, channel_type'(genPkt())};"##, Ok((_, _)) ); + // TODO + // $ can't be parsed because it is not constant_primary //test!( // many1(module_item), - // r##"Packet p; - // int size; + // r##"initial begin + // Packet p; + // int size; - // size = channel[0] + 4; - // p = Packet'( channel[0 : size - 1] ); // convert stream to Packet - // channel = channel[ size : $ ]; // update the stream so it now - // // lacks that packet"##, + // size = channel[0] + 4; + // p = Packet'( channel[0 : size - 1] ); // convert stream to Packet + // channel = channel[ size : $ ]; // update the stream so it now + // // lacks that packet + // end"##, // Ok((_, _)) //); test!( @@ -1702,19 +1714,21 @@ mod spec { #[test] fn clause7() { - //test!( - // many1(module_item), - // r##"struct { bit [7:0] opcode; bit [23:0] addr; }IR; // anonymous structure - // // defines variable IR - // IR.opcode = 1; // set field in IR. + test!( + many1(module_item), + r##"struct { bit [7:0] opcode; bit [23:0] addr; }IR; // anonymous structure + // defines variable IR + initial begin + IR.opcode = 1; // set field in IR. + end - // typedef struct { - // bit [7:0] opcode; - // bit [23:0] addr; - // } instruction; // named structure type - // instruction IR; // define variable"##, - // Ok((_, _)) - //); + typedef struct { + bit [7:0] opcode; + bit [23:0] addr; + } instruction; // named structure type + instruction IR; // define variable"##, + Ok((_, _)) + ); test!( many1(module_item), r##"struct packed signed { @@ -1765,18 +1779,21 @@ mod spec { r##"packet1 pi = '{1,2,'{2,3,4,5}}; //suppresses the typedef initialization"##, Ok((_, _)) ); - //test!( - // many1(module_item), - // r##"typedef union { int i; shortreal f; } num; // named union type - // num n; - // n.f = 0.0; // set n in floating point format + test!( + many1(module_item), + r##"typedef union { int i; shortreal f; } num; // named union type + num n; - // typedef struct { - // bit isfloat; - // union { int i; shortreal f; } n; // anonymous union type - // } tagged_st; // named structure"##, - // Ok((_, _)) - //); + initial begin + n.f = 0.0; // set n in floating point format + end + + typedef struct { + bit isfloat; + union { int i; shortreal f; } n; // anonymous union type + } tagged_st; // named structure"##, + Ok((_, _)) + ); test!( many1(module_item), r##"typedef union packed { // default unsigned @@ -1940,57 +1957,69 @@ mod spec { // remain unsized and uninitialized"##, Ok((_, _)) ); - //test!( - // many1(module_item), - // r##"int arr[2][][]; - // arr[0] = new [4]; // dynamic subarray arr[0] sized to length 4 + test!( + many1(module_item), + r##"int arr[2][][]; + initial begin + arr[0] = new [4]; // dynamic subarray arr[0] sized to length 4 - // arr[0][0] = new [2]; // legal, arr[0][n] created above for n = 0..3 + arr[0][0] = new [2]; // legal, arr[0][n] created above for n = 0..3 - // arr[1][0] = new [2]; // illegal, arr[1] not initialized so arr[1][0] does - // // not exist + arr[1][0] = new [2]; // illegal, arr[1] not initialized so arr[1][0] does + // not exist - // arr[0][1][1] = new[2]; // illegal, arr[0][1][1] is an int, not a dynamic - // // array"##, - // Ok((_, _)) - //); - //test!( - // many1(module_item), - // r##"int idest[], isrc[3] = '{5, 6, 7}; - // idest = new [3] (isrc); // set size and array element data values (5, 6, 7)"##, - // Ok((_, _)) - //); - //test!( - // many1(module_item), - // r##"int src[3], dest1[], dest2[]; - // src = '{2, 3, 4}; - // dest1 = new[2] (src); // dest1's elements are {2, 3}. - // dest2 = new[4] (src); // dest2's elements are {2, 3, 4, 0}."##, - // Ok((_, _)) - //); - //test!( - // many1(module_item), - // r##"integer addr[]; // Declare the dynamic array. - // addr = new[100]; // Create a 100-element array. - // // Double the array size, preserving previous values. - // // Preexisting references to elements of addr are outdated. - // addr = new[200](addr);"##, - // Ok((_, _)) - //); - //test!( - // many1(module_item), - // r##"int j = addr.size; - // addr = new[ addr.size() * 4 ] (addr); // quadruple addr array"##, - // Ok((_, _)) - //); - //test!( - // many1(module_item), - // r##"int ab [] = new[ N ]; // create a temporary array of size N - // // use ab - // ab.delete; // delete the array contents - // $display( "%d", ab.size ); // prints 0"##, - // Ok((_, _)) - //); + arr[0][1][1] = new[2]; // illegal, arr[0][1][1] is an int, not a dynamic + // array + end"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"int idest[], isrc[3] = '{5, 6, 7}; + initial begin + idest = new [3] (isrc); // set size and array element data values (5, 6, 7) + end"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"int src[3], dest1[], dest2[]; + initial begin + src = '{2, 3, 4}; + dest1 = new[2] (src); // dest1's elements are {2, 3}. + dest2 = new[4] (src); // dest2's elements are {2, 3, 4, 0}. + end"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"integer addr[]; // Declare the dynamic array. + initial begin + addr = new[100]; // Create a 100-element array. + // Double the array size, preserving previous values. + // Preexisting references to elements of addr are outdated. + addr = new[200](addr); + end"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"initial begin + int j = addr.size; + addr = new[ addr.size() * 4 ] (addr); // quadruple addr array + end"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"initial begin + int ab [] = new[ N ]; // create a temporary array of size N + // use ab + ab.delete; // delete the array contents + $display( "%d", ab.size ); // prints 0 + end"##, + Ok((_, _)) + ); test!( many1(module_item), r##"int A[10:1]; // fixed-size array of 10 elements @@ -2009,35 +2038,41 @@ mod spec { initial #10 V2 = W;"##, Ok((_, _)) ); - //test!( - // many1(module_item), - // r##"int A[2][100:1]; - // int B[] = new[100]; // dynamic array of 100 elements - // int C[] = new[8]; // dynamic array of 8 elements - // int D [3][][]; // multidimensional array with dynamic subarrays - // D[2] = new [2]; // initialize one of D's dynamic subarrays - // D[2][0] = new [100]; - // A[1] = B; // OK. Both are arrays of 100 ints - // A[1] = C; // type check error: different sizes (100 vs. 8 ints) - // A = D[2]; // A[0:1][100:1] and subarray D[2][0:1][0:99] both - // // comprise 2 subarrays of 100 ints"##, - // Ok((_, _)) - //); - //test!( - // many1(module_item), - // r##"int A[100:1]; // fixed-size array of 100 elements - // int B[]; // empty dynamic array - // int C[] = new[8]; // dynamic array of size 8 + test!( + many1(module_item), + r##"int A[2][100:1]; + int B[] = new[100]; // dynamic array of 100 elements + int C[] = new[8]; // dynamic array of 8 elements + int D [3][][]; // multidimensional array with dynamic subarrays + initial begin + D[2] = new [2]; // initialize one of D's dynamic subarrays + D[2][0] = new [100]; + A[1] = B; // OK. Both are arrays of 100 ints + A[1] = C; // type check error: different sizes (100 vs. 8 ints) + A = D[2]; // A[0:1][100:1] and subarray D[2][0:1][0:99] both + // comprise 2 subarrays of 100 ints + end"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"int A[100:1]; // fixed-size array of 100 elements + int B[]; // empty dynamic array + int C[] = new[8]; // dynamic array of size 8 - // B = A; // ok. B has 100 elements - // B = C; // ok. B has 8 elements"##, - // Ok((_, _)) - //); - //test!( - // many1(module_item), - // r##"B = new[ C.size ] (C);"##, - // Ok((_, _)) - //); + initial begin + B = A; // ok. B has 100 elements + B = C; // ok. B has 8 elements + end"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"initial begin + B = new[ C.size ] (C); + end"##, + Ok((_, _)) + ); test!( many1(module_item), r##"string d[1:5] = '{ "a", "b", "c", "d", "e" }; @@ -2131,18 +2166,18 @@ mod spec { end"##, Ok((_, _)) ); - //test!( - // many1(module_item), - // r##"initial begin - // int map[ string ]; - // map[ "hello" ] = 1; - // map[ "sad" ] = 2; - // map[ "world" ] = 3; - // map.delete( "sad" ); // remove entry whose index is "sad" from "map" - // map.delete; // remove all entries from the associative array "map" - // end"##, - // Ok((_, _)) - //); + test!( + many1(module_item), + r##"initial begin + int map[ string ]; + map[ "hello" ] = 1; + map[ "sad" ] = 2; + map[ "world" ] = 3; + map.delete( "sad" ); // remove entry whose index is "sad" from "map" + map.delete; // remove all entries from the associative array "map" + end"##, + Ok((_, _)) + ); test!( many1(module_item), r##"initial begin @@ -2238,6 +2273,8 @@ mod spec { end"##, Ok((_, _)) ); + // TODO + // $ can't be parsed because it is not constant_primary //test!( // many1(module_item), // r##"initial begin @@ -2257,6 +2294,8 @@ mod spec { // end"##, // Ok((_, _)) //); + // TODO + // $ can't be parsed because it is not constant_primary //test!( // many1(module_item), // r##"initial begin @@ -2265,51 +2304,55 @@ mod spec { // end"##, // Ok((_, _)) //); - //test!( - // many1(module_item), - // r##"initial begin - // string SA[10], qs[$]; - // int IA[int], qi[$]; + test!( + many1(module_item), + r##"initial begin + string SA[10], qs[$]; + int IA[int], qi[$]; - // // Find all items greater than 5 - // qi = IA.find( x ) with ( x > 5 ); - // qi = IA.find( x ); // shall be an error + // Find all items greater than 5 + qi = IA.find( x ) with ( x > 5 ); + qi = IA.find( x ); // shall be an error - // // Find indices of all items equal to 3 - // qi = IA.find_index with ( item == 3 ); + // Find indices of all items equal to 3 + qi = IA.find_index with ( item == 3 ); - // // Find first item equal to Bob - // qs = SA.find_first with ( item == "Bob" ); + // Find first item equal to Bob + qs = SA.find_first with ( item == "Bob" ); - // // Find last item equal to Henry - // qs = SA.find_last( y ) with ( y == "Henry" ); + // Find last item equal to Henry + qs = SA.find_last( y ) with ( y == "Henry" ); - // // Find index of last item greater than Z - // qi = SA.find_last_index( s ) with ( s > "Z" ); + // Find index of last item greater than Z + qi = SA.find_last_index( s ) with ( s > "Z" ); - // // Find smallest item - // qi = IA.min; + // Find smallest item + qi = IA.min; - // // Find string with largest numerical value - // qs = SA.max with ( item.atoi ); + // Find string with largest numerical value + qs = SA.max with ( item.atoi ); - // // Find all unique string elements - // qs = SA.unique; + // Find all unique string elements + qs = SA.unique; - // // Find all unique strings in lowercase - // qs = SA.unique( s ) with ( s.tolower ); - // end"##, - // Ok((_, _)) - //); + // Find all unique strings in lowercase + qs = SA.unique( s ) with ( s.tolower ); + end"##, + Ok((_, _)) + ); //test!( // many1(module_item), // r##"initial begin // string s[] = { "hello", "sad", "world" }; // s.reverse; // s becomes { "world", "sad", "hello" }; + // end + // initial begin // int q[$] = { 4, 5, 3, 1 }; // q.sort; // q becomes { 1, 3, 4, 5 } + // end + // initial begin // struct { byte red, green, blue; } c [512]; // c.sort with ( item.red ); // sort c using the red field only // c.sort( x ) with ( {x.blue, x.green} ); // sort by blue then green @@ -2324,28 +2367,32 @@ mod spec { // y = b.sum ; // y becomes 10 => 1 + 2 + 3 + 4 // y = b.product ; // y becomes 24 => 1 * 2 * 3 * 4 // y = b.xor with ( item + 4 ); // y becomes 12 => 5 ^ 6 ^ 7 ^ 8 + // end + // initial begin // logic [7:0] m [2][2] = '{ '{5, 10}, '{15, 20} }; // int y; // y = m.sum with (item.sum with (item)); // y becomes 50 => 5+10+15+20 + // end + // initial begin // logic bit_arr [1024]; // int y; // y = bit_arr.sum with ( int'(item) ); // forces result to be 32-bit // end"##, // Ok((_, _)) //); - //test!( - // many1(module_item), - // r##"initial begin - // int arr[]; - // int q[$]; + test!( + many1(module_item), + r##"initial begin + int arr[]; + int q[$]; - // // find all items equal to their position (index) - // q = arr.find with ( item == item.index ); - // end"##, - // Ok((_, _)) - //); + // find all items equal to their position (index) + q = arr.find with ( item == item.index ); + end"##, + Ok((_, _)) + ); } #[test] @@ -9057,6 +9104,4 @@ mod spec { } #[test] -fn debug() { - //nom_tracable::statistics(Span::new_extra("", SpanInfo::default())); -} +fn debug() {}