Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix VhdlExtractor.is_array + use setup.cfg + clean #10

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions hdlparse/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = '1.1.0'
9 changes: 5 additions & 4 deletions hdlparse/minilexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@

"""Minimalistic lexer engine inspired by the PyPigments RegexLexer"""

__version__ = '1.0.7'

log = logging.getLogger(__name__)
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter('%(name)s - %(levelname)s - %(message)s'))
log.addHandler(handler)

if not log.handlers: # only add the handler if no handlers are already registered
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter('%(name)s - %(levelname)s - %(message)s'))
log.addHandler(handler)


class MiniLexer(object):
Expand Down
7 changes: 3 additions & 4 deletions hdlparse/verilog_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
import io
import os
from collections import OrderedDict

from hdlparse.minilexer import MiniLexer
from .minilexer import MiniLexer

"""Verilog documentation parser"""

Expand All @@ -25,7 +24,7 @@
r'^[\(\s]*(input|inout|output)\s+(reg|supply0|supply1|tri|triand|trior|tri0|tri1|wire|wand|wor)?'
r'\s*(signed)?\s*((\[[^]]+\])+)?',
'module_port_start', 'module_port'),
(r'endmodule', 'end_module', '#pop'),
(r'\bendmodule\b', 'end_module', '#pop'),
(r'/\*', 'block_comment', 'block_comment'),
(r'//#\s*{{(.*)}}\n', 'section_meta'),
(r'//.*\n', None),
Expand Down Expand Up @@ -226,7 +225,7 @@ def is_verilog(fname):
Returns:
True when file has a Verilog extension.
"""
return os.path.splitext(fname)[1].lower() in ('.vlog', '.v')
return os.path.splitext(fname)[-1].lower() in ('.vlog', '.v', '.sv')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The verilog parser currently offers next to no SystemVerilog extension support, so I'm not sure we should add .sv here unless we intend to start adding minimal support. The problem is even if all we did was parse logic, I'm pretty sure something like wire [7:0] logic is valid verilog... We'd ideally want to make it an optional flag.

I am in favor of basic support as I mention here:
#4 (comment)

but we can maybe start a different branch / PR for that?



class VerilogExtractor:
Expand Down
83 changes: 45 additions & 38 deletions hdlparse/vhdl_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
import os
import re
from pprint import pprint
from hdlparse.minilexer import MiniLexer
from typing import List, Optional
from .minilexer import MiniLexer

"""VHDL documentation parser"""

Expand Down Expand Up @@ -171,20 +172,48 @@ def __init__(self, name, desc=None):
self.kind = 'unknown'
self.desc = desc

def remove_outer_parenthesis(s: Optional[str]):
if s:
n = 1
while n:
s, n = re.subn(r'\([^()]*\)', '', s.strip()) # remove non-nested/flat balanced parts
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple of things here:

  • This regex seems to remove anything nested in parentheses which isn't what its name suggests.
  • Parenthesis should be plural parentheses
  • This function isn't called anywhere and isn't in a class?

return s

class VhdlParameterType:
"""Parameter type definition

Args:
name (str): Name of the type
direction(str): "to" or "downto"
r_bound (str): A simple expression based on digits or variable names
l_bound (str): A simple expression based on digits or variable names
arange (str): Original array range string
"""

def __init__(self, name, direction="", r_bound="", l_bound="", arange=""):
self.name = name
self.direction = direction.lower().strip()
self.r_bound = r_bound.strip()
self.l_bound = l_bound.strip()
self.arange = arange

def __repr__(self):
return f"VhdlParameterType('{self.name}','{self.arange}')"


class VhdlParameter:
"""Parameter to subprograms, ports, and generics

Args:
name (str): Name of the object
mode (str): Direction mode for the parameter
data_type (str): Type name for the parameter
default_value (str): Default value of the parameter
desc (str): Description from object metacomments
param_desc (str): Description of the parameter
mode (optional str): Direction mode for the parameter
data_type (optional VhdlParameterType): Type name for the parameter
default_value (optional str): Default value of the parameter
desc (optional str): Description from object metacomments
param_desc (optional str): Description of the parameter
"""

def __init__(self, name, mode=None, data_type=None, default_value=None, desc=None, param_desc=None):
def __init__(self, name, mode: Optional[str] = None, data_type: Optional[VhdlParameterType] = None, default_value: Optional[str] = None, desc: Optional[str] = None, param_desc: Optional[str] = None):
self.name = name
self.mode = mode
self.data_type = data_type
Expand All @@ -210,28 +239,6 @@ def __repr__(self):
return f"VhdlParameter('{self.name}', '{self.mode}', '{self.data_type.name + self.data_type.arange}')"


class VhdlParameterType:
"""Parameter type definition

