UNPKG

@scinorandex/sparse

Version:

Yet another parser generator

73 lines 3.92 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildProductions = exports.tryBuildProductions = exports.grammarLexerGenerator = exports.GrammarTokenType = void 0; const slex_1 = require("@scinorandex/slex"); var GrammarTokenType; (function (GrammarTokenType) { GrammarTokenType[GrammarTokenType["PRODUCTION_NAME"] = 0] = "PRODUCTION_NAME"; GrammarTokenType[GrammarTokenType["TOKEN_NAME"] = 1] = "TOKEN_NAME"; GrammarTokenType[GrammarTokenType["COLON"] = 2] = "COLON"; GrammarTokenType[GrammarTokenType["SEMICOLON"] = 3] = "SEMICOLON"; GrammarTokenType[GrammarTokenType["EOF"] = 4] = "EOF"; })(GrammarTokenType || (exports.GrammarTokenType = GrammarTokenType = {})); exports.grammarLexerGenerator = new slex_1.Slex({ EOF_TYPE: GrammarTokenType.EOF, isHigherPrecedence: () => false, }); exports.grammarLexerGenerator.addRule("lowercase", "a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x | y | z"); exports.grammarLexerGenerator.addRule("uppercase", "A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z"); exports.grammarLexerGenerator.addRule("letter", "${lowercase} | ${uppercase}"); exports.grammarLexerGenerator.addRule("digit", "0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9"); exports.grammarLexerGenerator.addRule("alphanumeric", "${letter} | ${digit}"); exports.grammarLexerGenerator.addRule("identifier", "(${letter} | ${digit} | $_)*"); exports.grammarLexerGenerator.addRule("colon", "$:", GrammarTokenType.COLON); exports.grammarLexerGenerator.addRule("semicolon", "$;", GrammarTokenType.SEMICOLON); exports.grammarLexerGenerator.addRule("production_name", "$< ${identifier} $>", GrammarTokenType.PRODUCTION_NAME); exports.grammarLexerGenerator.addRule("token_name", "$[ ${identifier} $]", GrammarTokenType.TOKEN_NAME); const tryBuildProductions = (lexer) => { if (typeof lexer === "string") lexer = exports.grammarLexerGenerator.generate(lexer, () => ({})); const productions = []; const expect = (type) => { const token = lexer.peekNextToken(); if (token.type !== type) throw new Error(`Expected ${type}, got ${token.type}`); lexer.getNextToken(); }; const buildProduction = () => { const productionLHS = lexer.getNextToken(); expect(GrammarTokenType.COLON); const production = { lhs: productionLHS, rhs: [] }; while (lexer.peekNextToken().type != GrammarTokenType.SEMICOLON) { const productionRHS = lexer.getNextToken(); if (productionRHS.type == GrammarTokenType.PRODUCTION_NAME) production.rhs.push({ type: "variable", token: productionRHS }); else if (productionRHS.type == GrammarTokenType.TOKEN_NAME) production.rhs.push({ type: "terminal", token: productionRHS }); else return { success: false, reason: `Unexpected token type: ${GrammarTokenType[productionRHS.type]}`, token: productionRHS, }; } expect(GrammarTokenType.SEMICOLON); return { success: true, value: production }; }; while (lexer.hasNextToken()) { const result = buildProduction(); if (result.success === false) return result; productions.push(result.value); } return { success: true, value: productions }; }; exports.tryBuildProductions = tryBuildProductions; const buildProductions = (lexer) => { const result = (0, exports.tryBuildProductions)(lexer); if (result.success === false) throw new Error(`Encountered error "${result.reason}" while parsing grammar at ${result.token.line}:${result.token.column}`); return result.value; }; exports.buildProductions = buildProductions; //# sourceMappingURL=grammarParser.js.map