JavaScript 词法分析器通过 Iterator 接口与生成器实现流式 token 提取,每个 token 含 type、value、start、end;Lexer 类以 [Symbol.iterator]() 返回生成器,按正则优先级逐字符匹配并更新位置,支持状态切换与实用辅助方法。

用 JavaScript 的 Iterator 接口 + 自定义生成器实现轻量词法分析器,核心是把输入文本按规则切分成带类型和位置的 token 流,用生成器函数逐个产出,避免一次性构建全部 token 数组,节省内存、支持流式处理。
定义 Token 结构与基础 Lexer 类骨架
每个 token 至少包含 type(如 'IDENTIFIER'、'NUMBER'、'STRING')、value(原始内容)、start 和 end(字符索引位置)。Lexer 类不直接返回数组,而是提供一个 [Symbol.iterator]() 方法,返回生成器实例:
- 构造时只保存源码字符串和初始位置(如
this.source = source; this.pos = 0;) -
[Symbol.iterator]()返回function* tokenize() { ... },内部调用私有解析逻辑 - 每次
next()触发一次 token 提取,直到源码耗尽
用正则驱动的逐字符扫描实现核心 tokenize 生成器
在生成器函数中,用 while 循环配合正则测试当前位置是否匹配某类 token。推荐从最长/最具体模式开始匹配(如先试字符串字面量,再试关键字,最后试标识符),避免歧义:
- 跳过空白和单行/多行注释(用
/s+|//.*$|/*[sS]*?*//gm或手动识别) - 对每种 token 类型写独立正则,例如:
/^"[^"\\]*(?:\\.[^"\\]*)*"/匹配双引号字符串(支持转义) - 匹配成功后,提取 value、计算 end 位置、更新
this.pos,yield当前 token 对象 - 若无任何匹配,抛出错误或生成
{ type: 'ILLEGAL', value: this.source[this.pos] }
支持上下文敏感词法(如模板字符串中的插值)
简单 lexer 可能只做扁平扫描,但真实场景需状态切换。可在生成器内维护一个 state 栈(如 ['INIT', 'IN_STRING', 'IN_TEMPLATE']),根据当前状态决定匹配规则:
立即学习“Java免费学习笔记(深入)”;
- 遇到
`进入IN_TEMPLATE状态,此时除普通内容外还要识别${开始的表达式插值 - 进入插值后切换到
IN_INTERPOLATION,匹配结束括号}后恢复上一状态 - 状态变更时 yield 对应的开始/结束 token(如
{ type: 'TEMPLATE_HEAD', value: '...' })
暴露实用方法增强可用性
除了标准迭代器,可添加辅助方法提升开发体验:
-
peek():不消耗当前 token,返回下一个 token 的副本(需缓存一次next()结果) -
skip(type):跳过指定类型的 token(如跳过所有逗号),方便语法分析层使用 -
takeWhile(predicate):收集满足条件的连续 token(如提取参数列表中的所有标识符) - 所有方法都基于同一生成器实例,保持位置同步,不破坏迭代状态
不复杂但容易忽略:生成器必须严格管理 this.pos 偏移,避免漏字符或重复消费;正则全局标志 g 在多次 exec 中会改变 lastIndex,建议每次用 regex.exec(str.slice(pos)) 并手动计算偏移,更可控。


















