Exemplo n.º 1
0
def type_to_ehlit(typ: Type) -> ast.Node:
    res: Optional[ast.Node] = None
    if typ.kind in uint_types:
        res = ast.CompoundIdentifier(
            [ast.Identifier(0, '@uint' + str(typ.get_size() * 8))])
    elif typ.kind in int_types:
        res = ast.CompoundIdentifier(
            [ast.Identifier(0, '@int' + str(typ.get_size() * 8))])
    elif typ.kind in decimal_types:
        res = ast.CompoundIdentifier(
            [ast.Identifier(0, decimal_types[typ.kind])])
    else:
        try:
            res = globals()['type_' + typ.kind.name](typ)
        except KeyError:
            logging.debug('c_compat: unimplemented: type_%s' % typ.kind.name)
    if res is None:
        return ast.CompoundIdentifier([ast.Identifier(0, '@any')])
    elif not isinstance(res, ast.Symbol):
        return res
    if typ.is_const_qualified():
        res.qualifiers = res.qualifiers | ast.Qualifier.CONST
    if typ.is_volatile_qualified():
        res.qualifiers = res.qualifiers | ast.Qualifier.VOLATILE
    if typ.is_restrict_qualified():
        res.qualifiers = res.qualifiers | ast.Qualifier.RESTRICT
    return res
Exemplo n.º 2
0
def _macro_var_type(tokens: List[Token]) -> ast.Symbol:
    for tok in tokens:
        if tok.kind == TokenKind.LITERAL:
            if tok.spelling[0] == '"':
                return ast.CompoundIdentifier([ast.Identifier(0, '@str')])
            if all(x in '0123456789' for x in tok.spelling):
                return ast.CompoundIdentifier([ast.Identifier(0, '@int32')])
            if all(x in '0123456789.' for x in tok.spelling):
                return ast.CompoundIdentifier([ast.Identifier(0, '@float')])
    return CAnyType.make_symbol()
Exemplo n.º 3
0
def type_POINTER(typ: Type) -> ast.Node:
    subtype: Type = typ.get_pointee()
    builtin_type: Optional[ast.Symbol] = {
        TypeKind.CHAR_S: ast.CompoundIdentifier([ast.Identifier(0, '@str')]),
        TypeKind.SCHAR: ast.CompoundIdentifier([ast.Identifier(0, '@str')]),
        TypeKind.VOID: ast.CompoundIdentifier([ast.Identifier(0, '@any')])
    }.get(subtype.kind)
    if builtin_type is not None:
        return builtin_type
    res = type_to_ehlit(subtype)
    if isinstance(res, ast.TemplatedIdentifier) and res.name == '@func':
        return res
    assert isinstance(res, ast.Symbol)
    return ast.Reference(res)
Exemplo n.º 4
0
def parse_ENUM_DECL(cursor: Cursor) -> ast.Node:
    if not cursor.is_definition():
        return ast.EhEnum(0, ast.Identifier(0, cursor.spelling), None)
    fields: List[ast.Identifier] = []
    expect: bool = False
    for t in cursor.get_tokens():
        if t.spelling == '{' or t.spelling == ',':
            expect = True
        elif t.spelling == '}':
            break
        elif expect:
            fields.append(ast.Identifier(0, t.spelling))
            expect = False
    return ast.EhEnum(0, ast.Identifier(0, cursor.spelling), fields)
Exemplo n.º 5
0
def parse_FUNCTION_DECL(cursor: Cursor) -> ast.Node:
    args: List[ast.VariableDeclaration] = []
    for c in cursor.get_children():
        if c.kind == CursorKind.PARM_DECL:
            typ = type_to_ehlit(c.type)
            assert isinstance(typ, ast.Symbol)
            args.append(
                ast.VariableDeclaration(typ, ast.Identifier(0, c.spelling)))

    ret_type = type_to_ehlit(cursor.type.get_result())
    assert isinstance(ret_type, ast.Symbol)
    return ast.Function(
        0, ast.Qualifier.NONE,
        ast.TemplatedIdentifier(0, '@func', [
            ast.FunctionType(ret_type, args,
                             cursor.type.is_function_variadic())
        ]), ast.Identifier(0, cursor.spelling))
Exemplo n.º 6
0
def _parse_container_structure_fields(
        cursor: Cursor) -> List[ast.VariableDeclaration]:
    fields: List[ast.VariableDeclaration] = []
    for f in cursor.type.get_fields():
        typ: ast.Node = type_to_ehlit(f.type)
        assert isinstance(typ, ast.Symbol)
        fields.append(
            ast.VariableDeclaration(typ, ast.Identifier(0, f.spelling), None))
    return fields
