@tonkite/tlb-parser
Version:
Parse TL-B syntax into TypeScript objects
169 lines (131 loc) • 4.05 kB
text/typescript
const grammar = String.raw`
TLB {
// See:
// https://github.com/andreypfau/TL-B-docs
// Root definition
Program = SourceElement*
// Utilities
// Override Ohm's built-in definition of space.
space := whitespace | lineTerminator | comment
whitespace =
| "\t"
| "\x0B" -- verticalTab
| "\x0C" -- formFeed
| " "
| "\u00A0" -- noBreakSpace
| "\uFEFF" -- byteOrderMark
| "\u2000".."\u200B"
| "\u3000"
sourceCharacter = any
lineTerminator = "\n" | "\r" | "\u2028" | "\u2029"
// Comments
comment = multiLineComment | singleLineComment
multiLineComment = "/*" (~"*/" sourceCharacter)* "*/"
singleLineComment = "//" (~lineTerminator sourceCharacter)*
// Data types
binaryDigit = "0" | "1"
decimalDigit = "0".."9"
hex = hexChar*
hexChar = decimalDigit | letter
// Identifiers
identifier = identifierStart identifierPart*
identifierStart = "_" | letter
identifierPart = identifierStart | digit
// Primitives
number = digit+
// Builtins
builtins_one_arg = "#<=" | "#<" | "##"
builtins_zero_args = "#"
builtins_field = "#" | "Type"
// ----------
// Base rules
// ----------
SourceElement = Declaration | comment
Declaration = Constructor Fields "=" Combinator ";"
// Constructors
// ~~~~~~~~~~~~
Constructor = ConstructorStart ConstructorTag?
ConstructorStart = "!"? ("_" | identifier)
ConstructorTag =
| "$" ("_" | binaryDigit+) -- binary
| "#" ("_" | hex) -- hex
// Fields
// ~~~~~~
Fields = FieldDefinition*
FieldDefinition =
| FieldBuiltinDef
| FieldCurlyExprDef
| FieldAnonymousDef
| FieldNamedDef
| FieldExprDef
FieldBuiltinDef = "{" identifier ":" builtins_field "}"
FieldCurlyExprDef = "{" CurlyExpression "}"
FieldAnonymousDef = FieldAnonRef | FieldNamedAnonRef
FieldNamedDef = identifier ":" CondExpr
FieldExprDef = CondExpr
FieldAnonRef = "^"? "[" FieldDefinition* "]"
FieldNamedAnonRef = identifier ":" FieldAnonRef
// Combinators
// ~~~~~~~~~~~
Combinator = identifier SimpleExpr*
// Expressions
// ~~~~~~~~~~~
// First come the complex rules we only use to define fields.
// The line between fields definition and expressions is blury at this point.
CurlyExpression = CompareExpr
CondExpr =
| CondDotAndQuestionExpr
| CondQuestionExpr
| CondTypeExpr
CondDotted = TypeExpr "." number
CondDotAndQuestionExpr = ( CondDotted | Parens<CondDotted> ) "?" TypeExpr
CondQuestionExpr = TypeExpr "?" TypeExpr
CondTypeExpr = TypeExpr
// Compares:
CompareExpr =
| CompareOperatorExpr
| Parens<CompareExpr>
| MathExpr
CompareOperatorExpr =
| MathExpr "<=" MathExpr
| MathExpr ">=" MathExpr
| MathExpr "!=" MathExpr
| MathExpr "=" MathExpr
| MathExpr "<" MathExpr
| MathExpr ">" MathExpr
// Base rule for field defining expressions:
TypeExpr =
| CellRefExpr
| BuiltinExpr
| CombinatorExpr
| SimpleExpr
| Parens<TypeExpr>
// Math:
MathExpr = MulExpr ("+" MulExpr)*
// You can multiply by constant values only: 'Bit' and numbers, basically
MulExpr = SimpleExpr ("*" RefExpr)*
// TypeExpr's items:
CellRefExpr = "^" ( CellRefInner | Parens<CellRefInner> )
CellRefInner = CombinatorExpr | identifier
BuiltinExpr = BuiltinOneArg | BuiltinZeroArgs
// This needs extra 'Parens' because of '(##)' expr:
BuiltinOneArg = "(" ( builtins_one_arg | Parens<builtins_one_arg> ) RefExpr ")"
BuiltinZeroArgs = builtins_zero_args
// It is different from 'Combinator' only in the quantity part:
// we always need at least one argument here and it can be complex.
CombinatorExpr = "(" identifier TypeExpr+ ")"
SimpleExpr =
| NegateExpr
| MathExpr
| RefExpr
| Parens<SimpleExpr>
NegateExpr = "~" SimpleExpr
RefExpr = RefInner | Parens<RefInner>
RefInner = identifier | number
// Helpers
// ~~~~~~~
// Generic rule to allow parens around some expressions:
Parens<expr> = "(" expr ")"
}
`;
export default grammar;