CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-peggy

Parser generator for JavaScript that produces fast parsers with excellent error reporting capabilities

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

parser-generation.mddocs/

Parser Generation

Core functionality for generating parsers from PEG grammars. The generate function is the main entry point for all parser generation operations, providing multiple output formats and extensive configuration options.

Capabilities

Generate Parser Function

The primary function for creating parsers from PEG grammar definitions. Supports multiple output formats including parser objects, source code, and ASTs.

/**
 * Returns a generated parser object (default behavior)
 * @param grammar - PEG grammar string or array of source texts
 * @param options - Parser build options
 * @returns Parser object ready for parsing input
 * @throws {SyntaxError} If grammar contains syntax errors
 * @throws {GrammarError} If grammar contains semantic errors
 */
function generate(
  grammar: GrammarInput,
  options?: ParserBuildOptions
): Parser;

/**
 * Returns the generated source code as a string
 * @param grammar - PEG grammar string or array of source texts
 * @param options - Source build options with output: "source"
 * @returns Generated parser source code
 */
function generate(
  grammar: GrammarInput,
  options: SourceBuildOptions<"source">
): string;

/**
 * Returns source code with embedded source map as data URI
 * @param grammar - PEG grammar string or array of source texts
 * @param options - Source build options with output: "source-with-inline-map"
 * @returns Generated parser source code with inline source map
 */
function generate(
  grammar: GrammarInput,
  options: SourceBuildOptions<"source-with-inline-map">
): string;

/**
 * Returns SourceNode object with source code and source map
 * @param grammar - PEG grammar string or array of source texts
 * @param options - Source build options with output: "source-and-map"
 * @returns SourceNode object for generating code and source maps
 */
function generate(
  grammar: GrammarInput,
  options: SourceBuildOptions<"source-and-map">
): SourceNode;

/**
 * Returns the processed grammar AST
 * @param grammar - PEG grammar string or array of source texts
 * @param options - Source build options with output: "ast"
 * @returns Processed grammar AST with all compilation passes applied
 */
function generate(
  grammar: GrammarInput,
  options: SourceOptionsBase<"ast">
): ast.Grammar;

Usage Examples:

import { generate } from "peggy";
import { SourceNode } from "source-map-generator"; // Required for source-and-map output

// Basic parser generation
const grammar = `
  start = "hello" " " name:[a-z]+ { return "Hello, " + name.join(""); }
`;

// Generate parser object (default)
const parser = generate(grammar);
const result = parser.parse("hello world"); // "Hello, world"

// Generate source code string
const sourceCode = generate(grammar, { output: "source" });
console.log(sourceCode); // Generated JavaScript code

// Generate with source maps
const sourceWithMap = generate(grammar, {
  output: "source-and-map",
  grammarSource: "my-grammar.peggy"
});
const { code, map } = sourceWithMap.toStringWithSourceMap();

// Generate AST for inspection
const ast = generate(grammar, { output: "ast" });
console.log(ast.rules); // Grammar rules

Advanced Parser Options

Configure parser generation with extensive options for caching, start rules, plugins, and output formats.

/**
 * Parser build options for generating parser objects
 */
interface ParserBuildOptions extends BuildOptionsBase {
  /** Output format - defaults to "parser" */
  output?: "parser";
}

/**
 * Source build options for generating source code
 */
interface SourceBuildOptions<Output extends SourceOutputs = "source"> extends BuildOptionsBase {
  /** Output format */
  output: Output;
  /** Module format for generated code */
  format?: "amd" | "bare" | "commonjs" | "es" | "globals" | "umd";
  /** Module dependencies mapping */
  dependencies?: Dependencies;
  /** Global variable name for "globals" and "umd" formats */
  exportVar?: string;
}

/**
 * Base build options shared by all generation modes
 */
interface BuildOptionsBase {
  /** Rules allowed as start rules (default: first rule) */
  allowedStartRules?: string[];
  /** Enable result caching to avoid exponential parsing time */
  cache?: boolean;
  /** Source identifier for error reporting and source maps */
  grammarSource?: any;
  /** Plugins to extend compilation process */
  plugins?: Plugin[];
  /** Enable parse tracing for debugging */
  trace?: boolean;
  /** Error callback for compilation diagnostics */
  error?: DiagnosticCallback;
  /** Warning callback for compilation diagnostics */
  warning?: DiagnosticCallback;
  /** Info callback for compilation diagnostics */
  info?: DiagnosticCallback;
  /** Override default reserved words */
  reservedWords?: string[];
}

/**
 * Module dependencies for AMD, CommonJS, ES, and UMD formats
 */
interface Dependencies {
  [variable: string]: string;
}

/**
 * Grammar input types
 */
type GrammarInput = SourceText[] | string;

/**
 * Source text entry with source identifier
 */
interface SourceText {
  source: any;
  text: string;
}

/**
 * Available output formats
 */
type SourceOutputs = "parser" | "source-and-map" | "source-with-inline-map" | "source" | "ast";

Advanced Usage Examples:

import { generate } from "peggy";

// Multiple start rules
const parser = generate(grammar, {
  allowedStartRules: ["expression", "statement", "program"]
});

// Enable caching for complex grammars
const cachedParser = generate(complexGrammar, {
  cache: true
});

// CommonJS module generation
const commonjsCode = generate(grammar, {
  output: "source",
  format: "commonjs",
  dependencies: {
    "utils": "./utils",
    "lodash": "lodash"
  }
});

// ES module generation
const esmCode = generate(grammar, {
  output: "source",
  format: "es",
  dependencies: {
    "validator": "./validator.js"
  }
});

// UMD with global variable
const umdCode = generate(grammar, {
  output: "source",
  format: "umd",
  exportVar: "MyParser"
});

// With plugins and diagnostics
const parserWithPlugin = generate(grammar, {
  plugins: [myPlugin],
  trace: true,
  error: (stage, message, location) => console.error(`${stage}: ${message}`),
  warning: (stage, message, location) => console.warn(`${stage}: ${message}`)
});

Plugin System

Extend Peggy's compilation process with custom plugins that can modify parser behavior, add new passes, or customize code generation.

/**
 * Plugin interface for extending Peggy
 */
interface Plugin {
  /**
   * Called during parser generation to configure compilation
   * @param config - Mutable configuration object
   * @param options - Build options passed to generate()
   */
  use(config: Config, options: ParserBuildOptions): void;
}

/**
 * Plugin configuration object
 */
interface Config {
  /** Parser object for grammar parsing */
  parser: Parser;
  /** Compilation passes by stage */
  passes: Stages;
  /** Reserved words list */
  reservedWords: string[];
}

/**
 * Compilation stages with their passes
 */
interface Stages {
  /** Preparation passes (linking, etc.) */
  prepare: Pass[];
  /** Validation passes */
  check: Pass[];
  /** AST transformation passes */
  transform: Pass[];
  /** Semantic analysis passes */
  semantic: Pass[];
  /** Code generation passes */
  generate: Pass[];
}

/**
 * Compilation pass function
 */
type Pass = (
  ast: ast.Grammar,
  options: ParserBuildOptions,
  session: Session
) => void;

/**
 * Compilation session for error reporting
 */
interface Session {
  problems: Problem[];
  error(message: string, location?: LocationRange, notes?: DiagnosticNote[]): void;
  warning(message: string, location?: LocationRange, notes?: DiagnosticNote[]): void;
  info(message: string, location?: LocationRange, notes?: DiagnosticNote[]): void;
}

Plugin Usage Example:

import { generate } from "peggy";

// Custom plugin that logs compilation stages
const loggingPlugin = {
  use(config, options) {
    // Add custom pass to transform stage
    config.passes.transform.push((ast, options, session) => {
      session.info(`Processing ${ast.rules.length} rules`);
    });
    
    // Modify reserved words
    config.reservedWords.push("myReservedWord");
  }
};

const parser = generate(grammar, {
  plugins: [loggingPlugin],
  info: (stage, message) => console.log(`[${stage}] ${message}`)
});

Error Handling

Comprehensive error handling with detailed location information and multiple error types.

/**
 * Grammar semantic error
 */
class GrammarError extends SyntaxError {
  /** Error location in grammar */
  location?: LocationRange;
  /** Additional diagnostic notes */
  diagnostics: DiagnosticNote[];
  /** Compilation stage where error occurred */
  stage: Stage | null;
  /** All problems from compilation session */
  problems: Problem[];
  
  /**
   * Format error with source context
   * @param sources - Mapping from source to text for formatting
   * @returns Formatted error message with source context
   */
  format(sources: SourceText[]): string;
}

/**
 * Diagnostic callback for compilation messages
 */
type DiagnosticCallback = (
  stage: Stage,
  message: string,
  location?: LocationRange,
  notes?: DiagnosticNote[]
) => void;

/**
 * Diagnostic note with location
 */
interface DiagnosticNote {
  message: string;
  location: LocationRange;
}

/**
 * Problem tuple from compilation
 */
type Problem = [
  severity: "error" | "info" | "warning",
  message: string,
  location?: LocationRange,
  diagnostics?: DiagnosticNote[]
];

/**
 * SourceNode from source-map-generator package (separate dependency)
 * Used for source-and-map output format
 */
interface SourceNode {
  toStringWithSourceMap(options?: { file?: string }): { code: string; map: any };
  toString(): string;
}

Error Handling Example:

import { generate, GrammarError } from "peggy";

try {
  const parser = generate("invalid grammar syntax @#$");
} catch (error) {
  if (error instanceof GrammarError) {
    console.log("Grammar error:", error.message);
    console.log("Location:", error.location);
    console.log("Stage:", error.stage);
    
    // Format with source context
    const formatted = error.format([{
      source: "my-grammar.peggy",
      text: "invalid grammar syntax @#$"
    }]);
    console.log(formatted);
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-peggy

docs

ast-compilation.md

cli.md

generated-parsers.md

grammar-parsing.md

index.md

parser-generation.md

tile.json