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

如何在ANTLR4中实现嵌套表达式(海岛)与普通文本的正确分离

修复ANTLR4类StringSubstitutor语言的语法解析问题

问题背景

我基于ANTLR4实现一款类StringSubstitutor的简单语言语法(因使用C#无法直接用原Java库),支持在普通文本中做变量替换,示例输入:

text ${aaa}${/asd/${yyy}} goes on ${fff} and on

语言支持${id}、${/some/path}格式,且路径允许嵌套表达式。

当前已实现无外围普通文本时的解析,但添加普通文本识别后,TEXT规则会在IN_LOCAL_EXPR模式下错误匹配ID,导致本该解析为localVariable或path的内容被识别为text,出现重复解析问题。需要修复语法,同时支持嵌套表达式和外围普通文本识别。

当前有问题的代码

Lexer代码

lexer grammar LocalExpressionLexer;

BEGIN : '${';
END : '}';
SPACE          : [ \t\r\n]-> skip;

ID : [0-9a-zA-Z_]+;
PATH_SEPARATOR : '/';

LOCAL_EXPRESSION
 : BEGIN -> more, pushMode(IN_LOCAL_EXPR) 
 ;

TEXT
 : ~[$]+
 ;
  
mode IN_LOCAL_EXPR;
  LOCAL_EXPR_END : END -> more, popMode;

Parser代码

parser grammar LocalExpressionParser;

options {
  tokenVocab=LocalExpressionLexer;
}

parse
 : (atom | text)+ EOF
 ;

atom
 : BEGIN (localVariable | path) END
 ;

localVariable
 : ID;
 
path
 : (PATH_SEPARATOR (atom | ID))+
 ;

text
 : TEXT
 ;

修复方案

修复后的Lexer代码

lexer grammar LocalExpressionLexer;

// 全局模式规则
BEGIN : '${' -> pushMode(IN_LOCAL_EXPR);
END : '}';
SPACE : [ \t\r\n] -> skip;

// 匹配普通文本:除$外的字符,或单独的$(非${开头)
TEXT : (~[$] | '$' ~'{')+;

mode IN_LOCAL_EXPR;
  // 表达式内的结束符,退出当前模式
  IN_END : '}' -> popMode;
  // 表达式内的标识符
  IN_ID : [0-9a-zA-Z_]+;
  // 表达式内的路径分隔符
  IN_PATH_SEPARATOR : '/';
  // 表达式内嵌套的开始符,推入新的表达式模式
  IN_BEGIN : '${' -> pushMode(IN_LOCAL_EXPR);
  // 跳过表达式内的空白(如需保留可删除此规则)
  IN_SPACE : [ \t\r\n] -> skip;

修复后的Parser代码

parser grammar LocalExpressionParser;

options {
  tokenVocab=LocalExpressionLexer;
}

parse
 : (atom | text)+ EOF
 ;

text
 : TEXT
 ;

atom
 : BEGIN (localVariable | path) END
 ;

localVariable
 : IN_ID;
 
path
 : (IN_PATH_SEPARATOR (atom | IN_ID))+
 ;

修复说明

  1. 核心问题解决:原Lexer在IN_LOCAL_EXPR模式下未定义ID、路径分隔符等规则,导致Lexer回退到全局规则匹配TEXT,错误识别表达式内的内容。现在在IN_LOCAL_EXPR模式下单独定义对应规则,确保表达式内的标识符、路径分隔符和嵌套表达式被正确识别。
  2. TEXT规则优化:将全局TEXT规则改为(~[$] | '$' ~'{')+,既匹配非$的普通文本,也兼容单独的$字符(避免误判为表达式开头)。
  3. 移除冗余配置:删除原LOCAL_EXPR规则的more命令,该命令会追加令牌内容,不符合当前解析需求;同时全局模式下不再需要ID和PATH_SEPARATOR规则,所有相关令牌都在表达式模式内定义。
  4. Parser规则适配:将Parser中引用的ID、PATH_SEPARATOR改为IN_LOCAL_EXPR模式下的IN_ID、IN_PATH_SEPARATOR,确保令牌匹配正确。

验证效果

修复后的语法可正确解析示例输入,识别出所有普通文本段、变量表达式和嵌套路径表达式,无重复解析或错误匹配问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 08:17:53