Пример #1
0
def build_block(phrase: Phrase, context: Phrase, temp_phrase: List[Token], phrase_line: int):
    if temp_phrase[0].token_class == TokenClass.word:
        phrase.keyword = temp_phrase[0]
    else:
        raise InterpretationError(
            PeaceError(f"Unexpected phrase sequence.",
                       ErrorType.phrase_build_error, phrase_line))

    if phrase.keyword.value == "main":
        if context.phrase_subclass == PhraseSubclass.program:
            phrase.phrase_subclass = PhraseSubclass.body
        else:
            raise InterpretationError(
                PeaceError(f"Main block can not be defined inside {context.phrase_subclass.name}.",
                           ErrorType.phrase_build_error, phrase_line))
    elif context.phrase_subclass == PhraseSubclass.program:
        phrase.phrase_subclass = PhraseSubclass.expression
    elif context.phrase_subclass == PhraseSubclass.body or context.phrase_subclass == PhraseSubclass.expression:
        phrase.phrase_subclass = PhraseSubclass.device
    else:
        raise InterpretationError(
            PeaceError(f"Unspecified \"{phrase.keyword.value}\" block subclass.",
                       ErrorType.phrase_build_error, phrase_line))

    if len(temp_phrase) > 1:
        if phrase.phrase_subclass == PhraseSubclass.device:
            phrase.params = temp_phrase[1:]
        else:
            raise InterpretationError(
                PeaceError(f"Not allowed to use parameters in \"{phrase.keyword.value}\" definition.",
                           ErrorType.phrase_build_error, phrase_line))
Пример #2
0
def build_operator(phrase: Phrase, context: Phrase, temp_phrase: List[Token], phrase_line):
    if context.phrase_subclass != PhraseSubclass.program:
        if temp_phrase[0].token_class == TokenClass.word:
            phrase.keyword = temp_phrase[0]
        else:
            raise InterpretationError(
                PeaceError(f"Unexpected phrase sequence.",
                           ErrorType.phrase_build_error, phrase_line))

        phrase.params = temp_phrase[1:]
    else:
        raise InterpretationError(
            PeaceError(f"Operator \"{temp_phrase[0].value}\" not allowed to be used outside blocks.",
                       ErrorType.phrase_build_error, phrase_line))
Пример #3
0
 def test_build_parametrised_label(self):
     built_phrase = phrase_builder(self.expression_context, PhraseClass.label,
                                   [Token(TokenClass.word, "label"),
                                    Token(TokenClass.parameter, "@")], 0)
     expected_expr = Phrase(PhraseClass.label, phrase_subclass=None,
                            keyword=Token(TokenClass.word, "label"), params=[Token(TokenClass.parameter, "@")])
     self.assertTrue(are_phrases_equal(built_phrase, expected_expr))
Пример #4
0
    def _signature_inference(self, phrase: Phrase, line_number: int):
        if phrase.phrase_class == PhraseClass.operator:
            candidates = self.lang_dict.get_candidates(phrase.keyword.value)
            unsuitable_candidates = InterpretationError()
            temp_params: Optional[dict] = None
            for signature_id in candidates:
                signature = self.lang_dict.get_signature(signature_id)
                if self._expr_params is not None:
                    temp_params = self._expr_params.copy()

                try:
                    self._signature_check(signature, phrase, temp_params, line_number)

                except PeaceError as error:
                    unsuitable_candidates.add_error(error)

                else:
                    if self._expr_params is not None:
                        self._expr_params.update(temp_params)
                    phrase.signature_id = signature_id
                    break

            if phrase.signature_id is None:
                raise unsuitable_candidates
        elif phrase.phrase_class == PhraseClass.label:
            if len(phrase.params) > 0:
                if self._expr_signature is not None:
                    self._expr_signature.contains_param = True
        elif phrase.phrase_subclass == PhraseSubclass.device:
            if len(phrase.params) > 0:
                if self._expr_signature is not None:
                    self._expr_signature.contains_param = True
