CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-pegjs

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

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

Built-in parser for PEG grammar syntax that converts grammar strings into abstract syntax trees for compilation into executable parsers.

Capabilities

Grammar Parser

Parses PEG grammar strings into abstract syntax tree representations.

/**
 * Built-in grammar parser module
 */
const parser = {
  /**
   * Parse PEG grammar string into AST
   * @param input - PEG grammar string to parse  
   * @param options - Optional parsing configuration
   * @returns Grammar AST object
   * @throws {SyntaxError} If grammar syntax is invalid
   */
  parse: function(input, options),
  
  /**
   * Syntax error constructor for grammar parsing failures
   */
  SyntaxError: function(message, expected, found, location)
};

Usage Examples:

const peg = require("pegjs");

// Parse a simple grammar
const grammarText = `
start = "hello" "world"
`;

const ast = peg.parser.parse(grammarText);
console.log(ast); // Grammar AST object

// Parse with options
const ast = peg.parser.parse(grammarText, {
  startRule: "grammar"
});

Syntax Error Handling

Grammar parsing errors provide detailed information about syntax problems.

/**
 * Grammar syntax error class
 */
class SyntaxError extends Error {
  name: "SyntaxError";
  message: string;
  expected: ExpectedItem[];
  found: string | null;
  location: LocationRange;
  
  /**
   * Build human-readable error message
   * @param expected - Array of expected items
   * @param found - What was actually found
   * @returns Formatted error message
   */
  static buildMessage(expected, found): string;
}

/**
 * Expected item in error reporting
 */
interface ExpectedItem {
  type: "literal" | "class" | "any" | "end" | "other";
  text?: string;
  description?: string;
  inverted?: boolean;
  parts?: (string | [string, string])[];
}

/**
 * Location range information
 */
interface LocationRange {
  start: { offset: number; line: number; column: number };
  end: { offset: number; line: number; column: number };
}

Error Handling Example:

try {
  const ast = peg.parser.parse("invalid grammar syntax");
} catch (error) {
  if (error.name === "SyntaxError") {
    console.error("Grammar syntax error:", error.message);
    console.error("Expected:", error.expected);
    console.error("Found:", error.found);
    console.error(`At line ${error.location.start.line}, column ${error.location.start.column}`);
    
    // Build custom error message
    const customMessage = peg.parser.SyntaxError.buildMessage(
      error.expected, 
      error.found
    );
    console.error("Custom message:", customMessage);
  }
}

Grammar Syntax

Grammar Structure

PEG grammars consist of rules that define parsing patterns using various expression types.

Basic Grammar Format:

// Optional initializer (JavaScript code executed before parsing)
{
  function helper() {
    return "helper function";
  }
}

// Rules define parsing patterns
ruleName "human readable name"
  = expression

anotherRule
  = expression / alternative

Expression Types

The grammar parser recognizes these expression patterns:

Literals and Characters

// String literals (case-sensitive)
"exact text"
'single quotes'

// Case-insensitive literals  
"text"i
'TEXT'i

// Any single character
.

// Character classes
[a-z]        // lowercase letters
[^0-9]       // anything except digits  
[a-zA-Z0-9]  // alphanumeric
[abc]i       // case-insensitive class

Quantifiers and Grouping

// Optional (zero or one)
expression?

// Zero or more
expression*

// One or more  
expression+

// Grouping
(expression)

Predicates

// Positive lookahead (and predicate)
&expression

// Negative lookahead (not predicate)  
!expression

// Semantic predicates
&{ return condition; }
!{ return condition; }

Sequences and Choices

// Sequence (all must match in order)
expression1 expression2 expression3

// Choice (first match wins)
expression1 / expression2 / expression3

Labels and Actions

// Labels for capturing results
label:expression

// Actions for transforming results
expression { return transformedValue; }

// Text capture
$expression

Rule References

// Reference to another rule
ruleName

// Rule with human-readable name
integer "integer"
  = digits:[0-9]+ { return parseInt(digits.join(""), 10); }

Grammar AST Structure

The parser produces AST nodes with these types:

/**
 * Root grammar node
 */
interface GrammarNode {
  type: "grammar";
  initializer?: InitializerNode;
  rules: RuleNode[];
}

/**
 * Rule definition node
 */
interface RuleNode {
  type: "rule";
  name: string;
  displayName?: string;
  expression: ExpressionNode;
}

/**
 * Expression node types
 */
type ExpressionNode = 
  | ChoiceNode | SequenceNode | LabeledNode | ActionNode
  | OptionalNode | ZeroOrMoreNode | OneOrMoreNode
  | SimpleAndNode | SimpleNotNode | SemanticAndNode | SemanticNotNode
  | TextNode | RuleRefNode | LiteralNode | ClassNode | AnyNode;

/**
 * Choice expression (alternatives)
 */
interface ChoiceNode {
  type: "choice";
  alternatives: ExpressionNode[];
}

/**
 * Sequence expression  
 */
interface SequenceNode {
  type: "sequence";
  elements: ExpressionNode[];
}

/**
 * Labeled expression
 */
interface LabeledNode {
  type: "labeled";
  label: string;
  expression: ExpressionNode;
}

AST Usage Example:

const ast = peg.parser.parse(`
start = greeting name
greeting = "hello" / "hi"  
name = [a-zA-Z]+
`);

console.log(ast.type); // "grammar"
console.log(ast.rules.length); // 3
console.log(ast.rules[0].name); // "start"
console.log(ast.rules[0].expression.type); // "sequence"

Advanced Features

Initializer Code

Grammars can include JavaScript code executed before parsing begins:

{
  // Global variables and functions available in actions
  var utils = {
    capitalize: function(str) {
      return str.charAt(0).toUpperCase() + str.slice(1);
    }
  };
}

start = word { return utils.capitalize(text()); }
word = [a-z]+

Semantic Actions

Actions transform parse results using JavaScript code:

number = digits:[0-9]+ { 
  return parseInt(digits.join(""), 10); 
}

array = "[" head:value tail:("," value)* "]" {
  return [head].concat(tail.map(function(t) { return t[1]; }));
}

Location Information

Actions can access location information:

rule = expression {
  var loc = location();
  return {
    value: expression,
    line: loc.start.line,
    column: loc.start.column
  };
}

Error Reporting

Custom error messages in actions:

rule = expression {
  if (!isValid(expression)) {
    expected("valid expression");
  }
  return expression;
}

Install with Tessl CLI

npx tessl i tessl/npm-pegjs

docs

cli-tool.md

compiler-system.md

grammar-parsing.md

index.md

parser-generation.md

utility-modules.md

tile.json