UNPKG

@ton-community/tlb-parser

Version:

Parse TLB syntax into TypeScript objects

284 lines (228 loc) 5.88 kB
export abstract class ASTRootBase { // If the `parent` field is `null` it means that we've reached the root node. // only `Program` has `parent` as null. // All other nodes have valid node parents. // We define `parent` while building the tree // in the intermediate represtantation. readonly parent!: ASTBase | null // Node locations, start with `{ 1, 1 }` readonly locations!: { readonly line: number, readonly column: number, } // Attributes of this node, required for `walk` function, don't use directly. static readonly _attributes: string[] = [] } export abstract class ASTBase extends ASTRootBase { override readonly parent!: ASTBase } export class Program extends ASTRootBase { static override readonly _attributes: string[] = ['declarations'] override readonly parent: null = null constructor( readonly declarations: Declaration[], ) { super() } } export class Declaration extends ASTBase { static override readonly _attributes: string[] = [ 'constructorDef', 'fields', 'combinator', ] constructor( readonly constructorDef: Constructor, readonly fields: FieldDefinition[], readonly combinator: Combinator, ) { super() } } export class Constructor extends ASTBase { constructor( readonly name: string, readonly tag: string | null, ) { super() } getTagType(): 'binary' | 'hex' | null { if (this.tag === null) { return null } return this.tag.startsWith('$') ? 'binary' : 'hex' } } // Fields // ------ export type FieldDefinition = | FieldBuiltinDef | FieldCurlyExprDef | FieldAnonymousDef | FieldNamedDef | FieldExprDef export abstract class Field extends ASTBase {} export const FieldBuiltinType = ['#', 'Type'] as const export class FieldBuiltinDef extends Field { constructor( readonly name: string, readonly type: typeof FieldBuiltinType[number], ) { super() } } export class FieldCurlyExprDef extends Field { static override readonly _attributes: string[] = ['expr'] constructor( readonly expr: Expression, ) { super() } } // TODO: I am not sure that `name` is allowed. Maybe it can only be `_` // See https://github.com/ton-blockchain/ton/issues/540 export class FieldAnonymousDef extends Field { static override readonly _attributes: string[] = ['fields'] constructor( readonly name: string | null, readonly isRef: boolean, readonly fields: FieldDefinition[], ) { super() } } export class FieldNamedDef extends Field { static override readonly _attributes: string[] = ['expr'] constructor( readonly name: string, readonly expr: CondExpr | TypeExpr, ) { super() } } export class FieldExprDef extends Field { static override readonly _attributes: string[] = ['expr'] constructor( readonly expr: CondExpr, ) { super() } } // Combinators // ----------- export class Combinator extends ASTBase { static override readonly _attributes: string[] = ['args'] constructor( readonly name: string, readonly args: TypeExpr[], ) { super() } } // Expressions // ----------- export abstract class Expression extends ASTBase {} // TODO: add validation that `dotExpr` cannot be set without `condExpr` export class CondExpr extends Expression { static override readonly _attributes: string[] = ['left', 'condExpr'] constructor( readonly left: TypeExpr, readonly dotExpr: number | null, readonly condExpr: TypeExpr, ) { super() } } export const CompareOperator = ['<=', '>=', '!=', '=', '<', '>'] as const export class CompareExpr extends Expression { static override readonly _attributes: string[] = ['left', 'right'] constructor( readonly left: SimpleExpr, readonly op: typeof CompareOperator[number], readonly right: SimpleExpr, ) { super() } } // TypeExpr export type TypeExpr = | CellRefExpr | BuiltinExpr | CombinatorExpr | SimpleExpr export class CellRefExpr extends Expression { static override readonly _attributes: string[] = ['expr'] constructor( readonly expr: Expression, ) { super() } } export class BuiltinExpr extends Expression {} export const BuiltinOneArgOperators = ['#<=', '#<', '##'] as const export class BuiltinOneArgExpr extends BuiltinExpr { static override readonly _attributes: string[] = ['arg'] constructor( readonly name: typeof BuiltinOneArgOperators[number], readonly arg: Reference, ) { super() } } export const BuiltinZeroArgsOperators = ['#'] as const export class BuiltinZeroArgs extends BuiltinExpr { constructor( readonly name: typeof BuiltinZeroArgsOperators[number], ) { super() } } export class CombinatorExpr extends Expression { static override readonly _attributes: string[] = ['args'] constructor( readonly name: string, readonly args: TypeExpr[], ) { super() } } // SimpleExpr export type SimpleExpr = | NegateExpr | MathExpr | Reference export const MathOperator = ['*', '+'] as const export class MathExpr extends Expression { static override readonly _attributes: string[] = ['left', 'right'] // TODO: narrower type for `left` and `right`? // TODO: use `SimpleExpr` and `number`? constructor( readonly left: SimpleExpr, readonly op: typeof MathOperator[number], readonly right: SimpleExpr, ) { super() } } export class NegateExpr extends Expression { static override readonly _attributes: string[] = ['expr'] constructor( readonly expr: Expression, ) { super() } } export class RefExpr extends Expression {} export type Reference = NameExpr | NumberExpr export class NameExpr extends RefExpr { constructor( readonly name: string, ) { super() } } export class NumberExpr extends RefExpr { constructor( readonly num: number, ) { super() } }