Esempio n. 1
0
    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)
Esempio n. 3
0
    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
Esempio n. 4
0
    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