コード例 #1
0
ファイル: parse.py プロジェクト: jjkester/checkmerge
    def parse_clang_node(cls, cursor: clang.Cursor, parent: typing.Optional[ir.Node] = None) -> ir.Node:
        """
        Parses a Clang AST node identified by a cursor into an IR node.

        :param cursor: The cursor pointing to the node.
        :param parent: The parent IR node.
        :return: The corresponding IR node.
        """
        type_str = getattr(cursor.type, 'spelling', '')

        # Build label
        label = f"{type_str}: {cursor.spelling}" if cursor.is_definition() and type_str else cursor.spelling

        # Default node data
        kwargs = dict(
            typ=cursor.kind.name,
            label=label,
            ref=cursor.get_usr(),
            parent=parent,
            source_range=cls.get_range(cursor),
        )

        # Overrides for root node
        if parent is None and cursor.kind == clang.CursorKind.TRANSLATION_UNIT:
            kwargs['label'] = os.path.basename(kwargs['label'])

        # Overrides for specific kinds of nodes
        if cursor.kind in cls._customizers:
            cls._customizers[cursor.kind](cursor, kwargs)

        # Build node
        node = ir.Node(**kwargs)

        return node
コード例 #2
0
ファイル: c_header.py プロジェクト: lefta/ehlit-prototype
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)
コード例 #3
0
ファイル: __init__.py プロジェクト: yuhc/ava
    def convert_decl(c: Cursor):
        nonlocal utility_mode, utility_mode_start, replacement_mode, replacement_mode_start, metadata_type
        assert not (replacement_mode and utility_mode)
        if c.kind in ignored_cursor_kinds:
            return

        normal_mode = not replacement_mode and not utility_mode

        # not (c.kind == CursorKind.VAR_DECL and c.displayname.startswith(
        #     NIGHTWATCH_PREFIX)) and (utility_mode or replacement_mode):
        included_extent = True
        if (normal_mode and c.kind == CursorKind.FUNCTION_DECL
                and c.location.file.name == filename
                and c.spelling == "ava_metadata"):
            metadata_type = convert_type(c.result_type.get_pointee(),
                                         "ava_metadata", annotation_set(),
                                         set())
        elif (normal_mode and c.kind == CursorKind.FUNCTION_DECL
              and c.displayname.startswith(NIGHTWATCH_PREFIX + "category_")):
            name = strip_unique_suffix(
                strip_prefix(NIGHTWATCH_PREFIX + "category_", c.displayname))
            annotations = extract_annotations(c)
            attr_annotations = extract_attr_annotations(c)
            rule_list = default_rules if "default" in attr_annotations else rules
            annotations.pop("default", None)
            if name == "type":
                rule_list.append(
                    Types(c.result_type.get_pointee(), annotations))
            elif name == "functions":
                rule_list.append(Functions(annotations))
            elif name == "pointer_types":
                rule_list.append(PointerTypes(annotations))
            elif name == "const_pointer_types":
                rule_list.append(ConstPointerTypes(annotations))
            elif name == "nonconst_pointer_types":
                rule_list.append(NonconstPointerTypes(annotations))
            elif name == "non_transferable_types":
                rule_list.append(NonTransferableTypes(annotations))
        elif normal_mode and c.kind == CursorKind.VAR_DECL and c.storage_class == StorageClass.STATIC:
            # This is a utility function for the API forwarding code.
            parse_expects(
                c.linkage == LinkageKind.INTERNAL,
                f"at {term.yellow(c.displayname)}",
                "API utility functions should be static (or similar) since they are included in header files.",
                loc=convert_location(c.location),
            )
            utility_extents.append((c.extent.start.line, c.extent.end.line))
        elif c.kind == CursorKind.VAR_DECL and c.displayname.startswith(
                NIGHTWATCH_PREFIX):
            name = strip_unique_suffix(strip_nw(c.displayname))
            if name == "begin_utility":
                parse_requires(
                    not utility_mode,
                    "ava_begin_utility can only be used outside utility mode to enter that mode."
                )
                utility_mode = True
                utility_mode_start = c.extent.start.line
            elif name == "end_utility":
                parse_requires(
                    utility_mode,
                    "ava_end_utility can only be used inside utility mode to exit that mode."
                )
                utility_mode = False
                parse_assert(utility_mode_start is not None,
                             "Should be unreachable.")
                utility_extents.append((utility_mode_start, c.extent.end.line))
            elif name == "begin_replacement":
                parse_requires(
                    not replacement_mode,
                    "ava_begin_replacement can only be used outside replacement mode to enter that mode.",
                )
                replacement_mode = True
                replacement_mode_start = c.extent.start.line
            elif name == "end_replacement":
                parse_requires(
                    replacement_mode,
                    "ava_end_replacement can only be used inside replacement mode to exit that mode."
                )
                replacement_mode = False
                parse_assert(replacement_mode_start is not None,
                             "Should be unreachable.")
                replacement_extents.append(
                    (replacement_mode_start, c.extent.end.line))
            else:
                global_config[name] = get_string_literal(c)
        elif (normal_mode and c.kind == CursorKind.VAR_DECL
              and c.type.spelling.endswith("_resource")
              and c.type.spelling.startswith("ava_")):
            # TODO: Use the resource declarations to check resource usage.
            pass
        elif c.kind == CursorKind.FUNCTION_DECL and c.location.file.name == filename:
            if normal_mode and c.is_definition(
            ) and c.storage_class == StorageClass.STATIC:
                # This is a utility function for the API forwarding code.
                parse_expects(
                    c.linkage == LinkageKind.INTERNAL,
                    f"at {term.yellow(c.displayname)}",
                    "API utility functions should be static (or similar) since they are included in header files.",
                    loc=convert_location(c.location),
                )
                utility_extents.append(
                    (c.extent.start.line, c.extent.end.line))
            elif normal_mode:
                # This is an API function.
                f = convert_function(c)
                if f:
                    functions[c.mangled_name] = f
            elif replacement_mode:
                # Remove the function from the list because it is replaced
                replaced_functions[c.mangled_name] = c
        elif (normal_mode and c.kind == CursorKind.FUNCTION_DECL
              and c.location.file.name
              in [f.name for f in primary_include_files.values()]):
            included_extent = False
            f = convert_function(c, supported=False)
            if f:
                include_functions[c.mangled_name] = f
        elif (normal_mode and c.kind == CursorKind.INCLUSION_DIRECTIVE
              and not c.displayname.endswith(nightwatch_parser_c_header)
              and c.location.file.name == filename):
            try:
                primary_include_files[c.displayname] = c.get_included_file()
            except AssertionError as e:
                parse_assert(not e, str(e), loc=convert_location(c.location))
        # elif normal_mode and c.kind == CursorKind.INCLUSION_DIRECTIVE and c.tokens[-1].spelling == '"' \
        #         and not c.displayname.endswith(nightwatch_parser_c_header):
        #     parse_assert(False, "Including AvA specifications in other specifications is not yet supported.")
        elif (normal_mode
              and c.kind in (CursorKind.MACRO_DEFINITION,
                             CursorKind.STRUCT_DECL, CursorKind.TYPEDEF_DECL)
              and c.location.file and c.location.file.name == filename):
            # This is a utility macro for the API forwarding code.
            type_extents.append((c.extent.start.line, c.extent.end.line))
        elif (
                # pylint: disable=too-many-boolean-expressions
            (normal_mode or replacement_mode)
                and c.kind in (CursorKind.UNEXPOSED_DECL, ) and len(c.tokens)
                and c.tokens[0].spelling == "extern"
                and c.location.file in primary_include_files.values()):
            for cc in c.get_children():
                convert_decl(cc)
            return  # Skip the extents processing below
        elif normal_mode:
            # Default case for normal mode.
            is_semicolon = len(c.tokens) == 1 and c.tokens[0].spelling == ";"
            if c.location.file and not is_semicolon:
                parse_expects(
                    c.location.file.name != filename,
                    f"Ignoring unsupported: {c.kind} {c.spelling}",
                    loc=convert_location(c.location),
                )
            # if len(c.tokens) >= 1 and c.tokens[0].spelling == "extern" and c.kind == CursorKind.UNEXPOSED_DECL:
            #     print(c.kind, c.tokens[0].spelling)
        else:
            # Default case for non-normal modes
            return  # Skip the extents processing below

        if c.location.file in primary_include_files.values():
            primary_include_extents.append(
                (c.location.file, c.extent.start.line, c.extent.end.line,
                 included_extent))
コード例 #4
0
ファイル: c_header.py プロジェクト: lefta/ehlit-prototype
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))