or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

atn-dfa.mdcontext.mdcore-classes.mderror-handling.mdindex.mdparse-trees.mdstreams.mdutilities.md
tile.json

atn-dfa.mddocs/

ATN and DFA

Advanced Augmented Transition Network and Deterministic Finite Automaton classes for parser optimization and configuration. These classes provide the low-level parsing engine that powers ANTLR4's adaptive parsing capabilities.

Capabilities

ATN (Augmented Transition Network)

Core ATN classes for representing the parsing automaton.

/**
 * Augmented Transition Network representing parser logic
 */
class ATN {
  /** Invalid alternative number constant */
  static readonly INVALID_ALT_NUMBER: number;
  
  /** Array of all ATN states */
  states: ATNState[];
  
  /** Decision states indexed by decision number */
  decisionToState: DecisionState[];
  
  /** Rule start states indexed by rule number */
  ruleToStartState: RuleStartState[];
  
  /** Rule stop states indexed by rule number */
  ruleToStopState: RuleStopState[];
  
  /**
   * Get expected tokens at a specific ATN state
   * @param stateNumber - ATN state number
   * @param ctx - Rule context for prediction
   * @returns Set of expected token types
   */
  getExpectedTokens(stateNumber: number, ctx: RuleContext): IntervalSet;
  
  /**
   * Get next possible tokens from ATN state
   * @param atnState - ATN state to analyze
   * @param ctx - Rule context (optional)
   * @returns Set of possible next tokens
   */
  nextTokens(atnState: ATNState, ctx?: RuleContext): IntervalSet;
}

/**
 * Configuration state during ATN simulation
 */
class ATNConfig {
  /** ATN state this configuration represents */
  state: ATNState;
  
  // Additional configuration data for prediction
}

/**
 * Set of ATN configurations for decision making
 */
class ATNConfigSet {
  /** Array of ATN configurations */
  configs: ATNConfig[];
}

ATN Deserialization

Classes for loading serialized ATN data.

/**
 * Options for ATN deserialization
 */
class ATNDeserializationOptions {
  /** Whether ATN should be read-only (optional) */
  readOnly?: boolean;
  
  /** Whether to verify ATN integrity (optional) */
  verifyATN?: boolean;
  
  /** Whether to generate rule bypass transitions (optional) */
  generateRuleBypassTransitions?: boolean;
}

/**
 * Deserializes ATN from serialized data format
 */
class ATNDeserializer {
  /**
   * Create ATN deserializer with options
   * @param options - Deserialization options (optional)
   */
  constructor(options?: ATNDeserializationOptions);
  
  /**
   * Deserialize ATN from numeric array data
   * @param data - Serialized ATN data as number array
   * @returns Deserialized ATN instance
   */
  deserialize(data: number[]): ATN;
}

ATN Simulators

Simulators that execute the ATN for parsing decisions.

/**
 * Base class for ATN simulators
 */
abstract class ATNSimulator {
  // Empty base class providing common interface
}

/**
 * ATN simulator for lexer operations
 */
class LexerATNSimulator implements ATNSimulator {
  /** Array of DFA instances for decisions */
  decisionToDFA: DFA[];
  
  /**
   * Create lexer ATN simulator
   * @param recog - Recognizer using this simulator
   * @param atn - ATN to simulate
   * @param decisionToDFA - DFA array for caching decisions
   * @param sharedContextCache - Shared prediction context cache
   */
  constructor(recog: Recognizer<number>, atn: ATN, decisionToDFA: DFA[], sharedContextCache: PredictionContextCache);
  
  /**
   * Consume input character and update simulation state
   * @param input - Character stream to consume from
   */
  consume(input: CharStream): void;
}

/**
 * ATN simulator for parser operations
 */
class ParserATNSimulator extends ATNSimulator {
  /** Current prediction mode */
  predictionMode: PredictionMode;
  
  /** Array of DFA instances for decisions */
  decisionToDFA: DFA[];
  
  /** ATN being simulated */
  atn: ATN;
  
  /** Debug mode flag (optional) */
  debug?: boolean;
  
  /** ATN simulation tracing flag (optional) */
  trace_atn_sim?: boolean;
  
  /**
   * Create parser ATN simulator
   * @param recog - Recognizer using this simulator
   * @param atn - ATN to simulate
   * @param decisionToDFA - DFA array for caching decisions
   * @param sharedContextCache - Shared prediction context cache
   */
  constructor(recog: Recognizer<Token>, atn: ATN, decisionToDFA: DFA[], sharedContextCache: PredictionContextCache);
  
  /**
   * Perform adaptive prediction for a decision
   * @param input - Token stream to predict from
   * @param decision - Decision number to predict
   * @param outerContext - Outer parser rule context
   * @returns Predicted alternative number
   */
  adaptivePredict(input: TokenStream, decision: number, outerContext: ParserRuleContext): number;
}

