コード例 #1
0
ファイル: parser.py プロジェクト: exescribis/ScribesInfra
 def _checkSystemExist(isLast=False):
     if not self.usecaseModel.isSystemDefined:
         LocalizedSourceIssue(
             sourceFile=self,
             level=Levels.Fatal,
             message='System is not defined %s' %
             (' yet.' if not isLast else '!'),
             line=line_no,
         )
コード例 #2
0
ファイル: sources.py プロジェクト: exescribis/ScribesInfra
 def checkAllowed(self, feature, message, lineNo=None, level=Levels.Fatal):
     # type: (Text, Text, int, Level, Text) -> bool
     """
     Check if a feature is allowed.
     If this not the case raise an issue with
     a proper message (see the code).
     """
     is_allowed = feature in self.allowedFeatures
     if not is_allowed:
         if lineNo is None:
             Issue(self, level=level, message=message)
         else:
             LocalizedSourceIssue(sourceFile=self,
                                  level=level,
                                  message=message,
                                  line=lineNo)
     return is_allowed
コード例 #3
0
ファイル: parser.py プロジェクト: exescribis/ScribesInfra
    def _parse():
        for line_no in range(1, len(modelSource.sourceLines) + 1):

            # --------- model definition ----------------------
            md = _matchModelDefinition(lineNo=line_no,
                                       modelSourceFile=modelSource,
                                       justMatch=False,
                                       noSymbolChecking=noSymbolChecking,
                                       recognizeUSEOCLNativeModelDefinition=
                                       recognizeUSEOCLNativeModelDefinition)
            if md is not None:
                if modelSource.importBox.modelName is not None:
                    LocalizedSourceIssue(
                        sourceFile=modelSource,
                        line=line_no,
                        level=Levels.Warning,
                        message=('The model is already named : "%s"' %
                                 modelSource.model.modelName))

                modelSource.importBox.setModelInfo(modelName=md.name,
                                                   modelKind=md.modelKind)
                continue

            # --------- model import ----------------------

            mi = _matchModelImport(lineNo=line_no,
                                   modelSourceFile=modelSource,
                                   justMatch=False)
            if mi is not None:
                if DEBUG >= 1 or Config.realtimeImportPrint >= 1:
                    print('\nimp: >>>>>>>> ' + repr(mi))

                modelSource.importBox.addImport(SourceImport(importStmt=mi))

                if DEBUG >= 1 or Config.realtimeImportPrint >= 1:
                    from modelscripts.scripts.megamodels.printer.imports import ImportBoxPrinter
                    ImportBoxPrinter(modelSource.importBox).display()
                    print('imp: <<<<<<<< ' + repr(mi) + '\n')
                continue

            # --------- any other line is ok -------------------
            continue
コード例 #4
0
ファイル: issues.py プロジェクト: exescribis/ScribesInfra
 def __init__(self,
              modelElement,
              level,
              message,
              locationElement=None):
     #type: ('ModelElement', Level, Text, 'ModelElement') -> None
     self.modelElement=modelElement #type: 'ModelElement'
     self.locationElement=(
         locationElement if locationElement is not None
         else modelElement)
     if DEBUG>=2:
         print('ISM: %s ' % self.locationElement)
     #type: 'ModelElement'
     if hasattr(self.locationElement, 'lineNo'):
         line_no=self.locationElement.lineNo
     else:
         line_no=None
     if line_no is None:
         if DEBUG>=1:
             print('ISM: Unlocated Model Issue %s' % message)
         issue=Issue(
             origin=modelElement.model,
             level=level,
             message=message)
     else:
         if DEBUG>=1:
             print('ISM: Localized Model Issue at %s %s' % (
                 line_no,
                 message))
         issue=LocalizedSourceIssue(
             sourceFile=self.locationElement.model.source,
             level=level,
             message=message,
             line=line_no,
         )
     self.actualIssue=issue