Args:
name (str): Name of the type
direction(str): "to" or "downto"
r_bound (str): A simple expression based on digits or variable names
l_bound (str): A simple expression based on digits or variable names
arange (str): Original array range string
"""

def __init__(self, name, direction="", r_bound="", l_bound="", arange=""):
self.name = name
self.direction = direction.strip()
self.r_bound = r_bound.strip()
self.l_bound = l_bound.strip()
self.arange = arange

def __repr__(self):
return f"VhdlParameterType('{self.name}','{self.arange}')"


class VhdlPackage(VhdlObject):
"""Package declaration

Expand Down Expand Up @@ -357,7 +364,7 @@ class VhdlEntity(VhdlObject):
desc (str, optional): Description from object metacomments
"""

def __init__(self, name, ports, generics=None, sections=None, desc=None):
def __init__(self, name: str, ports: List[VhdlParameter], generics: List[VhdlParameter] = [], sections: List[str] = [], desc: Optional[str] = None):
VhdlObject.__init__(self, name, desc)
self.kind = 'entity'
self.generics = generics if generics is not None else []
Expand Down Expand Up @@ -602,7 +609,7 @@ def parse_vhdl(text):
saved_type = groups[0]

elif action in (
'array_type', 'file_type', 'access_type', 'record_type', 'range_type', 'enum_type', 'incomplete_type'):
'array_type', 'file_type', 'access_type', 'record_type', 'range_type', 'enum_type', 'incomplete_type'):
vobj = VhdlType(saved_type, cur_package, action, metacomments)
objects.append(vobj)
kind = None
Expand Down Expand Up @@ -684,7 +691,7 @@ def is_vhdl(fname):
Returns:
True when file has a VHDL extension.
"""
return os.path.splitext(fname)[1].lower() in ('.vhdl', '.vhd')
return os.path.splitext(fname)[-1].lower() in ('.vhdl', '.vhd')


class VhdlExtractor:
Expand Down Expand Up @@ -721,7 +728,11 @@ def extract_objects(self, fname, type_filter=None):
self._register_array_types(objects)

if type_filter:
objects = [o for o in objects if isinstance(o, type_filter)]
if not isinstance(type_filter, list):
type_filter = [type_filter]
objects = [
o for o in objects if any(map(lambda clz: isinstance(o, clz), type_filter))
]

return objects

Expand Down Expand Up @@ -750,11 +761,7 @@ def is_array(self, data_type):
Returns:
True if ``data_type`` is a known array type.
"""

# Split off any brackets
data_type = data_type.split('[')[0].strip()

return data_type.lower() in self.array_types
return data_type.name.lower() in self.array_types
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing in vhdl_ex.is_array("unsigned") now fails because string does not have an attribute name.


def _add_array_types(self, type_defs):
"""Add array data types to internal registry
Expand Down
31 changes: 31 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[metadata]
name = hdlparse
author = Kevin Thibedeau
author_email = [email protected]
url = http://kevinpt.github.io/hdlparse
download_url = http://kevinpt.github.io/hdlparse
description = HDL parser
long_description = file: README.rst
description_file = README.rst
version = attr: hdlparse.__version__
license = MIT
keywords = HDL parser
classifiers =
Development Status :: 5 - Production/Stable
Operating System :: OS Independent
Intended Audience :: Developers
Topic :: Text Processing :: General
Natural Language :: English
Programming Language :: Python :: 3
License :: OSI Approved :: MIT License

[options]
packages = hdlparse
py_modules =
install_requires =
include_package_data = True


[pycodestyle]
max_line_length = 120
ignore = E501
43 changes: 1 addition & 42 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,3 @@
from setuptools import setup

# Use README.rst for the long description
with open('README.rst') as fh:
long_description = fh.read()

# Scan the script for the version string
version_file = 'hdlparse/minilexer.py'
version = None
with open(version_file) as fh:
try:
version = [line.split('=')[1].strip().strip("'") for line in fh if
line.startswith('__version__')][0]
except IndexError:
pass

if version is None:
raise RuntimeError('Unable to find version string in file: {0}'.format(version_file))

setup(name='hdlparse',
version=version,
author='Kevin Thibedeau',
author_email='[email protected]',
url='http://kevinpt.github.io/hdlparse',
download_url='http://kevinpt.github.io/hdlparse',
description='HDL parser',
long_description=long_description,
platforms=['Any'],
install_requires=[],
packages=['hdlparse'],
py_modules=[],
include_package_data=True,

keywords='HDL parser',
license='MIT',
classifiers=['Development Status :: 5 - Production/Stable',
'Operating System :: OS Independent',
'Intended Audience :: Developers',
'Topic :: Text Processing :: General',
'Natural Language :: English',
'Programming Language :: Python :: 3',
'License :: OSI Approved :: MIT License'
]
)
setup()