如何让Peggy生成的解析器的解析动作访问类实例环境
类实例内调用Peggy解析器并共享运行环境的实现方法
Peggy生成的解析器原生支持通过parse方法的第二个入参传递自定义上下文,不需要修改生成的解析器代码即可实现需求,以下是两种可直接落地的方案:
方案1:传入完整类实例(适合需要访问多个实例属性/方法的场景)
Peggy语法中的动作代码可以直接读取parse方法传入的options对象,你可以把当前类实例作为属性放入options传递给解析器。
1. 定义Peggy语法规则
// myGrammar.peggy // 示例规则:逐行解析文本并调用实例方法处理每行内容 start = line+ line = content:[a-zA-Z0-9]+ '\n' { // 直接通过options访问传入的类实例,调用实例方法 return options.self.processLine(content.join('')); }
2. 类内调用解析器
// 引入Peggy编译生成的解析器 const parser = require('./compiled-parser.js'); class TextProcessor { constructor() { // 实例运行时数据,解析器动作内可直接访问 this.linePrefix = '[Parsed] '; } // 提供给解析器调用的实例方法 processLine(lineContent) { // 这里的this正确指向当前类实例 return `${this.linePrefix}${lineContent}`; } // 触发解析的入口方法 parseInput(rawText) { // 核心:将当前实例通过options传入解析器 return parser.parse(rawText, { self: this }); } } // 调用示例 const processor = new TextProcessor(); console.log(processor.parseInput('hello\nworld\n')); // 输出:[ '[Parsed] hello', '[Parsed] world' ]
方案2:仅传入绑定好this的方法(适合最小化暴露实例能力的场景)
如果不需要给解析器开放整个实例的访问权限,可以只把需要用到的方法绑定当前实例的this后传入:
1. Peggy语法调整
start = line+ line = content:[a-zA-Z0-9]+ '\n' { return options.processLine(content.join('')); }
2. 类内传参调整
parseInput(rawText) { return parser.parse(rawText, { // 绑定this确保方法内指向当前类实例 processLine: this.processLine.bind(this) }); } // 如果你用类字段箭头函数定义processLine,不需要手动bind: // processLine = (lineContent) => { return `${this.linePrefix}${lineContent}`; }
常见问题排查
- 如果出现
this指向错误:检查方法传入时是否完成bind,或者是否用了箭头函数定义实例方法 - 如果解析器找不到传入的方法/属性:确认
options里的属性名和语法动作里调用的属性名完全一致
内容的提问来源于stack exchange,提问作者rogerl
相关产品推荐
相关产品推荐

