예제 #1
0
    def copy_p_tracking(self, p: P, from_: int = 1, to: int = 0) -> None:
        """Don't know why P's tracking info (lexpos and lineno) sometimes missing.
        Particular in recursion grammar situation. We have to copy it manually.

        Add this function in a p_xxx function when:
            1. the p[0] is gona to be used in another parsing target.
            2. and the tracking information is gona to be used there.
        """
        p.set_lexpos(to, p.lexpos(from_))
        p.set_lineno(to, p.lineno(from_))
예제 #2
0
def p_funccall_or_exp_plus(p: yacc.YaccProduction):
    """FUNCCALL_OR_EXPRESSION : PLUS FACTOR REC_UNARYEXPR REC_PLUS_MINUS_TERM OPT_REL_OP_NUM_EXPR
                              | MINUS FACTOR REC_UNARYEXPR REC_PLUS_MINUS_TERM OPT_REL_OP_NUM_EXPR"""
    right_node = p[2]['node']
    if p[1] == '-':
        right_node.value *= -1

    if p[3]:
        result_type = check_type(p[3]['node'], right_node, p[3]['operation'],
                                 p.lineno(1))
        right_node = Node(p[3]['node'], right_node, p[3]['operation'],
                          result_type)

    if p[4]:
        result_type = check_type(p[4]['node'], right_node, p[4]['operation'],
                                 p.lineno(1))
        right_node = Node(p[4]['node'], right_node, p[4]['operation'],
                          result_type)

    num_expressions.append(right_node)
예제 #3
0
def p_relation_deprecated_comment(p: YaccProduction) -> None:
    "relation : class_ref ID multi REL multi class_ref ID MLS"
    if not (p[4] == "--"):
        LOGGER.warning(
            "DEPRECATION: use of %s in relation definition is deprecated, use -- (in %s)"
            % (p[4], Location(file, p.lineno(4))))
    rel = DefineRelation((p[1], p[2], p[3]), (p[6], p[7], p[5]))
    rel.comment = str(p[8])
    p[0] = rel
    attach_lnr(p, 2)
    deprecated_relation_warning(p)
예제 #4
0
    def p_alias(self, p: P) -> None:
        if len(p) == 6:
            name, type, lineno, token = p[2], p[4], p.lineno(2), p[2]
        else:
            name, type, lineno, token = p[3], p[2], p.lineno(3), p[3]
            write_stderr(
                f"syntax warning: keyword typedef deprecated, suggestion: type {name} = ..."
            )

        p[0] = alias = Alias(
            name=name,
            type=type,
            filepath=self.current_filepath(),
            lineno=lineno,
            token=token,
            indent=self.current_indent(p),
            scope_stack=self.current_scope_stack(),
            comment_block=self.collect_comment_block(),
            _bound=self.current_proto(),
        )
        self.current_scope().push_member(alias)
예제 #5
0
def p_numexp(p: yacc.YaccProduction):
    """NUMEXPRESSION : TERM REC_PLUS_MINUS_TERM"""
    if p[2] is None:
        p[0] = p[1]

    else:
        result_type = check_type(p[1]['node'], p[2]['node'], p[2]['operation'],
                                 p.lineno(1))
        p[0] = {
            'node':
            Node(p[1]['node'], p[2]['node'], p[2]['operation'], result_type)
        }
예제 #6
0
 def p_open_message_scope(self, p: P) -> None:
     message = Message(
         name=p[2],
         extensible=p[3],
         token=p[2],
         lineno=p.lineno(2),
         filepath=self.current_filepath(),
         indent=self.current_indent(p),
         comment_block=self.collect_comment_block(),
         scope_stack=self.current_scope_stack(),
         _bound=self.current_proto(),
     )
     self.push_scope(message)
예제 #7
0
 def p_open_enum_scope(self, p: P) -> None:
     enum = Enum(
         name=p[2],
         type=p[4],
         token=p[2],
         lineno=p.lineno(2),
         filepath=self.current_filepath(),
         indent=self.current_indent(p),
         comment_block=self.collect_comment_block(),
         scope_stack=self.current_scope_stack(),
         _bound=self.current_proto(),
     )
     self.push_scope(enum)
예제 #8
0
 def p_constant_reference_for_array_capacity(self, p: P) -> None:
     referenced = p[1]
     if isinstance(referenced, IntegerConstant):
         integer_constant = cast(IntegerConstant, referenced)
         p[0] = integer_constant.unwrap()  # Using int format
     else:
         raise InvalidArrayCap(
             message=
             "Non integer constant referenced to use as array capacity.",
             filepath=self.current_filepath(),
             token=p[1].name,
             lineno=p.lineno(1),
         )
예제 #9
0
 def p_constant_reference_for_calculation(self, p: P) -> None:
     referenced = p[1]
     if isinstance(referenced, IntegerConstant):
         integer_constant = cast(IntegerConstant, referenced)
         p[0] = integer_constant.unwrap()
     else:
         raise CalculationExpressionError(
             message=
             "Non integer constant referenced to use in calculation expression.",
             filepath=self.current_filepath(),
             token=p[1].name,
             lineno=p.lineno(1),
         )
예제 #10
0
    def p_import(self, p: P) -> None:
        # Get filepath to import.
        importing_path = p[len(p) - 2]
        filepath = self._get_child_filepath(importing_path)

        # Check if this filepath already in parsing.
        if self._check_parsing_file(filepath):
            raise CyclicImport(
                message=f"cyclic importing {filepath}",
                filepath=self.current_filepath(),
                token=importing_path,
                lineno=p.lineno(2),
            )

        # Check if this filepath already parsed by current proto.
        for _, proto in self.current_proto().protos(recursive=False):
            if os.path.samefile(proto.filepath, filepath):
                raise DuplicatedImport(filepath=self.current_filepath(),
                                       token=filepath,
                                       lineno=p.lineno(1))

        # Parse.
        p[0] = child = self.parse_child(filepath)
        name = child.name
        if len(p) == 5:  # Importing as `name`
            name = p[2]

        # Check if import (as) name already taken.
        if name in self.current_proto().members:
            raise DuplicatedDefinition(
                message="imported proto name already used",
                token=name,
                lineno=p.lineno(1),
                filepath=self.current_filepath(),
            )

        # Push to current scope
        self.current_scope().push_member(child, name)
예제 #11
0
def p_statement_break(p: yacc.YaccProduction):
    """STATEMENT : BREAK SEMICOLON"""
    # If is not inside loop scope, consider semantic failure
    current_scope = scope_stack.seek()

    # Go into upper scopes trying to find a for loop
    while True:
        if current_scope.is_loop:
            break

        current_scope = current_scope.upper_scope

        if current_scope is None:
            raise BreakWithoutLoopError(p.lineno(2))
예제 #12
0
 def p_error(self, p: P) -> None:
     filepath = self.current_filepath()
     if p is None:
         raise GrammarError(message="Grammar error at eof.",
                            filepath=filepath)
     if isinstance(p, LexToken):
         raise GrammarError(filepath=filepath,
                            token=str(p.value),
                            lineno=p.lineno)
     if len(p) > 1:
         raise GrammarError(filepath=filepath,
                            token=p.value(1),
                            lineno=p.lineno(1))
     raise GrammarError()
예제 #13
0
 def p_option(self, p: P) -> None:
     name, value = p[2], p[4]
     p[0] = option = Option.from_value(
         value=value,
         name=name,
         scope_stack=self.current_scope_stack(),
         comment_block=self.collect_comment_block(),
         indent=self.current_indent(p),
         _bound=self.current_proto(),
         filepath=self.current_filepath(),
         lineno=p.lineno(2),
         token=p[2],
     )
     self.current_scope().push_member(option)
예제 #14
0
 def p_enum_field(self, p: P) -> None:
     name = p[1]
     value = p[3]
     field = EnumField(
         name=name,
         value=value,
         token=p[1],
         lineno=p.lineno(1),
         indent=self.current_indent(p),
         filepath=self.current_filepath(),
         scope_stack=self.current_scope_stack(),
         comment_block=self.collect_comment_block(),
         _bound=self.current_proto(),
     )
     self.current_scope().push_member(field)
