def handle_input_path(cls, path) -> None: """ Sets cls.paths_to_compilation_units with a list of absolute paths to NESTML files. Use glob to search directories recursively. """ cls.provided_input_path = path if not path or path == ['']: # mandatory path arg has not been handed over code, message = Messages.get_input_path_not_found(path="") Logger.log_message(code=code, message=message, log_level=LoggingLevel.ERROR) raise InvalidPathException(message) if type(path) is str: path = [path] cls.paths_to_compilation_units = list() for _path in path: if not os.path.isabs(_path): # turn relative to absolute path pynestml_dir = os.getcwd() _path = os.path.join(pynestml_dir, _path) if os.path.isfile(_path): cls.paths_to_compilation_units.append(_path) elif os.path.isdir(_path): for fn in glob.glob(os.path.join(_path, "**", "*.nestml"), recursive=True): cls.paths_to_compilation_units.append( os.path.join(_path, fn)) else: # input_path should be either a file or a directory code, message = Messages.get_input_path_not_found(path=_path) Logger.log_message(code=code, message=message, log_level=LoggingLevel.ERROR) raise InvalidPathException(message) if not cls.paths_to_compilation_units: code, message = Messages.get_no_files_in_input_path(" ".join(path)) Logger.log_message(code=code, message=message, log_level=LoggingLevel.ERROR) raise InvalidPathException(message) Logger.log_message(message="List of files that will be processed:", log_level=LoggingLevel.INFO) for fn in cls.paths_to_compilation_units: Logger.log_message(message=fn, log_level=LoggingLevel.INFO)
def handle_input_path(cls, path): if path is None or path == '': # check if the mandatory path arg has been handed over, just terminate raise InvalidPathException('No input path specified.') cls.paths_to_compilation_units = list() if os.path.isabs(path): cls.provided_path = path else: # a relative path, reconstruct it. get the parent dir where models, pynestml etc. is located pynestml_dir = os.getcwd() cls.provided_path = os.path.join(pynestml_dir, path) if os.path.isfile(cls.provided_path): cls.paths_to_compilation_units.append(cls.provided_path) elif os.path.isdir(cls.provided_path): for filename in os.listdir(cls.provided_path): if filename.endswith('.nestml'): cls.paths_to_compilation_units.append( os.path.join(cls.provided_path, filename)) else: # input_path should be either a file or a directory code, message = Messages.get_input_path_not_found( path=cls.provided_path) Logger.log_message(code=code, message=message, log_level=LoggingLevel.ERROR) raise Exception(message)
def parse_model(cls, file_path=None): """ Parses a handed over model and returns the meta_model representation of it. :param file_path: the path to the file which shall be parsed. :type file_path: str :return: a new ASTNESTMLCompilationUnit object. :rtype: ASTNestMLCompilationUnit """ try: input_file = FileStream(file_path) except IOError: code, message = Messages.get_input_path_not_found(path=file_path) Logger.log_message(node=None, code=None, message=message, error_position=None, log_level=LoggingLevel.ERROR) return code, message = Messages.get_start_processing_file(file_path) Logger.log_message(node=None, code=code, message=message, error_position=None, log_level=LoggingLevel.INFO) # create a lexer and hand over the input lexer = PyNestMLLexer() lexer.removeErrorListeners() lexer.addErrorListener(ConsoleErrorListener()) lexerErrorListener = NestMLErrorListener() lexer.addErrorListener(lexerErrorListener) # lexer._errHandler = BailErrorStrategy() # N.B. uncomment this line and the next to halt immediately on lexer errors # lexer._errHandler.reset(lexer) lexer.inputStream = input_file # create a token stream stream = CommonTokenStream(lexer) stream.fill() if lexerErrorListener._error_occurred: code, message = Messages.get_lexer_error() Logger.log_message(node=None, code=None, message=message, error_position=None, log_level=LoggingLevel.ERROR) return # parse the file parser = PyNestMLParser(None) parser.removeErrorListeners() parser.addErrorListener(ConsoleErrorListener()) parserErrorListener = NestMLErrorListener() parser.addErrorListener(parserErrorListener) # parser._errHandler = BailErrorStrategy() # N.B. uncomment this line and the next to halt immediately on parse errors # parser._errHandler.reset(parser) parser.setTokenStream(stream) compilation_unit = parser.nestMLCompilationUnit() if parserErrorListener._error_occurred: code, message = Messages.get_parser_error() Logger.log_message(node=None, code=None, message=message, error_position=None, log_level=LoggingLevel.ERROR) return # create a new visitor and return the new AST ast_builder_visitor = ASTBuilderVisitor(stream.tokens) ast = ast_builder_visitor.visit(compilation_unit) # create and update the corresponding symbol tables SymbolTable.initialize_symbol_table(ast.get_source_position()) for neuron in ast.get_neuron_list(): neuron.accept(ASTSymbolTableVisitor()) SymbolTable.add_neuron_scope(neuron.get_name(), neuron.get_scope()) # store source paths for neuron in ast.get_neuron_list(): neuron.file_path = file_path ast.file_path = file_path return ast
def parse_model(cls, file_path=None): """ Parses a handed over model and returns the meta_model representation of it. :param file_path: the path to the file which shall be parsed. :type file_path: str :return: a new ASTNESTMLCompilationUnit object. :rtype: ASTNestMLCompilationUnit """ try: input_file = FileStream(file_path) except IOError: code, message = Messages.get_input_path_not_found(path=file_path) Logger.log_message(neuron=None, code=None, message=message, error_position=None, log_level=LoggingLevel.ERROR) return code, message = Messages.get_start_processing_file(file_path) Logger.log_message(neuron=None, code=code, message=message, error_position=None, log_level=LoggingLevel.INFO) # create a lexer and hand over the input lexer = PyNestMLLexer() lexer.removeErrorListeners() lexer.addErrorListener(ConsoleErrorListener()) lexerErrorListener = NestMLErrorListener() lexer.addErrorListener(lexerErrorListener) # lexer._errHandler = BailErrorStrategy() # N.B. uncomment this line and the next to halt immediately on lexer errors # lexer._errHandler.reset(lexer) lexer.inputStream = input_file # create a token stream stream = CommonTokenStream(lexer) stream.fill() if lexerErrorListener._error_occurred: code, message = Messages.get_lexer_error() Logger.log_message(neuron=None, code=None, message=message, error_position=None, log_level=LoggingLevel.ERROR) return # parse the file parser = PyNestMLParser(None) parser.removeErrorListeners() parser.addErrorListener(ConsoleErrorListener()) parserErrorListener = NestMLErrorListener() parser.addErrorListener(parserErrorListener) # parser._errHandler = BailErrorStrategy() # N.B. uncomment this line and the next to halt immediately on parse errors # parser._errHandler.reset(parser) parser.setTokenStream(stream) compilation_unit = parser.nestMLCompilationUnit() if parserErrorListener._error_occurred: code, message = Messages.get_parser_error() Logger.log_message(neuron=None, code=None, message=message, error_position=None, log_level=LoggingLevel.ERROR) return # create a new visitor and return the new AST ast_builder_visitor = ASTBuilderVisitor(stream.tokens) ast = ast_builder_visitor.visit(compilation_unit) # create and update the corresponding symbol tables SymbolTable.initialize_symbol_table(ast.get_source_position()) log_to_restore = copy.deepcopy(Logger.get_log()) counter = Logger.curr_message # replace all derived variables through a computer processable names: e.g. g_in''' -> g_in__ddd restore_differential_order = [] for ode in ASTUtils.get_all(ast, ASTOdeEquation): lhs_variable = ode.get_lhs() if lhs_variable.get_differential_order() > 0: lhs_variable.differential_order = lhs_variable.get_differential_order() - 1 restore_differential_order.append(lhs_variable) for shape in ASTUtils.get_all(ast, ASTOdeShape): lhs_variable = shape.get_variable() if lhs_variable.get_differential_order() > 0: lhs_variable.differential_order = lhs_variable.get_differential_order() - 1 restore_differential_order.append(lhs_variable) # than replace remaining variables for variable in ASTUtils.get_all(ast, ASTVariable): if variable.get_differential_order() > 0: variable.set_name(variable.get_name() + "__" + "d" * variable.get_differential_order()) variable.differential_order = 0 # now also equations have no ' at lhs. replace every occurrence of last d to ' to compensate for ode_variable in restore_differential_order: ode_variable.differential_order = 1 Logger.set_log(log_to_restore, counter) for neuron in ast.get_neuron_list(): neuron.accept(ASTSymbolTableVisitor()) SymbolTable.add_neuron_scope(neuron.get_name(), neuron.get_scope()) return ast