grammar Bootstrap { } entry class Root { Statement* } union Statement { | GrammarStatement | ClassStatement | UnionStatement | GroupStatement } // === grammar === ----------------------------------------------------------------------------------------------------- class GrammarStatement { ^KW_GRAMMAR Identifier GrammarBlock } class GrammarBlock { '{' '}' } // === class === ----------------------------------------------------------------------------------------------------- class ClassStatement { DecoratorCall* ModifierCall* ^KW_CLASS (name:Identifier) ('->' cast:Identifier)? OP_REMARK? ClassBlock } class ClassBlock { '{' '|'? Expression '}' } token { OP_REMARK: '^' } // === union === ----------------------------------------------------------------------------------------------------- class UnionStatement { DecoratorCall* ModifierCall* ^KW_UNION (name:Identifier) OP_REMARK? UnionBlock } class UnionBlock { '{' UnionBranch* '}' } class UnionBranch { '|' ExpressionHard BranchTag? } @style(field) atomic class BranchTag { '#' Identifier RightAssociativity? } class RightAssociativity { '>' } // === group === ------------------------------------------------------------------------------------------------------- class GroupStatement { DecoratorCall* ModifierCall* ^KW_GROUP Identifier? GroupBlock } class GroupBlock { '{' GroupPair* '}' } class GroupPair { Identifier ':' Atomic } // === Decorators === ------------------------------------------------------------------------------------------------- class DecoratorCall { DecoratorName CallBody } @style(annotation) class DecoratorName { [@#] Identifier } class FunctionCall { FunctionName CallBody } @style(function) class FunctionName { '@' Identifier } class CallBody { '(' (Expression (',' Expression)* ','?)? ')' } // === expression === -------------------------------------------------------------------------------------------------- class Expression { ExpressionHard ('|' ExpressionHard)* } class ExpressionHard { ExpressionSoft ('~' ExpressionSoft)* } class ExpressionSoft { ExpressionTag ExpressionTag* } class ExpressionTag { (Identifier ':')? Term } class Term { Prefix* Atomic Suffix* } union Prefix { | '!' #Negative | '&' #Positive | '^' #Remark } union Suffix { | '?' #Optional | '*' #Many | '+' #Many1 } // === atoms === ------------------------------------------------------------------------------------------------------- union Atomic { | GroupExpression | FunctionCall | Boolean | String | RegexEmbed | RegexRange | Identifier } class GroupExpression { '(' '|'? Expression ')' } // === String === ------------------------------------------------------------------------------------------------------- atomic union String { | "'" StringRaw "'" #Raw | '"' StringNormal '"' #Normal } text class StringRaw { /[^']*/ } class StringNormal { StringItem* } union StringItem { | EscapedUnicode | EscapedCharacter | TextAny } @style(escape) text group { EscapedUnicode: /\\\\u[0-9a-zA-Z]{4}/ EscapedCharacter: /\\./ TextAny: /[^\"\\]+/ } // === regex === ------------------------------------------------------------------------------------------------------- atomic class RegexEmbed { '/' RegexInner '/' } text class RegexInner { /([^\\\\\\/]|\\\\.)+/ } text atomic class RegexRange { '[' RegexNegative? (!']' ANY)* ']' } class RegexNegative { '^' } // === identifier === -------------------------------------------------------------------------------------------------- class NamepathFree -> Namepath { Identifier (('.' | '::') Identifier)* } class Namepath { Identifier ('::' Identifier)* } text class Identifier { /[_\p{XID_start}]\p{XID_continue}*/ } union Boolean { | 'true' #True | 'false' #False } // === keywords === ---------------------------------------------------------------------------------------------------- atomic class ModifierCall ^ { !(KW_CLASS | KW_UNION | KW_GROUP | KW_MACRO | KW_CLIMB) ^Identifier } @style(keyword) token { KW_GRAMMAR: /grammar/ KW_IMPORT: /using|import|use/ KW_CLASS: /class|struct/ KW_UNION: /union|enum/ KW_GROUP: /group|token/ KW_CLIMB: /climb/ KW_MACRO: /macro|def|function|func|fun|fn/ } // === ignores === ----------------------------------------------------------------------------------------------------- ignore class WhiteSpace { /\p{White_Space}+/ } @style(comment) ignore class Comment { | /\/\/[^\n\r]*/ // | '/*' '*/' }