Skip to content

Parsing YAML

Package: @lanexio/parser-grammar-yaml Stable Layer: 2 (Grammar). Depends only on @lanexio/parser-core. Runtime: Universal (browser, server, edge worker).

parseYaml implements an iterative YAML 1.2.2 parser with an explicit indentation/container stack. It handles block mappings and sequences, flow collections ({…} and […]), scalars, anchors, aliases, tags, comments, directives, and multi-document streams.

Input is always a Uint8Array. Output is always a LexTree. Malformed input produces YamlKind.Error nodes — parseYaml never throws.

Parse YAML produces structured trees: flow sequences emit FlowSequence → SequenceItem and flow mappings emit FlowMapping → MappingPair → (Key, Value). Block structures mirror the YAML indentation hierarchy.

import {
parseYaml,
YamlKind,
YAML_KIND_NAMES_BY_ID,
yamlGrammar,
type ParseYamlOptions,
type YamlKindValue,
} from '@lanexio/parser-grammar-yaml';
import { parseYaml } from '@lanexio/parser-grammar-yaml';
const encoder = new TextEncoder();
const tree = parseYaml(encoder.encode('key: value\nlist:\n - one\n - two'));
console.log(tree.nodeCount); // total nodes
console.log(tree.root.kind); // Stream root kind id (0x0a00)

parseYaml accepts a Uint8Array. Always use TextEncoder when converting a string to bytes.

Flow mappings and sequences produce structured subtrees, not flat leaf nodes:

import { parseYaml, YamlKind } from '@lanexio/parser-grammar-yaml';
const encoder = new TextEncoder();
const tree = parseYaml(encoder.encode('{ x: 1, y: [2, 3] }'));
// Walk: Stream → Document → FlowMapping → MappingPair → (Key, Value)
// MappingPair → Key("y"), Value(FlowSequence → ...)
const tree = parseYaml(encoder.encode('---\nfirst: doc\n---\nsecond: doc\n...'));
// Stream contains two Document nodes, each with its own BlockMapping root
FieldTypeDefaultDescription
strictModebooleanundefinedReserved for future use. Currently has no effect.
import { parseYaml, YamlKind } from '@lanexio/parser-grammar-yaml';
const encoder = new TextEncoder();
const tree = parseYaml(encoder.encode('key:\n\t-inconsistent indent'));
for (const node of tree.root.children()) {
if (node.kind === YamlKind.Error) {
console.log('parse error at', node.range);
}
}

parseYaml never throws. Malformed input produces YamlKind.Error nodes. The parser always recovers and continues. The flow-collection state machine also carries a structural forward-progress guard: even a hypothetical dispatch gap degrades to an Error node plus a one-byte advance rather than a hang.

import { YamlKind } from '@lanexio/parser-grammar-yaml';
// YamlKind is a const object. Use 'as const' pattern, never enum.
const kind: YamlKindValue = YamlKind.BlockMapping;
// Example: walk only scalar nodes
const cursor = tree.cursor();
visit: while (true) {
if (cursor.current.kind === YamlKind.Scalar) {
console.log('scalar at', cursor.current.range);
}
if (cursor.gotoFirstChild()) continue;
while (!cursor.gotoNextSibling()) {
if (!cursor.gotoParent()) break visit;
}
}

YamlKind values are stable across versions. Never use raw numbers — always reference YamlKind.<name>.

ExportTypeDescription
parseYaml(bytes: Uint8Array, options?: ParseYamlOptions) => LexTreeParse YAML 1.2.2. Never throws.
ParseYamlOptions{ readonly strictMode?: boolean }Options for parseYaml.
YamlKindconst objectNumeric kind IDs for all YAML node types (0x0A00 block).
YamlKindValuetype unionUnion of all YamlKind values.
YAML_KIND_NAMES_BY_IDReadonlyMap<number, string>Kind-name lookup by numeric ID.
yamlGrammarLanexioParserPureGrammarGrammar descriptor — pass to createParser from @lanexio/parser.
MetricValue
yaml-test-suite valid267 / 268 (99.6%)
Internal conformance171 / 171
verify:no-throw67 entry points
Fuzz soak (300s)10.7M rounds / 0 crashes
  • @lanexio/parser-core — shared buffer protocol, LexTree, LexNode, LexCursor.
  • @lanexio/parser — unified entry point; pass this package’s grammar descriptor to createParser for a string-accepting, never-throwing parser handle.