Exemplo n.º 7
0
def _macro_alias_value(tokens: List[Token]) -> Optional[ast.Symbol]:
    name: str = tokens[0].spelling
    tokens = tokens[2:] if tokens[1].spelling == '(' else tokens[1:]
    if tokens[0].kind == TokenKind.KEYWORD:
        typ: Optional[ast.Symbol] = _macro_alias_type(tokens)
        if type is not None:
            return typ
    elif len(tokens) == 1 or (len(tokens) == 2 and tokens[1].spelling == ')'):
        return ast.CompoundIdentifier([ast.Identifier(0, tokens[0].spelling)])
    logging.debug('c_parser: failed to parse macro: {}'.format(name))
    return None
Exemplo n.º 8
0
def type_RECORD(typ: Type) -> ast.Node:
    decl: Cursor = typ.get_declaration()
    # If the type do not have a name, it may not be referenced. In the case, we have to embed
    # the type definition in its usage. Otherwise, we reference it with its identifier.
    if decl.spelling == '':
        res: Optional[ast.Node] = cursor_to_ehlit(decl)
        if res is None:
            # The underlying type is not handled, so make this elaborated type unhandled too
            raise KeyError
        return res
    return ast.CompoundIdentifier([ast.Identifier(0, decl.spelling)])
Exemplo n.º 9
0
def parse_MACRO_DEFINITION(cursor: Cursor) -> Optional[ast.Node]:
    tokens: List[Token] = list(cursor.get_tokens())
    if tokens[0].spelling in builtin_defines:
        return None

    sym: ast.Identifier = ast.Identifier(0, tokens[0].spelling)

    # Simple define
    if len(tokens) == 1:
        return CDefine(sym)
    # Function macro
    if tokens[1].spelling == '(':
        i = 2
        arg_cnt = 0
        while i < len(tokens):
            if tokens[i].kind != TokenKind.IDENTIFIER or i + 1 >= len(tokens):
                break
            arg_cnt += 1
            if tokens[i + 1].spelling == ')':
                if i + 2 >= len(tokens) and ',' not in [
                        t.spelling for t in tokens
                ]:
                    break
                return CMacroFunction(sym, arg_cnt)
            elif tokens[i + 1].spelling != ',':
                break
            i += 2
    # Constant macro
    next_relevant_token = 2 if tokens[1].spelling == '(' else 1
    if tokens[next_relevant_token].kind == TokenKind.LITERAL:
        return ast.VariableDeclaration(_macro_var_type(tokens), sym)
    # Alias macro
    alias: Optional[ast.Symbol] = _macro_alias_value(tokens)
    if alias is not None:
        return ast.Alias(alias, ast.Identifier(0, tokens[0].spelling))
    return None
Exemplo n.º 10
0
 def visit_function_arguments(self, node: ParseTreeNode,
                              children: Tuple[ast.VariableDeclaration]
                              ) -> Tuple[List[ast.VariableDeclaration], Optional[ast.Symbol]]:
     args: List[ast.VariableDeclaration] = []
     variadic_type: Optional[ast.Symbol] = None
     for child in children[::2]:
         arg = child
         if isinstance(arg, ast.VariableDeclaration):
             args.append(arg)
         else:
             if arg == '...':
                 variadic_type = ast.CompoundIdentifier([ast.Identifier(0, '@any')])
             else:
                 assert isinstance(arg, ast.Symbol)
                 variadic_type = arg
     return args, variadic_type
Exemplo n.º 11
0
def parse_VAR_DECL(cursor: Cursor) -> ast.Node:
    assign: Optional[Cursor] = cursor.get_definition()
    value: Optional[ast.Expression] = None
    if assign is not None:
        got_eq: bool = False
        for t in assign.get_tokens():
            if value is not None:
                logging.debug(
                    'c_compat: error: unhandled token while getting value: {}'.
                    format(t.spelling))
            elif got_eq:
                value = value_to_ehlit(t.spelling, cursor.type)
            elif t.spelling == '=':
                got_eq = True
        if got_eq is False:
            logging.debug('c_compat: error: unhandled assignment')
    typ: ast.Node = type_to_ehlit(cursor.type)
    assert isinstance(typ, ast.Symbol)
    return ast.VariableDeclaration(
        typ, ast.Identifier(0, cursor.spelling),
        ast.Assignment(value) if value is not None else None)
Exemplo n.º 12
0
 def visit_destructor(self, node: ParseTreeNode, children: Tuple[str, ast.UnparsedContents]
                      ) -> ast.Dtor:
     qualifiers: ast.Qualifier = ast.Qualifier.NONE
     i: int = 0
     while isinstance(children[i], str):
         if children[i] == 'inline':
             qualifiers |= ast.Qualifier.INLINE
         elif children[i] == 'priv':
             qualifiers |= ast.Qualifier.PRIVATE
         elif children[i] == 'dtor':
             break
         i += 1
     i += 1
     body = None
     if len(children) > i:
         body = children[i]
     typ = ast.TemplatedIdentifier(node.position, '@func', [ast.FunctionType(
         ast.CompoundIdentifier([ast.Identifier(node.position, '@void')]),
         []
     )])
     assert(body is None or isinstance(body, ast.UnparsedContents))
     return ast.Dtor(node.position, qualifiers, typ, body)