예제 #15
0
def p_term_unary_exp(p: yacc.YaccProduction):
    """TERM : UNARYEXPR REC_UNARYEXPR"""
    if p[2]:
        # If there's another operation being made
        result_type = check_type(p[1]['node'], p[2]['node'], p[2]['operation'],
                                 p.lineno(1))
        p[0] = {
            'node':
            Node(p[1]['node'], p[2]['node'], p[2]['operation'], result_type),
            'operation':
            p[2]['operation']
        }

    else:
        # Pass the UNARYEXPR node upwards
        p[0] = {'node': p[1]['node']}
예제 #16
0
 def p_message_field(self, p: P) -> None:
     name = p[2]
     type = p[1]
     field_number = p[4]
     p[0] = message_field = MessageField(
         name=name,
         type=type,
         number=field_number,
         token=p[2],
         lineno=p.lineno(2),
         filepath=self.current_filepath(),
         comment_block=self.collect_comment_block(),
         indent=self.current_indent(p),
         scope_stack=self.current_scope_stack(),
         _bound=self.current_proto(),
     )
     self.current_scope().push_member(message_field)
예제 #17
0
 def p_enum_item_unsupported(self, p: P) -> None:
     if isinstance(p[1], Alias):
         raise AliasInEnumUnsupported.from_token(token=p[1])
     if isinstance(p[1], Constant):
         raise ConstInEnumUnsupported.from_token(token=p[1])
     if isinstance(p[1], Proto):
         raise ImportInEnumUnsupported.from_token(token=p[1])
     if isinstance(p[1], Option):
         raise OptionInEnumUnsupported.from_token(token=p[1])
     if isinstance(p[1], Enum):
         raise EnumInEnumUnsupported.from_token(token=p[1])
     if isinstance(p[1], Message):
         raise MessageInEnumUnsupported.from_token(token=p[1])
     if isinstance(p[1], MessageField):
         raise MessageFieldInEnumUnsupported.from_token(token=p[1])
     raise StatementInMessageUnsupported(lineno=p.lineno(1),
                                         filepath=self.current_filepath())
예제 #18
0
def p_follow_ident_alloc(p: yacc.YaccProduction):
    """FOLLOW_IDENT : OPT_ALLOC_NUMEXP REC_UNARYEXPR REC_PLUS_MINUS_TERM OPT_REL_OP_NUM_EXPR"""
    node = None
    operation = ''

    if p[2]:
        node = p[2]['node']
        operation = p[2]['operation']

    if p[3]:
        if node is None:
            node = p[3]['node']
            operation = p[3]['operation']

        else:
            result_type = check_type(node, p[3]['node'], p[3]['operation'],
                                     p.lineno(0))
            node = Node(node, p[3]['node'], p[3]['operation'], result_type)

    p[0] = {'vec_access': p[1], 'node': node, 'operation': operation}
예제 #19
0
def p_rec_plus_minus(p: yacc.YaccProduction):
    """REC_PLUS_MINUS_TERM : PLUS_OR_MINUS TERM REC_PLUS_MINUS_TERM
                           | empty
    """
    if len(p) < 3:
        # Case empty
        p[0] = None

    elif p[3]:
        # Case there's another recursive operation being made
        result_type = check_type(p[2]['node'], p[3]['node'], p[3]['operation'],
                                 p.lineno(1))
        p[0] = {
            'node':
            Node(p[2]['node'], p[3]['node'], p[3]['operation'], result_type),
            'operation':
            p[1]['operation']
        }
    else:
        # Case there's no more operattions to the right
        p[0] = {'node': p[2]['node'], 'operation': p[1]['operation']}