Prediction Modes and Contexts

Configuration for parser prediction behavior.

/**
 * Prediction modes for parsing decisions
 */
class PredictionMode {
  /** Strong LL prediction mode */
  static readonly SLL: number;
  
  /** Full LL prediction mode */
  static readonly LL: number;
  
  /** LL with exact ambiguity detection */
  static readonly LL_EXACT_AMBIG_DETECTION: number;
}

/**
 * Cache for prediction contexts to improve performance
 */
class PredictionContextCache {
  // Empty base class for caching prediction contexts
}

DFA (Deterministic Finite Automaton)

DFA classes for optimized decision caching.

/**
 * Deterministic Finite Automaton for caching parser decisions
 */
class DFA {
  /**
   * Create DFA for decision caching
   * @param ds - Decision state
   * @param index - DFA index
   */
  constructor(ds: any, index: number);
  
  /**
   * Convert DFA to string representation for lexer
   * @returns String representation of DFA
   */
  toLexerString(): string;
}

ATN State Classes

Different types of states in the ATN.

/**
 * Base class for ATN states
 */
abstract class ATNState {
  /** ATN containing this state */
  atn: ATN;
  
  /** Unique state number within ATN */
  stateNumber: number;
}

/**
 * ATN state that represents a decision point
 */
class DecisionState extends ATNState {
  /** Decision number for this state */
  decision: number;
  
  /** Whether decision is non-greedy */
  nonGreedy: boolean;
}

/**
 * Start state of a grammar rule
 */
class RuleStartState extends ATNState {
  /** Corresponding rule stop state */
  stopState: RuleStopState;
  
  /** Whether this rule is left-recursive */
  isLeftRecursiveRule: boolean;
}

/**
 * Final state of a grammar rule
 */
class RuleStopState extends ATNState {
  // Final state - no additional properties
}

Usage Examples

Creating and configuring ATN simulator:

import { ParserATNSimulator, ATN, DFA, PredictionContextCache, PredictionMode } from "antlr4";

// Typically done by generated parser, but can be customized
class CustomParser extends Parser {
  constructor(input: TokenStream) {
    super(input);
    
    // Create custom ATN simulator with debug mode
    const atn = this.getATN(); // Get parser's ATN
    const decisionToDFA = this._interp.decisionToDFA; // Get DFA array
    const sharedContextCache = new PredictionContextCache();
    
    this._interp = new ParserATNSimulator(this, atn, decisionToDFA, sharedContextCache);
    this._interp.predictionMode = PredictionMode.LL; // Use full LL parsing
    this._interp.debug = true; // Enable debug mode
  }
}

Setting different prediction modes:

import { PredictionMode } from "antlr4";

const parser = new MyParser(tokens);

// Use Strong LL for faster parsing (may not handle all grammars)
parser._interp.predictionMode = PredictionMode.SLL;

try {
  const tree = parser.expression();
  console.log("SLL parsing successful");
} catch (e) {
  // Fall back to full LL on SLL failure
  console.log("SLL failed, falling back to LL");
  parser.reset();
  parser._interp.predictionMode = PredictionMode.LL;
  const tree = parser.expression();
}

Using exact ambiguity detection:

import { PredictionMode, DiagnosticErrorListener } from "antlr4";

const parser = new MyParser(tokens);

// Enable exact ambiguity detection
parser._interp.predictionMode = PredictionMode.LL_EXACT_AMBIG_DETECTION;

// Add diagnostic listener to catch ambiguities
const diagnosticListener = new DiagnosticErrorListener();
parser.addErrorListener(diagnosticListener);

const tree = parser.expression();
console.log("Parsing complete - check listener for ambiguity reports");

Custom ATN deserialization:

import { ATNDeserializer, ATNDeserializationOptions } from "antlr4";

// Custom deserialization options
const options = new ATNDeserializationOptions();
options.verifyATN = true; // Verify ATN integrity
options.generateRuleBypassTransitions = true; // Generate bypass transitions

const deserializer = new ATNDeserializer(options);

// Deserialize ATN from data (typically embedded in generated parser)
const atnData = getATNData(); // Your serialized ATN data
const atn = deserializer.deserialize(atnData);

console.log(`ATN loaded with ${atn.states.length} states`);
console.log(`Number of rules: ${atn.ruleToStartState.length}`);

Analyzing ATN structure:

import { ATN, DecisionState, RuleStartState } from "antlr4";

