UNPKG

@igorivaniuk/tlb-parser

Version:

Parse TLB syntax into TypeScript objects

202 lines (201 loc) 7.97 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.exprNodes = exports.combinatorNodes = exports.fieldNodes = exports.constructorNodes = exports.rootNodes = void 0; const ast = __importStar(require("./ast/nodes")); const locations_1 = require("./ast/locations"); exports.rootNodes = { Program(node) { return (0, locations_1.withLocations)(new ast.Program(node.children.map((child) => child['root']())), node); }, SourceElement(node) { return (0, locations_1.withLocations)(new ast.Declaration(node.child(0)['Constructor'](), node.child(1)['Field'](), node.child(3)['Combinator']()), node); }, }; exports.constructorNodes = { Constructor(name, tag) { const nameValue = name.sourceString; let tagValue = null; if (tag.numChildren !== 0) { tagValue = tag.child(0)['Constructor'](); } return (0, locations_1.withLocations)(new ast.Constructor(nameValue, tagValue), name); }, ConstructorTag(node) { // This is a string-only node: return node.sourceString; }, }; exports.fieldNodes = { Fields(node) { return node.children.map((child) => child['Field']()); }, FieldDefinition(node) { return node['Field'](); // just a wrapper node, unwrapping }, FieldBuiltinDef(lpar, name, _sep, type, _rpar) { // TODO: validate `type.sourceString` to be in allowed values. return (0, locations_1.withLocations)(new ast.FieldBuiltinDef(name.sourceString, type.sourceString), lpar); }, FieldCurlyExprDef(lpar, expr, _rpar) { return (0, locations_1.withLocations)(new ast.FieldCurlyExprDef(expr['expr']()), lpar); }, FieldAnonymousDef(node) { const { name, isRef, fields } = node['Field'](); return (0, locations_1.withLocations)(new ast.FieldAnonymousDef(name, isRef, fields), node); }, FieldNamedDef(name, _sep, expr) { return (0, locations_1.withLocations)(new ast.FieldNamedDef(name.sourceString, expr['expr']()), name); }, FieldExprDef(node) { return (0, locations_1.withLocations)(new ast.FieldExprDef(node['expr']()), node); }, // Helpers to parse complex anonymous fields: // TODO: move out of this semantics FieldAnonRef(ref, _lpar, fields, _rpar) { return { 'name': null, 'isRef': ref.numChildren !== 0, 'fields': fields.children.map((field) => field['Field']()), }; }, FieldNamedAnonRef(name, _sep, fields) { return Object.assign(Object.assign({}, fields['Field']()), { 'name': name.sourceString }); }, }; exports.combinatorNodes = { Combinator(name, exprs) { return (0, locations_1.withLocations)(new ast.Combinator(name.sourceString, exprs.children.map((typeExpr) => typeExpr['expr']())), name); }, }; exports.exprNodes = { // Math MathExpr(left, ops, rights) { return parseMath(left, ops, rights); }, MulExpr(left, ops, rights) { return parseMath(left, ops, rights); }, CompareExpr(node) { return node['expr'](); }, CompareOperatorExpr(left, op, right) { return (0, locations_1.withLocations)(new ast.CompareExpr(left['expr'](), op.sourceString, right['expr']()), op); }, // Conditional types CondExpr(expr) { const { leftExpr, dotExpr, condExpr } = expr['expr'](); if (dotExpr === undefined && condExpr === undefined) { return leftExpr; } return (0, locations_1.withLocations)(new ast.CondExpr(leftExpr, dotExpr, condExpr), expr); }, // TODO: move out of this semantics CondDotAndQuestionExpr(dotNode, _sep, condNode) { return Object.assign(Object.assign({}, dotNode['expr']()), { 'condExpr': condNode['expr']() }); }, CondQuestionExpr(left, _sep, condNode) { return { 'leftExpr': left['expr'](), 'dotExpr': null, 'condExpr': condNode['expr'](), }; }, CondTypeExpr(node) { return { 'leftExpr': node['expr'](), }; }, CondDotted(left, _sep, number) { return { 'leftExpr': left['expr'](), 'dotExpr': new Number(number.sourceString), }; }, // TypeExpr CombinatorExpr(lpar, name, args, _rpar) { return (0, locations_1.withLocations)(new ast.CombinatorExpr(name.sourceString, args.children.map((arg) => arg['expr']())), lpar); }, CellRefExpr(ref, node) { return (0, locations_1.withLocations)(new ast.CellRefExpr(node['expr']()), ref); }, BuiltinExpr(node) { return (0, locations_1.withLocations)(node['expr'](), node); }, NegateExpr(op, node) { return (0, locations_1.withLocations)(new ast.NegateExpr(node['expr']()), op); }, // Builtins BuiltinOneArg(lpar, expr, arg, _rpar) { // TODO: validate `expr` to be in allowed set of operators return (0, locations_1.withLocations)(new ast.BuiltinOneArgExpr(expr.sourceString, arg['expr']()), lpar); }, BuiltinZeroArgs(expr) { // TODO: validate `expr` to be in allowed set of operators return (0, locations_1.withLocations)(new ast.BuiltinZeroArgs(expr.sourceString), expr); }, // Base rules identifier(start, rest) { return (0, locations_1.withLocations)(new ast.NameExpr(start.sourceString + rest.sourceString), start); }, number(node) { return (0, locations_1.withLocations)(new ast.NumberExpr(parseInt(node.sourceString)), node); }, // Helpers Parens(lpar, node, _rpar) { // Just drop `()` around an expression, it should be fine return (0, locations_1.withLocations)(node['expr'](), lpar); }, }; function parseMath(left, ops, rights) { const leftExpr = left['expr'](); const opsSigns = []; for (let child of ops.children) { // TODO: validate op is in ast.MathOperators opsSigns.push(child.sourceString); } const rightExprs = []; for (let child of rights.children) { const rightExpr = child['expr'](); if (rightExpr !== undefined) { rightExprs.push(rightExpr); } } if (opsSigns.length !== rightExprs.length) { throw new Error('Invalid math operation'); // should not happen } if (opsSigns.length === 0) { // This is not a math expr, just the left part return (0, locations_1.withLocations)(leftExpr, left); } // We always use the left part for all the math expressions, // it should be fine for now. let expr = (0, locations_1.withLocations)(new ast.MathExpr(leftExpr, opsSigns[0], rightExprs[0]), left); for (let index = 1; index < opsSigns.length; index++) { expr = (0, locations_1.withLocations)(new ast.MathExpr(expr, opsSigns[index], // validated earlier rightExprs[index]), left); } return expr; }