UNPKG

bhai-lang-parser

Version:
690 lines (660 loc) 24 kB
var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __markAsModule = (target) => __defProp(target, "__esModule", { value: true }); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __reExport = (target, module2, copyDefault, desc) => { if (module2 && typeof module2 === "object" || typeof module2 === "function") { for (let key of __getOwnPropNames(module2)) if (!__hasOwnProp.call(target, key) && (copyDefault || key !== "default")) __defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable }); } return target; }; var __toCommonJS = /* @__PURE__ */ ((cache) => { return (module2, temp) => { return cache && cache.get(module2) || (temp = __reExport(__markAsModule({}), module2, 1), cache && cache.set(module2, temp), temp); }; })(typeof WeakMap !== "undefined" ? /* @__PURE__ */ new WeakMap() : 0); // src/components/parser/statement/expression/identifier_expression.ts var identifier_expression_exports = {}; __export(identifier_expression_exports, { default: () => IdentifierExpression }); // src/constants/constants.ts var NodeType = { AdditiveExpression: "AdditiveExpression", MultiplicativeExpression: "MultiplicativeExpression", PrimaryExpression: "PrimaryExpression", ParanthesizedExpression: "ParanthesizedExpression", IdentifierExpression: "IdentifierExpression", AssignmentExpression: "AssignmentExpression", BinaryExpression: "BinaryExpression", BlockStatement: "BlockStatement", EmptyStatement: "EmptyStatement", ExpressionStatement: "ExpressionStatement", InitStatement: "InitStatement", PrintStatement: "PrintStatement", VariableStatement: "VariableStatement", BooleanLiteral: "BooleanLiteral", NumericLiteral: "NumericLiteral", StringLiteral: "StringLiteral", NullLiteral: "NullLiteral", VariableDeclaration: "VariableDeclaration", Program: "Program" }; // src/components/parser/index.ts var Parser = class { constructor(tokenizer, program, tokenExecutor) { this._tokenizer = tokenizer; this._program = program; this._tokenExecutor = tokenExecutor; this._stringToTokenize = ""; } parse(stringToTokenize) { this._stringToTokenize = stringToTokenize; this._tokenizer.initTokenizer(this._stringToTokenize); this._tokenExecutor.setLookahead(this._tokenizer.getNextToken()); return this._program.getProgram(); } }; // src/components/parser/program.ts var Program = class { constructor(statementList) { this._statementList = statementList; } getProgram() { return { type: NodeType.Program, body: this._statementList.getInitialStatementList() }; } }; // src/constants/bhaiLangSpec.ts var TokenTypes = { NULL_TYPE: null, HI_BHAI_TYPE: "hi bhai", BYE_BHAI_TYPE: "bye bhai", BOL_BHAI_TYPE: "bol bhai", BHAI_YE_HAI_TYPE: "bhai ye hai", SEMI_COLON_TYPE: ";", OPEN_CURLY_BRACE_TYPE: "{", CLOSED_CURLY_BRACE_TYPE: "}", OPEN_PARENTHESIS_TYPE: "(", CLOSED_PARENTHESIS_TYPE: ")", COMMA_TYPE: ",", NUMBER_TYPE: "NUMBER", IDENTIFIER_TYPE: "IDENTIFIER", SIMPLE_ASSIGN_TYPE: "SIMPLE_ASSIGN", COMPLEX_ASSIGN_TYPE: "COMPLEX_ASSIGN", ADDITIVE_OPERATOR_TYPE: "ADDITIVE_OPERATOR", MULTIPLICATIVE_OPERATOR_TYPE: "MULTIPLICATIVE_OPERATOR", STRING_TYPE: "STRING", BOOLEAN_TYPE: "BOOLEAN" }; var SPEC = [ { regex: /^\s+/, tokenType: TokenTypes.NULL_TYPE }, { regex: /^\/\/.*/, tokenType: TokenTypes.NULL_TYPE }, { regex: /^\/\*[\s\S]*?\*\//, tokenType: TokenTypes.NULL_TYPE }, { regex: /^;/, tokenType: TokenTypes.SEMI_COLON_TYPE }, { regex: /^\{/, tokenType: TokenTypes.OPEN_CURLY_BRACE_TYPE }, { regex: /^\}/, tokenType: TokenTypes.CLOSED_CURLY_BRACE_TYPE }, { regex: /^\(/, tokenType: TokenTypes.OPEN_PARENTHESIS_TYPE }, { regex: /^\)/, tokenType: TokenTypes.CLOSED_PARENTHESIS_TYPE }, { regex: /^,/, tokenType: TokenTypes.COMMA_TYPE }, { regex: /^\bhi bhai\b/, tokenType: TokenTypes.HI_BHAI_TYPE }, { regex: /^\bbye bhai\b/, tokenType: TokenTypes.BYE_BHAI_TYPE }, { regex: /^\bbol bhai\b/, tokenType: TokenTypes.BOL_BHAI_TYPE }, { regex: /^\bbhai ye hai\b/, tokenType: TokenTypes.BHAI_YE_HAI_TYPE }, { regex: /^\d+/, tokenType: TokenTypes.NUMBER_TYPE }, { regex: /^sahi/, tokenType: TokenTypes.BOOLEAN_TYPE }, { regex: /^galat/, tokenType: TokenTypes.BOOLEAN_TYPE }, { regex: /^\w+/, tokenType: TokenTypes.IDENTIFIER_TYPE }, { regex: /^=/, tokenType: TokenTypes.SIMPLE_ASSIGN_TYPE }, { regex: /^[\*\/\+\-]=/, tokenType: TokenTypes.COMPLEX_ASSIGN_TYPE }, { regex: /^[+\-]/, tokenType: TokenTypes.ADDITIVE_OPERATOR_TYPE }, { regex: /^[*\/]/, tokenType: TokenTypes.MULTIPLICATIVE_OPERATOR_TYPE }, { regex: /^"[^"]*"/, tokenType: TokenTypes.STRING_TYPE }, { regex: /^'[^']*'/, tokenType: TokenTypes.STRING_TYPE } ]; // src/components/parser/statement/index.ts var Statement = class { constructor(tokenExecutor) { this._tokenExecutor = tokenExecutor; } static getStatementImpl(lookahead) { switch (lookahead.type) { case TokenTypes.BOL_BHAI_TYPE: return BhaiLangModule.getPrintStatement(); case TokenTypes.SEMI_COLON_TYPE: return BhaiLangModule.getEmptyStatement(); case TokenTypes.OPEN_CURLY_BRACE_TYPE: return BhaiLangModule.getBlockStatement(); case TokenTypes.BHAI_YE_HAI_TYPE: return BhaiLangModule.getVariableStatement(); default: return BhaiLangModule.getExpressionStatement(); } } }; // src/components/parser/statement/blockStatement.ts var BlockStatement = class extends Statement { constructor(tokenExecutor, statementList) { super(tokenExecutor); this._statementList = statementList; } getStatement() { var _a; this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.OPEN_CURLY_BRACE_TYPE); const body = ((_a = this._tokenExecutor.getLookahead()) == null ? void 0 : _a.type) === TokenTypes.CLOSED_CURLY_BRACE_TYPE ? [] : this._statementList.getStatementList(TokenTypes.CLOSED_CURLY_BRACE_TYPE); this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.CLOSED_CURLY_BRACE_TYPE); return { type: NodeType.BlockStatement, body }; } }; // src/components/parser/statement/emptyStatement.ts var EmptyStatement = class extends Statement { getStatement() { this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.SEMI_COLON_TYPE); return { type: NodeType.EmptyStatement }; } }; // src/components/parser/statement/expression/addititve_expression.ts var AdditiveExpression = class extends Expression { getExpression() { return this.getBinaryExpression(NodeType.MultiplicativeExpression, TokenTypes.ADDITIVE_OPERATOR_TYPE); } }; // src/components/parser/statement/expression/assignment_expression.ts var AssignmentExpression = class extends Expression { constructor() { super(...arguments); this._additiveExpression = Expression.getExpressionImpl(NodeType.AdditiveExpression); } getExpression() { var _a; const left = this._additiveExpression.getExpression(); if (!this._isAssignmentOperator((_a = this._tokenExecutor.getLookahead()) == null ? void 0 : _a.type)) { return left; } return { type: NodeType.AssignmentExpression, operator: this._getAssignmentOperator().value, left: this._checkValidAssignmentTarget(left), right: this.getExpression() }; } _isAssignmentOperator(tokenType) { return tokenType && (tokenType === TokenTypes.SIMPLE_ASSIGN_TYPE || tokenType === TokenTypes.COMPLEX_ASSIGN_TYPE); } _getAssignmentOperator() { const lookahead = this._tokenExecutor.getLookahead(); if (!lookahead || lookahead.type === TokenTypes.SIMPLE_ASSIGN_TYPE) return this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.SIMPLE_ASSIGN_TYPE); return this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.COMPLEX_ASSIGN_TYPE); } _checkValidAssignmentTarget(node) { if (node.type === NodeType.IdentifierExpression) return node; throw new SyntaxError("Invalid left hand side in assignment expression"); } }; // src/components/parser/statement/expression/literals/index.ts var Literal = class { constructor(tokenExecutor) { this._tokenExecutor = tokenExecutor; } static getLiteralImpl(tokenType) { switch (tokenType) { case TokenTypes.NUMBER_TYPE: return BhaiLangModule.getNumericLiteral(); case TokenTypes.BOOLEAN_TYPE: return BhaiLangModule.getBooleanLiteral(); default: return BhaiLangModule.getStringLiteral(); } } }; // src/components/parser/statement/expression/literals/boolean_literal.ts var BooleanLiteral = class extends Literal { getLiteral() { const token = this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.BOOLEAN_TYPE); return { type: NodeType.BooleanLiteral, value: token.value }; } }; // src/components/parser/statement/expression/literals/null_literal.ts var NullLiteral = class extends Literal { getLiteral() { return { type: NodeType.NullLiteral, value: null }; } }; // src/components/parser/statement/expression/literals/numeric_literal.ts var NumericLiteral = class extends Literal { getLiteral() { const token = this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.NUMBER_TYPE); return { type: NodeType.NumericLiteral, value: Number(token.value) }; } }; // src/components/parser/statement/expression/literals/string_literal.ts var StringLiteral = class extends Literal { getLiteral() { const token = this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.STRING_TYPE); return { type: NodeType.StringLiteral, value: token.value.slice(1, -1) }; } }; // src/components/parser/statement/expression/multiplicative_expression.ts var MultiplicativeExpression = class extends Expression { getExpression() { return this.getBinaryExpression(NodeType.PrimaryExpression, TokenTypes.MULTIPLICATIVE_OPERATOR_TYPE); } }; // src/components/parser/statement/expression/paranthesized_expression.ts var ParanthesizedExpression = class extends Expression { getExpression() { this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.OPEN_PARENTHESIS_TYPE); const expression = Expression.getExpressionImpl(NodeType.AdditiveExpression).getExpression(); this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.CLOSED_PARENTHESIS_TYPE); return expression; } }; // src/components/parser/statement/expression/primary_expression.ts var PrimaryExpression = class extends Expression { getExpression() { const token = this._tokenExecutor.getLookahead(); switch (token == null ? void 0 : token.type) { case TokenTypes.OPEN_PARENTHESIS_TYPE: return Expression.getExpressionImpl(NodeType.ParanthesizedExpression).getExpression(); case TokenTypes.STRING_TYPE: case TokenTypes.NUMBER_TYPE: case TokenTypes.BOOLEAN_TYPE: return Literal.getLiteralImpl(token.type).getLiteral(); default: return this._getLeftHandSideExpression(); } } _getLeftHandSideExpression() { return Expression.getExpressionImpl(NodeType.IdentifierExpression).getExpression(); } }; // src/components/parser/statement/expressionStatement.ts var ExpressionStatement = class extends Statement { getStatement() { const expression = Expression.getExpressionImpl(NodeType.AssignmentExpression).getExpression(); this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.SEMI_COLON_TYPE); return { type: NodeType.ExpressionStatement, expression }; } }; // src/components/parser/statement/initStatement.ts var InitStatement = class extends Statement { constructor(tokenExecutor, statementList) { super(tokenExecutor); this._statementList = statementList; } getStatement() { var _a; this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.HI_BHAI_TYPE); const body = ((_a = this._tokenExecutor.getLookahead()) == null ? void 0 : _a.type) !== TokenTypes.BYE_BHAI_TYPE ? this._statementList.getStatementList(TokenTypes.BYE_BHAI_TYPE) : []; this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.BYE_BHAI_TYPE); return { type: NodeType.InitStatement, body }; } }; // src/components/parser/statement/printStatement.ts var PrintStatement = class extends Statement { getStatement() { this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.BOL_BHAI_TYPE); const expressions = this._getExpressionList(); this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.SEMI_COLON_TYPE); return { type: NodeType.PrintStatement, expressions }; } _getExpressionList() { var _a; const expressions = []; do { expressions.push(this._getExpression()); } while (((_a = this._tokenExecutor.getLookahead()) == null ? void 0 : _a.type) === TokenTypes.COMMA_TYPE && this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.COMMA_TYPE)); return expressions; } _getExpression() { return Expression.getExpressionImpl(NodeType.AdditiveExpression).getExpression(); } }; // src/components/parser/statement/variableStatement.ts var VariableStatement = class extends Statement { constructor(tokenExecutor, nullLiteral) { super(tokenExecutor); this._nullLiteral = nullLiteral; } getStatement() { this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.BHAI_YE_HAI_TYPE); const declarations = this._getVariableDeclarationList(); this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.SEMI_COLON_TYPE); return { type: NodeType.VariableStatement, declarations }; } _getVariableDeclarationList() { var _a; const declarations = []; do { declarations.push(this._getVariableDeclaration()); } while (((_a = this._tokenExecutor.getLookahead()) == null ? void 0 : _a.type) === TokenTypes.COMMA_TYPE && this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.COMMA_TYPE)); return declarations; } _getVariableDeclaration() { var _a, _b; const id = Expression.getExpressionImpl(NodeType.IdentifierExpression).getExpression(); const init = ((_a = this._tokenExecutor.getLookahead()) == null ? void 0 : _a.type) !== TokenTypes.SEMI_COLON_TYPE && ((_b = this._tokenExecutor.getLookahead()) == null ? void 0 : _b.type) !== TokenTypes.COMMA_TYPE ? this._getVariableInitializer() : this._nullLiteral.getLiteral(); return { type: NodeType.VariableDeclaration, id, init }; } _getVariableInitializer() { this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.SIMPLE_ASSIGN_TYPE); return Expression.getExpressionImpl(NodeType.AssignmentExpression).getExpression(); } }; // src/components/parser/statementList.ts var StatementList = class { constructor(tokenExecutor) { this._tokenExecutor = tokenExecutor; } getInitialStatementList() { for (let lookahead = this._tokenExecutor.getLookahead(); lookahead !== null && lookahead.type !== TokenTypes.HI_BHAI_TYPE; lookahead = this._tokenExecutor.getLookahead()) { this._tokenExecutor.eatTokenAndForwardLookahead(lookahead.type); } return BhaiLangModule.getInitStatement().getStatement(); } getStatementList(stopLookaheadType) { const statementlist = []; for (let lookahead = this._tokenExecutor.getLookahead(); lookahead !== null && lookahead.type !== stopLookaheadType; lookahead = this._tokenExecutor.getLookahead()) { statementlist.push(Statement.getStatementImpl(lookahead).getStatement()); } return statementlist; } }; // src/components/parser/tokenExecutor.ts var TokenExecutor = class { constructor(tokenizer) { this._lookahead = null; this._tokenizer = tokenizer; } eatTokenAndForwardLookahead(tokenType) { const token = this._lookahead; if (token == null) { throw new SyntaxError(`Unexpected end of input, expected : "${tokenType}"`); } if (token.type !== tokenType) { throw new SyntaxError(`Unexpected token: "${token.value}", expected : "${tokenType}"`); } this.setLookahead(this._tokenizer.getNextToken()); return token; } getLookahead() { return this._lookahead; } setLookahead(lookahead) { this._lookahead = lookahead; } }; // src/exceptions/invalidStateException.ts var InvalidStateException = class extends Error { constructor(errorMessage) { super(errorMessage); this.name = this.constructor.name; this.message = errorMessage; } }; // src/components/tokenizer/index.ts var TokenizerImpl = class { constructor(spec) { this._string = void 0; this._spec = spec; this._cursor = 0; } initTokenizer(stringToTokenize) { this._string = stringToTokenize; this._cursor = 0; } isEOF() { if (!this._string) return true; return this._cursor === this._string.length; } hasMoreTokens() { if (!this._string) return false; return this._cursor < this._string.length; } getNextToken() { if (!this._string) throw new InvalidStateException("Tokenizer is not initialized with string. Please call initTokenizer method first."); if (!this.hasMoreTokens()) { return null; } const string = this._string.slice(this._cursor); for (const { regex, tokenType } of this._spec) { const tokenValue = this._matched(regex, string); if (tokenValue === null) { continue; } if (tokenType === null) { return this.getNextToken(); } return { type: tokenType, value: tokenValue }; } throw new SyntaxError(`Unexpected token: "${string[0]}"`); } _matched(regex, string) { const matched = regex.exec(string); if (matched === null) { return null; } this._cursor += matched[0].length; return matched[0]; } }; // src/module/bhaiLangModule.ts var BhaiLangModule = class { static getTokenizer() { if (!this._tokenizer) this._tokenizer = new TokenizerImpl(SPEC); return this._tokenizer; } static getTokenExecutor() { if (!this._tokenExecutor) this._tokenExecutor = new TokenExecutor(this.getTokenizer()); return this._tokenExecutor; } static getStatementList() { if (!this._statementList) this._statementList = new StatementList(this.getTokenExecutor()); return this._statementList; } static getInitStatement() { if (!this._initStatement) this._initStatement = new InitStatement(this.getTokenExecutor(), this.getStatementList()); return this._initStatement; } static getPrintStatement() { if (!this._printStatement) { this._printStatement = new PrintStatement(this.getTokenExecutor()); } return this._printStatement; } static getExpressionStatement() { if (!this._expresionStatement) { this._expresionStatement = new ExpressionStatement(this.getTokenExecutor()); } return this._expresionStatement; } static getEmptyStatement() { if (!this._emptyStatement) { this._emptyStatement = new EmptyStatement(this.getTokenExecutor()); } return this._emptyStatement; } static getBlockStatement() { if (!this._blockStatement) { this._blockStatement = new BlockStatement(this.getTokenExecutor(), this.getStatementList()); } return this._blockStatement; } static getVariableStatement() { if (!this._variableStatement) this._variableStatement = new VariableStatement(this.getTokenExecutor(), this.getNullLiteral()); return this._variableStatement; } static getAdditiveExpression() { if (!this._additiveExpression) { this._additiveExpression = new AdditiveExpression(this.getTokenExecutor()); } return this._additiveExpression; } static getMultiplicativeExpression() { if (!this._multiplicativeExpression) { this._multiplicativeExpression = new MultiplicativeExpression(this.getTokenExecutor()); } return this._multiplicativeExpression; } static getPrimaryExpression() { if (!this._primaryExpression) { this._primaryExpression = new PrimaryExpression(this.getTokenExecutor()); } return this._primaryExpression; } static getParanthesizedExpression() { if (!this._paranthesizedExpression) { this._paranthesizedExpression = new ParanthesizedExpression(this.getTokenExecutor()); } return this._paranthesizedExpression; } static getIndentifierExpression() { if (!this._idetifierExpression) this._idetifierExpression = new IdentifierExpression(this.getTokenExecutor()); return this._idetifierExpression; } static getAssignmentExpression() { if (!this._assignmentExpression) this._assignmentExpression = new AssignmentExpression(this.getTokenExecutor()); return this._assignmentExpression; } static getNumericLiteral() { if (!this._numericLiteral) { this._numericLiteral = new NumericLiteral(this.getTokenExecutor()); } return this._numericLiteral; } static getStringLiteral() { if (!this._stringLiteral) { this._stringLiteral = new StringLiteral(this.getTokenExecutor()); } return this._stringLiteral; } static getBooleanLiteral() { if (!this._booleanLiteral) { this._booleanLiteral = new BooleanLiteral(this.getTokenExecutor()); } return this._booleanLiteral; } static getNullLiteral() { if (!this._nullLiteral) { this._nullLiteral = new NullLiteral(this.getTokenExecutor()); } return this._nullLiteral; } static getProgram() { if (!this._program) this._program = new Program(this.getStatementList()); return this._program; } static getParser() { if (!this._parser) this._parser = new Parser(this.getTokenizer(), this.getProgram(), this.getTokenExecutor()); return this._parser; } }; // src/components/parser/statement/expression/index.ts var Expression = class { constructor(tokenExecutor) { this._tokenExecutor = tokenExecutor; } static getExpressionImpl(expressionType) { switch (expressionType) { case NodeType.AdditiveExpression: return BhaiLangModule.getAdditiveExpression(); case NodeType.MultiplicativeExpression: return BhaiLangModule.getMultiplicativeExpression(); case NodeType.PrimaryExpression: return BhaiLangModule.getPrimaryExpression(); case NodeType.ParanthesizedExpression: return BhaiLangModule.getParanthesizedExpression(); case NodeType.AssignmentExpression: return BhaiLangModule.getAssignmentExpression(); default: return BhaiLangModule.getIndentifierExpression(); } } getBinaryExpression(expressionType, operatorToken) { var _a; let left = Expression.getExpressionImpl(expressionType).getExpression(); while (((_a = this._tokenExecutor.getLookahead()) == null ? void 0 : _a.type) === operatorToken) { const operator = this._tokenExecutor.eatTokenAndForwardLookahead(operatorToken); const right = Expression.getExpressionImpl(expressionType).getExpression(); left = { type: NodeType.BinaryExpression, operator: operator.value, left, right }; } return left; } }; // src/components/parser/statement/expression/identifier_expression.ts var IdentifierExpression = class extends Expression { getExpression() { const name = this._tokenExecutor.eatTokenAndForwardLookahead(TokenTypes.IDENTIFIER_TYPE).value; return { type: NodeType.IdentifierExpression, name }; } }; module.exports = __toCommonJS(identifier_expression_exports); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = {});