@noldova/context.parsers

中文文档
0.0.4发布于 2026/11/02MITTypeScriptES Module构建来源已验证

The shared foundation for CONTEXT language parsers: an immutable source with spans and line positions, a reader over it, and the lexer and parser base classes every language parser builds on. It contains no grammar; TypeScript, Regex, and future languages

原始使用文档
文档目录6 节
  1. Install
  2. Model
  3. Diagnostics
  4. Trust boundary
  5. Use
  6. License

noldova.context.parsers

The shared foundation for CONTEXT language parsers: an immutable source with spans and line positions, a reader over it, and the lexer and parser base classes every language parser builds on. It contains no grammar; TypeScript, Regex, and future languages are separate packages.

Install

npm install @noldova/context.parsers

Model

  • Source holds the text once. SourceSpan is a half-open UTF-16 range in it; SourceLineMap maps offsets to lines and back.
  • SourceReader is a cursor over a source or a bounded region of it. At the end it returns the null character and code point 0, so a lexer compares characters instead of checking for the end; where a null character can be legitimate input, isAtEnd decides.
  • Node is the base of every syntax node: a span and optional trivia. A language adds behavior to nodes through declaration merging in its own package; grammar code recognizes node types with instanceof.
  • Lexer owns its reader, reports into the parser context's diagnostic collector, and produces one node per call. It checks two invariants for every language: a lex either advances or produces the EndOfFileNode exactly at the end, and re-lexing obeys the same rules.
  • Parser holds one current node. It advances, consumes by node type, looks ahead and tries interpretations with exact rewind, and re-lexes the current node when the grammar position changes what a token means, such as >> inside type arguments or / beginning a regular expression.
  • ParserContext carries grammar state and owns the published DiagnosticCollector. A language derives its own context for its flags and caches.

Diagnostics

One sequence, owned by the parser context, receives every diagnostic in the order it is reported: the lexer's as each node is lexed, the grammar's as it parses. That is the sequence grammar decisions may consult. A rewind restores the current node, the reader offset, and the sequence length, and nothing is ever removed from the middle. A re-lex removes nothing either; the replacement scan reports after what is already there, and a language whose scans can repeat a diagnostic at the same position applies its own suppression rule, as TypeScript does with tsc's same-offset rule.

Trust boundary

Positions handed back to the reader, through seek, advance, a relative peek, or span creation, come from the reader itself and are not validated again; this keeps the per-token path free of checks. Everything that accepts an offset or span from elsewhere validates it: Source, the SourceReader constructor, SourceLineMap, SourceLine, and SourcePosition.

Use

A language parser derives its nodes, lexer and parser from these classes:

import { DiagnosticCollector, EndOfFileNode, Lexer, LiteralNode, Node, Parser, ParserContext, Source, SourceSpan } from "@noldova/context.parsers";

class TextLiteralNode extends LiteralNode {
  public constructor(value: string, span: SourceSpan) {
    super(value, span);
  }
}

class TextLexer extends Lexer {
  public constructor(source: Source, diagnosticCollector: DiagnosticCollector) {
    super(source, diagnosticCollector);
  }

  protected override lexNode(): Node {
    const startOffset = this.reader.currentOffset;
    if (this.reader.isAtEnd)
      return new EndOfFileNode(new SourceSpan(startOffset, 0));

    const text = this.reader.readWhile(() => true).toString();
    return new TextLiteralNode(text, new SourceSpan(startOffset, text.length));
  }
}

class TextParser extends Parser<LiteralNode> {
  public constructor(context: ParserContext, lexer: TextLexer) {
    super(context, lexer);
  }

  protected override parseRootNode(): LiteralNode {
    const root = this.requireCurrentNode(LiteralNode);
    this.advance();
    return root;
  }
}

const source = new Source("text");
const context = new ParserContext(source);
const result = new TextParser(context, new TextLexer(source, context.diagnosticCollector)).parse();
console.assert(result.rootNode.value === "text" && result.diagnostics.length === 0);

The example's console needs Node's types: @types/node, with "types": ["node"] in tsconfig.json. The declaration file api/index.d.ts documents every member with its contract and examples.

License

MIT; see LICENSE.

版本与发布记录

@noldova/context.parsers 共发布 5 个版本,首次发布于 2026/10/31;过去 12 个月发布了 5 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.0.4latest2026/11/021 天前
0.0.32026/10/313 天前
0.0.22026/10/313 天前
0.0.12026/10/313 天前
0.0.0-stage2026/10/313 天前

关于 @noldova/context.parsers 的常见问题

@noldova/context.parsers 是什么?

CONTEXT语言解析器的共享基础:一个具有跨度和行位置的不可变源,它上面的一个读取器,以及每个语言解析器所基于的词法分析器和解析器基类。它没有语法;TypeScript, Regex和未来的语言

如何安装 @noldova/context.parsers?

在项目目录运行 npm install @noldova/context.parsers,或使用 pnpm add / yarn add / bun add。

@noldova/context.parsers 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@noldova/context.parsers 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@noldova/context.parsers 可以商用吗?

@noldova/context.parsers 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@noldova/context.parsers 还在维护吗?

最新版本 0.0.4 发布于 2026/11/02(1 天前);至今共发布 5 个版本,其中过去 12 个月发布了 5 个;首次发布于 2026/10/31。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。