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 なら作者だけ、2 以上なら他の誰かもビルドしています。鍵は自己生成で背後に登録された身元がないため、数えているのは人ではなく鍵です。 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