Skip to content

yacc: %union type declarations have real record/struct morphology but class_start is wired None #2644

Description

@squid-protocol

Found while reviewing rosetta's unreviewed class_start n/a cells (keyword-rosetta docs/GATING.md "n/a semantics" review).

What happens

yacc.py:72 wires "class_start": None with docs/language_status/yacc.md (§1, §4) documenting this as deliberate: "a grammar file has no object/type concept." That's true for OOP-style classes, but it misses that Bison/Yacc's %union { ... } directive declares a real compound type — the C union spanning every grammar rule's semantic value ($$/$1/$2, already captured by args). This is the exact same shape the engine already wires class_start to elsewhere for non-OOP languages:

  • Fortran's TYPE ... END TYPE derived-type declarations (fortran.py:180-183, comment: "Fortran's struct/class equivalent")
  • COBOL's PROGRAM-ID/CLASS-ID (cobol.py:231-234)
  • generic assembly's struc/STRUCT macros (assembly.py:105-108)

%union isn't embedded C incidentally picked up by the C-action rules either — it's core yacc/bison grammar syntax. yacc.py's own internal_discriminator (line 48) already lists union among the definitive %-directive markers used to identify a file as yacc in the first place, but no signal rule anywhere in the 47-key dict captures it as a structural entity.

Evidence

Both real .y files in the crucible corpus use %union in the standard form:

# language-crucible-local/data/yacc/freebsd/config.y:1-6
%union {
	char	*str;
	int	val;
	struct	file_list *file;
}

(jailparse.y:45 has the same shape.) This is standard, common bison idiom, not an obscure corner case — 2/2 real gathered files use it.

Fix shape

  1. yacc.py: add a class_start rule anchored on the %union directive, e.g. re.compile(r"^[ \t]*%union\b", re.M), following the same line-start-anchor convention already used for %token/%type in this file's structural_boundaries rule. (Optionally capture a name group for bison's less-common named-tag variant %union name { ... } for parity with how class_start elsewhere captures an entity name — presence detection alone already closes the gap, since a grammar has at most one %union block.)
  2. Re-run crucible_check.py/golden masters — expected diff is class_start 0→1 on any real .y/.yy/.ypp file using %union (both freebsd corpus files).
  3. Update docs/language_status/yacc.md §1/§3/§4 to move class_start out of the "16 explicit None" count and document the %union mapping alongside func_start's existing "closest function-analog" framing.
  4. Corpus follow-up (keyword-rosetta): once merged, the yacc/class_start n/a cell becomes plantable — rosetta corpus PR adding a %union probe to data/yacc/*.y and updating expected_signals.json, same cross-repo choreography as jcl-2610/COND=.

Found by the #1096/#2560 rosetta n/a review sweep.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    core-engineModifications to the central physics and parsing engineenhancementNew feature, sensor, or structural signaturestatus: blockedWaiting on upstream dependencies or user clarification

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions