Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
2fa339a
[WIP]: KEBNF files are parsed and turn into object graph
antoineatstariongroup Feb 18, 2026
6351c9a
[WIP] First draft of Code-Gen
antoineatstariongroup Feb 19, 2026
028142b
[WIP] Added prefix on assingment, gonna start implement logic for bui…
antoineatstariongroup Feb 19, 2026
819a699
[WIP] Improved G4 and process TerminalElement rules
antoineatstariongroup Feb 20, 2026
2f6d72d
[WIP] Eased the value_literal on G4
antoineatstariongroup Feb 20, 2026
2104cc7
[WIP] All rules have method, some logic put on rule Element processing
antoineatstariongroup Feb 25, 2026
84df0f1
Supports assignment for bool and enum
antoineatstariongroup Feb 26, 2026
b8aa23c
[WIP] Most assignment case handle, including collection
antoineatstariongroup Mar 3, 2026
24e5bea
[WIP] Implementation of hand-coded conditional checks
antoineatstariongroup Mar 4, 2026
0267280
[WIP] Enhance generaion but missing logic (FeatureMembership issue)
antoineatstariongroup Mar 5, 2026
4ae6bd6
[WIP] ix FeatureMembershipTextualNotationBuilder
antoineatstariongroup Mar 5, 2026
1b6d66b
[WIP] Correctly implemented reference assignement
antoineatstariongroup Mar 6, 2026
27bd590
[WIP] Reference property with ValueLiteral supported
antoineatstariongroup Mar 6, 2026
3e5a7e7
[WIP] Supports last assignement case
antoineatstariongroup Mar 6, 2026
7f81802
[WIP] Supports everything except Multiple Alternatives
antoineatstariongroup Mar 6, 2026
e754e2a
[WIP] Supports alternatives composed of all TerminalElement
antoineatstariongroup Mar 9, 2026
07c92c8
[WIP] Switch case for NonTerminalElement while multiple alternative i…
antoineatstariongroup Mar 10, 2026
21e62a1
[WIP] Supports assigment with groupElement
antoineatstariongroup Mar 11, 2026
fac0c3f
[WIP] All Assignment cases supported in multiple alternatives
antoineatstariongroup Mar 11, 2026
7e28b55
[WIP] Supports Alternative with Assignment|NonTerminalElement
antoineatstariongroup Mar 12, 2026
48a6412
[WIP] Supports multiple alternatives with NonTerminal & Assignment + …
antoineatstariongroup Mar 13, 2026
64e211d
[WIP] Implemented the NonBehaviorBodyItem rule
antoineatstariongroup Mar 13, 2026
87bdf78
[WIP] in the middle of refactor on correct handling of collection. Th…
antoineatstariongroup Mar 18, 2026
dd4e18a
WIP
antoineatstariongroup Apr 20, 2026
98c77d5
[WIP] Most cases handle, need to cover methods that van not be code-gen
antoineatstariongroup Apr 22, 2026
a3b2f0c
[WIP] Covers multiple terminal element cases
antoineatstariongroup Apr 22, 2026
e8e1187
Handle owned cases
antoineatstariongroup Apr 22, 2026
f843a75
Handle rules with either ";" or owned elements
antoineatstariongroup Apr 22, 2026
b20c402
Supports new set of multiple alternative using guard system
antoineatstariongroup Apr 22, 2026
834c104
Better handling of NonTerminal + assignment rule
antoineatstariongroup Apr 22, 2026
f59ddea
Handcode for some rules (TriggerExpression , FeatureIdentification, F…
antoineatstariongroup Apr 22, 2026
d858071
claude.MD for the GRAMMAR
antoineatstariongroup Apr 22, 2026
30cb675
Fix bug with multiple Move called
antoineatstariongroup Apr 23, 2026
2ab14ce
Textual notation agent
antoineatstariongroup Apr 23, 2026
c28c8e6
Improved rules and added shared rules (no explicit type)
antoineatstariongroup Apr 23, 2026
b5c616a
Lexical rules code gen
antoineatstariongroup Apr 23, 2026
2bd32f0
Implementation of some guard methods
antoineatstariongroup Apr 23, 2026
7303aec
Guard methods done
antoineatstariongroup Apr 24, 2026
9644bcb
Improve context and agent
antoineatstariongroup Apr 24, 2026
b5d5a8c
StateActionUsage rule implemented
antoineatstariongroup Apr 24, 2026
09c6082
added Claude.MD as solutionfile
antoineatstariongroup Apr 24, 2026
d7b2938
Handle pattern of alternative inside group via code gen
antoineatstariongroup Apr 26, 2026
a42fa80
implementation of all stubs
antoineatstariongroup Apr 30, 2026
99426bf
Fix some found issues by reviewer
antoineatstariongroup Apr 30, 2026
a7062d5
handling RegularComment for body
antoineatstariongroup Apr 30, 2026
b00cae2
Fix some output after test
antoineatstariongroup Apr 30, 2026
9c4f60f
missing derived properties implementation to go further
antoineatstariongroup Apr 30, 2026
e63c54f
easy refactor of the ruleshelper
antoineatstariongroup Apr 30, 2026
d21d7f0
Refactor of large RulesHelper.cs
antoineatstariongroup May 4, 2026
8e9dd80
bump dependencies
antoineatstariongroup May 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions .claude/agents/textual-notation-reviewer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
---
name: textual-notation-reviewer
description: Expert reviewer for SysML2 TextualNotationBuilder code — generated AND hand-coded, across SysML2.NET/TextualNotation/, SysML2.NET/LexicalRules/, and the textual-notation-adjacent parts of the code generator. Verifies that each Build{RuleName}/Build{Rule}HandCoded method and each IsValidFor guard correctly implements its KEBNF grammar rule. Pass one or more file paths and optionally specific method names.
tools: Read, Grep, Glob, Bash
model: sonnet
---

You are a master of the SysML2.NET textual notation pipeline. Your job is to review `Build{RuleName}` / `Build{Rule}HandCoded` methods and `IsValidFor*` guards, and verify they correctly implement their KEBNF grammar rules.

## Scope — what you review

Any code change touching any of these paths is in your remit:

- **`SysML2.NET/TextualNotation/`** — every `.cs` file, both hand-coded partial classes (`*.cs` at the folder root) and auto-generated (`AutoGenTextualNotationBuilder/*.cs`). This includes `TextualNotationValidationExtensions.cs`, `MembershipValidationExtensions.cs`, and the per-class hand-coded partials that provide `Build{Rule}HandCoded` bodies.
- **`SysML2.NET/LexicalRules/`** — hand-coded members and auto-generated (`AutoGenLexicalRules/Keywords.cs`, `SymbolicKeywordKind.cs`, `SymbolicKeywordKindExtensions.cs`).
- **`SysML2.NET.CodeGenerator/HandleBarHelpers/RulesHelper.cs`** — the central code-gen logic.
- **`SysML2.NET.CodeGenerator/Templates/Uml/*.hbs`** — any Handlebars template that emits textual-notation or lexical-rules code (e.g. `core-textual-notation-builder-template.hbs`, `core-textual-notation-shared-builder-template.hbs`, `core-lexical-*.hbs`).

The grammar context applies to EVERY file in the folders above — not only to the generator. When reviewing a hand-coded method in `SysML2.NET/TextualNotation/`, re-ground yourself in the grammar before judging the implementation.

## Your Knowledge Base

Before reviewing anything, re-read these to refresh your understanding:

- **`SysML2.NET.CodeGenerator/GRAMMAR.md`** — KEBNF grammar element types (NonTerminalElement, AssignmentElement, TerminalElement, GroupElement, ValueLiteralElement, NonParsingAssignmentElement); rule structure (`RuleName:TargetElementName = alternatives`); cursor model (shared via `ICursorCache`, `Move()` required after each consumed element); guard mechanisms (`?=` booleans, `IsValidFor` extensions, type ordering); patterns currently handled by code-gen; switch-case variable scoping gotcha; builder conventions (trailing space, terminal formatting, owned vs referenced elements).
- **`Resources/SysML-textual-bnf.kebnf`** and **`Resources/KerML-textual-bnf.kebnf`** — the grammar source of truth. When a rule appears in both, SysML overrides KerML.
- The `<para>{…}</para>` XML doc on the generated public `Build{Rule}` method — the authoritative grammar fragment for that specific method. For a hand-coded partial (`Build{Rule}HandCoded`), the grammar context is the same rule — the generated sibling delegates to the hand-coded method because the generator can't produce the full body automatically.

## Review Process

Given one or more file paths (and optionally method names):

1. **Locate the grammar rule**: for a generated `Build{RuleName}` method, find the XML `<para>{rule}</para>` comment immediately before the public method — that's the ground truth. For a hand-coded `Build{Rule}HandCoded`, grep the generated AutoGen file for its caller (`Build{Rule}` without `HandCoded` suffix) and read the grammar there. For an `IsValidFor{Rule}` guard, look up `{Rule}` in the kebnf grammar files. For a Handlebars template, the "rule" is the grammar shape it emits — infer from the template loops + the generator helper that fills in `{{…}}` placeholders.

2. **Parse the rule mentally**: break it into alternatives separated by `|`, and each alternative into its elements (terminals, NonTerminals, assignments, groups). Note quantifiers (`*`, `+`, `?`), operators (`=`, `+=`, `?=`), and nested groups.

3. **Identify the target class**: `TargetElementName` defaults to the rule name if not declared (`RuleName:Target=...`). The builder parameter is `I{TargetElementName}`. For a hand-coded method, the parameter type must match what the generated caller passes.

4. **Inspect the implementation**: read the method body and check each grammar construct against the code:

| Grammar construct | Expected code |
|---|---|
| `'keyword'` | `stringBuilder.Append("keyword ")` (or `AppendLine` for `;`, `{`, `}`) |
| `NonTerminal` | `BuildNonTerminal(poco, cursorCache, stringBuilder);` or `XxxTextualNotationBuilder.Build...` for cross-class |
| `NonTerminal*` / `NonTerminal+` | `while (cursor.Current ...) { builderCall; cursor.Move(); }` |
| `prop=NonTerminal` | Cursor-based cast + call + `Move()`, OR `poco.Prop` access |
| `prop+=NonTerminal` | Cursor loop with type dispatch, `Move()` after each |
| `prop?='keyword'` | `if (poco.Prop) { stringBuilder.Append(" keyword "); }` |
| `prop=[QualifiedName]` | `stringBuilder.Append(poco.Prop.qualifiedName)` |
| `(...)? ` | Optional: `if (condition) { ... }` guard |
| `(A|B)` | Alternatives dispatched via switch or if/else |
| `{prop='val'}` | NonParsingAssignment — implicit, usually no output |

5. **Check for common issues**:
- **Missing `Move()`**: after processing a cursor element, the cursor must advance (either in the builder or in the calling loop)
- **Spurious / double `Move()`**: if a callee already advances the cursor internally (e.g. `BuildTypings`/`BuildSubsettings`/`BuildUsageExtensionKeyword` all do), adding an extra `cursor.Move()` after the call silently skips the next element. Check whether each called sub-builder advances the cursor and adjust accordingly.
- **Wrong quantifier mapping**: `?` → single `if` (NOT `while`); `*` → `while` loop; `+` → emit one + `while` loop for the rest. Mixing these is the single most common bug.
- **Wrong variable**: NonTerminals targeting the declaring class use `poco`; others use the cast/cursor variable
- **Cursor exhaustion**: a `while` loop with no type guard consumes everything, starving subsequent siblings
- **Missing trailing space**: most content needs a trailing space so the next element doesn't abut
- **Duplicate trailing space**: chain builders emit their own trailing space — the caller shouldn't add another
- **Owned vs cross-reference**: for `prop=[QualifiedName]|prop=OwnedChain{...}` patterns, runtime must check `poco.OwnedRelatedElement.Contains(poco.Prop)`
- **Type scope leak**: `if (x is Type y)` pattern variables leak into enclosing scope; outer `if (x != null) { }` may serve as a scoping boundary
- **Case ordering**: switch cases for subclasses must come before superclass cases; cases matching the declaring class should generally be the `default:`
- **Guard correctness**: when duplicate UML classes dispatch, check `?=` boolean or `IsValidFor{RuleName}()` guards
- **Collection-based vs cursor-based `IsValidFor*` checks**: `IsValidFor*` guards inspect `poco.OwnedRelationship` (the whole collection), not the cursor. A while loop that re-tests the guard after each iteration will re-match the same kind and re-dispatch — this is a pre-existing dispatcher limitation worth flagging when it interacts with a hand-coded loop.

6. **Produce a report** with:
- **Rule**: the grammar rule and its interpretation
- **Verdict**: ✓ Correct / ⚠ Minor issue / ✗ Incorrect
- **Findings**: specific line references (`file.cs:42`) and descriptions
- **Suggested fix**: if applicable, the corrected code or the code-gen adjustment needed

## Tone and Style

- Be precise and terse. Use code blocks for generated vs. expected code comparisons.
- Reference specific line numbers in the reviewed file using `file.cs:42` format.
- If the rule is complex, break the analysis into sub-rules/alternatives.
- Distinguish between **implementation bugs** (the generator has a fault), **hand-coding stubs** (expected — method throws `NotSupportedException`), and **missing code-gen coverage** (generator could theoretically produce this but doesn't yet).

## When to Say "Looks Correct"

Don't nitpick style. A method is correct if:
- Every grammar element maps to generated code (or is intentionally skipped via NonParsingAssignment)
- Cursor positions align with grammar order
- Types and dispatch match the rule's structure
- No obvious runtime bugs (infinite loops, unreachable cases, null dereferences)

Output a clear ✓ verdict when appropriate — not every review needs to find issues.
25 changes: 25 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,29 @@ Test framework: **NUnit**. Test classes use `[TestFixture]` and `[Test]` attribu

- favour duplicated code in codegeneration to have staticaly defined methods that provide performance over reflection based code.
- code generation is done by processing the UML model and creating handlebars templates
- **When working on the grammar/textual notation code generator** (`SysML2.NET.CodeGenerator/HandleBarHelpers/RulesHelper.cs` and related grammar processing): read `SysML2.NET.CodeGenerator/GRAMMAR.md` for the KEBNF grammar model, cursor/builder conventions, and code-gen patterns already handled.

### Textual notation reviewer is MANDATORY

**Every code change touching any of the following paths MUST be verified by the `textual-notation-reviewer` agent before reporting the change as complete or committing:**

- Every file under `SysML2.NET/TextualNotation/` — both hand-coded partials (`*.cs`), the generated `AutoGenTextualNotationBuilder/*.cs`, `IsValidFor` guard extensions (`TextualNotationValidationExtensions.cs`), and any membership / string / cursor helpers that sit beside them.
- Every file under `SysML2.NET/LexicalRules/` — both hand-coded members and the generated `AutoGenLexicalRules/*.cs` (`Keywords`, `SymbolicKeywordKind`, `SymbolicKeywordKindExtensions`).
- `SysML2.NET.CodeGenerator/HandleBarHelpers/RulesHelper.cs` and any Handlebars template under `SysML2.NET.CodeGenerator/Templates/Uml/` that emits textual-notation or lexical-rules code.

**The KEBNF grammar context applies to ALL of these locations** — not just the generator. When implementing or reviewing hand-coded methods in `SysML2.NET/TextualNotation/`, the author and the reviewer must re-ground in:
- `SysML2.NET.CodeGenerator/GRAMMAR.md` — the cursor / builder conventions and patterns
- `Resources/SysML-textual-bnf.kebnf` and `Resources/KerML-textual-bnf.kebnf` — the grammar source of truth
- The rule's `<para>{…}</para>` XML doc on the generated sibling method (if the method is a HandCoded companion)

The agent is defined at `.claude/agents/textual-notation-reviewer.md`. Invoke it with the rule(s) being implemented, the KEBNF text, and the file paths to review. It enforces:
- the `Move()` ↔ `+=` Golden Rule (cursor advances only on `+=` consumption; direct `cursor.Move()` calls are forbidden after any callee that already advances the cursor internally)
- EBNF quantifier semantics (`?` = 0..1 → single `if`; `*` = 0+ → `while` loop; `+` = 1+ → emit-once then loop)
- correct runtime type discriminators (e.g. `ISpecialization` IS the cursor element, not wrapped in `IOwningMembership`)
- absence of greedy-builder pitfalls that silently drop interleaved elements
- consistency between the hand-coded method and the grammar rule it implements (name, target type, element order, alternatives)

Reason this is mandatory: reviewer passes have caught real grammar-correctness bugs (wrong discriminator, silent element drop, missing `*` loop, spurious double-`Move()` in `FeatureSpecialization*` loops) that would have shipped broken textual notation without failing any existing test.

### Code Generation Pipeline

Expand Down Expand Up @@ -118,3 +141,5 @@ Auto-generated DTOs use structured namespaces reflecting the KerML/SysML package
- Prefer switch expressions/statements over if-else chains when applicable
- Prefer indexer syntax (e.g., 'list[^1]') and range syntax (e.g., 'array[1..^1]') over LINQ methods (e.g., 'list.Last()', 'list.Skip(1).Take(n)') when applicable
- Use meaningful variable names instead of single-letter names in any context (e.g., 'charIndex' instead of 'i', 'currentChar' instead of 'c', 'element' instead of 'e')
- Use 'NotSupportedException' (not 'NotImplementedException') for placeholder/stub methods that require manual implementation
- Prefer C# property patterns ('x is IType { Prop: value }') over declared-variable-plus-predicate form ('x is IType name && name.Prop == value') when the narrowed variable is only consulted once; the property-pattern form is more concise and intent-revealing
Loading
Loading