Example #1
0
def parse_c(source: str,
            initial_scope: CParserScope) -> Tuple[ca.FileAST, CParserScope]:
    # This is a modified version of `CParser.parse()` which initializes `_scope_stack`,
    # which contains the only stateful part of the parser that needs to be preserved
    # when parsing multiple files.
    c_parser = CParser()
    c_parser.clex.filename = "<source>"
    c_parser.clex.reset_lineno()
    c_parser._scope_stack = [initial_scope.copy()]
    c_parser._last_yielded_token = None
    try:
        ast = c_parser.cparser.parse(input=source, lexer=c_parser.clex)
    except ParseError as e:
        msg = str(e)
        position, msg = msg.split(": ", 1)
        parts = position.split(":")
        if len(parts) >= 2:
            # Adjust the line number by 1 to correct for the added typedefs
            lineno = int(parts[1]) - 1
            posstr = f" at line {lineno}"
            if len(parts) >= 3:
                posstr += f", column {parts[2]}"
            try:
                line = source.split("\n")[lineno].rstrip()
                posstr += "\n\n" + line
            except IndexError:
                posstr += "(out of bounds?)"
        else:
            posstr = ""
        raise DecompFailure(
            f"Syntax error when parsing C context.\n{msg}{posstr}")
    return ast, c_parser._scope_stack[0].copy()
Example #2
0
def cparse(text, types, filename='', debuglevel=0) -> CType:
    parser = CParser()

    parser.clex.filename = filename
    parser.clex.reset_lineno()
    parser._last_yielded_token = None
    parser._scope_stack = [dict()]

    for i, (k, _) in enumerate(types.items()):
        parser._add_typedef_name(k, (i, 0))

    try:
        result = parser.cparser.parse(input=text,
                                      lexer=parser.clex,
                                      debug=debuglevel)
    except Exception as e:
        raise RuntimeError(f'Could not parse `{text}`') from e

    return CType.from_ast(result)