コード例 #5
0
ファイル: parser.py プロジェクト: exescribis/ScribesInfra
def _matchModelDefinition(
        lineNo,
        modelSourceFile,
        justMatch=False,
        # prefixRegexp=r' *(--)? *@?',
        noSymbolChecking=False,
        recognizeUSEOCLNativeModelDefinition=False):
    # type: (int, ModelSourceFile, bool, bool, bool) -> Optional[Union[bool,DefinitionStatement]]
    """
        Check if the line is a model definition statement.

        If justMatch just indicates if the line is recognized.
        In that case it returns True otherwise None.

        If not justMatch build an ImportStatement (if possible)
        Return None if this is not the case.
        Return a ModelDefinitionStatement if the stmt is valid.
        Otherwise raise a value error.
        Definition statements looks like this
            preliminary usecase model MyModel
            class model MyModel

        If 'recognizeUSEOCLNativeModelDefinition' then the line
        "model <NAME>" is accepted as the model definition in USE OCL
        files. This is a patch good enough for now for .use file.
        Later the .use file could be generated and the syntax improved.
    """
    def _parseStandardSyntax():
        re_stmt = (r'^ *((?P<modelKind>\w+) +)?' + r'(?P<metamodelLabel>\w+)' +
                   r' +model' + r' +(?P<name>\w+) *$')
        line = modelSourceFile.realSourceLines[lineNo - 1]
        m = re.match(re_stmt, line, re.MULTILINE)
        if m is None:
            return None
        else:
            if m.group('modelKind') == 'import':  # because overlapping regexp
                return None
            if justMatch:
                return True
            else:
                return {
                    'modelKind': m.group('modelKind'),
                    'metamodelLabel': m.group('metamodelLabel'),
                    'name': m.group('name')
                }

    def _parseUSEOCLSyntax():
        re_stmt = ('^' + r' *model' + r' +(?P<name>\w+) *$')
        line = modelSourceFile.realSourceLines[lineNo - 1]
        m = re.match(re_stmt, line, re.MULTILINE)
        if m is None:
            return None
        if justMatch:
            return True
        else:
            return {
                'modelKind': '',
                'metamodelLabel': 'class',
                'name': m.group('name')
            }

    def _parse():
        r1 = _parseStandardSyntax()
        if r1 is not None or not recognizeUSEOCLNativeModelDefinition:
            return r1
        else:
            # No match so search USEOCL
            return _parseUSEOCLSyntax()

    m = _parse()
    if m in [True, None]:
        return m
    else:
        source_metamodel = modelSourceFile.metamodel

        # get actual metamodel
        metamodel_label = m['metamodelLabel']
        try:
            # could raise ValueError
            from modelscripts.megamodels import Megamodel
            metamodel = Megamodel.theMetamodel(
                label=metamodel_label)  #type: Metamodel
        except ValueError as e:
            LocalizedSourceIssue(
                sourceFile=modelSourceFile,
                line=lineNo,
                level=Levels.Fatal,  # could be error with some work
                message=str(e))

        # check model_kind
        model_kind = ('' if m['modelKind'] is None else m['modelKind'])
        # noinspection PyUnboundLocalVariable
        if model_kind not in metamodel.modelKinds:
            LocalizedSourceIssue(
                sourceFile=modelSourceFile,
                line=lineNo,
                level=Levels.Fatal,  # could be error with some work
                message=(
                    '%s models can\'t be "%s".'
                    ' Choose one of %s.' %
                    (metamodel_label, model_kind, str(metamodel.modelKinds))))

        # Check that the metamodel is the expected one
        # if metamodel != source_metamodel:
        #     LocalizedSourceIssue(
        #         sourceFile=modelSourceFile,
        #         line=lineNo,
        #         level=Levels.Fatal,  # could be error with some work
        #         message=(
        #             'A %s model cannot be defined in a "%s" file.' % (
        #                 metamodel.label,
        #                 source_metamodel.extension,
        #             )))

        # Check name
        name = m['name']
        if not noSymbolChecking and not (Symbol.is_CamlCase(name)):
            LocalizedSourceIssue(
                sourceFile=modelSourceFile,
                line=lineNo,
                level=Levels.Error,
                message=('Invalid model name "%s". It must be in CamlCases.' %
                         (name)))
        if name.lower() != modelSourceFile.name.lower():
            if not recognizeUSEOCLNativeModelDefinition:
                LocalizedSourceIssue(
                    sourceFile=modelSourceFile,
                    line=lineNo,
                    level=Levels.Error,
                    message=(
                        'Model must be named %s according to the name of the file'
                        % (
                            # modelSourceFile.fileName,
                            modelSourceFile.name)))
        return DefinitionStatement(lineNo=lineNo,
                                   sourceFile=modelSourceFile,
                                   modelKind=model_kind,
                                   metamodel=metamodel,
                                   name=name)
