You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否在Tatsu语法中将终结符指定为任意外部函数而非BNF规则?

在Tatsu中用外部函数实现终结符匹配

完全可以在Tatsu语法中实现类似peginator的外部函数绑定终结符的功能,主要有两种实用方案:

1. 语法内直接嵌入外部函数调用

Tatsu允许在语法规则中用{...}块嵌入Python代码,你可以直接在这里调用外部函数处理终结符匹配,替代传统BNF规则。

假设你有一个外部函数match_phone_number(input_str, pos),它接收当前输入字符串和匹配位置,返回(匹配结果, 新位置)或None表示匹配失败,语法可这样写:

start = phone_number ;

phone_number = {
    result, new_pos = match_phone_number(self._input, self.pos)
    if result is not None:
        self.pos = new_pos
        return result
    raise self.error("Invalid phone number")
} ;

解析器生成时,Tatsu会执行这段代码,将外部函数的匹配逻辑直接绑定到phone_number终结符上。

2. 自定义令牌器(Lexer)处理终结符

如果需要全局复用外部函数的匹配逻辑,更推荐自定义Lexer,将外部函数集成到令牌识别流程中:

第一步:实现自定义Lexer

from tatsu.lexer import Lexer
from tatsu.util import Token

# 外部匹配函数示例
def match_custom_token(input_str, pos):
    # 自定义匹配逻辑,比如识别特定格式字符串
    if pos + 5 <= len(input_str) and input_str[pos:pos+5] == "CUSTM":
        return Token("CUSTOM_TOKEN", "CUSTM", pos, pos+5)
    return None

class ExternalFunctionLexer(Lexer):
    def next_token(self):
        # 优先用外部函数匹配自定义终结符
        token = match_custom_token(self.input, self.pos)
        if token:
            self.pos = token.end
            return token
        # 外部函数不匹配时, fallback到默认Lexer的令牌处理
        return super().next_token()

第二步:在语法中使用自定义令牌

start = CUSTOM_TOKEN ;

第三步:生成解析器时指定Lexer

from tatsu import compile

grammar = """
start = CUSTOM_TOKEN ;
"""

parser = compile(grammar, lexer=ExternalFunctionLexer)
# 测试解析
result = parser.parse("CUSTM")
print(result)  # 输出: CUSTM

注意事项

  • 外部函数需正确处理输入位置偏移,确保Tatsu能跟踪当前匹配进度
  • 语法内嵌入代码时,可通过self._input访问完整输入,self.pos访问当前匹配位置,修改self.pos更新进度
  • 自定义Lexer时,要确保外部函数的匹配逻辑和默认Lexer规则不冲突,避免令牌识别混乱

内容的提问来源于stack exchange,提问作者perrymil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 12:33:10