### Configuring and Using Dialects Source: https://context7.com/lezer-parser/lr/llms.txt Configure a parser to use a specific dialect. This example shows how to create a parser with the 'jsx' dialect enabled. ```typescript import { parser } from "./javascript-parser" const jsxParser = parser.configure({ dialect: "jsx" }) const tree = jsxParser.parse("
hello
") ``` -------------------------------- ### Controlled Incremental Advance with PartialParse Source: https://context7.com/lezer-parser/lr/llms.txt Use `startParse` to get a `PartialParse` object and `advance()` to drive parsing step-by-step. `stopAt(pos)` limits parsing to a specific position, useful for viewport-based updates. The loop yields to the UI if parsing exceeds a budget. ```typescript import { parser } from "./generated-parser" import { TreeFragment } from "@lezer/common" const largeDoc = "/* 100k characters of code */" const partial = parser.startParse(largeDoc, [], [{ from: 0, to: largeDoc.length }]) // Only parse the first 5000 characters for now (e.g., visible viewport) partial.stopAt(5000) let tree = null const BUDGET_MS = 16 // one frame const deadline = Date.now() + BUDGET_MS while (!tree) { tree = partial.advance() if (Date.now() > deadline) break // yield to UI, resume next frame } if (tree) { console.log("Fully parsed up to stopAt:", tree.length) } else { // Can inspect partial.parsedPos to know how far we've gotten console.log("Parsed so far:", partial.parsedPos) } ``` -------------------------------- ### External Tokenizer with `Stack.context` Source: https://context7.com/lezer-parser/lr/llms.txt Access grammar context using `Stack.context` to make tokenizer decisions. This example emits the 'in' keyword only when inside a for-header. ```typescript import { ExternalTokenizer } from "@lezer/lr" import { identifier, kwIn } from "./my-grammar.terms" // Example: emit 'in' only as keyword when context says we are in a for-header export const forKeywordTokenizer = new ExternalTokenizer( (input, stack) => { const ctx = stack.context as { inForHeader: boolean } | null if (!ctx?.inForHeader) return // Match "in" literally if (input.next === 105 /* 'i' */) { input.advance() if (input.next === 110 /* 'n' */) { input.advance() // Ensure it's not part of a longer identifier const next = input.next if (next < 65 || (next > 90 && next < 97) || next > 122) { input.acceptToken(kwIn) } } } }, { contextual: true } ) ``` -------------------------------- ### Define ParserConfig for LRParser.configure Source: https://context7.com/lezer-parser/lr/llms.txt Shows how to define a `ParserConfig` object to customize an `LRParser`. Options are optional and composable, with omitted fields inherited from the base parser. This example includes setting `top`, `dialect`, `strict`, `bufferLength`, `tokenizers`, and `wrap` for mixed-language parsing. ```typescript import { ParserConfig, ExternalTokenizer } from "@lezer/lr" import { parseMixed } from "@lezer/common" const myTokenizer = new ExternalTokenizer((input, stack) => { // custom tokenizer logic (see ExternalTokenizer section) }) const config: ParserConfig = { top: "Module", dialect: "jsx", strict: false, bufferLength: 512, tokenizers: [{ from: existingTokenizer, to: myTokenizer }], // Wrap with mixed-language parser (e.g. JS inside HTML) wrap: parseMixed((node) => { if (node.type.name === "TemplateString") return { parser: cssParser } return null }), } const tuned = baseParser.configure(config) ``` -------------------------------- ### External Tokenizer with `Stack.canShift` Source: https://context7.com/lezer-parser/lr/llms.txt Use `Stack.canShift` to conditionally emit tokens based on parser state. This example emits `templateContent` only when inside a template literal. ```typescript import { ExternalTokenizer } from "@lezer/lr" import { templateContent, noTemplateContent } from "./js.terms" // Only emit templateContent when the parser is inside a template literal export const templateTokenizer = new ExternalTokenizer( (input, stack) => { if (!stack.canShift(templateContent)) { input.acceptToken(noTemplateContent) return } let content = "" while (input.next >= 0 && input.next !== 96 /* ` */ && input.next !== 36 /* $ */) { input.advance() } input.acceptToken(templateContent) }, { contextual: true } ) ``` -------------------------------- ### External Tokenizer with `Stack.dialectEnabled` Source: https://context7.com/lezer-parser/lr/llms.txt Check if a grammar dialect is active using `Stack.dialectEnabled`. This tokenizer only lexes '<' as a JSX open-tag start when the 'jsx' dialect is enabled. ```typescript import { ExternalTokenizer } from "@lezer/lr" import { Dialect_jsx, jsxOpenTag } from "./javascript.terms" import { lessThan } from "./javascript.terms" // Only lex '<' as JSX open-tag start when jsx dialect is enabled export const jsxTokenizer = new ExternalTokenizer( (input, stack) => { if (input.next !== 60 /* '<' */) return if (!stack.dialectEnabled(Dialect_jsx)) { // Fall through to normal '<' tokenizer return } input.advance() // Further JSX tag scanning… input.acceptToken(jsxOpenTag) }, { fallback: true } ) ``` -------------------------------- ### Configure LRParser with Custom Settings Source: https://context7.com/lezer-parser/lr/llms.txt Demonstrates creating a reconfigured `LRParser` instance with modified settings like `top` rule, `dialect`, `props`, `strict` mode, `tokenizers`, and `bufferLength`. The original parser remains unmodified. ```typescript import { parser } from "./generated-parser" import { NodeProp } from "@lezer/common" // Add a custom node prop to all nodes const indentProp = new NodeProp({ deserialize: n => Number(n) }) const configuredParser = parser.configure({ // Parse from a specific @top rule (if grammar defines multiple) top: "Expression", // Enable a grammar dialect (e.g. TypeScript-specific syntax) dialect: "ts", // Add node props (for e.g. indentation, highlighting) props: [indentProp.add({ FunctionBody: 2, Block: 2 })], // Strict mode: throw instead of error-recover on invalid input strict: false, // Replace an external tokenizer at runtime tokenizers: [{ from: oldTokenizer, to: newTokenizer }], // Increase tree buffer size (default: 1024) bufferLength: 2048, }) const tree = configuredParser.parse("x + y") console.log(configuredParser.topNode.name) // → "Expression" ``` -------------------------------- ### Incremental Parse with LRParser Source: https://context7.com/lezer-parser/lr/llms.txt Shows how to perform an incremental parse using `startParse` and `advance` for editor integration. The `advance` method returns a `Tree` when parsing is complete, or `null` otherwise. ```typescript // --- Incremental / partial parse (for editor integration) --- const partialParse = parser.startParse(input) let result = null while (!result) { result = partialParse.advance() // returns Tree when done, null otherwise } console.log(result.type.name) // → "Script" ``` -------------------------------- ### LRParser.configure Source: https://context7.com/lezer-parser/lr/llms.txt Creates a reconfigured copy of an LRParser instance with specified settings changed, such as the top rule, grammar dialects, external tokenizers, node props, strict mode, and parse wrappers. ```APIDOC ## `LRParser.configure` — Create a reconfigured parser copy Returns a new `LRParser` instance with the specified settings changed, leaving the original parser unmodified. Supports changing the top rule, enabling grammar dialects, replacing external tokenizers or specializers, adding node props, toggling strict mode, and attaching parse wrappers for mixed-language parsing. ```typescript import { parser } from "./generated-parser" import { NodeProp } from "@lezer/common" // Add a custom node prop to all nodes const indentProp = new NodeProp({ deserialize: n => Number(n) }) const configuredParser = parser.configure({ // Parse from a specific @top rule (if grammar defines multiple) top: "Expression", // Enable a grammar dialect (e.g. TypeScript-specific syntax) dialect: "ts", // Add node props (for e.g. indentation, highlighting) props: [indentProp.add({ FunctionBody: 2, Block: 2 })], // Strict mode: throw instead of error-recover on invalid input strict: false, // Replace an external tokenizer at runtime tokenizers: [{ from: oldTokenizer, to: newTokenizer }], // Increase tree buffer size (default: 1024) bufferLength: 2048, }) const tree = configuredParser.parse("x + y") console.log(configuredParser.topNode.name) // → "Expression" ``` ``` -------------------------------- ### Full Synchronous Parse with LRParser Source: https://context7.com/lezer-parser/lr/llms.txt Demonstrates a complete synchronous parse of a string input using the LRParser. Ensure the parser is imported from a generated JavaScript file. ```typescript import { parser } from "./generated-javascript-parser" // produced by @lezer/generator import { StringInput } from "@lezer/common" // --- Full synchronous parse --- const input = "let x = 1 + 2;" const tree = parser.parse(input) console.log(tree.toString()) // → "Script(VariableDeclaration(let,VariableDeclarator(x,BinaryExpression(1,+,2))))" ``` -------------------------------- ### Incremental Parsing with TreeFragment Source: https://context7.com/lezer-parser/lr/llms.txt Demonstrates how to use `TreeFragment` for incremental parsing, allowing reuse of previous parse trees when the document changes. `TreeFragment.applyChanges` computes valid fragments from a previous `Tree` given document changes. ```APIDOC ## Incremental Parsing with `TreeFragment` — Reuse previous parse trees Lezer's key editor feature is incremental parsing: when the document changes, only the affected region is re-parsed, and subtrees from the previous parse are reused where safe. `TreeFragment.applyChanges` computes the still-valid fragments from a previous `Tree` given a list of document changes, which are then passed to `startParse`. ```typescript import { parser } from "./generated-parser" import { TreeFragment } from "@lezer/common" let source = "function foo() { return 1; }" let tree = parser.parse(source) let fragments = TreeFragment.addTree(tree) // Simulate a document edit: replace "1" with "42" const changes = [{ fromA: 24, toA: 25, fromB: 24, toB: 26 }] source = "function foo() { return 42; }" // Apply changes to existing fragments fragments = TreeFragment.applyChanges(fragments, changes) // Re-parse with fragments; subtrees outside the edit region are reused const updatedTree = parser.parse(source, fragments) console.log(updatedTree.toString()) // → "Script(FunctionDeclaration(foo,ParamList,Block(ReturnStatement(42))))" ``` ``` -------------------------------- ### LRParser - Main parser class Source: https://context7.com/lezer-parser/lr/llms.txt The LRParser class holds parse tables and is the main entry point for parsing. It extends the abstract Parser class and is created using LRParser.deserialize. The parse and startParse methods drive the parsing process. ```APIDOC ## LRParser — Main parser class `LRParser` holds the parse tables for a grammar and is the primary entry point for parsing. It extends the abstract `Parser` class from `@lezer/common`. Instances are created by calling `LRParser.deserialize` with the data object emitted by `@lezer/generator`; they are immutable and reusable across parses. The `parse` and `startParse` methods (inherited from `@lezer/common`) drive actual parsing. ```typescript import { parser } from "./generated-javascript-parser" // produced by @lezer/generator import { StringInput } from "@lezer/common" // --- Full synchronous parse --- const input = "let x = 1 + 2;" const tree = parser.parse(input) console.log(tree.toString()) // → "Script(VariableDeclaration(let,VariableDeclarator(x,BinaryExpression(1,+,2))))" // --- Incremental / partial parse (for editor integration) --- const partialParse = parser.startParse(input) let result = null while (!result) { result = partialParse.advance() // returns Tree when done, null otherwise } console.log(result.type.name) // → "Script" // --- Parse with position ranges (e.g. embedded language regions) --- const tree2 = parser.parse(input, [], [ { from: 0, to: 8 }, { from: 12, to: input.length } ]) ``` ``` -------------------------------- ### Tokenize Rust-style Raw Strings with ExternalTokenizer Source: https://context7.com/lezer-parser/lr/llms.txt Create a tokenizer for Rust-style raw string literals (r"...") using ExternalTokenizer. This tokenizer handles varying numbers of '#' characters between 'r' and the opening quote, and ensures the closing quote is matched by the same number of hashes. It requires a token ID for raw strings. ```typescript import { ExternalTokenizer } from "@lezer/lr" import { rawString } from "./my-grammar.terms" // Tokenize a raw string literal: r"..."# (Rust-style) export const rawStringTokenizer = new ExternalTokenizer((input) => { if (input.next !== 114 /* 'r' */) return // must start with 'r' input.advance() let hashCount = 0 while (input.next === 35 /* '#' */) { hashCount++; input.advance() } if (input.next !== 34 /* '"' */) return // must have opening quote input.advance() // Scan until we find the matching closing quote + hashes outer: for (;;) { if (input.next < 0) return // unexpected EOF if (input.next === 34 /* '"' */) { input.advance() let closeHashes = 0 while (input.next === 35 && closeHashes < hashCount) { closeHashes++ input.advance() } if (closeHashes === hashCount) break outer } else { input.advance() } } input.acceptToken(rawString) // emit token ending at current pos }) ``` -------------------------------- ### Manage Indentation Context with ContextTracker Source: https://context7.com/lezer-parser/lr/llms.txt Implement indentation-sensitive parsing using ContextTracker for languages like Python. This tracker maintains the current indentation depth and a stack of previous depths, updating them on indent and dedent tokens. It requires token IDs for indent and dedent, and a helper function to count spaces. ```typescript import { ContextTracker } from "@lezer/lr" import { indent, dedent } from "./python-grammar.terms" interface IndentContext { readonly depth: number readonly stack: readonly number[] } export const indentTracker = new ContextTracker({ start: { depth: 0, stack: [] }, // Called when the parser shifts a token shift(context, term, _stack, input) { if (term === indent) { // Push new indentation level on shift of INDENT token const col = countSpaces(input.read(input.pos, input.pos + 40)) return { depth: col, stack: [...context.stack, context.depth] } } if (term === dedent) { // Pop indentation level on DEDENT const stack = context.stack.slice() return { depth: stack.pop() ?? 0, stack } } return context }, // Cheap numeric hash for efficient incremental-reuse comparison hash(context) { return context.depth }, strict: true, // only reuse nodes parsed in the same context }) function countSpaces(str: string) { let n = 0 for (const ch of str) { if (ch === " ") n++; else break } return n } ``` -------------------------------- ### InputStream Source: https://context7.com/lezer-parser/lr/llms.txt InputStream provides a navigable stream of Unicode code units for tokenizers. It allows inspection and consumption of characters, handling non-contiguous ranges transparently. Key members include next, pos, peek, advance, acceptToken, and acceptTokenTo. ```APIDOC ## `InputStream` — Character stream interface for tokenizers `InputStream` presents the document being parsed as a navigable stream of Unicode code units. Tokenizer functions use it to inspect and consume characters. It transparently handles documents parsed in non-contiguous ranges (e.g. embedded language regions). Key members: `next` (current char code or -1), `pos` (current position), `peek(offset)`, `advance(n?)`, `acceptToken(type, endOffset?)`, `acceptTokenTo(type, endPos)`. ```typescript import { ExternalTokenizer } from "@lezer/lr" import { rawString } from "./my-grammar.terms" // Tokenize a raw string literal: r#"..."# (Rust-style) export const rawStringTokenizer = new ExternalTokenizer((input) => { if (input.next !== 114 /* 'r' */) return // must start with 'r' input.advance() let hashCount = 0 while (input.next === 35 /* '#' */) { hashCount++; input.advance() } if (input.next !== 34 /* '"' */) return // must have opening quote input.advance() // Scan until we find the matching closing quote + hashes outer: for (;;) { if (input.next < 0) return // unexpected EOF if (input.next === 34 /* '"' */) { input.advance() let closeHashes = 0 while (input.next === 35 && closeHashes < hashCount) { closeHashes++ input.advance() } if (closeHashes === hashCount) break outer } else { input.advance() } } input.acceptToken(rawString) // emit token ending at current pos }) ``` ``` -------------------------------- ### ContextTracker Source: https://context7.com/lezer-parser/lr/llms.txt ContextTracker maintains a stateful value that evolves with the parser, accessible via stack.context. It's declared using @context and used for indentation-sensitive languages or tracking parent elements. Context values must be treated as immutable. ```APIDOC ## `ContextTracker` — Stateful parse context for tokenizers `ContextTracker` maintains a stateful value that evolves as the parser shifts and reduces, accessible to `ExternalTokenizer`s via `stack.context`. It is declared in a Lezer grammar as `@context exportName from "module"`. Context values must be treated as immutable; callbacks return new values rather than mutating. Used for indentation-sensitive languages (Python), parent-element tracking (XML/HTML), etc. ```typescript import { ContextTracker } from "@lezer/lr" import { indent, dedent } from "./python-grammar.terms" interface IndentContext { readonly depth: number readonly stack: readonly number[] } export const indentTracker = new ContextTracker({ start: { depth: 0, stack: [] }, // Called when the parser shifts a token shift(context, term, _stack, input) { if (term === indent) { // Push new indentation level on shift of INDENT token const col = countSpaces(input.read(input.pos, input.pos + 40)) return { depth: col, stack: [...context.stack, context.depth] } } if (term === dedent) { // Pop indentation level on DEDENT const stack = context.stack.slice() return { depth: stack.pop() ?? 0, stack } } return context }, // Cheap numeric hash for efficient incremental-reuse comparison hash(context) { return context.depth }, strict: true, // only reuse nodes parsed in the same context }) function countSpaces(str: string) { let n = 0 for (const ch of str) { if (ch === " ") n++; else break } return n } ``` ``` -------------------------------- ### Incremental Parsing with `TreeFragment` Source: https://context7.com/lezer-parser/lr/llms.txt Reuse previous parse trees for efficient incremental parsing. `TreeFragment.applyChanges` computes valid fragments after document edits, which are then used by `parser.parse`. ```typescript import { parser } from "./generated-parser" import { TreeFragment } from "@lezer/common" let source = "function foo() { return 1; }" let tree = parser.parse(source) let fragments = TreeFragment.addTree(tree) // Simulate a document edit: replace "1" with "42" const changes = [{ fromA: 24, toA: 25, fromB: 24, toB: 26 }] source = "function foo() { return 42; }" // Apply changes to existing fragments fragments = TreeFragment.applyChanges(fragments, changes) // Re-parse with fragments; subtrees outside the edit region are reused const updatedTree = parser.parse(source, fragments) console.log(updatedTree.toString()) // → "Script(FunctionDeclaration(foo,ParamList,Block(ReturnStatement(42))))" ``` -------------------------------- ### Parse with Position Ranges using LRParser Source: https://context7.com/lezer-parser/lr/llms.txt Illustrates parsing a string while specifying position ranges, useful for handling embedded language regions. The `parse` method accepts an array of `from` and `to` objects. ```typescript // --- Parse with position ranges (e.g. embedded language regions) --- const tree2 = parser.parse(input, [], [ { from: 0, to: 8 }, { from: 12, to: input.length } ]) ``` -------------------------------- ### ParserConfig Interface Source: https://context7.com/lezer-parser/lr/llms.txt The ParserConfig interface defines the options accepted by LRParser.configure, allowing customization of parser behavior like top rule, dialect, strict mode, tokenizers, and parse wrappers. ```APIDOC ## `ParserConfig` — Configuration interface for `LRParser.configure` `ParserConfig` is the TypeScript interface describing all options accepted by `LRParser.configure`. Options are individually optional and composable; omitted fields are inherited from the base parser. ```typescript import { ParserConfig, ExternalTokenizer } from "@lezer/lr" import { parseMixed } from "@lezer/common" const myTokenizer = new ExternalTokenizer((input, stack) => { // custom tokenizer logic (see ExternalTokenizer section) }) const config: ParserConfig = { top: "Module", dialect: "jsx", strict: false, bufferLength: 512, tokenizers: [{ from: existingTokenizer, to: myTokenizer }], // Wrap with mixed-language parser (e.g. JS inside HTML) wrap: parseMixed((node) => { if (node.type.name === "TemplateString") return { parser: cssParser } return null }), } const tuned = baseParser.configure(config) ``` ``` -------------------------------- ### Stack.canShift Source: https://context7.com/lezer-parser/lr/llms.txt Checks if shifting a given terminal is a valid action from the current parse state, considering pending reductions. This is useful for external tokenizers to make context-sensitive decisions. ```APIDOC ## `Stack.canShift` — Check whether a token can be accepted `Stack.canShift(term)` returns `true` if shifting the given terminal (by numeric term ID) is a valid action from the current parse state, accounting for any pending reductions. This is the primary way external tokenizers make context-sensitive decisions about which tokens to emit. ```typescript import { ExternalTokenizer } from "@lezer/lr" import { templateContent, noTemplateContent } from "./js.terms" // Only emit templateContent when the parser is inside a template literal export const templateTokenizer = new ExternalTokenizer( (input, stack) => { if (!stack.canShift(templateContent)) { input.acceptToken(noTemplateContent) return } let content = "" while (input.next >= 0 && input.next !== 96 /* ` */ && input.next !== 36 /* $ */) { input.advance() } input.acceptToken(templateContent) }, { contextual: true } ) ``` ``` -------------------------------- ### Stack.context Source: https://context7.com/lezer-parser/lr/llms.txt Accesses the current value maintained by the grammar's ContextTracker. Returns `null` if no context tracker is configured. Useful for external tokenizers to make decisions based on accumulated parse state. ```APIDOC ## `Stack.context` — Access the current context tracker value `Stack.context` returns the current value maintained by the grammar's `ContextTracker`, or `null` if no context tracker is configured. The type matches the generic parameter `T` of the `ContextTracker` used by the grammar. Useful in external tokenizers to make decisions based on accumulated parse state. ```typescript import { ExternalTokenizer } from "@lezer/lr" import { identifier, kwIn } from "./my-grammar.terms" // Example: emit 'in' only as keyword when context says we are in a for-header export const forKeywordTokenizer = new ExternalTokenizer( (input, stack) => { const ctx = stack.context as { inForHeader: boolean } | null if (!ctx?.inForHeader) return // Match "in" literally if (input.next === 105 /* 'i' */) { input.advance() if (input.next === 110 /* 'n' */) { input.advance() // Ensure it's not part of a longer identifier const next = input.next if (next < 65 || (next > 90 && next < 97) || next > 122) { input.acceptToken(kwIn) } } } }, { contextual: true } ) ``` ``` -------------------------------- ### ExternalTokenizer Source: https://context7.com/lezer-parser/lr/llms.txt ExternalTokenizer wraps a tokenizer function for @external tokens declarations. It allows custom logic to read from an InputStream and emit tokens using acceptToken. Options control caching, priority, and parallel execution. ```APIDOC ## `ExternalTokenizer` — Custom tokenizer for `@external tokens` `ExternalTokenizer` wraps a tokenizer function referenced by an `@external tokens` declaration in a Lezer grammar. The function receives an `InputStream` and a `Stack`, reads characters from the stream, and calls `input.acceptToken(tokenType)` to emit a token. Options control caching behavior (`contextual`), priority (`fallback`), and parallel running (`extend`). ```typescript import { ExternalTokenizer } from "@lezer/lr" import { InputStream } from "@lezer/lr" // Token IDs come from the generated terms file import { insertSemicolon, noSemicolon } from "./generated-parser.terms" // Automatic semicolon insertion tokenizer (JavaScript-style) export const semicolonTokenizer = new ExternalTokenizer( (input: InputStream, stack) => { const prev = input.peek(-1) // look behind 1 char // If the previous character was a newline and the stack allows a semicolon if ( (prev === 10 /* \n */ || prev === 13 /* \r */ || prev === -1 /* EOF */) && stack.canShift(insertSemicolon) ) { input.acceptToken(insertSemicolon) } else { input.acceptToken(noSemicolon) } }, { contextual: true, // don't cache; result depends on parse stack state fallback: false, // run with normal priority extend: false, // stop other tokenizers after this one matches } ) ``` ``` -------------------------------- ### Implement Automatic Semicolon Insertion with ExternalTokenizer Source: https://context7.com/lezer-parser/lr/llms.txt Use ExternalTokenizer to implement JavaScript-style automatic semicolon insertion. This tokenizer checks the previous character and the parser stack to decide whether to insert a semicolon token. It requires token IDs from a generated terms file. ```typescript import { ExternalTokenizer } from "@lezer/lr" import { InputStream } from "@lezer/lr" // Token IDs come from the generated terms file import { insertSemicolon, noSemicolon } from "./generated-parser.terms" // Automatic semicolon insertion tokenizer (JavaScript-style) export const semicolonTokenizer = new ExternalTokenizer( (input: InputStream, stack) => { const prev = input.peek(-1) // look behind 1 char // If the previous character was a newline and the stack allows a semicolon if ( (prev === 10 /* \n */ || prev === 13 /* \r */ || prev === -1 /* EOF */) && stack.canShift(insertSemicolon) ) { input.acceptToken(insertSemicolon) } else { input.acceptToken(noSemicolon) } }, { contextual: true, // don't cache; result depends on parse stack state fallback: false, // run with normal priority extend: false, // stop other tokenizers after this one matches } ) ``` -------------------------------- ### Stack.dialectEnabled Source: https://context7.com/lezer-parser/lr/llms.txt Tests if a grammar dialect is active. Returns `true` if the specified dialect ID is currently enabled on the parser. Used to conditionally emit dialect-specific tokens. ```APIDOC ## `Stack.dialectEnabled` — Test if a grammar dialect is active `Stack.dialectEnabled(dialectID)` returns `true` when the given dialect (identified by its numeric ID as exported from the grammar's terms file) is currently enabled on the parser. Used inside tokenizers or specializers to conditionally emit dialect-specific tokens. ```typescript import { ExternalTokenizer } from "@lezer/lr" import { Dialect_jsx, jsxOpenTag } from "./javascript.terms" import { lessThan } from "./javascript.terms" // Only lex '<' as JSX open-tag start when jsx dialect is enabled export const jsxTokenizer = new ExternalTokenizer( (input, stack) => { if (input.next !== 60 /* '<' */) return if (!stack.dialectEnabled(Dialect_jsx)) { // Fall through to normal '<' tokenizer return } input.advance() // Further JSX tag scanning… input.acceptToken(jsxOpenTag) }, { fallback: true } ) // Enabling the dialect when building the parser: import { parser } from "./javascript-parser" const jsxParser = parser.configure({ dialect: "jsx" }) const tree = jsxParser.parse("
hello
") ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.