From d6f2fbabc2c6acbf56725fc7881724b0b9ef9f66 Mon Sep 17 00:00:00 2001 From: dalance Date: Fri, 28 Jun 2019 12:16:13 +0900 Subject: [PATCH] Add identifier --- src/identifier.rs | 538 ++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 + src/number.rs | 60 ++---- src/util.rs | 44 ++++ 4 files changed, 599 insertions(+), 45 deletions(-) create mode 100644 src/identifier.rs create mode 100644 src/util.rs diff --git a/src/identifier.rs b/src/identifier.rs new file mode 100644 index 0000000..d0f0c24 --- /dev/null +++ b/src/identifier.rs @@ -0,0 +1,538 @@ +use crate::util::*; +use nom::branch::*; +use nom::bytes::complete::*; +use nom::combinator::*; +use nom::multi::*; +use nom::sequence::*; +use nom::IResult; + +// ----------------------------------------------------------------------------- + +const AZ_: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"; +const AZ09_: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; +const AZ09_DOLLAR: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$"; + +#[derive(Debug)] +pub struct Identifier<'a> { + pub raw: Vec<&'a str>, +} + +#[derive(Debug)] +pub struct ScopedIdentifier<'a> { + pub scope: Option>, + pub identifier: HierarchicalIdentifier<'a>, +} + +#[derive(Debug)] +pub enum Scope<'a> { + LocalScope, + PackageScope(Identifier<'a>), + ClassScope, + ImplicitClassHandle, + GenerateBlockScope(Vec>), +} + +#[derive(Debug)] +pub struct GenerateBlockScope<'a> { + pub identifier: Identifier<'a>, + pub constant_expression: Option>, +} + +#[derive(Debug)] +pub struct HierarchicalIdentifier<'a> { + pub hierarchy: Vec>, + pub identifier: Identifier<'a>, +} + +impl<'a> From> for HierarchicalIdentifier<'a> { + fn from(x: Identifier<'a>) -> Self { + HierarchicalIdentifier { + hierarchy: vec![], + identifier: x, + } + } +} + +#[derive(Debug)] +pub struct Hierarchy<'a> { + pub identifier: Identifier<'a>, + pub constant_bit_select: Option>, +} + +// ----------------------------------------------------------------------------- + +pub fn array_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn block_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn bin_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn c_identifier(s: &str) -> IResult<&str, Identifier> { + let (s, x) = is_a(AZ_)(s)?; + let (s, y) = opt(is_a(AZ09_))(s)?; + let raw = if let Some(y) = y { vec![x, y] } else { vec![x] }; + Ok((s, Identifier { raw })) +} + +pub fn cell_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn checker_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn class_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn class_variable_identifier(s: &str) -> IResult<&str, Identifier> { + variable_identifier(s) +} + +pub fn clocking_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn config_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn const_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn constraint_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn covergroup_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn covergroup_variable_identifier(s: &str) -> IResult<&str, Identifier> { + variable_identifier(s) +} + +pub fn cover_point_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn cross_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn dynamic_array_variable_identifier(s: &str) -> IResult<&str, Identifier> { + variable_identifier(s) +} + +pub fn enum_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn escaped_identifier(s: &str) -> IResult<&str, Identifier> { + let (s, x) = tag("\\")(s)?; + let (s, y) = is_not(" \t\r\n")(s)?; + Ok((s, Identifier { raw: vec![x, y] })) +} + +pub fn formal_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn formal_port_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn function_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn generate_block_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn genvar_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn hierarchical_array_identifier(s: &str) -> IResult<&str, HierarchicalIdentifier> { + hierarchical_identifier(s) +} + +pub fn hierarchical_block_identifier(s: &str) -> IResult<&str, HierarchicalIdentifier> { + hierarchical_identifier(s) +} + +pub fn hierarchical_event_identifier(s: &str) -> IResult<&str, HierarchicalIdentifier> { + hierarchical_identifier(s) +} + +pub fn hierarchy(s: &str) -> IResult<&str, Hierarchy> { + let (s, identifier) = identifier(s)?; + let (s, constant_bit_select) = sp(constant_bit_select)(s)?; + let (s, _) = sp(tag("."))(s)?; + + let constant_bit_select = Some(constant_bit_select); + + Ok(( + s, + Hierarchy { + identifier, + constant_bit_select, + }, + )) +} + +pub fn hierarchical_identifier(s: &str) -> IResult<&str, HierarchicalIdentifier> { + let (s, x) = opt(terminated(tag("$root"), sp(tag("."))))(s)?; + let (s, mut hierarchy) = many0(hierarchy)(s)?; + let (s, identifier) = sp(identifier)(s)?; + + if let Some(x) = x { + hierarchy.insert( + 0, + Hierarchy { + identifier: Identifier { raw: vec![x] }, + constant_bit_select: None, + }, + ); + } + + Ok(( + s, + HierarchicalIdentifier { + hierarchy, + identifier, + }, + )) +} + +pub fn hierarchical_net_identifier(s: &str) -> IResult<&str, HierarchicalIdentifier> { + hierarchical_identifier(s) +} + +pub fn hierarchical_parameter_identifier(s: &str) -> IResult<&str, HierarchicalIdentifier> { + hierarchical_identifier(s) +} + +pub fn hierarchical_property_identifier(s: &str) -> IResult<&str, HierarchicalIdentifier> { + hierarchical_identifier(s) +} + +pub fn hierarchical_sequence_identifier(s: &str) -> IResult<&str, HierarchicalIdentifier> { + hierarchical_identifier(s) +} + +pub fn hierarchical_task_identifier(s: &str) -> IResult<&str, HierarchicalIdentifier> { + hierarchical_identifier(s) +} + +pub fn hierarchical_tf_identifier(s: &str) -> IResult<&str, HierarchicalIdentifier> { + hierarchical_identifier(s) +} + +pub fn hierarchical_variable_identifier(s: &str) -> IResult<&str, HierarchicalIdentifier> { + hierarchical_identifier(s) +} + +pub fn identifier(s: &str) -> IResult<&str, Identifier> { + alt((escaped_identifier, simple_identifier))(s) +} + +pub fn index_variable_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn interface_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn interface_instance_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn inout_port_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn input_port_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn instance_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn library_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn member_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn method_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn modport_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn module_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn net_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn output_port_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn package_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn package_scope(s: &str) -> IResult<&str, Scope> { + let (s, x) = alt(( + terminated(package_identifier, sp(tag("::"))), + terminated( + map(tag("$unit"), |x| Identifier { raw: vec![x] }), + sp(tag("::")), + ), + ))(s)?; + Ok((s, Scope::PackageScope(x))) +} + +pub fn parameter_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn port_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn production_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn program_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn property_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn ps_class_identifier(s: &str) -> IResult<&str, ScopedIdentifier> { + let (s, scope) = opt(package_scope)(s)?; + let (s, identifier) = sp(class_identifier)(s)?; + let identifier = identifier.into(); + Ok((s, ScopedIdentifier { scope, identifier })) +} + +pub fn ps_covergroup_identifier(s: &str) -> IResult<&str, ScopedIdentifier> { + let (s, scope) = opt(package_scope)(s)?; + let (s, identifier) = sp(covergroup_identifier)(s)?; + let identifier = identifier.into(); + Ok((s, ScopedIdentifier { scope, identifier })) +} + +pub fn ps_checker_identifier(s: &str) -> IResult<&str, ScopedIdentifier> { + let (s, scope) = opt(package_scope)(s)?; + let (s, identifier) = sp(checker_identifier)(s)?; + let identifier = identifier.into(); + Ok((s, ScopedIdentifier { scope, identifier })) +} + +pub fn ps_identifier(s: &str) -> IResult<&str, ScopedIdentifier> { + let (s, scope) = opt(package_scope)(s)?; + let (s, identifier) = sp(identifier)(s)?; + let identifier = identifier.into(); + Ok((s, ScopedIdentifier { scope, identifier })) +} + +pub fn ps_or_hierarchical_array_identifier(s: &str) -> IResult<&str, ScopedIdentifier> { + let (s, scope) = opt(alt(( + terminated(implicit_class_handle, sp(tag("."))), + class_scope, + package_scope, + )))(s)?; + let (s, identifier) = sp(hierarchical_array_identifier)(s)?; + Ok((s, ScopedIdentifier { scope, identifier })) +} + +pub fn ps_or_hierarchical_net_identifier(s: &str) -> IResult<&str, ScopedIdentifier> { + let (s, scope) = opt(package_scope)(s)?; + let (s, identifier) = alt(( + map(sp(net_identifier), |x| x.into()), + sp(hierarchical_net_identifier), + ))(s)?; + Ok((s, ScopedIdentifier { scope, identifier })) +} + +pub fn ps_or_hierarchical_property_identifier(s: &str) -> IResult<&str, ScopedIdentifier> { + let (s, scope) = opt(package_scope)(s)?; + let (s, identifier) = alt(( + map(sp(property_identifier), |x| x.into()), + sp(hierarchical_property_identifier), + ))(s)?; + Ok((s, ScopedIdentifier { scope, identifier })) +} + +pub fn ps_or_hierarchical_sequence_identifier(s: &str) -> IResult<&str, ScopedIdentifier> { + let (s, scope) = opt(package_scope)(s)?; + let (s, identifier) = alt(( + map(sp(sequence_identifier), |x| x.into()), + sp(hierarchical_sequence_identifier), + ))(s)?; + Ok((s, ScopedIdentifier { scope, identifier })) +} + +pub fn ps_or_hierarchical_tf_identifier(s: &str) -> IResult<&str, ScopedIdentifier> { + let (s, scope) = opt(package_scope)(s)?; + let (s, identifier) = alt(( + map(sp(tf_identifier), |x| x.into()), + sp(hierarchical_tf_identifier), + ))(s)?; + Ok((s, ScopedIdentifier { scope, identifier })) +} + +pub fn ps_parameter_identifier(s: &str) -> IResult<&str, ScopedIdentifier> { + let (s, scope) = opt(alt((package_scope, class_scope, generate_block_scope)))(s)?; + let (s, identifier) = sp(parameter_identifier)(s)?; + let identifier = identifier.into(); + Ok((s, ScopedIdentifier { scope, identifier })) +} + +pub fn generate_block_scope(s: &str) -> IResult<&str, Scope> { + let (s, x) = many0(tuple(( + sp(generate_block_identifier), + opt(delimited( + sp(tag("[")), + sp(constant_expression), + sp(tag("]")), + )), + sp(tag(".")), + )))(s)?; + + let mut ret = Vec::new(); + for (identifier, constant_expression, _) in x { + ret.push(GenerateBlockScope { + identifier, + constant_expression, + }); + } + + Ok((s, Scope::GenerateBlockScope(ret))) +} + +pub fn ps_type_identifier(s: &str) -> IResult<&str, ScopedIdentifier> { + let (s, scope) = opt(alt(( + map(terminated(tag("local"), sp(tag("::"))), |_| { + Scope::LocalScope + }), + package_scope, + class_scope, + )))(s)?; + let (s, identifier) = sp(type_identifier)(s)?; + let identifier = identifier.into(); + Ok((s, ScopedIdentifier { scope, identifier })) +} + +pub fn sequence_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn signal_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn simple_identifier(s: &str) -> IResult<&str, Identifier> { + let (s, x) = is_a(AZ_)(s)?; + let (s, y) = opt(is_a(AZ09_DOLLAR))(s)?; + let raw = if let Some(y) = y { vec![x, y] } else { vec![x] }; + Ok((s, Identifier { raw })) +} + +pub fn specparam_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn system_tf_identifier(s: &str) -> IResult<&str, Identifier> { + let (s, x) = tag("$")(s)?; + let (s, y) = is_a(AZ09_DOLLAR)(s)?; + Ok((s, Identifier { raw: vec![x, y] })) +} + +pub fn task_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn tf_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn terminal_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn topmodule_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn type_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn udp_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +pub fn variable_identifier(s: &str) -> IResult<&str, Identifier> { + identifier(s) +} + +// ----------------------------------------------------------------------------- + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + assert_eq!( + format!("{:?}", all_consuming(identifier)("shiftreg_a")), + "Ok((\"\", Identifier { raw: [\"shiftreg_a\"] }))" + ); + assert_eq!( + format!("{:?}", all_consuming(identifier)("_bus3")), + "Ok((\"\", Identifier { raw: [\"_bus\", \"3\"] }))" + ); + assert_eq!( + format!("{:?}", all_consuming(identifier)("n$657")), + "Ok((\"\", Identifier { raw: [\"n\", \"$657\"] }))" + ); + assert_eq!( + format!("{:?}", all_consuming(identifier)("\\busa+index")), + "Ok((\"\", Identifier { raw: [\"\\\\\", \"busa+index\"] }))" + ); + assert_eq!( + format!("{:?}", all_consuming(identifier)("\\-clock")), + "Ok((\"\", Identifier { raw: [\"\\\\\", \"-clock\"] }))" + ); + assert_eq!( + format!("{:?}", all_consuming(system_tf_identifier)("$display")), + "Ok((\"\", Identifier { raw: [\"$\", \"display\"] }))" + ); + } +} diff --git a/src/lib.rs b/src/lib.rs index 8bfd060..eb6d296 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,3 @@ +pub mod identifier; pub mod number; +pub mod util; diff --git a/src/number.rs b/src/number.rs index fc3fc55..8c48779 100644 --- a/src/number.rs +++ b/src/number.rs @@ -1,3 +1,4 @@ +use crate::util::*; use nom::branch::*; use nom::bytes::complete::*; use nom::character::complete::*; @@ -90,12 +91,10 @@ pub fn integral_number(s: &str) -> IResult<&str, Number> { } pub fn decimal_number(s: &str) -> IResult<&str, IntegralNumber> { - let (s, (size, _, decimal_base, _, decimal_value)) = tuple(( + let (s, (size, decimal_base, decimal_value)) = tuple(( opt(size), - space0, - decimal_base, - space0, - alt((unsigned_number, x_number, z_number)), + sp(decimal_base), + sp(alt((unsigned_number, x_number, z_number))), ))(s)?; Ok(( s, @@ -113,8 +112,8 @@ pub fn integral_unsigned_number(s: &str) -> IResult<&str, IntegralNumber> { } pub fn binary_number(s: &str) -> IResult<&str, IntegralNumber> { - let (s, (size, _, binary_base, _, binary_value)) = - tuple((opt(size), space0, binary_base, space0, binary_value))(s)?; + let (s, (size, binary_base, binary_value)) = + tuple((opt(size), sp(binary_base), sp(binary_value)))(s)?; Ok(( s, IntegralNumber::BinaryNumber(BinaryNumber { @@ -126,8 +125,8 @@ pub fn binary_number(s: &str) -> IResult<&str, IntegralNumber> { } pub fn octal_number(s: &str) -> IResult<&str, IntegralNumber> { - let (s, (size, _, octal_base, _, octal_value)) = - tuple((opt(size), space0, octal_base, space0, octal_value))(s)?; + let (s, (size, octal_base, octal_value)) = + tuple((opt(size), sp(octal_base), sp(octal_value)))(s)?; Ok(( s, IntegralNumber::OctalNumber(OctalNumber { @@ -139,8 +138,7 @@ pub fn octal_number(s: &str) -> IResult<&str, IntegralNumber> { } pub fn hex_number(s: &str) -> IResult<&str, IntegralNumber> { - let (s, (size, _, hex_base, _, hex_value)) = - tuple((opt(size), space0, hex_base, space0, hex_value))(s)?; + let (s, (size, hex_base, hex_value)) = tuple((opt(size), sp(hex_base), sp(hex_value)))(s)?; Ok(( s, IntegralNumber::HexNumber(HexNumber { @@ -243,51 +241,23 @@ pub fn hex_value(s: &str) -> IResult<&str, Vec<&str>> { } pub fn decimal_base(s: &str) -> IResult<&str, &str> { - alt(( - tag("'d"), - tag("'sd"), - tag("'Sd"), - tag("'D"), - tag("'sD"), - tag("'SD"), - ))(s) + alt((tag_no_case("'d"), tag_no_case("'sd")))(s) } pub fn binary_base(s: &str) -> IResult<&str, &str> { - alt(( - tag("'b"), - tag("'sb"), - tag("'Sb"), - tag("'B"), - tag("'sB"), - tag("'SB"), - ))(s) + alt((tag_no_case("'b"), tag_no_case("'sb")))(s) } pub fn octal_base(s: &str) -> IResult<&str, &str> { - alt(( - tag("'o"), - tag("'so"), - tag("'So"), - tag("'O"), - tag("'sO"), - tag("'SO"), - ))(s) + alt((tag_no_case("'o"), tag_no_case("'so")))(s) } pub fn hex_base(s: &str) -> IResult<&str, &str> { - alt(( - tag("'h"), - tag("'sh"), - tag("'Sh"), - tag("'H"), - tag("'sH"), - tag("'SH"), - ))(s) + alt((tag_no_case("'h"), tag_no_case("'sh")))(s) } pub fn x_number(s: &str) -> IResult<&str, Vec<&str>> { - let (s, x) = alt((tag("x"), tag("X")))(s)?; + let (s, x) = tag_no_case("x")(s)?; fold_many0( alt((tag("_"), is_a("_"))), vec![x], @@ -299,7 +269,7 @@ pub fn x_number(s: &str) -> IResult<&str, Vec<&str>> { } pub fn z_number(s: &str) -> IResult<&str, Vec<&str>> { - let (s, x) = alt((tag("z"), tag("Z"), tag("?")))(s)?; + let (s, x) = alt((tag_no_case("z"), tag("?")))(s)?; fold_many0( alt((tag("_"), is_a("_"))), vec![x], diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..502d6d6 --- /dev/null +++ b/src/util.rs @@ -0,0 +1,44 @@ +use crate::identifier::*; +use nom::character::complete::*; +use nom::IResult; + +// ----------------------------------------------------------------------------- + +pub fn sp<'a, O, F>(f: F) -> impl Fn(&'a str) -> IResult<&'a str, O> +where + F: Fn(&'a str) -> IResult<&'a str, O>, +{ + move |s: &'a str| { + let (s, _) = space0(s)?; + let (s, x) = f(s)?; + Ok((s, x)) + } +} + +// ----------------------------------------------------------------------------- + +#[derive(Debug)] +pub struct ConstantBitSelect<'a> { + pub raw: Vec<&'a str>, +} + +#[derive(Debug)] +pub struct ConstantExpression<'a> { + pub raw: Vec<&'a str>, +} + +pub fn implicit_class_handle(s: &str) -> IResult<&str, Scope> { + Ok((s, Scope::ImplicitClassHandle)) +} + +pub fn class_scope(s: &str) -> IResult<&str, Scope> { + Ok((s, Scope::ClassScope)) +} + +pub fn constant_bit_select(s: &str) -> IResult<&str, ConstantBitSelect> { + Ok((s, ConstantBitSelect { raw: vec![] })) +} + +pub fn constant_expression(s: &str) -> IResult<&str, ConstantExpression> { + Ok((s, ConstantExpression { raw: vec![] })) +}