Exemplo n.º 13
0
 def visit_constructor(self, node: ParseTreeNode,
                       children: Tuple[str, Tuple[List[ast.VariableDeclaration],
                                                  Optional[ast.Symbol]],
                                       ast.UnparsedContents]
                       ) -> ast.Ctor:
     qualifiers: ast.Qualifier = ast.Qualifier.NONE
     i: int = 0
     while isinstance(children[i], str):
         if children[i] == 'inline':
             qualifiers |= ast.Qualifier.INLINE
         elif children[i] == 'priv':
             qualifiers |= ast.Qualifier.PRIVATE
         elif children[i] == 'ctor':
             break
         i += 1
     i += 1
     args: List[ast.VariableDeclaration]
     variadic_type: Optional[ast.Symbol]
     body = None
     if len(children) < i or isinstance(children[i], ast.UnparsedContents):
         args = []
         variadic_type = None
         if len(children) > i:
             body = children[i]
     else:
         child_i = children[i]
         assert(isinstance(child_i, tuple))
         args, variadic_type = child_i
         if len(children) > i + 1:
             body = children[i + 1]
     typ = ast.TemplatedIdentifier(node.position, '@func', [ast.FunctionType(
         ast.CompoundIdentifier([ast.Identifier(node.position, '@void')]),
         args,
         variadic_type is not None,
         variadic_type
     )])
     assert(body is None or isinstance(body, ast.UnparsedContents))
     return ast.Ctor(node.position, qualifiers, typ, body)
Exemplo n.º 14
0
 def visit_function_type(self, node: ParseTreeNode,
                         children: Tuple[StrMatch, ast.Symbol, Tuple[ast.Symbol, ...]]
                         ) -> ast.TemplatedIdentifier:
     args: List[ast.VariableDeclaration] = []
     variadic: bool = False
     variadic_type: Optional[ast.Symbol] = ast.CompoundIdentifier([ast.Identifier(0, '@any')])
     if len(children) > 2:
         i = 0
         while i < len(children[2]):
             arg = children[2][i]
             if arg == '...':
                 variadic = True
             elif len(children[2]) > i + 1 and children[2][i + 1] == '...':
                 assert isinstance(arg, ast.Symbol)
                 variadic_type = arg
                 variadic = True
             else:
                 args.append(ast.VariableDeclaration(arg, None))
             i += 2
     return ast.TemplatedIdentifier(
         node.position,
         '@func',
         [ast.FunctionType(children[1], args, variadic, variadic_type)]
     )
Exemplo n.º 15
0
def type_TYPEDEF(typ: Type) -> ast.Node:
    return ast.CompoundIdentifier(
        [ast.Identifier(0,
                        typ.get_declaration().spelling)])
Exemplo n.º 16
0
def parse_TYPEDEF_DECL(cursor: Cursor) -> ast.Node:
    typ: ast.Node = type_to_ehlit(cursor.underlying_typedef_type)
    assert isinstance(typ, ast.Type) or isinstance(typ, ast.Symbol)
    return ast.Alias(typ, ast.Identifier(0, cursor.spelling))
Exemplo n.º 17
0
 def visit_identifier(self, node: ParseTreeNode, children: Tuple[Union[RegExMatch, StrMatch]]
                      ) -> ast.Identifier:
     return ast.Identifier(node.position, str(children[0]))
Exemplo n.º 18
0
def type_VOID(typ: Type) -> ast.Symbol:
    return ast.CompoundIdentifier([ast.Identifier(0, '@void')])
Exemplo n.º 19
0
 def __init__(self, sym: ast.Identifier) -> None:
     super().__init__(0, ast.CompoundIdentifier([ast.Identifier(0,
                                                                '@any')]),
                      sym, ast.Qualifier.NONE)
     self.declaration_type = ast.DeclarationType.C
Exemplo n.º 20
0
 def make_symbol() -> ast.Symbol:
     return ast.CompoundIdentifier([ast.Identifier(0, '@c_any')])
Exemplo n.º 21
0
def parse_UNION_DECL(cursor: Cursor) -> ast.Node:
    if not cursor.is_definition():
        return ast.EhUnion(0, ast.Identifier(0, cursor.spelling), None)
    return ast.EhUnion(0, ast.Identifier(0, cursor.spelling),
                       _parse_container_structure_fields(cursor))