@top Bibliography { (Declaration | StringDeclaration)* } @tokens { whiteSpace { @whitespace+ } Identifier { $[a-zA-Z:_0-9-]+ } StringName { $[a-zA-Z:_] $[a-zA-Z:_0-9-]* } FieldName {$[a-zA-Z-_0-9]+} LiteralString { '"' (!["] | "\\" _)* '"'? } EntryTypeName { $[a-zA-Z]+ } Number { @digit+ } StringKeyword {"@"$[Ss]$[Tt]$[Rr]$[Ii]$[Nn]$[Gg]} "{"[closedBy="}"] "}"[openedBy="{"] "@" "\"" "," "#" "@string" Comment { "%" ![\n]* } } // FIXME: Technically skipping comments is wrong here. They can only appear // alone on a line, but I'm not sure how to express that easily in Lezer @skip {whiteSpace | Comment} StringDeclaration { StringKeyword "{" Field* "}" } Declaration { EntryName { "@" EntryTypeName } "{" Identifier fieldEntry { ("," Field ) }* ("," )? "}" } Field { Name "=" Expression } Expression { BracedString | Number | StringConcatenation } @local tokens { OpenBracedContents[closedBy="}", @name="{"] {"{"} CloseBracedContents[openedBy="{", @name="}"] {"}"} @else nonClosingBracedContents } @skip {}{ bracedStringContents { ( nonClosingBracedContents | nestedBracedString { OpenBracedContents bracedStringContents CloseBracedContents } )* } BracedString { "{" bracedStringContents CloseBracedContents } } @precedence { concatenation @left } StringConcatenation { StringConcatenation !concatenation "#" StringConcatenation | LiteralString | StringName } @external propSource highlighting from "./highlight.mjs"