CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-jison

A parser generator with Bison's API for creating bottom-up parsers from grammar definitions

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

parser-generation.mddocs/

Parser Generation

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.

Capabilities

Source Code Generation

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:

  • moduleName: Name for the generated parser (default: "parser")
  • moduleType: Format type - "commonjs", "amd", or "js" (default: "commonjs")
  • debug: Include debug information in generated code

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");

CommonJS Module Generation

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 instance
  • Parser - The parser constructor
  • parse - Convenience function that calls parser.parse
  • main - Main function for CLI usage

Usage 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);

AMD Module Generation

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);
// });

Plain JavaScript Generation

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);

Parser Runtime Interface

Generated parsers implement a consistent runtime interface regardless of the generation format.

Generated Parser Object

/**
 * 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
}

Runtime Usage

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);

Code Generation Options

Module Naming

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 parser

Debug Mode

Include 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 information

Custom Module Template

Advanced 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;
};

File Output Patterns

Single File Output

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);

Multiple File Output

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);

Performance Considerations

Table Compression

Jison automatically compresses parsing tables for optimal size:

  • Removes duplicate entries
  • Uses variable assignment for repeated patterns
  • Minimizes generated code size
  • Optimizes for V8 engine performance

Memory Usage

Generated parsers are optimized for memory efficiency:

  • Compact table representation
  • Shared action functions
  • Minimal runtime overhead
  • Efficient symbol mapping

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`);

Error Handling in Generated Parsers

Generated parsers include comprehensive error handling:

Parse Error Recovery

// 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"
}

Custom Error Handling

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}`);
};

docs

algorithm-selection.md

cli.md

grammar-processing.md

index.md

parser-creation.md

parser-generation.md

tile.json