A parser generator with Bison's API for creating bottom-up parsers from grammar definitions
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Code generation system that creates standalone parser modules in various formats (CommonJS, AMD, plain JavaScript) from processed grammars. The generated parsers are self-contained and can run independently of Jison.
Generate complete parser source code that can be saved to files and used independently.
/**
* Generate parser source code
* @param options - Generation options including module format and name
* @returns Generated parser source code as string
*/
generate(options);Options object properties:
Usage Examples:
const jison = require("jison");
const grammar = {
"lex": {
"rules": [["\\s+", ""], ["[a-zA-Z]+", "return 'WORD';"]]
},
"bnf": {
"list": [["list WORD", "$$ = $1 + ' ' + $2;"], ["WORD", "$$ = $1;"]]
}
};
const generator = new jison.Generator(grammar);
// Generate CommonJS module
const commonjsCode = generator.generate({
moduleName: "WordParser",
moduleType: "commonjs"
});
// Save to file
require('fs').writeFileSync('word-parser.js', commonjsCode);
// Use generated parser
const parser = require('./word-parser');
const result = parser.parse("hello world");Generate parser as a CommonJS module with exports for Node.js environments.
/**
* Generate CommonJS module source
* @param options - Module generation options
* @returns CommonJS module source code with exports
*/
generateCommonJSModule(options);Generated CommonJS modules export:
parser - The parser instanceParser - The parser constructorparse - Convenience function that calls parser.parsemain - Main function for CLI usageUsage Examples:
const generator = new jison.Generator(grammar);
const moduleCode = generator.generateCommonJSModule({
moduleName: "MyParser"
});
// Generated code can be used as:
// const { parse, Parser } = require('./my-parser');
// const result = parse(input);Generate parser as an AMD (Asynchronous Module Definition) module for browser environments with RequireJS.
/**
* Generate AMD module source
* @param options - AMD module generation options
* @returns AMD module source code
*/
generateAMDModule(options);Usage Examples:
const generator = new jison.Generator(grammar);
const amdCode = generator.generateAMDModule({
moduleName: "BrowserParser"
});
// Generated AMD module can be used as:
// define(['./browser-parser'], function(parser) {
// return parser.parse(input);
// });Generate parser as plain JavaScript that works in any environment.
/**
* Generate plain JavaScript module
* @param options - JavaScript generation options
* @returns Plain JavaScript parser code
*/
generateModule(options);Usage Examples:
const generator = new jison.Generator(grammar);
const jsCode = generator.generate({
moduleType: "js",
moduleName: "GlobalParser"
});
// Generated code creates a global variable that can be used as:
// var result = GlobalParser.parse(input);Generated parsers implement a consistent runtime interface regardless of the generation format.
/**
* Generated parser instance structure
*/
interface GeneratedParser {
/** Parse input string and return result or throw error */
parse(input: string): any;
/** Shared state object accessible in semantic actions */
yy: object;
/** Associated lexer instance (if lexer was generated) */
lexer?: Lexer;
/** Symbol name to number mapping */
symbols_: Record<string, number>;
/** Terminal number to name mapping */
terminals_: Record<number, string>;
/** Internal production rules representation */
productions_: Array<[number, number]>;
/** LR parsing table */
table: Array<Record<number, number | number[]>>;
/** Default actions by state */
defaultActions: Record<number, number[]>;
/** Handle parse errors */
parseError(str: string, hash: ErrorHash): void;
/** Semantic action execution function */
performAction(yytext: string, yyleng: number, yylineno: number,
yy: object, yystate: number, $$: any[], _$: any[]): any;
}
/**
* Token location information
*/
interface LocationInfo {
first_line: number; // Starting line number
last_line: number; // Ending line number
first_column: number; // Starting column number
last_column: number; // Ending column number
range?: [number, number]; // Character range in input
}
/**
* Parse error information
*/
interface ErrorHash {
text: string; // Matched text
token: string; // Terminal token
line: number; // Line number
loc: LocationInfo; // Location details
expected: string[]; // Expected tokens
recoverable: boolean; // Whether error is recoverable
}Generated parsers can be used immediately after generation:
// Create parser instance
const parser = generator.createParser();
// Parse input
try {
const result = parser.parse("2 + 3 * 4");
console.log("Parse result:", result);
} catch (error) {
console.error("Parse failed:", error.message);
if (error.hash) {
console.error("At line:", error.hash.line);
console.error("Expected:", error.hash.expected.join(", "));
}
}
// Access parser internals
console.log("Symbols:", Object.keys(parser.symbols_));
console.log("Productions:", parser.productions_.length);Control the name of the generated parser module and its components.
const options = {
moduleName: "Calculator", // Creates Calculator variable/export
moduleType: "commonjs"
};
const code = generator.generate(options);
// Generated code exports Calculator parserInclude additional debugging information in generated parsers.
const options = {
debug: true,
moduleType: "commonjs"
};
const debugCode = generator.generate(options);
// Generated parser includes:
// - Detailed error messages
// - State transition logging
// - Conflict resolution informationAdvanced users can customize the module generation template:
// Override module generation methods
const customGenerator = Object.create(jison.Generator.prototype);
customGenerator.generateModule = function(options) {
// Custom module generation logic
return customModuleTemplate;
};Generate complete self-contained parser in a single file:
const fs = require('fs');
const parser = new jison.Generator(grammar);
const code = parser.generate({ moduleType: 'commonjs' });
fs.writeFileSync('generated-parser.js', code);
// Use the generated parser
const generatedParser = require('./generated-parser');
const result = generatedParser.parse(input);For complex parsers, consider splitting into multiple files:
// Generate parser
const parserCode = generator.generate({ moduleType: 'commonjs' });
// Generate lexer separately if needed
const lexerCode = generator.lexer.generateModule();
fs.writeFileSync('parser.js', parserCode);
fs.writeFileSync('lexer.js', lexerCode);Jison automatically compresses parsing tables for optimal size:
Generated parsers are optimized for memory efficiency:
Monitoring generated parser size:
const code = generator.generate(options);
console.log(`Generated parser size: ${code.length} characters`);
console.log(`Estimated gzipped size: ~${Math.round(code.length * 0.3)} bytes`);Generated parsers include comprehensive error handling:
// Generated parsers can handle syntax errors
try {
const result = parser.parse("2 + + 3"); // Invalid syntax
} catch (error) {
console.log("Parse error:", error.message);
// "Parse error on line 1: Unexpected '+' at position 4"
}Override error handling in generated parsers:
const parser = generator.createParser();
parser.yy.parseError = function(str, hash) {
console.log("Custom error handler:", str);
throw new Error(`Parse failed: ${str}`);
};