Repository navigation
Grammar wishlist from the docs: seven constructs the examples use that the parser does not implement #27
Description
Filed so the grammar questions can be evaluated on their own, separately from getting the docs site rendering again. The examples are being rewritten onto today's syntax first, so this is not blocking anything.
How this was found
Every live <notation> element in docs/content was extracted and run through load() on v1.1.0.
live examples: 148 | failing: 39 | clean: 109
clean but containing ___ (renders as literal text): 5
pages affected: 8
NotationBlock.updatePreview() logs to the console and renders nothing when load() returns errors, so those 39 are blank boxes on the site with the explanation only in devtools.
The constructs
| Construct | Example from the docs | Examples affected | What the parser does today |
|---|---|---|---|
| Bar separator in a role line | Sw: S , R , | G , M , || |
22 | Unexpected Character: |. See issue 19 |
| Silent space | Sw: S , ___ , |
5 clean, more inside failing ones | Parses, becomes {"type":"Literal","value":"___"}. See issue 17 |
| Sharps | \accidentals(M#), M# |
5 | Unexpected Character: # |
| Free-time passages | \noTala |
2 | Throws out of load(), see the separate issue on that |
| Paren gamaka grouping | ((S R G) kampitam) M |
4 | Unexpected Token: 'OPEN_PAREN' |
| Floating embellishment operator | [S R] ~:- [G M], S R ~ G M P ~ |
4 | OPEN_SQ, COMMA, $end depending on position |
| Unknown gamaka name | ~kampita |
1 | Invalid embelishment. Probably just a typo for ~kampitam |
What each would take, and the question it raises
Bar separators (issue 19). | is excluded from IdentChar and never declared as a token, so it fails at the tokenizer. The cheap version is a BAR token plus an Atoms production that accepts and discards it, which makes the docs render and gives the reader nothing. The question is whether a bar should instead assert a cycle position, so Sw: S R | G M reports an error when the bar falls somewhere the cycle says it should not. That is a real feature with its own error reporting, and it is the reason people write bars in the first place.
Silent spaces (issue 17). The Space -> UNDER_SCORE { newSilentSpace } production already exists; %token UNDER_SCORE does not. _ is a valid IdentChar, which is why ___ currently lexes as an IDENT and renders as visible text. Declaring the token at a priority above IDENT fixes it. Two questions: does one _ equal one silent space regardless of run length, which is what the existing production implies, and does any real notation use underscores inside a literal name, which would change meaning under the new token.
Sharps. # is excluded from IdentChar. The cheap version is to stop excluding it, so M# becomes a literal named M# with no semantics, which renders correctly and means nothing to the layout engine. The real version models accidentals, which needs a decision about whether the library represents pitch at all. Today it deliberately does not, per src/ARCHITECTURE.md: literals carry no assigned meaning. \accidentals(M#) as a document-level declaration only makes sense in the second reading.
Free-time passages. \noTala is used for alapana and tanam sections, where there is no cycle and no beat grid. Adding the command is trivial; deciding what GlobalBeatLayout.processBlock does when there is no cycle is not. Worth checking whether the existing layout code can express an unmetered line at all.
Paren gamaka grouping. ((S R G) kampitam) is a function-call shape with a named gamaka, which is a different model from the ~ operator the grammar implements, where the embellishment attaches to a literal. Either the docs are describing a design that was never built, or [ ] grouping and ( ) gamaka application are meant to coexist. Worth settling before either is touched, since it affects how the embellishment reference reads.
Floating embellishment operators. Lit -> Lit POST_EMB requires the operator to attach to a literal. The docs write it standing alone between groups. Same underlying question as the row above.
Suggested order, if these get picked up
Issue 17 and the sharps row are the two where the cheap version is genuinely the right version and needs no design work. Issue 19 is worth doing properly rather than cheaply. The last three are design questions before they are grammar questions.
Activity
panyam commentedon Sep 21, 2026
Three of the seven rows are handled in #32, which leaves the four that are design questions before they are grammar questions.
Done
%token UNDER_SCORE /_(?!{IdentChar})/. Both questions this issue raised turned out to be already answered insrc/utils.ts:107, whereparseSyllablehas always built oneSpace(ONE, true)per_. So one underscore is one silent space, and the lookahead keeps runs and embedded underscores as literals, which is the non-breaking half. Write_ _ _for three. The grammar andparseSyllablestill disagree aboutS_N_D, filed as parseSyllable and the grammar disagree about an underscore inside a word #33.%skip /\|\|?/, taking the decoration reading rather than the validating one. The reasoning is in Bar separators|inside a role line are a tokenizer error, but the docs use them #19:beatviews.tsalready draws these from the cycle, so a typed bar was redundant with what gets drawn. Validation still wants doing and is still a feature.Still open, in rough order of how much design they need
M#correctly, so this only needs grammar work if the library is going to model pitch.\noTala. Adding the command is trivial, deciding what the beat layout does without a cycle is not.((S R G) kampitam).[S R] ~:- [G M].The last two are the same question asked twice, which is whether the paren notation in the docs was ever a design or just got written down.