diff --git a/src/language/code_generator.py b/src/language/code_generator.py index 61c6340394..a1e9f3d6d6 100644 --- a/src/language/code_generator.py +++ b/src/language/code_generator.py @@ -10,7 +10,6 @@ import logging import os from pathlib import Path -import shlex import shutil import subprocess import tempfile diff --git a/src/language/node_info.py b/src/language/node_info.py index a089a7c0de..0baa1912d5 100644 --- a/src/language/node_info.py +++ b/src/language/node_info.py @@ -11,9 +11,9 @@ nmodl blocks defining variables, nmodl constructs that define variables etc. These all data types are defined in this file. -\todo : Other way is to add extra attributes to YAML language definitions. +TODO: Other way is to add extra attributes to YAML language definitions. YAML will become more verbose but advantage would be that the YAML will be -self sufficien, single definition file instead of hard-coded names here. +self sufficient, single definition file instead of hard-coded names here. We should properties like is_enum, data_type, is_symbol, is_global etc. """ @@ -103,12 +103,12 @@ # when translating back to nmodl, we need print each statement # to new line. Those nodes are are used from this list. -STATEMENT_TYPES=["Statement", - "IndependentDef", - "DependentDef", - "ParamAssign", - "ConstantStatement", - "Stepped"] +STATEMENT_TYPES = ["Statement", + "IndependentDef", + "DependentDef", + "ParamAssign", + "ConstantStatement", + "Stepped"] # data types which have token as an argument to the constructor LEXER_DATA_TYPES = ["Name", @@ -136,7 +136,7 @@ PTR_EXCLUDE_TYPES = ["BinaryOperator", "UnaryOperator", "ReactionOperator"] # these node names are explicitly added because they are used in ast/visitor -# printer classes. In otder to avoid hardcoding in the printer functions, they +# printer classes. In order to avoid hardcoding in the printer functions, they # are defined here. PROGRAM_BLOCK = "Program" BASE_BLOCK = "Block" diff --git a/src/language/nodes.py b/src/language/nodes.py index 1a57a3baef..30a76eee8f 100644 --- a/src/language/nodes.py +++ b/src/language/nodes.py @@ -12,9 +12,10 @@ is represented by ChildNode. """ -from node_info import * import textwrap -from utils import * + +import node_info +from utils import to_snake_case class BaseNode: @@ -32,27 +33,27 @@ def __init__(self, args): self.is_abstract = False def __lt__(self, other): - return (self.class_name < other.class_name) + return self.class_name < other.class_name def get_data_type_name(self): """ return type name for the node """ - return DATA_TYPES[self.class_name] + return node_info.DATA_TYPES[self.class_name] @property def is_statement_block_node(self): - return self.class_name == STATEMENT_BLOCK_NODE + return self.class_name == node_info.STATEMENT_BLOCK_NODE @property def is_statement_node(self): - return self.class_name in STATEMENT_TYPES + return self.class_name in node_info.STATEMENT_TYPES @property def is_global_block_node(self): - return self.class_name in GLOBAL_BLOCKS + return self.class_name in node_info.GLOBAL_BLOCKS @property def is_prime_node(self): - return self.class_name == PRIME_NAME_NODE + return self.class_name == node_info.PRIME_NAME_NODE @property def is_program_node(self): @@ -60,7 +61,7 @@ def is_program_node(self): check if current node is main program container node :return: True if main program block otherwise False """ - return self.class_name == PROGRAM_BLOCK + return self.class_name == node_info.PROGRAM_BLOCK @property def is_block_node(self): @@ -71,73 +72,73 @@ def is_block_node(self): :return: True or False """ - return self.class_name in BLOCK_TYPES + return self.class_name in node_info.BLOCK_TYPES @property def is_unit_block(self): - return self.class_name == UNIT_BLOCK + return self.class_name == node_info.UNIT_BLOCK @property def is_data_type_node(self): - return self.class_name in DATA_TYPES + return self.class_name in node_info.DATA_TYPES @property def is_symbol_var_node(self): - return self.class_name in SYMBOL_VAR_TYPES + return self.class_name in node_info.SYMBOL_VAR_TYPES @property def is_symbol_helper_node(self): - return self.class_name in SYMBOL_TABLE_HELPER_NODES + return self.class_name in node_info.SYMBOL_TABLE_HELPER_NODES @property def is_symbol_block_node(self): - return self.class_name in SYMBOL_BLOCK_TYPES + return self.class_name in node_info.SYMBOL_BLOCK_TYPES @property def is_base_type_node(self): - return self.class_name in BASE_TYPES + return self.class_name in node_info.BASE_TYPES @property def is_string_node(self): - return self.class_name == STRING_NODE + return self.class_name == node_info.STRING_NODE @property def is_integer_node(self): - return self.class_name == INTEGER_NODE + return self.class_name == node_info.INTEGER_NODE @property def is_number_node(self): - return self.class_name == NUMBER_NODE + return self.class_name == node_info.NUMBER_NODE @property def is_boolean_node(self): - return self.class_name == BOOLEAN_NODE + return self.class_name == node_info.BOOLEAN_NODE @property def is_identifier_node(self): - return self.class_name == IDENTIFIER_NODE + return self.class_name == node_info.IDENTIFIER_NODE @property def is_name_node(self): - return self.class_name == NAME_NODE + return self.class_name == node_info.NAME_NODE @property def is_enum_node(self): - data_type = DATA_TYPES[self.class_name] - return data_type in ENUM_BASE_TYPES + data_type = node_info.DATA_TYPES[self.class_name] + return data_type in node_info.ENUM_BASE_TYPES @property def is_pointer_node(self): - return not (self.class_name in PTR_EXCLUDE_TYPES or + return not (self.class_name in node_info.PTR_EXCLUDE_TYPES or self.is_base_type_node) @property def is_ptr_excluded_node(self): - return self.class_name in PTR_EXCLUDE_TYPES + return self.class_name in node_info.PTR_EXCLUDE_TYPES @property def requires_default_constructor(self): - return (self.class_name in LEXER_DATA_TYPES or + return (self.class_name in node_info.LEXER_DATA_TYPES or self.is_program_node or self.is_ptr_excluded_node) @@ -257,14 +258,14 @@ def is_block_scoped_node(self): Check if node is derived from BASE_BLOCK :return: True / False """ - return self.base_class == BASE_BLOCK + return self.base_class == node_info.BASE_BLOCK def has_parent_block_node(self): """ check is base or parent is structured base block :return: True if parent is BASE_BLOCK otherwise False """ - return self.base_class == BASE_BLOCK + return self.base_class == node_info.BASE_BLOCK @property def is_base_block_node(self): @@ -272,7 +273,7 @@ def is_base_block_node(self): check if node is Block :return: True if node type/name is BASE_BLOCK """ - return self.class_name == BASE_BLOCK + return self.class_name == node_info.BASE_BLOCK @property def is_symtab_needed(self): @@ -301,13 +302,14 @@ def is_symtab_method_required(self): if self.has_children(): - if self.class_name in SYMBOL_VAR_TYPES or self.class_name in SYMBOL_BLOCK_TYPES: + if(self.class_name in node_info.SYMBOL_VAR_TYPES or + self.class_name in node_info.SYMBOL_BLOCK_TYPES): method_required = True if self.is_program_node or self.has_parent_block_node(): method_required = True - if self.class_name in SYMBOL_TABLE_HELPER_NODES: + if self.class_name in node_info.SYMBOL_TABLE_HELPER_NODES: method_required = True return method_required @@ -317,7 +319,7 @@ def is_base_class_number_node(self): """ Check if node is of type Number """ - return self.base_class == NUMBER_NODE + return self.base_class == node_info.NUMBER_NODE def ctor_declaration(self): args = [f'{c.get_typename()} {c.varname}' for c in self.children] diff --git a/src/language/parser.py b/src/language/parser.py index 12d51b726f..85f458ab5d 100644 --- a/src/language/parser.py +++ b/src/language/parser.py @@ -15,9 +15,10 @@ import sys import yaml + from argument import Argument from nodes import Node -from node_info import * +import node_info class LanguageParser: @@ -27,17 +28,16 @@ def __init__(self, filename, debug=False): self.filename = filename self.debug = debug - @classmethod - def is_token(self, name): + @staticmethod + def is_token(name): """check if the name (i.e. class) is a token type in lexer Lexims returned from Lexer have position and hence token object. Return True if this node is returned by lexer otherwise False """ - if name in LEXER_DATA_TYPES or name in SYMBOL_BLOCK_TYPES or name in ADDITIONAL_TOKEN_BLOCKS: - return True - else: - return False + return (name in node_info.LEXER_DATA_TYPES or + name in node_info.SYMBOL_BLOCK_TYPES or + name in node_info.ADDITIONAL_TOKEN_BLOCKS) def parse_child_rule(self, child): """parse child specification and return argument as properties @@ -59,7 +59,6 @@ def parse_child_rule(self, child): # type i.e. class of the variable args.class_name = properties['type'] - if self.debug: print(('Child {}, {}'.format(args.varname, args.class_name))) @@ -125,7 +124,6 @@ def parse_child_rule(self, child): return args - def parse_yaml_rules(self, nodelist, base_class=None): abstract_nodes = [] nodes = [] @@ -148,7 +146,6 @@ def parse_yaml_rules(self, nodelist, base_class=None): # classes like AST which don't have base class # are not added (we print AST class separately) if base_class: - args = Argument() args.base_class = base_class args.class_name = class_name @@ -203,8 +200,7 @@ def parse_file(self): with open(self.filename, 'r') as stream: try: rules = yaml.load(stream) - # abstract nodes are not used though - abstract_nodes, nodes = self.parse_yaml_rules(rules) + _, nodes = self.parse_yaml_rules(rules) except yaml.YAMLError as e: print(("Error while parsing YAML definition file {0} : {1}".format(self.filename, e.strerror))) sys.exit(1) diff --git a/src/language/utils.py b/src/language/utils.py index b6b7a55694..87b90d72ab 100644 --- a/src/language/utils.py +++ b/src/language/utils.py @@ -7,12 +7,14 @@ import re -# convert string of the form "AabcDef" to "Abc_Def" + def camel_case_to_underscore(name): + """convert string from 'AaaBbbbCccDdd' -> 'Aaa_Bbbb_Ccc_Ddd'""" s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name) typename = re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1) return typename -# convert string of the form "AabcDef" to "abc_def" + def to_snake_case(name): - return camel_case_to_underscore(name).lower() + """convert string from 'AaaBbbbCccDdd' -> 'aaa_bbbb_ccc_ddd'""" + return camel_case_to_underscore(name).lower()