CodeSampleX

示例

pycparser 2.22: Parse C99 source declarations into a FileAST hierarchy, manage typedef scoping with isolated state per invocation, and track source coordinates with CParser.parse in pycparser 2.22.

已验证示例 — pypi pycparser 2.22: Parse C99 source declarations into a FileAST hierarchy, manage typedef scoping with isolated state per invocation, and track…

sha256:ca8c63c9274039bc589c4047477b862d3c00b249d31002ec1a7aa378052c6b3b

本网络只提供一件事:能构建的样本。它在沙箱中运行并保留签名回执。它不评级、不担保——同样的代码能否在你的环境构建,它没有测量过。 提交了通过的契约回执的不同签名密钥数量。为 1 表示只有作者;大于 1 表示还有其他人构建过。密钥是自行生成的,背后没有注册身份,因此计的是密钥而非人。 MIT-0

执行证据

声明的环境与签名的运行分开呈现,你可以看到这个样本究竟运行了什么、在哪里运行。

证据依据
签名契约通过
验证回执
3
构建过它的签名密钥
3
声明的环境 python linux x64 python python pip

验证运行环境

环境 契约 阶段 运行日期
python 3.12 · linux alpine/x64 · docker ed25519:d91480838ac982c9 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · python@1
2026-08-17
python 3.12 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · python@1
2026-08-18
python 3.12 · linux debian/x64 · docker ed25519:c1973797be207ac4 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · python@1python:3.12-slim@sha256:09f7da3bc104…
2026-09-08

案例

HOW
目标
Parse C99 source declarations into a FileAST hierarchy, manage typedef scoping with isolated state per invocation, and track source coordinates with CParser.parse in pycparser 2.22.
包
符号
  • pycparser.c_parser.CParser.parse
环境
python
创建时间
2026-08-17T23:06:18Z

契约

  1. CParser().parse parses C99 source declarations into a typed FileAST hierarchy preserving node coordinates and declaration structures.
  2. CParser().parse isolates typedef symbol table scope across successive parse calls on the same instance, raising ParseError when undeclared types are referenced.
  3. CParser().parse recognizes #line preprocessor directives and overrides source file and line coordinate attributes accordingly.
  4. CParser().parse requires preprocessed C source input, raising ParseError on unsupported preprocessor directives and raw comments.
  5. CParser().parse parses empty input strings into a FileAST instance with an empty declaration list.

文件

  • NOTES.md
  • csx.json
  • requirements.txt
  • test/contract.py

下载源代码构件 (tar.gz)

源代码

NOTES.md
# pycparser Behavior Notes

## Prior Solution Search

`search_known_solution` returned `REFERENCE_ONLY` pointing to sample `sha256:3c5ca6f4d0fbebc7e9f426b8ff85289533a86a2af0b05839306773534fb7b397` for `pycparser` 3.0. No existing verified sample targeted `pycparser` 2.22.

## Pinned Release

- Package: `pycparser`
- Version: `2.22`
- Manifest: `requirements.txt` (`pycparser==2.22`)

## Observed Behaviour

In `pycparser` 2.22:
- `pycparser.c_parser.CParser().parse(text, filename="...")` parses C99 source declarations into a typed `pycparser.c_ast.FileAST` tree.
- AST nodes preserve source coordinate metadata (`coord.file`, `coord.line`, `coord.column`) across typedefs, structs, and function definitions.
- The parser handles the C typedef-name ambiguity by updating its lexer scope stack during parsing. Subsequent declarations within the same input recognize previously declared typedef identifiers as `TYPEID`.
- Calling `parse()` on an existing `CParser` instance resets the parser's internal scope stack (`_scope_stack`) and lexer line numbering, preventing typedef declarations from leaking across successive parse invocations.
- `#line` preprocessor line directives are parsed and update the coordinate file and line attributes for subsequent AST nodes.
- Preprocessed C source is required: raw unhandled preprocessor directives (such as `#include`) raise `pycparser.c_parser.ParseError` with message `Directives not supported yet`, and raw C comments raise `ParseError` (e.g. `before: /`) because `CLexer` tokenizes comments as arithmetic division rather than stripping them.
- Empty input strings parse cleanly into a `FileAST` node with an empty declaration list `ext == []`.
csx.json
{"case":{"caseId":"case:sha256:714ada2391b23026743fa2ba3f86cda34e0860e50728661f5d2338c7dd3b28c7","contract":["CParser().parse parses C99 source declarations into a typed FileAST hierarchy preserving node coordinates and declaration structures.","CParser().parse isolates typedef symbol table scope across successive parse calls on the same instance, raising ParseError when undeclared types are referenced.","CParser().parse recognizes #line preprocessor directives and overrides source file and line coordinate attributes accordingly.","CParser().parse requires preprocessed C source input, raising ParseError on unsupported preprocessor directives and raw comments.","CParser().parse parses empty input strings into a FileAST instance with an empty declaration list."],"goal":"Parse C99 source declarations into a FileAST hierarchy, manage typedef scoping with isolated state per invocation, and track source coordinates with CParser.parse in pycparser 2.22.","kind":"HOW","packages":["pkg:pypi/pycparser@2.22"],"schemaVersion":1,"symbols":["pycparser.c_parser.CParser.parse"]},"contractCommand":["python","test/contract.py"],"environment":{"arch":"x64","ecosystem":"pypi","executionContext":"python","language":"python","os":"linux","packageManager":"pip","runtime":"python","schemaVersion":1},"license":"MIT-0","packages":["pkg:pypi/pycparser@2.22"],"schemaVersion":1,"symbols":["pycparser.c_parser.CParser.parse"],"verifierAdapter":"python@1"}
requirements.txt
pycparser==2.22
test/contract.py
"""
Verifies pycparser 2.22 CParser.parse behavior: AST generation, coordinate
tracking, typedef scope management and isolation across parse calls, #line
directive support, and preprocessed input requirements.
"""

