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

ANTLR4解析器词法上下文问题:WOOL语言语法解析解决方案咨询

WOOL语言ANTLR4词法歧义问题解决

问题背景

WOOL语言允许以下三种结构:

[[ text | NodeName ]]
[[ NodeName ]]
[[ text | NodeName | text ]]

其中:

  • text需保留输入原样(包含空格,仅排除|和])
  • NodeName是符合规则的标识符(格式为[a-zA-Z_][a-zA-Z_0-9]*或标识符.标识符)

核心问题:词法分析器无法区分[[后的内容是文本还是NodeName标识符,将nodeName规则中的CHAR替换为ID时,会触发语法错误:

line 1:21 no viable alternative at input '[this is some text. | NodeName '

现有最小化语法

WParser.g4

parser grammar WParser;
options { tokenVocab=WLexer;}

// 语法起始规则
program: replies EOF ;

// 回复列表最多包含一个特殊回复
replies : reply* specialreply? reply* ;

// 普通回复包含1或2个管道符,必须包含nodeName
reply : LBOX CHAR PIPE nodeName RBOX
      | LBOX CHAR PIPE nodeName PIPE CHAR RBOX ;

// 特殊回复仅包含nodeName
specialreply : LBOX nodeName RBOX ;

// NodeName格式
nodeName : CHAR 
    | CHAR DOT CHAR;

WLexer.g4(原始版本)

lexer grammar WLexer;

COMMENT_TXT : '//' ~( '\r' | '\n' )* -> skip ;
WS: [\n\r\f]+ -> skip ;              // 此模式下空格不被跳过

LBOX : '[' ;
RBOX : ']' ;
PIPE : '|' ;
DOT  : '.' ;

ID: [a-zA-Z_][a-zA-Z_0-9]* ;
CHAR : ~( '\f' | '\n' | '\r' | '[' | ']' | '>' | '|' | '<' | '/' | '=' | '$' )+ ;

问题根源

原始词法规则中,CHAR的匹配范围完全覆盖了ID的字符集,而ANTLR4词法分析遵循「最长匹配+先定义优先」原则,导致本该被识别为ID的NodeName被优先匹配成CHAR,最终触发解析错误。

解决方法:使用词法模式(Lexer Modes)

通过切换词法模式,在进入[[后启动专属处理模式,明确区分文本、NodeName和分隔符:

修改后的WLexer.g4

lexer grammar WLexer;

COMMENT_TXT : '//' ~( '\r' | '\n' )* -> skip ;
WS: [\n\r\f]+ -> skip ;

// 全局模式仅匹配[[起始标记,切换到内容模式
LBOX_START : '[[' -> pushMode(BOX_CONTENT);

// 定义括号内内容的专属词法模式
mode BOX_CONTENT;
    // 匹配闭合标记并退出当前模式
    RBOX_END : ']]' -> popMode;
    // 分隔符标记
    PIPE : '|';
    DOT : '.';
    // 优先识别NodeName标识符
    ID: [a-zA-Z_][a-zA-Z_0-9]* ;
    // 匹配文本:除]]和|之外的所有字符(包含空格)
    TEXT : ~(']'|'|')+ ;
    // 单独的]不属于闭合标记,归为文本
    UNMATCHED_BRACKET : ']' -> type(TEXT);

修改后的WParser.g4

parser grammar WParser;
options { tokenVocab=WLexer;}

program: replies EOF ;

replies : reply* specialreply? reply* ;

// 普通回复的两种格式
reply : LBOX_START TEXT PIPE nodeName RBOX_END
      | LBOX_START TEXT PIPE nodeName PIPE TEXT RBOX_END ;

// 特殊回复格式
specialreply : LBOX_START nodeName RBOX_END ;

nodeName : ID 
    | ID DOT ID;

原理说明

  1. 模式切换:匹配到[[后进入BOX_CONTENT模式,仅处理括号内的内容,避免全局规则干扰。
  2. 优先级明确:在内容模式下,ID的定义优先于TEXT,确保NodeName被正确识别为标识符。
  3. 文本精准匹配:TEXT仅排除]]和|两个关键分隔符,既保留了文本的原始格式,又不会误匹配分隔标记。

内容的提问来源于stack exchange,提问作者rieks op den akker

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 23:50:26