Add identifier

This commit is contained in:
dalance 2019-06-28 12:16:13 +09:00
parent d6fffe250a
commit d6f2fbabc2
4 changed files with 599 additions and 45 deletions

538
src/identifier.rs Normal file
View File

@ -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<Scope<'a>>,
pub identifier: HierarchicalIdentifier<'a>,
}
#[derive(Debug)]
pub enum Scope<'a> {
LocalScope,
PackageScope(Identifier<'a>),
ClassScope,
ImplicitClassHandle,
GenerateBlockScope(Vec<GenerateBlockScope<'a>>),
}
#[derive(Debug)]
pub struct GenerateBlockScope<'a> {
pub identifier: Identifier<'a>,
pub constant_expression: Option<ConstantExpression<'a>>,
}
#[derive(Debug)]
pub struct HierarchicalIdentifier<'a> {
pub hierarchy: Vec<Hierarchy<'a>>,
pub identifier: Identifier<'a>,
}
impl<'a> From<Identifier<'a>> 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<ConstantBitSelect<'a>>,
}
// -----------------------------------------------------------------------------
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\"] }))"
);
}
}

View File

@ -1 +1,3 @@
pub mod identifier;
pub mod number;
pub mod util;

View File

@ -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],

44
src/util.rs Normal file
View File

@ -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![] }))
}