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

grammar-parsing.mddocs/

Grammar Parsing

Low-level grammar parsing functionality for converting PEG grammar strings into Abstract Syntax Trees. The parser namespace provides direct access to Peggy's grammar parser and syntax error handling.

Capabilities

Parse Grammar Function

Parses PEG grammar definitions into AST representations for further processing by the compiler.

namespace parser {
  /**
   * Parses grammar and returns the grammar AST
   * @param grammar - Source text of the PEG grammar
   * @param options - Parser options for grammar parsing
   * @returns Grammar AST ready for compilation
   * @throws {SyntaxError} If grammar has incorrect syntax
   */
  function parse(grammar: string, options?: Options): ast.Grammar;
  
  /**
   * Parser options for grammar parsing
   */
  interface Options {
    /** Source identifier attached to LocationRange objects */
    grammarSource?: any;
    /** Words not allowed as label names */
    reservedWords: string[];
    /** Start rule - must be "Grammar" */
    startRule?: "Grammar";
  }
}

Usage Examples:

import { parser } from "peggy";

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

try {
  const ast = parser.parse(grammar, {
    reservedWords: ["function", "class", "var"],
    grammarSource: "my-grammar.peggy"
  });
  
  console.log(ast.rules.length); // Number of rules
  console.log(ast.rules[0].name); // "start"
} catch (error) {
  console.error("Parse error:", error.message);
}

Grammar Syntax Errors

Detailed syntax error reporting with location information and expectation details.

namespace parser {
  /**
   * Grammar syntax error with detailed location and expectation info
   */
  class SyntaxError extends globalThis.SyntaxError {
    /** Location where error occurred */
    location: LocationRange;
    /** Possible tokens expected at error location */
    expected: Expectation[] | null;
    /** Character found at error location */
    found: string | null;
    
    constructor(
      message: string,
      expected: Expectation[] | null,
      found: string | null,
      location: LocationRange
    );
    
    /**
     * Format error with source context
     * @param sources - Source text mapping for context
     * @returns Formatted error with source lines
     */
    format(sources: SourceText[]): string;
    
    /**
     * Build human-readable message from expectations
     * @param expected - Array of expected items
     * @param found - Text found instead of expected
     * @returns Human-readable error message
     */
    static buildMessage(expected: Expectation[], found: string): string;
  }
}

Error Handling Example:

import { parser } from "peggy";

try {
  const ast = parser.parse("start = @invalid", {
    reservedWords: [],
    grammarSource: "test.peggy"
  });
} catch (error) {
  if (error instanceof parser.SyntaxError) {
    console.log("Syntax error at line", error.location.start.line);
    console.log("Expected:", error.expected);
    console.log("Found:", error.found);
    
    // Format with source context
    const formatted = error.format([{
      source: "test.peggy",
      text: "start = @invalid"
    }]);
    console.log(formatted);
  }
}

Expectation Types

Different types of expectations that can appear in syntax errors, describing what the parser was looking for.

namespace parser {
  /**
   * Union of all expectation types
   */
  type Expectation = 
    | LiteralExpectation
    | ClassExpectation
    | AnyExpectation
    | EndExpectation
    | OtherExpectation;
  
  /**
   * Expected literal string
   */
  interface LiteralExpectation {
    type: "literal";
    /** Expected sequence of characters */
    text: string;
    /** If true, case-insensitive matching */
    ignoreCase: boolean;
  }
  
  /**
   * Expected character class
   */
  interface ClassExpectation {
    type: "class";
    /** Character ranges and individual characters */
    parts: (string[] | string)[];
    /** If true, negated character class */
    inverted: boolean;
    /** If true, case-insensitive matching */
    ignoreCase: boolean;
  }
  
  /**
   * Expected any character
   */
  interface AnyExpectation {
    type: "any";
  }
  
  /**
   * Expected end of input
   */
  interface EndExpectation {
    type: "end";
  }
  
  /**
   * Expected other item (from expected() or rule names)
   */
  interface OtherExpectation {
    type: "other";
    /** Human-readable description */
    description: string;
  }
}

AST Structure

The Abstract Syntax Tree structure returned by the parser, representing the complete grammar definition.

Grammar Node

The root node representing the entire grammar with all its components.

namespace ast {
  /**
   * Root grammar AST node
   */
  interface Grammar extends Node<"grammar"> {
    /** Imported external grammars */
    imports: GrammarImport[];
    /** Code executed once when importing parser module */
    topLevelInitializer?: TopLevelInitializer | TopLevelInitializer[];
    /** Code executed each time parse() is called */
    initializer?: Initializer | Initializer[];
    /** All rules in the grammar */
    rules: Rule[];
    