コード例 #6
0
ファイル: parser.py プロジェクト: exescribis/ScribesInfra
def _matchModelImport(lineNo, modelSourceFile, justMatch=False):
    #Megamodel statements are always extracted from
    # RAW UNPROCESSED ORIGINAL source file.
    #type: (int, ModelSourceFile, bool) -> Optional[Union[bool,ImportStatement]]
    """
        Check if the line is an import statement.

        If justMatch just indicates if the line is recognized.
        In that case it returns True otherwise None.

        If not justMatch build an ImportStatement (if possible)
        Return None if this is not the case.
        Otherwise return a ModelImportStatement if the import is valid.
        Otherwise raise a fatal error that go in the issue box.
        Import statements looks like this
            import usecase model x.cs
            import glossary model a/b/../c.gls
    """
    re_stmt = (r'^ *(?P<import>import)' + r' +(?P<metamodelLabel>\w+)' +
               r' +model' + r' +from' + r' +\'(?P<target>[\w\./\-]+)\' *$')
    line = modelSourceFile.realSourceLines[lineNo - 1]
    m = re.match(re_stmt, line, re.MULTILINE)

    if m is None:
        return None
    else:
        if justMatch:
            return True
        else:
            source_metamodel = modelSourceFile.metamodel

            # get actual metamodel
            metamodel_label = m.group('metamodelLabel')
            try:
                # could raise ValueError
                from modelscripts.megamodels import Megamodel
                metamodel = Megamodel.theMetamodel(
                    label=metamodel_label)  #type: Metamodel
            except ValueError as e:
                LocalizedSourceIssue(
                    sourceFile=modelSourceFile,
                    line=lineNo,
                    level=Levels.Fatal,  # could be error with some work
                    message=str(e))

            # Check that metamodel dependency is allowed
            target_mms = source_metamodel.outMetamodels
            # noinspection PyUnboundLocalVariable
            if metamodel not in target_mms:
                LocalizedSourceIssue(
                    sourceFile=modelSourceFile,
                    line=lineNo,
                    level=Levels.Fatal,  # could be error with some work
                    message=('A %s model cannot reference a %s model.' %
                             (source_metamodel.label, metamodel.label)))

            # Check path
            literal_target_filename = m.group('target')
            abs_target_filename = os.path.abspath(
                os.path.join(modelSourceFile.directory,
                             literal_target_filename))
            file_extension = os.path.splitext(abs_target_filename)[1]
            if file_extension != metamodel.extension:
                LocalizedSourceIssue(
                    sourceFile=modelSourceFile,
                    line=lineNo,
                    level=Levels.Fatal,  # could be error with some work
                    message=('The extension of the file must be "%s".' %
                             (metamodel.extension)))
            if not os.path.isfile(abs_target_filename):
                LocalizedSourceIssue(
                    sourceFile=modelSourceFile,
                    line=lineNo,
                    level=Levels.Fatal,  # could be error with some work
                    message=('File not found: %s' % literal_target_filename))

            return ImportStatement(
                lineNo=lineNo,
                sourceFile=modelSourceFile,
                metamodel=metamodel,
                absoluteTargetFilename=abs_target_filename,
                literalTargetFileName=literal_target_filename)
