Skip to content

Commit f46f6ae

Browse files
committed
Add support for extended identifiers. Related to #1120.
1 parent 00cd695 commit f46f6ae

1 file changed

Lines changed: 49 additions & 42 deletions

File tree

vunit/vhdl_parser.py

Lines changed: 49 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ def parse(self, file_name):
4242
)
4343

4444

45+
_identifier_pattern = r"[A-Za-z]\w*|\\[^\n\r\\]+\\"
46+
47+
4548
class VHDLDesignFile(object): # pylint: disable=too-many-instance-attributes
4649
"""
4750
Contains VHDL objects found within a file
@@ -86,7 +89,7 @@ def parse(cls, code):
8689
)
8790

8891
_component_re = re.compile(
89-
r"[a-zA-Z]\w*\s*\:\s*(?:component)?\s*(?:(?:[a-zA-Z]\w*)\.)?([a-zA-Z]\w*)\s*"
92+
rf"(?:{_identifier_pattern})\s*\:\s*(?:component)?\s*(?:(?:{_identifier_pattern})\.)?({_identifier_pattern})\s*"
9093
r"(?:generic|port) map\s*\([\s\w\=\>\,\.\)\(\+\-\*\/\'\"]*\);",
9194
re.IGNORECASE,
9295
)
@@ -101,13 +104,13 @@ def __init__(self, identifier):
101104
self.identifier = identifier
102105

103106
_package_body_pattern = re.compile(
104-
r"""
107+
rf"""
105108
\b # Word boundary
106109
package # package keyword
107110
\s+ # At least one whitespace
108111
body # body keyword
109112
\s+ # At least one whitespace
110-
(?P<package>[a-zA-Z][\w]*) # A package
113+
(?P<package>{_identifier_pattern}) # A package
111114
\s+ # At least one whitespace
112115
is # is keyword
113116
""",
@@ -134,15 +137,15 @@ def __init__(self, identifier, entity):
134137
self.entity = entity
135138