from pycparser import c_ast
from pycparser.c_parser import CParser, ParseError


def test_parse_c99_ast_and_coordinates():
    parser = CParser()
    c_source = """
    typedef struct Buffer {
        char *data;
        int capacity;
    } Buffer;

    Buffer create_buffer(int capacity) {
        Buffer buf;
        buf.capacity = capacity;
        return buf;
    }
    """
    ast = parser.parse(c_source, filename="buffer.c")

    assert isinstance(ast, c_ast.FileAST), "Root node must be FileAST"
    assert len(ast.ext) == 2, f"Expected 2 top-level declarations, got {len(ast.ext)}"

    # Typedef verification
    typedef_node = ast.ext[0]
    assert isinstance(typedef_node, c_ast.Typedef)
    assert typedef_node.name == "Buffer"
    assert typedef_node.coord.file == "buffer.c"
    assert typedef_node.coord.line == 5

    struct_node = typedef_node.type.type
    assert isinstance(struct_node, c_ast.Struct)
    assert struct_node.name == "Buffer"
    assert len(struct_node.decls) == 2
    assert struct_node.decls[0].name == "data"
    assert struct_node.decls[1].name == "capacity"

    # Function definition verification
    func_node = ast.ext[1]
    assert isinstance(func_node, c_ast.FuncDef)
    assert func_node.decl.name == "create_buffer"
    assert func_node.decl.coord.file == "buffer.c"
    assert func_node.decl.coord.line == 7

    assert isinstance(func_node.decl.type, c_ast.FuncDecl)
    assert func_node.decl.type.type.type.names == ["Buffer"]

    params = func_node.decl.type.args.params
    assert len(params) == 1
    assert params[0].name == "capacity"
    assert params[0].type.type.names == ["int"]

    body_items = func_node.body.block_items
    assert len(body_items) == 3
    assert isinstance(body_items[0], c_ast.Decl)
    assert body_items[0].name == "buf"
    assert isinstance(body_items[1], c_ast.Assignment)
    assert body_items[1].op == "="
    assert isinstance(body_items[2], c_ast.Return)


def test_typedef_scoping_and_reset():
    parser = CParser()

    # First parse: define custom typedef and use it
    src1 = """
    typedef unsigned long custom_size_t;
    custom_size_t get_size(custom_size_t val) {
        return val + 1;
    }
    """
    ast1 = parser.parse(src1, filename="file1.c")
    assert isinstance(ast1, c_ast.FileAST)
    assert len(ast1.ext) == 2
    assert ast1.ext[0].name == "custom_size_t"

    # Second parse on the SAME parser instance: custom_size_t is no longer defined
    # CParser.parse() reinitializes _scope_stack per invocation
    src2 = "custom_size_t orphan_var = 100;"
    error_raised = False
    try:
        parser.parse(src2, filename="file2.c")
    except ParseError as e:
        error_raised = True
        err_msg = str(e)
        assert "file2.c:1:15: before: orphan_var" in err_msg or "file2.c:1:9: before: orphan_var" in err_msg

    assert error_raised, "Typedefs must not leak across successive parse() invocations"


def test_line_directive_coordinates():
    parser = CParser()
    c_source = """#line 120 "virtual_header.h"
    int exported_api_symbol(void);
    """
    ast = parser.parse(c_source, filename="input.c")

    assert len(ast.ext) == 1
    decl = ast.ext[0]
    assert isinstance(decl, c_ast.Decl)
    assert decl.name == "exported_api_symbol"
    assert decl.coord.file == "virtual_header.h"
    assert decl.coord.line == 120


def test_preprocessed_input_requirements():
    parser = CParser()

    # Unhandled preprocessor directives raise ParseError
    try:
        parser.parse("#include <stdint.h>\nint x;", filename="test.c")
        assert False, "Raw #include directive should raise ParseError"
    except ParseError as e:
        assert "Directives not supported yet" in str(e)

    # Raw C comments raise ParseError because CLexer tokenizes '/' instead of stripping comments
    try:
        parser.parse("/* comment */ int y;", filename="test.c")
        assert False, "Raw comments should raise ParseError"
    except ParseError as e:
        assert "before: /" in str(e)


def test_empty_input():
    parser = CParser()
    ast = parser.parse("", filename="empty.c")
    assert isinstance(ast, c_ast.FileAST)
    assert ast.ext == []


if __name__ == "__main__":
    test_parse_c99_ast_and_coordinates()
    test_typedef_scoping_and_reset()
    test_line_directive_coordinates()
    test_preprocessed_input_requirements()
    test_empty_input()
    print("Contract assertions passed.")

原始种子者

csx-seed