Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
148951a
Fix #218: PackageExtension methods implemented
antoineatstariongroup Apr 20, 2026
79e45fa
[WIP]: KEBNF files are parsed and turn into object graph
antoineatstariongroup Feb 18, 2026
ea686ba
[WIP] First draft of Code-Gen
antoineatstariongroup Feb 19, 2026
90cf346
[WIP] Added prefix on assingment, gonna start implement logic for bui…
antoineatstariongroup Feb 19, 2026
6779ca8
[WIP] Improved G4 and process TerminalElement rules
antoineatstariongroup Feb 20, 2026
129d6a3
[WIP] Eased the value_literal on G4
antoineatstariongroup Feb 20, 2026
c8ed9e4
[WIP] All rules have method, some logic put on rule Element processing
antoineatstariongroup Feb 25, 2026
2414031
Supports assignment for bool and enum
antoineatstariongroup Feb 26, 2026
2860e1a
[WIP] Most assignment case handle, including collection
antoineatstariongroup Mar 3, 2026
7114f6c
[WIP] Implementation of hand-coded conditional checks
antoineatstariongroup Mar 4, 2026
dba1e44
[WIP] Enhance generaion but missing logic (FeatureMembership issue)
antoineatstariongroup Mar 5, 2026
483b484
[WIP] ix FeatureMembershipTextualNotationBuilder
antoineatstariongroup Mar 5, 2026
c0f1b66
[WIP] Correctly implemented reference assignement
antoineatstariongroup Mar 6, 2026
4ba3773
[WIP] Reference property with ValueLiteral supported
antoineatstariongroup Mar 6, 2026
eafd67a
[WIP] Supports last assignement case
antoineatstariongroup Mar 6, 2026
337e60c
[WIP] Supports everything except Multiple Alternatives
antoineatstariongroup Mar 6, 2026
553b4cc
[WIP] Supports alternatives composed of all TerminalElement
antoineatstariongroup Mar 9, 2026
4f4cd35
[WIP] Switch case for NonTerminalElement while multiple alternative i…
antoineatstariongroup Mar 10, 2026
101ec13
[WIP] Supports assigment with groupElement
antoineatstariongroup Mar 11, 2026
cf0e800
[WIP] All Assignment cases supported in multiple alternatives
antoineatstariongroup Mar 11, 2026
4aea7c6
[WIP] Supports Alternative with Assignment|NonTerminalElement
antoineatstariongroup Mar 12, 2026
b595fcf
[WIP] Supports multiple alternatives with NonTerminal & Assignment + …
antoineatstariongroup Mar 13, 2026
aab90e8
[WIP] Implemented the NonBehaviorBodyItem rule
antoineatstariongroup Mar 13, 2026
202ca95
[WIP] in the middle of refactor on correct handling of collection. Th…
antoineatstariongroup Mar 18, 2026
3884b71
WIP
antoineatstariongroup Apr 20, 2026
e870cdf
[WIP] Most cases handle, need to cover methods that van not be code-gen
antoineatstariongroup Apr 22, 2026
fdb5e3a
[WIP] Covers multiple terminal element cases
antoineatstariongroup Apr 22, 2026
f1004ce
Handle owned cases
antoineatstariongroup Apr 22, 2026
5bdab23
Handle rules with either ";" or owned elements
antoineatstariongroup Apr 22, 2026
521ddf2
Supports new set of multiple alternative using guard system
antoineatstariongroup Apr 22, 2026
8adb68b
Better handling of NonTerminal + assignment rule
antoineatstariongroup Apr 22, 2026
e556e66
Handcode for some rules (TriggerExpression , FeatureIdentification, F…
antoineatstariongroup Apr 22, 2026
ce523e6
claude.MD for the GRAMMAR
antoineatstariongroup Apr 22, 2026
f61b697
Fix bug with multiple Move called
antoineatstariongroup Apr 23, 2026
55d4a6d
Textual notation agent
antoineatstariongroup Apr 23, 2026
c8d33c5
Improved rules and added shared rules (no explicit type)
antoineatstariongroup Apr 23, 2026
12bdb2f
Lexical rules code gen
antoineatstariongroup Apr 23, 2026
b8f552d
Implementation of some guard methods
antoineatstariongroup Apr 23, 2026
609fe8b
Guard methods done
antoineatstariongroup Apr 24, 2026
eb76f6d
Improve context and agent
antoineatstariongroup Apr 24, 2026
1ed67b3
StateActionUsage rule implemented
antoineatstariongroup Apr 24, 2026
f83551a
added Claude.MD as solutionfile
antoineatstariongroup Apr 24, 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
88 changes: 88 additions & 0 deletions .claude/agents/textual-notation-reviewer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
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
---

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