Skip to content

Commit

Permalink
Made vhdl parser tolerate things not starting on a new line. Issue #58.
Browse files Browse the repository at this point in the history
  • Loading branch information
kraigher committed Jul 8, 2015
1 parent bb23880 commit 7e1fe0e
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 35 deletions.
40 changes: 40 additions & 0 deletions vunit/test/unit/test_vhdl_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,46 @@ def test_parsing_entity_with_generics(self):
self.assertEqual(generics[1].subtype_indication.code, "boolean")
self.assertEqual(generics[1].subtype_indication.type_mark, "boolean")

def test_parsing_entity_with_generics_corner_cases(self):
self.parse_single_entity("""\
entity name is end entity;
""")

entity = self.parse_single_entity("""\
entity name is generic(g : t); end entity;
""")
self.assertEqual(len(entity.generics), 1)
self.assertEqual(entity.generics[0].identifier, "g")

entity = self.parse_single_entity("""\
entity name is generic
(
g : t
);
end entity;
""")
self.assertEqual(len(entity.generics), 1)
self.assertEqual(entity.generics[0].identifier, "g")

entity = self.parse_single_entity("""\
end architecture; entity name is generic
(
g : t
);
end entity;
""")
self.assertEqual(len(entity.generics), 1)
self.assertEqual(entity.generics[0].identifier, "g")

entity = self.parse_single_entity("""\
entity name is foo_generic
(
g : t
);
end entity;
""")
self.assertEqual(len(entity.generics), 0)

def test_parsing_entity_with_ports(self):
entity = self.parse_single_entity("""\
entity name is
Expand Down
55 changes: 20 additions & 35 deletions vunit/vhdl_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,7 @@ def __init__(self, identifier):
self.identifier = identifier

_package_body_pattern = re.compile(r"""
(^|\A) # Beginning of line or start of string
\s* # Potential whitespaces
\b # Word boundary
package # package keyword
\s+ # At least one whitespace
body # body keyword
Expand Down Expand Up @@ -151,8 +150,7 @@ def __init__(self, identifier, entity):
self.entity = entity

_configuration_re = re.compile(r"""
(^|\A) # Beginning of line or start of string
\s* # Potential whitespaces
\b # Word boundary
configuration # configuration keyword
\s+ # At least one whitespace
(?P<id>[a-zA-Z][\w]*) # An identifier
Expand Down Expand Up @@ -182,8 +180,7 @@ def __init__(self, identifier, entity):
self.entity = entity

_architecture_re = re.compile(r"""
(^|\A) # Beginning of line or start of string
\s* # Potential whitespaces
\b # Word boundary
architecture # architecture keyword
\s+ # At least one whitespace
(?P<id>[a-zA-Z][\w]*) # An identifier
Expand Down Expand Up @@ -219,8 +216,7 @@ def __init__(self, identifier, constant_declarations, # pylint: disable=too-man
self.array_types = array_types

_package_start_re = re.compile(r"""
(^|\A) # Beginning of line or start of string
\s* # Potential whitespaces
\b # Word boundary
package # package keyword
\s+ # At least one whitespace
(?P<id>[a-zA-Z][\w]*) # An identifier
Expand All @@ -236,8 +232,7 @@ def find(cls, code):
for package in cls._package_start_re.finditer(code):
identifier = package.group('id')
package_end = re.compile(r"""
(^|\A) # Beginning of line or start of string
[\s]* # Potential whitespaces
\b # Word boundary
end # end keyword
(\s+package)? # Optional package keyword
(\s+""" + identifier + r""")? # Optional identifier
Expand Down Expand Up @@ -321,8 +316,7 @@ def add_port(self, identifier, mode, subtype_code, init_value=None):
mode=mode))

_entity_start_re = re.compile(r"""
(^|\A) # Beginning of line or start of string
\s* # Potential whitespaces
\b # Word boundary
entity # entity keyword
\s+ # At least one whitespace
(?P<id>[a-zA-Z][\w]*) # An identifier
Expand All @@ -338,10 +332,8 @@ def find(cls, code):
for entity in cls._entity_start_re.finditer(code):
identifier = entity.group('id')
sub_code = code[entity.start():]

entity_end_re = re.compile(r"""
(^|\A) # Beginning of line or start of string
[\s]* # Potential whitespaces
\b # Word boundary
end # end keyword
[\s]* # Potential whitespaces
(entity)? # Optional entity keyword
Expand All @@ -363,8 +355,7 @@ def parse(cls, code):
# Extract identifier
re_flags = re.MULTILINE | re.IGNORECASE | re.VERBOSE
entity_start = re.compile(r"""
\A # Start of string
\s* # Potential whitespaces
\b # Word boundary
entity # entity keyword
\s+ # At least one whitespace
(?P<id>[a-zA-Z][\w]*) # An identifier
Expand All @@ -385,11 +376,10 @@ def _find_generic_clause(cls, code):
"""
re_flags = re.MULTILINE | re.IGNORECASE | re.VERBOSE
generic_clause_start = re.compile(r"""
^ # Beginning of line
[\s]* # Potential whitespaces
generic # generic keyword
[\s]* # Potential whitespaces
\( # Opening parenthesis
\b # Word boundary
generic # generic keyword
[\s]* # Potential whitespaces
\( # Opening parenthesis
""", re_flags)
match = generic_clause_start.search(code)
if match:
Expand Down Expand Up @@ -475,9 +465,8 @@ def __init__(self, identifier):
self.identifier = identifier

_context_start_re = re.compile(r"""
(^|\A) # Beginning of line or start of string
\s* # Potential whitespaces
context # context keyword
\b # Word boundary
context # context keyword
\s+ # At least one whitespace
(?P<id>[a-zA-Z][\w]*) # An identifier
\s+ # At least one whitespace
Expand Down Expand Up @@ -654,8 +643,7 @@ def __init__(self, identifier, literals):
self.literals = literals

_enum_declaration_re = re.compile(r"""
(^|\A) # Beginning of line or start of string
\s*
\b # Word boundary
type
\s+
(?P<id>[a-zA-Z][\w]*) # An identifier
Expand Down Expand Up @@ -688,8 +676,7 @@ def __init__(self, identifier, elements):
self.elements = elements

_record_declaration_re = re.compile(r"""
(^|\A) # Beginning of line or start of string
\s*
\b # Word boundary
type
\s+
(?P<id>[a-zA-Z][\w]*) # An identifier
Expand Down Expand Up @@ -763,8 +750,7 @@ def __init__(self, identifier, subtype_indication, range1, range2):
\s+range\s+<>\s*""", re.MULTILINE | re.IGNORECASE | re.VERBOSE | re.DOTALL)

_array_declaration_re = re.compile(r"""
(^|\A)
\s*
\b # Word boundary
type
\s+
(?P<id>[a-zA-Z][\w]*)
Expand Down Expand Up @@ -865,8 +851,7 @@ class VHDLReference(object):
"configuration")

_uses_re = re.compile(r"""
(^|\A) # Beginning of line or start of string
\s* # Potential whitespaces
\b # Word boundary
(?P<use_type>use|context) # use or context keyword
\s+ # At least one whitespace
(?P<id>[a-zA-Z][\w]*(\.[a-zA-Z][\w]*){1,2})
Expand Down Expand Up @@ -913,7 +898,7 @@ def get_ids(match):
return references

_entity_reference_re = re.compile(
r'(^|\A|\s)\s*entity\s+(?P<lib>[a-zA-Z]\w*)\.(?P<ent>[a-zA-Z]\w*)\s*(\((?P<arch>[a-zA-Z]\w*)\))?',
r'\bentity\s+(?P<lib>[a-zA-Z]\w*)\.(?P<ent>[a-zA-Z]\w*)\s*(\((?P<arch>[a-zA-Z]\w*)\))?',
re.MULTILINE | re.IGNORECASE)

@classmethod
Expand All @@ -930,7 +915,7 @@ def _find_entity_references(cls, code):
return references

_configuration_reference_re = re.compile(
r'(^|\A|\s)\s*configuration\s+(?P<lib>[a-zA-Z]\w*)\.(?P<cfg>[a-zA-Z]\w*)',
r'\bconfiguration\s+(?P<lib>[a-zA-Z]\w*)\.(?P<cfg>[a-zA-Z]\w*)',
re.MULTILINE | re.IGNORECASE)

@classmethod
Expand Down

0 comments on commit 7e1fe0e

Please sign in to comment.