コード例 #7
0
ファイル: parser.py プロジェクト: exescribis/ScribesInfra
    def parseToFillModel(self):
        def _checkSystemExist(isLast=False):
            if not self.usecaseModel.isSystemDefined:
                LocalizedSourceIssue(
                    sourceFile=self,
                    level=Levels.Fatal,
                    message='System is not defined %s' %
                    (' yet.' if not isLast else '!'),
                    line=line_no,
                )

        def _ensureActor(name):
            _checkSystemExist(isLast=False)
            if name in self.usecaseModel.actorNamed:
                return self.usecaseModel.actorNamed[name]
            else:
                return Actor(self.usecaseModel, name)

        def _ensureUsecase(name):
            _checkSystemExist(isLast=False)
            if name in (self.usecaseModel.system.usecaseNamed):
                return self.usecaseModel.system.usecaseNamed[name]
            else:
                return Usecase(self.usecaseModel.system, name)

        def begin(n):
            return '^' + '    ' * n

        end = ' *$'

        if DEBUG >= 1:
            print('\nParsing %s\n' % self.fileName)

        current_actor = None
        current_usecase = None
        #FIXME: use doc-for in all the parser
        current_element = self.usecaseModel
        current_scope = 'model'
        # model | system | actor | usecase | actor.usecases

        for (line_index, line) in enumerate(self.sourceLines):
            original_line = line
            # replace tabs by spaces
            line = line.replace('\t', ' ')
            line_no = line_index + 1

            if DEBUG >= 2:
                print('#%i : %s' % (line_no, original_line))

            #---- blank lines ---------------------------------
            r = '^ *$'
            m = re.match(r, line)
            if m:
                continue

            #---- comments -------------------------------------
            r = '^ *--.*$'
            m = re.match(r, line)
            if m:
                continue

            #---- description ----------------------------------
            r = '^ *\|(?P<line>.*)$'
            m = re.match(r, line)
            if m:
                current_element.description.addNewLine(
                    stringLine=m.group('line'),
                    lineNo=line_no,
                )
                continue

            #---- megamodel statements -------------
            is_mms = isMegamodelStatement(lineNo=line_no, modelSourceFile=self)
            if is_mms:
                # megamodel statements have already been
                # parse so silently ignore them
                continue

            #--- system X -------------------------
            r = begin(0) + r'system +(?P<name>\w+)' + end
            m = re.match(r, line)
            if m:
                if self.usecaseModel.isSystemDefined:
                    LocalizedSourceIssue(
                        sourceFile=self,
                        level=Levels.Warning,
                        message='System defined twice',
                        line=line_no,
                    )
                name = m.group('name')
                self.usecaseModel.system.setInfo(
                    name=name,
                    lineNo=line_no,
                )
                current_element = self.usecaseModel.system
                current_scope = 'system'
                continue

            #--- actor X --------------------------
            r = (begin(0) + r'(?P<kind>(human|system))?' +
                 ' *actor +(?P<name>\w+)' + end)
            m = re.match(r, line)
            if m:
                current_usecase = None
                name = m.group('name')
                current_actor = _ensureActor(name)
                current_actor.kind = m.group('kind'),
                current_actor.lineNo = line_no
                current_element = current_actor
                current_scope = 'actor'
                continue

            #--- usecase X --------------------------
            r = begin(0) + r'usecase +(?P<name>\w+)' + end
            m = re.match(r, line)
            if m:
                current_actor = None
                name = m.group('name')
                current_usecase = _ensureUsecase(name)
                current_usecase.lineNo = line_no
                current_element = current_usecase
                current_scope = 'usecase'
                continue

            if current_scope == 'actor':

                # --- ....usecases ------------------------
                r = begin(1) + r'usecases' + end
                m = re.match(r, line)
                if m:
                    current_scope = 'actor.usecases'
                    continue

            if current_scope == 'actor.usecases':
                r = begin(2) + r'(?P<name>\w+)' + end
                m = re.match(r, line)
                if m:
                    uc = _ensureUsecase(m.group('name'))
                    current_actor.addUsecase(uc)
                    current_element = uc
                    uc.lineNo = line_no
                continue

            LocalizedSourceIssue(sourceFile=self,
                                 level=Levels.Error,
                                 message=('Syntax error. Line ignored.'),
                                 line=line_no)

        # End of file
        line_no = len(self.sourceLines)
        _checkSystemExist(isLast=True)