Пример #5
0
 def test_build_empty_operator(self):
     built_phrase = phrase_builder(self.expression_context, PhraseClass.operator, [
         Token(TokenClass.word, "delay")
     ], 0)
     expected_expr = Phrase(PhraseClass.operator, phrase_subclass=None,
                            keyword=Token(TokenClass.word, "delay"), params=[])
     self.assertTrue(are_phrases_equal(built_phrase, expected_expr))
Пример #6
0
 def test_build_comment(self):
     built_phrase = phrase_builder(self.body_context, PhraseClass.comment,
                                   [Token(TokenClass.word, "w1"),
                                    Token(TokenClass.word, "w2"),
                                    Token(TokenClass.word, "w3")], 0)
     expected_expr = Phrase(PhraseClass.comment, phrase_subclass=None,
                            params=[Token(TokenClass.word, "w1"),
                                    Token(TokenClass.word, "w2"),
                                    Token(TokenClass.word, "w3")])
     self.assertTrue(are_phrases_equal(built_phrase, expected_expr))
Пример #7
0
def build_label(phrase: Phrase, context: Phrase, temp_phrase: List[Token], phrase_line):
    if context.phrase_subclass != PhraseSubclass.program:
        if temp_phrase[0].token_class == TokenClass.word:
            phrase.keyword = temp_phrase[0]
        else:
            raise InterpretationError(
                PeaceError(f"Unexpected phrase sequence.",
                           ErrorType.phrase_build_error, phrase_line))

        if len(temp_phrase) > 1 and context.phrase_subclass != PhraseSubclass.expression:
            raise InterpretationError(
                PeaceError(f"Parametrised label name can not be used inside main.",
                           ErrorType.phrase_build_error, phrase_line))
        else:
            phrase.params = temp_phrase[1:]
    else:
        raise InterpretationError(PeaceError(f"Label \"{temp_phrase[0].value}\" "
                                             f"not allowed to be used outside blocks.",
                                             ErrorType.phrase_build_error, phrase_line))
Пример #8
0
    def _name_processing(self, phrase: Phrase, line_number: int):
        if phrase.phrase_class == PhraseClass.block:
            identifier: str = phrase.get_identifier()
            if not self.table.is_symbol_presence(identifier):
                self.table.add_symbol(identifier, phrase.phrase_subclass)
            else:
                raise InterpretationError(
                    PeaceError(f"\nName \"{identifier}\" already used by "
                               f"{self.table.get_symbol(identifier).phrase_class.name}.",
                               ErrorType.naming_error, line_number, identifier))

        elif phrase.phrase_class == PhraseClass.label:
            identifier: str = phrase.get_identifier()
            if not self.table.is_symbol_presence(identifier):
                self.table.add_symbol(identifier, phrase.phrase_class)
            else:
                raise InterpretationError(
                    PeaceError(f"\nName \"{identifier}\" already used by "
                               f"{self.table.get_symbol(identifier).phrase_class.name}.",
                               ErrorType.naming_error, line_number, identifier))

        elif phrase.phrase_class == PhraseClass.operator:
            operator: str = phrase.keyword.value
            sig_type = self.lang_dict.get_signature(phrase.signature_id).signature_type
            if sig_type == SignatureType.operator:
                if len(phrase.params):
                    identifier: str = phrase.get_identifier()
                    if operator == "q":
                        if not self.table.is_symbol_presence(identifier):
                            self.table.add_symbol(identifier, phrase.phrase_class)
                        else:
                            raise InterpretationError(
                                PeaceError(f"Name \"{identifier}\" already used by "
                                           f"{self.table.get_symbol(identifier).phrase_class.name}.",
                                           ErrorType.naming_error, line_number, identifier))
                    elif operator == "dq":
                        if not self.table.is_symbol_presence(identifier):
                            raise InterpretationError(
                                PeaceError(f"\nName \"{identifier}\" was never defined.",
                                           ErrorType.naming_error, line_number, identifier))