function analyzeATN(atn: ATN): void {
  console.log(`ATN Analysis:`);
  console.log(`  Total states: ${atn.states.length}`);
  console.log(`  Rules: ${atn.ruleToStartState.length}`);
  console.log(`  Decisions: ${atn.decisionToState.length}`);
  
  // Count state types
  let decisionStates = 0;
  let ruleStartStates = 0;
  
  for (const state of atn.states) {
    if (state instanceof DecisionState) {
      decisionStates++;
    } else if (state instanceof RuleStartState) {
      ruleStartStates++;
    }
  }
  
  console.log(`  Decision states: ${decisionStates}`);
  console.log(`  Rule start states: ${ruleStartStates}`);
  
  // Analyze decisions
  for (let i = 0; i < atn.decisionToState.length; i++) {
    const decisionState = atn.decisionToState[i];
    if (decisionState) {
      console.log(`  Decision ${i}: State ${decisionState.stateNumber}, Non-greedy: ${decisionState.nonGreedy}`);
    }
  }
}

// Usage with parser's ATN
const parser = new MyParser(tokens);
const atn = parser.getATN();
analyzeATN(atn);

Getting expected tokens from ATN:

import { ATN, RuleContext, IntervalSet } from "antlr4";

function getExpectedTokensAtState(parser: Parser, stateNumber: number, context: RuleContext): string[] {
  const atn = parser.getATN();
  const expectedTokens = atn.getExpectedTokens(stateNumber, context);
  
  const tokenNames = parser.getTokenNames();
  const expected: string[] = [];
  
  for (let i = 0; i < expectedTokens.intervals.length; i++) {
    const interval = expectedTokens.intervals[i];
    for (let token = interval.start; token <= interval.stop; token++) {
      const tokenName = tokenNames[token] || `Token${token}`;
      expected.push(tokenName);
    }
  }
  
  return expected;
}

// Usage during error handling
class AnalyzingErrorListener extends ErrorListener<Token> {
  syntaxError(recognizer: Recognizer<Token>, offendingSymbol: Token, line: number, column: number, msg: string, e: RecognitionException | undefined): void {
    if (recognizer instanceof Parser) {
      const parser = recognizer as Parser;
      const expectedTokens = getExpectedTokensAtState(parser, parser.state, parser._ctx);
      
      console.error(`Syntax error at ${line}:${column}`);
      console.error(`Expected one of: ${expectedTokens.join(', ')}`);
      console.error(`But found: ${offendingSymbol?.text || 'EOF'}`);
    }
  }
  
  // Other methods...
  reportAmbiguity(): void {}
  reportAttemptingFullContext(): void {}
  reportContextSensitivity(): void {}
}

DFA performance monitoring:

import { DFA } from "antlr4";

class PerformanceMonitoringParser extends Parser {
  private dfaHits = new Map<number, number>();
  private dfaMisses = new Map<number, number>();
  
  constructor(input: TokenStream) {
    super(input);
    this.monitorDFAPerformance();
  }
  
  private monitorDFAPerformance(): void {
    // Override adaptivePredict to monitor DFA usage
    const originalPredict = this._interp.adaptivePredict.bind(this._interp);
    
    this._interp.adaptivePredict = (input: TokenStream, decision: number, outerContext: ParserRuleContext): number => {
      const dfa = this._interp.decisionToDFA[decision];
      const startState = dfa?.s0;
      
      if (startState) {
        // DFA has cached state
        this.dfaHits.set(decision, (this.dfaHits.get(decision) || 0) + 1);
      } else {
        // DFA miss - will need ATN simulation
        this.dfaMisses.set(decision, (this.dfaMisses.get(decision) || 0) + 1);
      }
      
      return originalPredict(input, decision, outerContext);
    };
  }
  
  getDFAStats(): { decision: number; hits: number; misses: number; hitRate: number }[] {
    const stats: { decision: number; hits: number; misses: number; hitRate: number }[] = [];
    
    const allDecisions = new Set([...this.dfaHits.keys(), ...this.dfaMisses.keys()]);
    
    for (const decision of allDecisions) {
      const hits = this.dfaHits.get(decision) || 0;
      const misses = this.dfaMisses.get(decision) || 0;
      const total = hits + misses;
      const hitRate = total > 0 ? hits / total : 0;
      
      stats.push({ decision, hits, misses, hitRate });
    }
    
    return stats.sort((a, b) => a.decision - b.decision);
  }
  
  printDFAStats(): void {
    const stats = this.getDFAStats();
    
    console.log("DFA Performance Statistics:");
    console.log("Decision | Hits | Misses | Hit Rate");
    console.log("---------|------|--------|----------");
    
    for (const stat of stats) {
      console.log(`${stat.decision.toString().padStart(8)} | ${stat.hits.toString().padStart(4)} | ${stat.misses.toString().padStart(6)} | ${(stat.hitRate * 100).toFixed(1)}%`);
    }
  }
}

// Usage
const parser = new PerformanceMonitoringParser(tokens);
const tree = parser.expression();
parser.printDFAStats();