Gramática
A gramática normativa é a gramática Lezer da qual o analisador do app é gerado. As palavras-chave estendem nomes, então sine: e loop: continuam sendo nomes de faixa válidos, e uma faixa sem padrão é aceita pela gramática e depois falha com EMPTY_PATTERN.
// Normative Lezer grammar of the Untzel language (docs/design/phase-1-sound.md, with
// the additions of docs/design/instruments.md).
// docs/03-linguagem.md describes the same language in informal EBNF; the conformance
// test keeps the two in agreement.
@top Source { (Line? newline)* Line? }
Line { TitleStatement | TempoStatement | KeyStatement | SwingStatement | LoopStatement | Track | SectionDecl | SongDecl }
TitleStatement { kw<"title"> String }
TempoStatement { kw<"tempo"> Number }
KeyStatement { kw<"key"> Tonic Name }
SwingStatement { kw<"swing"> Number }
LoopStatement { kw<"loop"> Number }
Track { (TrackName ":")? InstrumentName Preset? Pattern? ("|" Modifier)* }
Preset { PresetName }
TrackName { Name }
InstrumentName { Name }
SectionDecl { kw<"section"> Name Name+ ("|" Modifier)* }
SongDecl { kw<"song"> Part ("," Part)* ("|" kw<"loop">)? }
Part { Name Number }
Pattern { Bar ("/" Bar)* }
Bar { Element+ }
Element { Atom Accent? Probability? Repeat? }
Accent { "!" }
Probability { "?" Number? }
Repeat { "*" Number }
Atom { Hits | Note | Stack | Chord | Sustain | Group }
Stack { Note ("+" Note)+ }
Group { "[" Element+ "]" }
Modifier { ModifierName Value? }
ModifierName { Name | kw<"swing"> | kw<"tempo"> }
Value { Number | Signal Range? | Division | Name }
Signal { SignalShape "(" (Number | Division) ")" }
SignalShape { kw<"sine"> | kw<"tri"> | kw<"saw"> | kw<"square"> | kw<"rand"> | kw<"env"> }
Range { Number ".." Number }
Division { Number "/" Number }
kw<term> { @extend[@name={term}]<Name, term> }
@skip { space | Comment }
@tokens {
space { $[ \t]+ }
newline { "\r"? "\n" }
Comment { "//" ![\n]* }
Number { "-"? @digit+ ("." @digit+)? }
// The song title: one line, \" and \\ are the only escapes.
String { '"' (![\\\n"] | "\\" $["\\])* '"' }
Name { $[a-z] $[a-z0-9_\-]* }
Hits { $[xX.] $[xX.~]* }
Sustain { "~" }
Note { $[a-g] $[b#]? @digit }
Tonic { $[a-g] $[b#]? }
// A preset never starts with "x" (a hit) nor reads like a note or a tonic.
PresetName { $[h-wyz] $[a-z0-9\-]* | $[a-g] $[ac-z\-] $[a-z0-9\-]* | $[a-g] "b" $[a-z\-] $[a-z0-9\-]* }
Chord { $[A-G] $[b#]? ("maj7" | "m7" | "m" | "7" | "sus2" | "sus4" | "dim" | "6" | "m6" | "9"
| "m9" | "maj9" | "add9" | "madd9" | "aug" | "dim7" | "m7b5" | "7sus4" | "11" | "m11" | "13")? }
@precedence { Comment, "/" }
":" "|" "," "/" "?" "*" "[" "]" "(" ")" ".." "!" "+"
}Conteúdo da documentação do Untzel, sob a licença CPAL-1.0. Ler a licença