136139
_configuration_re = re.compile(
137-
r"""
140+
rf"""
138141
\b # Word boundary
139142
configuration # configuration keyword
140143
\s+ # At least one whitespace
141-
(?P<id>[a-zA-Z][\w]*) # An identifier
144+
(?P<id>{_identifier_pattern}) # An identifier
142145
\s+ # At least one whitespace
143146
of # of keyword
144147
\s+ # At least one whitespace
145-
(?P<entity_id>[a-zA-Z][\w]*) # An identifier
148+
(?P<entity_id>{_identifier_pattern}) # An identifier
146149
\s+ # At least one whitespace
147150
is # is keyword
148151
""",
@@ -168,15 +171,15 @@ def __init__(self, identifier, entity):
168171
self.entity = entity
169172

170173
_architecture_re = re.compile(
171-
r"""
174+
rf"""
172175
\b # Word boundary
173176
architecture # architecture keyword
174177
\s+ # At least one whitespace
175-
(?P<id>[a-zA-Z][\w]*) # An identifier
178+
(?P<id>{_identifier_pattern}) # An identifier
176179
\s+ # At least one whitespace
177180
of # of keyword
178181
\s+ # At least one whitespace
179-
(?P<entity_id>[a-zA-Z][\w]*) # An identifier
182+
(?P<entity_id>{_identifier_pattern}) # An identifier
180183
\s+ # At least one whitespace
181184
is # is keyword
182185
""",
@@ -194,7 +197,10 @@ def find(cls, code):
194197
yield VHDLArchitecture(identifier, entity_id)
195198

196199

197-
PACKAGE_INSTANCE_PATTERN = r"\bpackage\s+(?P<new_name>[a-zA-Z]\w*)\s+is\s+new\s+(?P<lib>[a-zA-Z]\w*)\.(?P<name>[a-zA-Z]\w*)" # pylint: disable=line-too-long
200+
PACKAGE_INSTANCE_PATTERN = (
201+
rf"\bpackage\s+(?P<new_name>{_identifier_pattern})\s+is\s+new\s+"
202+
rf"(?P<lib>{_identifier_pattern})\.(?P<name>{_identifier_pattern})"
203+
)
198204

199205

200206
class VHDLPackage(object):
@@ -209,11 +215,11 @@ def __init__(self, identifier, enumeration_types, record_types, array_types):
209215
self.array_types = array_types
210216

211217
_package_start_re = re.compile(
212-
r"""
218+
rf"""
213219
\b # Word boundary
214220
package # package keyword
215221
\s+ # At least one whitespace
216-
(?P<id>[a-zA-Z][\w]*) # An identifier
222+
(?P<id>{_identifier_pattern}) # An identifier
217223
\s+ # At least one whitespace
218224
is # is keyword
219225
""",
@@ -324,11 +330,11 @@ def add_port(self, identifier, mode, subtype_code, init_value=None):
324330
)
325331

326332
_entity_start_re = re.compile(
327-
r"""
333+
rf"""
328334
\b # Word boundary
329335
entity # entity keyword
330336
\s+ # At least one whitespace
331-
(?P<id>[a-zA-Z][\w]*) # An identifier
337+
(?P<id>{_identifier_pattern}) # An identifier
332338
\s+ # At least one whitespace
333339
is # is keyword
334340
""",
@@ -371,11 +377,11 @@ def parse(cls, code):
371377
# Extract identifier
372378
re_flags = re.MULTILINE | re.IGNORECASE | re.VERBOSE
373379
entity_start = re.compile(
374-
r"""
380+
rf"""
375381
\b # Word boundary
376382
entity # entity keyword
377383
\s+ # At least one whitespace
378-
(?P<id>[a-zA-Z][\w]*) # An identifier
384+
(?P<id>{_identifier_pattern}) # An identifier
379385
\s+ # At least one whitespace
380386
is # is keyword
381387
""",
@@ -560,11 +566,11 @@ def __init__(self, identifier):
560566
self.identifier = identifier
561567

562568
_context_start_re = re.compile(
563-
r"""
569+
rf"""
564570
\b # Word boundary
565571
context # context keyword
566572
\s+ # At least one whitespace
567-
(?P<id>[a-zA-Z][\w]*) # An identifier
573+
(?P<id>{_identifier_pattern}) # An identifier
568574
\s+ # At least one whitespace
569575
is # is keyword
570576
""",
@@ -600,10 +606,10 @@ def parse(cls, code):
600606
# Extract type mark and find out if it's an array type and if a constraint is given.
601607
re_flags = re.MULTILINE | re.IGNORECASE | re.VERBOSE
602608
subtype_indication_start = re.compile(
603-
r"""
609+
rf"""
604610
^ # Beginning of line
605611
[\s]* # Potential whitespaces
606-
(?P<type_mark>[a-zA-Z][\w]*) # An type mark
612+
(?P<type_mark>{_identifier_pattern}) # An type mark
607613
[\s]* # Potential whitespaces
608614
(?P<constraint>\(.*\))?
609615
""",
@@ -705,16 +711,16 @@ def __init__(self, identifier, literals):
705711
self.literals = literals
706712

707713
_enum_declaration_re = re.compile(
708-
r"""
714+
rf"""
709715
\b # Word boundary
710716
type
711717
\s+
712-
(?P<id>[a-zA-Z][\w]*) # An identifier
718+
(?P<id>{_identifier_pattern}) # An identifier
713719
\s+
714720
is
715721
\s*\(\s*
716-
(?P<literals>[a-zA-Z][\w]* # First enumeration literal
717-
(\s*,\s*[a-zA-Z][\w]*)*) # More enumeration literals
722+
(?P<literals>({_identifier_pattern}) # First enumeration literal
723+
(\s*,\s*(?:{_identifier_pattern}))*) # More enumeration literals
718724
\s*\)\s*;""",
719725
re.MULTILINE | re.IGNORECASE | re.VERBOSE,
720726
)
@@ -746,11 +752,11 @@ def __init__(self, identifier, elements):
746752
self.elements = elements
747753

748754
_record_declaration_re = re.compile(
749-
r"""
755+
rf"""
750756
\b # Word boundary
751757
type
752758
\s+
753-
(?P<id>[a-zA-Z][\w]*) # An identifier
759+
(?P<id>{_identifier_pattern}) # An identifier
754760
\s+
755761
is
756762
\s+
@@ -809,17 +815,17 @@ def __init__(self, identifier, subtype_indication, range1, range2):
809815
)
810816

811817
_range_attribute_ranges_re = re.compile(
812-
r"""
813-
\s*(?P<range_attribute>[a-zA-Z][\w]*'range)\s*""",
818+
rf"""
819+
\s*(?P<range_attribute>(?:{_identifier_pattern})'range)\s*""",
814820
re.MULTILINE | re.IGNORECASE | re.VERBOSE | re.DOTALL,
815821
)
816822

817823
_unconstrained_ranges_re = re.compile(
818-
r"""
819-
\s*(?P<range_type1>[a-zA-Z][\w]*)
824+
rf"""
825+
\s*(?P<range_type1>{_identifier_pattern})
820826
\s+range\s+<>\s*
821827
(,
822-
\s*(?P<range_type2>[a-zA-Z][\w]*)
828+
\s*(?P<range_type2>{_identifier_pattern})
823829
\s+range\s+<>\s*)?""",
824830
re.MULTILINE | re.IGNORECASE | re.VERBOSE | re.DOTALL,
825831
)
@@ -833,24 +839,24 @@ def __init__(self, identifier, subtype_indication, range1, range2):
833839
)
834840

835841
_range_attribute_range_re = re.compile(
836-
r"""
837-
\s*(?P<range_attribute>[a-zA-Z][\w]*'range)\s*""",
842+
rf"""
843+
\s*(?P<range_attribute>(?:{_identifier_pattern})'range)\s*""",
838844
re.MULTILINE | re.IGNORECASE | re.VERBOSE | re.DOTALL,
839845
)
840846

841847
_unconstrained_range_re = re.compile(
842-
r"""
843-
\s*(?P<range_type>[a-zA-Z][\w]*)
848+
rf"""
849+
\s*(?P<range_type>{_identifier_pattern})
844850
\s+range\s+<>\s*""",
845851
re.MULTILINE | re.IGNORECASE | re.VERBOSE | re.DOTALL,
846852
)
847853

848854
_array_declaration_re = re.compile(
849-
r"""
855+
rf"""
850856
\b # Word boundary
851857
type
852858
\s+
853-
(?P<id>[a-zA-Z][\w]*)
859+
(?P<id>{_identifier_pattern})
854860
\s+
855861
is
856862
\s+
@@ -950,12 +956,12 @@ class VHDLReference(object):
950956
_reference_types = ("package", "context", "entity", "configuration")
951957

952958
_uses_re = re.compile(
953-
r"""
959+
rf"""
954960
\b # Word boundary
955961
(?P<use_type>use|context) # use or context keyword
956962
\s+ # At least one whitespace
957-
(?P<id>[a-zA-Z][\w]*(\.[a-zA-Z][\w]*){1,2})
958-
(?P<extra>(\s*,\s*[a-zA-Z][\w]*(\.[a-zA-Z][\w]*){1,2})*)
963+
(?P<id>(?:{_identifier_pattern})(\.(?:{_identifier_pattern})){{1,2}})
964+
(?P<extra>(\s*,\s*(?:{_identifier_pattern})(\.(?:{_identifier_pattern})){{1,2}})*)
959965
\s* # Potential whitespaces
960966
; # Semi-colon
961967
""",
@@ -1002,7 +1008,8 @@ def get_ids(match):
10021008
return references
10031009

10041010
_entity_reference_re = re.compile(
1005-
r"\bentity\s+(?P<lib>[a-zA-Z]\w*)\.(?P<ent>[a-zA-Z]\w*)\s*(\((?P<arch>[a-zA-Z]\w*)\))?",
1011+
rf"\bentity\s+(?P<lib>{_identifier_pattern})\.(?P<ent>{_identifier_pattern})\s*(\("
1012+
rf"(?P<arch>{_identifier_pattern})\))?",
10061013
re.MULTILINE | re.IGNORECASE,
10071014
)
10081015

@@ -1027,7 +1034,7 @@ def _find_entity_references(cls, code):
10271034
return references
10281035

10291036
_configuration_reference_re = re.compile(
1030-
r"\bconfiguration\s+(?P<lib>[a-zA-Z]\w*)\.(?P<cfg>[a-zA-Z]\w*)",
1037+
rf"\bconfiguration\s+(?P<lib>{_identifier_pattern})\.(?P<cfg>{_identifier_pattern})",
10311038
re.MULTILINE | re.IGNORECASE,
10321039
)
10331040

0 commit comments

Comments
 (0)