コード例 #8
0
    def _parse_main_body(self):
        """
        Parse everything in the glossary except the description
        of entries. These descriptions are parsed by the
        subparser for TextBlock.
        In this first phase we just store the information
        as lines (and first line number). This info will
        be used in second phase to feed the embedded parser.
        """

        current_context=self.glossaryModel
        #type: Optional[Union[GlossaryModel, Domain, Entry]]

        for (line_index, line) in enumerate(self.sourceLines):
            original_line = line
            line = line.replace(u'\t',u' ')
            line_no = line_index+1

            #-----------------------------------------------
            #  comments
            #-----------------------------------------------

            r = '^ *--.*$'
            m=re.match(r, line)
            if m:
                continue

            #-----------------------------------------------
            #  blank lines
            #-----------------------------------------------
            r = '^ *$'
            m=re.match(r, line)
            if m:
                continue


            #-----------------------------------------------
            #  megamodel statements
            #-----------------------------------------------
            is_mms = isMegamodelStatement(
                lineNo=line_no,
                modelSourceFile=self)
            if is_mms:
                # megamodel statements have already been
                # parse so silently ignore them
                continue


            #-----------------------------------------------
            #  domain
            #-----------------------------------------------
            if (isinstance(current_context, (
                    GlossaryModel,
                    Domain,
                    Entry))):
                r=r'^domain +(?P<name>\w+) *$'
                m=re.match(r, line)
                if m:
                    name=m.group('name')
                    if name in self.glossaryModel.domainNamed:
                        # If the domain already exists, reuse it
                        current_content=(
                            self.glossaryModel.domainNamed[name])
                    else:
                        # Creates a new domain with this name
                        domain=Domain(
                            glossaryModel=self.glossaryModel,
                            name=name,
                            lineNo=line_no,
                        )
                        current_context=domain
                    continue


            #-----------------------------------------------
            #  entry
            #-----------------------------------------------
            if isinstance(current_context, (
                    Domain,
                    Entry)):
                r=r'^    (?P<word1>\w+)(?P<words> \w+[\w ]+)? *: *$'
                m = re.match(r, line, re.UNICODE)
                if m:
                    if m.group('words') is None:
                        words=[]
                    else:
                        words=[ w
                            for w in m.group('words').split(' ')
                            if w!='']
                    domain=(
                        current_context.domain
                        if isinstance(current_context, Entry)
                        else current_context)
                    name=m.group('word1')
                    if name in domain.entryNamed:
                        # The simplest way deal with the
                        # multiple definition is to concatenate
                        # text after existing definition. This
                        # avoid skipping the next lines.
                        LocalizedSourceIssue(
                            sourceFile=self,
                            level=Levels.Error,
                            message=
                                '%s.%s already exist.'
                                ' Definitions will be appended.' %
                                (domain.name, name),
                            line=line_no
                        )
                        # do not create an new entry
                        # reuse instead the old entry
                        entry=domain.entryNamed[name]
                    else:
                        # Create a new entry
                        entry=Entry(
                            domain=domain,
                            mainTerm=name,
                            alternativeTerms=words,
                            lineNo=line_no,
                        )
                        # Set the glossary of the description
                        entry.description.glossary=self.glossaryModel
                    current_context=entry
                    continue

            #-----------------------------------------------
            #  description
            #-----------------------------------------------

            if isinstance(current_context, Entry):
                r='^ *\|(?P<line>.*)'
                m = re.match(r, line)
                if m:
                    entry=current_context
                    entry.description.addNewLine(
                        stringLine=m.group('line'),
                        lineNo=line_no)
                    # .descriptionBlockSourcePerEntry[entry] \
                    #         .addTextLine(
                    #             textLine=m.group('line'),
                    #             lineNo=line_no)
                    continue

            #-----------------------------------------------
            #  error
            #-----------------------------------------------

            LocalizedSourceIssue(
                sourceFile=self,
                level=Levels.Error,
                message='Syntax error',
                line=line_no
            )