Пример #9
0
 def test_build_operator_with_parameters(self):
     built_phrase = phrase_builder(self.expression_context, PhraseClass.operator, [
         Token(TokenClass.word, "delay"),
         Token(TokenClass.num, "1"),
         Token(TokenClass.word, "two"),
         Token(TokenClass.string, "\"3\""),
         Token(TokenClass.parameter, "@4")
     ], 0)
     expected_expr = Phrase(PhraseClass.operator, phrase_subclass=None,
                            keyword=Token(TokenClass.word, "delay"),
                            params=[Token(TokenClass.num, "1"),
                                    Token(TokenClass.word, "two"),
                                    Token(TokenClass.string, "\"3\""),
                                    Token(TokenClass.parameter, "@4")])
     self.assertTrue(are_phrases_equal(built_phrase, expected_expr))
Пример #10
0
def phrase_builder(context: Phrase, phrase_class: PhraseClass, temp_phrase: List[Token], phrase_line: int) -> Phrase:
    phrase = Phrase(phrase_class, params=list())
    if phrase_class == PhraseClass.block:
        build_block(phrase, context, temp_phrase, phrase_line)
    elif phrase_class == PhraseClass.operator:
        build_operator(phrase, context, temp_phrase, phrase_line)
    elif phrase_class == PhraseClass.comment:
        build_comment(phrase, temp_phrase)
    elif phrase_class == PhraseClass.label:
        build_label(phrase, context, temp_phrase, phrase_line)
    elif phrase_class == PhraseClass.blockClose:
        build_block_close(phrase, temp_phrase)
    else:
        raise InterpretationError(
            PeaceError(f"Unexpected phrase class.",
                       ErrorType.phrase_build_error, phrase_line))
    return phrase
Пример #11
0
 def setUpClass(cls) -> None:
     cls.program_context = Phrase(PhraseClass.block, PhraseSubclass.program)
     cls.expression_context = Phrase(PhraseClass.block, PhraseSubclass.expression)
     cls.device_context = Phrase(PhraseClass.block, PhraseSubclass.device)
     cls.body_context = Phrase(PhraseClass.block, PhraseSubclass.body)
Пример #12
0
 def setUpClass(cls) -> None:
     cls.tree = ParseTree()
     cls.tree.add_leaf(Phrase(PhraseClass.block, PhraseSubclass.expression))
     cls.tree.submerge()
Пример #13
0
 def test_build_expression(self):
     built_phrase = phrase_builder(self.program_context, PhraseClass.block,
                                   [Token(TokenClass.word, "expression")], 0)
     expected_expr = Phrase(PhraseClass.block, PhraseSubclass.expression,
                            keyword=Token(TokenClass.word, "expression"))
     self.assertTrue(are_phrases_equal(built_phrase, expected_expr))
Пример #14
0
 def test_build_device_in_body(self):
     built_phrase = phrase_builder(self.body_context, PhraseClass.block,
                                   [Token(TokenClass.word, "device_in_body")], 0)
     expected_expr = Phrase(PhraseClass.block, PhraseSubclass.device,
                            keyword=Token(TokenClass.word, "device_in_body"))
     self.assertTrue(are_phrases_equal(built_phrase, expected_expr))
Пример #15
0
def build_comment(phrase: Phrase, temp_phrase: List[Token]):
    phrase.params = temp_phrase
Пример #16
0
 def __init__(self):
     self.root: Node = Node(
         None, Phrase(PhraseClass.block, PhraseSubclass.program))
     self.head: Node = self.root
Пример #17
0
 def test_get_context(self):
     context = Phrase(PhraseClass.block, PhraseSubclass.program)
     self.assertTrue(are_phrases_equal(self.tree.get_context(), context))
Пример #18
0
 def test_add_node(self):
     phrase_in_node = Phrase(PhraseClass.blockClose)
     expected_node = Node(self.tree.get_head(), phrase_in_node)
     self.tree.add_leaf(phrase_in_node)
     self.assertTrue(are_nodes_equal(self.tree.head.nodes[0],
                                     expected_node))
Пример #19
0
 def test_build_block_close(self):
     built_phrase = phrase_builder(self.program_context, PhraseClass.blockClose, [], 0)
     expected_expr = Phrase(PhraseClass.blockClose, phrase_subclass=None,
                            keyword=None, params=None)
     self.assertTrue(are_phrases_equal(built_phrase, expected_expr))