@scinorandex/sparse
Version:
Yet another parser generator
73 lines • 3.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildProductions = exports.tryBuildProductions = exports.grammarLexerGenerator = void 0;
const slex_1 = require("@scinorandex/slex");
const common_1 = require("./common");
exports.grammarLexerGenerator = new slex_1.Slex({
EOF_TYPE: common_1.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", "$:", common_1.GrammarTokenType.COLON);
exports.grammarLexerGenerator.addRule("semicolon", "$;", common_1.GrammarTokenType.SEMICOLON);
exports.grammarLexerGenerator.addRule("production_name", "$< ${identifier} $>", common_1.GrammarTokenType.PRODUCTION_NAME);
exports.grammarLexerGenerator.addRule("token_name", "$[ ${identifier} $]", common_1.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();
};
let productionIndex = 0;
const buildProduction = () => {
const productionLHS = lexer.getNextToken();
expect(common_1.GrammarTokenType.COLON);
const production = {
lhs: productionLHS,
identifier: productionLHS.lexeme,
rhs: [],
name: null,
originalProductionIndex: productionIndex++,
};
while (lexer.peekNextToken().type != common_1.GrammarTokenType.SEMICOLON) {
const productionRHS = lexer.getNextToken();
if (productionRHS.type == common_1.GrammarTokenType.PRODUCTION_NAME)
production.rhs.push({ type: "variable", token: productionRHS, identifier: productionRHS.lexeme, name: null });
else if (productionRHS.type == common_1.GrammarTokenType.TOKEN_NAME)
production.rhs.push({ type: "terminal", token: productionRHS, identifier: productionRHS.lexeme, name: null });
else
return {
success: false,
reason: `Unexpected token type: ${common_1.GrammarTokenType[productionRHS.type]}`,
token: productionRHS,
};
}
expect(common_1.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=handwritten.js.map