    // Added by compiler passes:
    /** Generated JavaScript code and source map */
    code?: SourceNode;
    /** String literals used in bytecode */
    literals?: string[];
    /** Character classes used in bytecode */
    classes?: GrammarCharacterClass[];
    /** Error expectations used in bytecode */
    expectations?: GrammarExpectation[];
    /** Imported names for library references */
    importedNames?: string[];
    /** User-defined functions (actions, predicates) */
    functions?: FunctionConst[];
    /** Location ranges used in bytecode */
    locations?: LocationRange[];
  }
  
  /**
   * Base AST node interface
   */
  interface Node<T> {
    /** Node type identifier */
    type: T;
    /** Source location of this node */
    location: LocationRange;
  }
}

Rule and Expression Types

Grammar rules and the various expression types that can appear in rule definitions.

namespace ast {
  /**
   * Grammar rule definition
   */
  interface Rule extends Expr<"rule"> {
    /** Rule identifier */
    name: string;
    /** Location of rule name for error reporting */
    nameLocation: LocationRange;
    /** Rule's parsing expression */
    expression: Expression | Named;
    /** Generated bytecode (added by compiler) */
    bytecode?: number[];
  }
  
  /**
   * Named rule expression
   */
  interface Named extends Expr<"named"> {
    /** Human-readable rule name for errors */
    name: string;
    /** Underlying expression */
    expression: Expression;
  }
  
  /**
   * Union of all expression types
   */
  type Expression =
    | Action
    | Choice
    | Labeled
    | Prefixed
    | Primary
    | Repeated
    | Sequence
    | Suffixed;
  
  /**
   * Base expression interface
   */
  interface Expr<T> extends Node<T> {
    /** Match result estimation (added by compiler) */
    match?: MatchResult;
  }
  
  /**
   * Match result enumeration
   */
  enum MatchResult {
    ALWAYS = 1,    // Always matches
    SOMETIMES = 0, // May or may not match
    NEVER = -1     // Never matches
  }
}

Primary Expression Types

The fundamental expression types that form the building blocks of PEG grammars.

namespace ast {
  /**
   * Union of primary expression types
   */
  type Primary =
    | Any
    | CharacterClass
    | Group
    | LibraryReference
    | Literal
    | RuleReference
    | SemanticPredicate;
  
  /**
   * Reference to another rule
   */
  interface RuleReference extends Expr<"rule_ref"> {
    /** Name of referenced rule */
    name: string;
  }
  
  /**
   * Reference to rule in imported library
   */
  interface LibraryReference extends Expr<"library_ref"> {
    /** Rule name (undefined for default rule) */
    name: string | undefined;
    /** Library namespace name */
    library: string;
    /** Import statement index */
    libraryNumber: number;
  }
  
  /**
   * Literal string match
   */
  interface Literal extends Expr<"literal"> {
    /** String to match */
    value: string;
    /** Case-insensitive matching */
    ignoreCase: boolean;
  }
  
  /**
   * Character class match
   */
  interface CharacterClass extends Expr<"class"> {
    /** Character ranges and individual characters */
    parts: (string[] | string | ClassEscape)[];
    /** Negated character class */
    inverted: boolean;
    /** Case-insensitive matching */
    ignoreCase: boolean;
    /** Unicode mode */
    unicode: boolean;
  }
  
  /**
   * Match any character
   */
  interface Any extends Expr<"any"> {}
  
  /**
   * Semantic predicate (code that returns boolean)
   */
  interface SemanticPredicate extends CodeBlockExpr<"semantic_and" | "semantic_not"> {}
  
  /**
   * Grouping expression for label scoping
   */
  interface Group extends Expr<"group"> {
    expression: Labeled | Sequence;
  }
}

AST Usage Example:

import { parser } from "peggy";

const grammar = `
  start = "hello" name:word { return "Hello, " + name; }
  word = [a-z]+
`;

const ast = parser.parse(grammar, { reservedWords: [] });

// Examine the AST structure
console.log("Number of rules:", ast.rules.length);
console.log("First rule name:", ast.rules[0].name);
console.log("First rule type:", ast.rules[0].expression.type);

// Walk through rules
ast.rules.forEach(rule => {
  console.log(`Rule ${rule.name} at line ${rule.location.start.line}`);
});

Complete AST Types

The ast namespace provides comprehensive type definitions for all AST node types in Peggy grammars.

Core AST Interfaces

Base interfaces used throughout the AST type system.

namespace ast {
  /**
   * Base AST node interface
   * @template T - Node type identifier
   */
  interface Node<T> {
    /** Node type identifier */
    type: T;
    /** Source location of this node */
    location: LocationRange;
  }
  
  /**
   * Base expression node interface
   * @template T - Expression type identifier  
   */
  interface Expr<T> extends Node<T> {
    /** Match result estimation (added by compiler passes) */
    match?: MatchResult;
  }
  
  /**
   * Match result enumeration for expressions
   */
  enum MatchResult {
    ALWAYS = 1,    // Expression always matches
    SOMETIMES = 0, // Expression may match
    NEVER = -1     // Expression never matches
  }
}

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