如何访问TatSu解析器的parserinfo对象?
如何获取TatSu中
parseinfo=True生成的解析细节 嘿,很高兴看到你已经用TatSu成功解析COBOL代码片段了!关于启用parseinfo=True后如何获取解析细节,我来给你演示几个实用的示例,帮你把这些信息用起来。
当你在调用parse()时设置parseinfo=True,TatSu会给生成的AST(抽象语法树)中的每个节点添加一个parseinfo属性,里面包含了这个节点对应的原始文本位置、匹配的规则名称、原始文本内容等关键信息。
改造你的代码来提取解析信息
我基于你的代码做了扩展,展示如何访问和打印这些解析细节:
from tatsu import parse, compile # 更安全的文件读取方式(用with语句自动关闭文件) with open("cobfd.bnf", "r") as cobbnf_file: cobbnf = cobbnf_file.read() with open("test.cob", "r") as cobtest_file: cobtest = cobtest_file.read() # 编译语法并开启解析信息收集 model = compile(cobbnf, "cobol") ast = model.parse(cobtest, parseinfo=True, trace=False) # 示例1:直接访问单个AST节点的解析信息 # 注意:这里的节点名称(比如'identification_division')需要和你的BNF规则对应 if hasattr(ast, 'identification_division'): div_parseinfo = ast.identification_division.parseinfo print("=== 单个节点解析信息 ===") print(f"匹配的规则名称: {div_parseinfo.rule}") print(f"起始位置: 第{div_parseinfo.start[0]}行,第{div_parseinfo.start[1]}列") print(f"结束位置: 第{div_parseinfo.end[0]}行,第{div_parseinfo.end[1]}列") print(f"匹配的原始文本:\n{div_parseinfo.text}\n") # 示例2:递归遍历所有AST节点,打印所有解析信息 def traverse_parseinfo(node, indent=0): indent_str = " " * indent # 检查当前节点是否有解析信息 if hasattr(node, 'parseinfo'): info = node.parseinfo print(f"{indent_str}▶️ 规则: {info.rule}") print(f"{indent_str} 位置: {info.start} → {info.end}") print(f"{indent_str} 文本片段:\n{indent_str} {info.text.strip().replace('\n', f'\n{indent_str} ')}") print(f"{indent_str}------------------------") # 递归遍历子节点(处理对象和列表类型的子节点) for attr_name in dir(node): # 跳过私有属性和方法 if attr_name.startswith('_'): continue attr_value = getattr(node, attr_name) # 如果是列表/元组,遍历每个元素 if isinstance(attr_value, (list, tuple)): for item in attr_value: if hasattr(item, '__dict__'): # 判断是否是TatSu生成的AST节点 traverse_parseinfo(item, indent + 1) # 如果是单个对象节点 elif hasattr(attr_value, '__dict__'): traverse_parseinfo(attr_value, indent + 1) # 调用遍历函数 print("=== 所有AST节点的解析信息 ===") traverse_parseinfo(ast)
关键说明
- 节点名称对应:示例中的
identification_division是COBOL常见的规则节点,你需要根据自己的cobfd.bnf中的规则名称来替换这个节点名,否则会找不到对应的属性。 - parseinfo的属性:每个
parseinfo对象包含这些核心字段:rule: 匹配当前节点的BNF规则名称start: 元组(行号, 列号),对应原始文本中节点的起始位置end: 元组(行号, 列号),对应原始文本中节点的结束位置text: 匹配当前节点的原始文本内容
- 递归遍历:示例中的
traverse_parseinfo函数可以帮你遍历整个AST结构,不管你的BNF嵌套多深,都能打印出所有带解析信息的节点。
如果你的BNF中有一些匿名规则或者用了skip指令,这些部分不会生成带parseinfo的节点,这是正常的,只有那些生成AST节点的规则才会包含解析信息。
内容的提问来源于stack exchange,提问作者dreamer
相关产品推荐
相关产品推荐

