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
CLI tool for generating parsers from grammar files with support for various output formats and parser algorithms. The CLI provides a convenient way to generate parsers without writing JavaScript code.
Install Jison globally to access the CLI:
npm install -g jisonBasic usage:
jison grammar.jison
jison grammar.jison lexer.jisonlex
jison --helpEntry point for the command-line interface that processes arguments and orchestrates parser generation.
/**
* Main CLI entry point
* @param opts - Command line options object
*/
function main(opts);The main function handles:
Command Line Options:
| Option | Short | Description | Default |
|---|---|---|---|
file | - | Grammar file path | - |
lexfile | - | Lexer file path (optional) | - |
--json | -j | Force JSON grammar format | Auto-detect |
--outfile | -o | Output filename | <input>.js |
--debug | -t | Enable debug mode | false |
--module-type | -m | Module format (commonjs, amd, js) | commonjs |
--parser-type | -p | Algorithm (lr0, slr, lalr, lr) | lalr |
--version | -V | Show version and exit | - |
Usage Examples:
# Generate parser from grammar file
jison calculator.jison
# Specify separate lexer file
jison grammar.jison lexer.jisonlex
# Custom output filename and module type
jison -o my-parser.js -m amd calculator.jison
# Use specific parser algorithm with debug output
jison -p lr -t calculator.jison
# Generate JSON grammar
jison -j calculator.json
# Process from stdin
echo "expr: NUM;" | jisonGenerate parser source code from processed grammar objects.
/**
* Generate parser source code from grammar object
* @param opts - Generation options from command line
* @param grammar - Parsed grammar object
* @returns Generated parser source code as string
*/
function generateParserString(opts, grammar);This function:
Usage Examples:
const cli = require("jison/lib/cli");
const grammar = {
"bnf": {
"expr": [["NUM", "return Number($1);"]]
}
};
const opts = {
"parser-type": "lalr",
"module-type": "commonjs",
"debug": false,
"moduleName": "Calculator"
};
const parserCode = cli.generateParserString(opts, grammar);
console.log(parserCode); // Complete parser sourceParse and process grammar and lexer files into internal grammar objects.
/**
* Process grammar and lexer files into grammar object
* @param file - Grammar file content as string
* @param lexFile - Lexer file content as string (optional)
* @param jsonMode - Whether to parse grammar as JSON
* @returns Processed grammar object ready for parser generation
*/
function processGrammars(file, lexFile, jsonMode);This function handles:
Usage Examples:
const cli = require("jison/lib/cli");
const fs = require("fs");
// Process Bison-style grammar
const grammarContent = fs.readFileSync("calculator.jison", "utf8");
const grammar = cli.processGrammars(grammarContent, null, false);
// Process JSON grammar with separate lexer
const jsonGrammar = fs.readFileSync("grammar.json", "utf8");
const lexerContent = fs.readFileSync("lexer.jisonlex", "utf8");
const combinedGrammar = cli.processGrammars(jsonGrammar, lexerContent, true);Bison-compatible grammar files with embedded lexer rules:
/* calculator.jison */
/* Lexical rules */
%lex
%%
\s+ /* skip whitespace */
[0-9]+("."[0-9]+)?\b return 'NUMBER'
"*" return '*'
"+" return '+'
"(" return '('
")" return ')'
<<EOF>> return 'EOF'
/lex
/* Grammar rules */
%left '+' '-'
%left '*' '/'
%%
expressions
: e EOF
{ return $1; }
;
e
: e '+' e
{ $$ = $1 + $3; }
| e '*' e
{ $$ = $1 * $3; }
| '(' e ')'
{ $$ = $2; }
| NUMBER
{ $$ = Number(yytext); }
;Generate parser:
jison calculator.jison
node calculator.js # Use the generated parserStructured JSON format for grammar definitions:
{
"lex": {
"rules": [
["\\s+", "/* skip whitespace */"],
["[0-9]+", "return 'NUMBER';"],
["\\+", "return '+';"],
["\\*", "return '*';"],
["\\(", "return '(';"],
["\\)", "return ')';"],
["$", "return 'EOF';"]
]
},
"bnf": {
"expressions": [["e EOF", "return $1;"]],
"e": [
["e + e", "$$ = $1 + $3;"],
["e * e", "$$ = $1 * $3;"],
["( e )", "$$ = $2;"],
["NUMBER", "$$ = Number(yytext);"]
]
},
"operators": [
["left", "+", "-"],
["left", "*", "/"]
]
}Generate parser:
jison --json calculator.jsonDedicated lexer files for complex tokenization:
/* lexer.jisonlex */
%%
\s+ /* skip whitespace */
"//".* /* skip comments */
[a-zA-Z_][a-zA-Z0-9_]* return 'IDENTIFIER'
[0-9]+ return 'NUMBER'
"+" return 'PLUS'
"*" return 'MULTIPLY'
"(" return 'LPAREN'
")" return 'RPAREN'
";" return 'SEMICOLON'
<<EOF>> return 'EOF'
%%Use with grammar:
jison grammar.jison lexer.jisonlex# Create calculator.jison
cat > calculator.jison << 'EOF'
%lex
%%
\s+ /* skip whitespace */
[0-9]+ return 'NUMBER'
"+" return '+'
"*" return '*'
"(" return '('
")" return ')'
<<EOF>> return 'EOF'
/lex
%%
expressions: e EOF { return $1; };
e: e '+' e { $$ = $1 + $3; }
| e '*' e { $$ = $1 * $3; }
| '(' e ')' { $$ = $2; }
| NUMBER { $$ = Number(yytext); }
;
EOF
# Generate parser
jison calculator.jison
# Test the parser
echo "console.log(require('./calculator').parse('2 + 3 * 4'))" | node
# Output: 14# Generate JSON parser with debug output
jison --debug --outfile json-parser.js --module-type commonjs json.jison
# Use in Node.js
cat > test.js << 'EOF'
const parser = require('./json-parser');
const result = parser.parse('{"name": "test", "value": 123}');
console.log(JSON.stringify(result, null, 2));
EOF
node test.js# Generate AMD module for browser use
jison --module-type amd --outfile browser-parser.js grammar.jison
# Use with RequireJS
cat > index.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
<script src="require.js"></script>
</head>
<body>
<script>
require(['./browser-parser'], function(parser) {
const result = parser.parse(inputString);
console.log(result);
});
</script>
</body>
</html>
EOFCommon error conditions and their resolutions:
# Invalid grammar syntax
jison invalid.jison
# Error: Could not parse jison grammar
# Missing lexer rules
jison grammar-without-lexer.jison
# Error: Lexical rules required
# Grammar conflicts
jison --debug conflicted.jison
# Shows detailed conflict information# Invalid parser type
jison --parser-type invalid grammar.jison
# Uses default LALR(1) algorithm
# Missing input file
jison
# Reads from stdin instead
# Invalid output directory
jison --outfile /invalid/path/parser.js grammar.jison
# Error: Cannot write to output file# File not found
jison nonexistent.jison
# Error: ENOENT: no such file or directory
# Permission denied
jison --outfile /root/parser.js grammar.jison
# Error: EACCES: permission denied
# Invalid JSON format
jison --json invalid.json
# Error: Could not parse jison grammarMakefile:
parser.js: grammar.jison
jison --outfile $@ $<
clean:
rm -f parser.js
.PHONY: cleannpm scripts:
{
"scripts": {
"build-parser": "jison --outfile lib/parser.js grammar/parser.jison",
"clean": "rm -f lib/parser.js"
}
}Webpack integration:
// webpack.config.js
const { execSync } = require('child_process');
module.exports = {
plugins: [
{
apply: (compiler) => {
compiler.hooks.beforeCompile.tap('JisonPlugin', () => {
execSync('jison --outfile src/parser.js grammar.jison');
});
}
}
]
};const cli = require("jison/lib/cli");
// Simulate command line arguments
const opts = {
file: "grammar.jison",
outfile: "generated-parser.js",
"module-type": "commonjs",
"parser-type": "lalr",
debug: false
};
try {
cli.main(opts);
console.log("Parser generated successfully");
} catch (error) {
console.error("Generation failed:", error.message);
}