noldova.context.parsers
上下文语言解析器的共享基础:具有的不可变源 跨度和行位置,上面的读取器,词法分析器和解析器基 类,每种语言解析器都建立在这些类之上。它没有语法;打印稿, Regex和未来的语言是单独的包。
安装
npm install @noldova/context.parsers
模型
Source保存文本一次。SourceSpan是一个半开放的UTF-16范围;SourceLineMap将偏移量映射到行和回。SourceReader源或源的有界区域上的游标。最后 它返回空字符和代码点0,因此词法分析器比较字符 而不是检查结束;在哪里空字符是合法的 输入,isAtEnd决定。Node是每个语法节点的基础:一个跨度和可选的琐事。一个 语言通过自己的声明合并向节点添加行为 包;语法代码识别节点类型instanceof.Lexer拥有它的阅读器,报告到解析器上下文的诊断 收集器,每次调用产生一个节点。它检查两个不变量 每一种语言:lex要么推进,要么产生EndOfFileNode正好在最后,重复词法也遵循同样的规则。Parser保存一个当前节点。它按节点类型推进、消耗、查找 向前,并尝试解释与精确倒带,并重新释放电流 节点时,语法位置改变了标记的含义,例如>>在类型参数或/正则表达式的开头。ParserContext携带语法状态并拥有已发布的内容DiagnosticCollector. 一种语言为它的标志和符号派生出它自己的上下文 缓存。
诊断
解析器上下文拥有的一个序列接收 报告的顺序:词法分析器的顺序是每个节点的顺序,语法的顺序是每个节点的顺序 解析。这是语法决策可以参考的序列。倒带恢复 当前节点,读取器偏移量,和序列长度,什么都没有 从中间移开。re-lex也不会移除任何东西;更换 扫描报告已经存在的东西,一种语言的扫描可以 在同一位置重复诊断应用其自身的抑制规则,如 TypeScript使用tsc的相同偏移量规则。
信任边界
将位置交还给读者,通过 seek, advance,相对的窥视;
或者跨度的创造,来自于读者本身,不需要再次验证;
这使每个令牌路径免于检查。所有接受偏移量的东西
或者从其他地方的span验证它: Source, SourceReader 构造函数,
SourceLineMap, SourceLine, SourcePosition.
使用
语言解析器从这些类派生其节点、词法分析器和解析器:
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);
例子的 console 需要Node的类型: @types/node,
"types": ["node"] 在 tsconfig.json. 声明文件 api/index.d.ts
记录每个成员的合同和示例。
许可证
麻省理工学院;看到 LICENSE.