예제 #20
0
    def p_const(self, p: P) -> None:
        name, value = p[2], p[4]

        constant_cls: Optional[T[Constant]] = None

        if isinstance(value, Constant):
            constant_ = cast(Constant, value)
            # Unwrap if value is a referenced constant.
            value = constant_.unwrap()

        p[0] = constant = Constant.from_value(
            value=value,
            name=name,
            scope_stack=self.current_scope_stack(),
            comment_block=self.collect_comment_block(),
            indent=self.current_indent(p),
            _bound=self.current_proto(),
            filepath=self.current_filepath(),
            token=p[2],
            lineno=p.lineno(2),
        )
        self.current_scope().push_member(constant)
예제 #21
0
파일: parse.py 프로젝트: ccliuyang/MyTrader
def p_expr_function(p: YaccProduction):
    """expr : ID LPAREN RPAREN
            | ID LPAREN args RPAREN"""
    # Judge whether the function has been defined
    if p[1] not in dir(builtins):
        raise UndefineError(p[1], p.lineno(1), p.lexpos(1))
    # Judge the count of arguments
    if len(p) == 4:
        input_args_count = 0
    elif len(p) == 5:
        print(p[3])
        input_args_count = len(p[3])
    func = getattr(builtins, p[1])
    args_count = func.__code__.co_argcount
    # why minus 1: because builtin function will be injected argument of 'env' at the first position
    if input_args_count != args_count - 1:
        raise ArgumentError(p[1], p.lineno(1), p.lexpos(1), args_count-1, input_args_count)
    if len(p) == 4:
        p[0] = Function(p[1], [], p.lineno(1), p.lineno(3), p.lexpos(1), p.lexpos(3))
    elif len(p) == 5:
        p[0] = Function(p[1], p[3], p.lineno(1), p.lineno(4), p.lexpos(1), p.lexpos(4))
예제 #22
0
def attach_lnr(p: YaccProduction, token: int = 1) -> None:
    v = p[0]
    v.location = Location(file, p.lineno(token))
    v.namespace = namespace
    v.lexpos = p.lexpos(token)
예제 #23
0
def p_function_call(p: YaccProduction) -> None:
    "function_call : ns_ref '(' function_param_list ')'"
    assert namespace
    (args, kwargs, wrapped_kwargs) = p[3]
    p[0] = FunctionCall(p[1], args, kwargs, wrapped_kwargs,
                        Location(file, p.lineno(2)), namespace)
예제 #24
0
def p_constructor(p: YaccProduction) -> None:
    "constructor : class_ref '(' param_list ')'"
    assert namespace
    p[0] = Constructor(p[1], p[3][0], p[3][1], Location(file, p.lineno(2)),
                       namespace)
예제 #25
0
 def __init__(self, prod: YaccProduction) -> None:
     self.line_number = prod.lineno(1)
     super(IllegalMultiwordError, self).__init__(
         f'Illegal multiword data at line {self.line_number}.')
예제 #26
0
 def __init__(self, prod: YaccProduction) -> None:
     self.line_number = prod.lineno(1)
     super(IllegalEmptyNodeError, self).__init__(
         f'Illegal empty-node data at line {self.line_number}.')
예제 #27
0
 def loc(p: yacc.YaccProduction) -> Dict[str, int]:
     return {
         'line': p.lineno(1),
         'column': find_column(p.lexpos(1)),
     }
예제 #28
0
def p_factor_expr(p: yacc.YaccProduction):
    """FACTOR : LPAREN NUMEXPRESSION RPAREN"""
    p[0] = p[2]

    num_expressions.append((p[2]['node'], p.lineno(1)))
예제 #29
0
def p_allocexp(p: yacc.YaccProduction):
    """ALLOCEXPRESSION : NEW DATATYPE LSQBRACKETS NUMEXPRESSION RSQBRACKETS OPT_ALLOC_NUMEXP"""
    num_expressions.append((p[4]['node'], p.lineno(1)))
예제 #30
0
def p_expression(p: yacc.YaccProduction):
    """EXPRESSION : NUMEXPRESSION OPT_REL_OP_NUM_EXPR"""
    num_expressions.append((p[1]['node'], p.lineno(1)))