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

如何基于ANTLR4定义支持缩进块的自定义语言语法规则?

问题根因分析

你的缩进解析异常是3个核心错误共同导致的:

  1. Lexer规则顺序与定义错误:你把WS规则放在NL之前,且WS的匹配范围包含了换行符,所有换行都会被WS直接吞掉并跳过,NL规则永远不会被触发,antlr-denter收不到换行事件,根本无法计算缩进层级、生成正确的INDENT/DEDENT标记。
  2. NL规则定义不符合要求:你当前的NL规则强制要求换行后紧跟制表符,不支持空格缩进的场景,也不符合antlr-denter对换行标记的要求。
  3. 语法规则未兼容无子块的场景:你的relation规则强制要求关系词后必须跟随缩进块,当关系词后没有子节点时会匹配失败,导致后续的节点被错误归到上一级块中。
修复步骤

1. 重写Lexer规则

调整规则顺序,拆分换行与行内空白的处理,仅skip行内的空格/制表符,保留换行符给denter处理:

// lexer规则调整顺序,NL放在WS前面
NL: ('\r'? '\n') ;
// 仅匹配行内的空格、制表符,跳过
WS: [ \t]+ -> skip;
RELATION_WORD: ('alternative' | 'or' | 'optional' | 'mandatory');
WORD: [a-zA-Z][a-zA-Z0-9_]*;

2. 修正denter初始化参数

将ignore_eof设为False,保证文件结束时会自动生成对应数量的DEDENT标记,避免语法解析缺标记报错:

def nextToken(self):
    if not self.denter:
        # 最后一个参数改为False
        self.denter = self.UVLDenter(self, self.NL, UVLParser.INDENT, UVLParser.DEDENT, False)
    return self.denter.next_token()

3. 调整语法规则兼容无子块的场景

修改relation规则,允许关系词后不跟随缩进块:

// 原relation规则强制要求缩进块,修改为可选
relation: relation_spec (INDENT child* DEDENT)?;
// 若允许features块下有多个child,可以调整features规则为
// features: 'features' INDENT child+ DEDENT;

验证说明

修改后重新生成词法、语法解析器,你的两个测试用例都会得到正确的层级结构:

  • 第一个用例中mandatory、optional都会被识别为Server的子节点,各自的子特征归到对应关系节点下
  • 第二个用例中无后续子节点的mandatory会正常匹配,不会把后续的optional吞入自己的子块

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 14:51:04