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

如何用ANTLR4解析可作为格式化文本内容的可选分隔符?

自定义配置格式的ANTLR4解析优化需求

输入示例

// Example 1:
/*
$NAME = John "Blue" Doe
$AGE = 20

$DESCRIPTION = Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et
    ====================================
    Bytes:
        - Byte 0 = example 1
        - Byte 1 = example 2
        - Byte 3 = example 3      
$ENDDESCRIPTION

$CITY = London     $DISTRICT = Sutton
*/

// Example 2:
/*
$NAME = Jane "Ruby" Doe
$AGE = 28

$DESCRIPTION 
    Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
    tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. 
    ====================================
    At vero eos et accusam et justo duo dolores et ea rebum.     
$ENDDESCRIPTION

$CITY = Berlin     $DISTRICT = Spandau
*/

需求

  • 存在大量键值对:
    • keywords定义为前缀$后跟大写字母。
    • pairs通常以=分隔,仅$DESCRIPTION的=分隔符可选(遗留文件已有30多年历史),$ENDDESCRIPTION无分隔符,用于标记文本结束。
    • values通常为“分隔符到换行符之间的内容”,仅$DESCRIPTION的值为可跨多行的格式化文本,以$ENDDESCRIPTION结束。
  • 部分行可包含多个关联赋值(如$CITY = London $DISTRICT = Sutton)
  • $DESCRIPTION的格式化文本内容可包含=(如作为分隔线)

我的尝试

解析器语法(Parser.g4)

parser grammar Parser;

options {
    tokenVocab = Lexer;
}

test : data* EOF ;

data : keyValuePair+ ;

// $KEYWORD = VALUE
keyValuePair
    : keyword ASSIGN value
    | (DESCRIPTION ) ASSIGN? text+ DESC_END
    ;

keyword : KEYWORD ;

value : VALUE ;

text : TEXT ;

词法分析器语法(Lexer.g4)

lexer grammar Lexer;

COMMENT     : '//' ~[\r\n]* -> channel(HIDDEN) ;
DESCRIPTION : '$DESCRIPTION' -> mode(DESC) ;
KEYWORD     : '$'[A-Z]+ ;
ASSIGN      : '=' -> mode(REGULAR) ;
WS          : [ \t\r\n]+ -> skip ;
ANY         : . -> skip ;

mode DESC;

DESC_END    : '$ENDDESCRIPTION' -> mode(DEFAULT_MODE) ;
DESC_ASSIGN : '=' -> type(ASSIGN) ;
TEXT        : (WORD  ((' ' | '\t')+ WORD)* | ASSIGN+ ) ;
DESC_WS     : WS -> skip ;
DESC_ANY    : ANY -> skip ;

mode REGULAR;

REGULAR_END     : [\r\n]+ -> mode(DEFAULT_MODE), channel(HIDDEN) ;
REGULAR_KEYWORD : KEYWORD -> type(KEYWORD), mode(DEFAULT_MODE) ; // take care of multiple assignments per line
VALUE           : WORD ((' ' | '\t')+ WORD)*  ;
REGULAR_WS      : WS -> skip ;
REGULAR_ANY     : ANY -> skip ;

fragment WORD      : CHAR+ ;
fragment CHAR      : [a-zA-Z0-9_?!@&%()<>|,.:;'\"*+/#=-] ; //must NOT contain $ symbol

问题

解析$DESCRIPTION的可选分隔符时出现异常:进入DESC模式后,Example 2能正常处理,但Example 1中$DESCRIPTION后的=会被包含在TEXT token中(值为"= Lorem ipsum...")。虽然后处理可以去除,但希望直接在语法层面解决;同时觉得CHAR的正则表达式写法不够合理,另外想知道有没有更好的方法收集完整的格式化文本用于后续输出。

改进建议

1. 修复DESCRIPTION后的=识别问题

ANTLR词法分析器会优先匹配更早定义的规则,因此在DESC模式中,将DESC_ASSIGN放在TEXT之前,同时调整TEXT规则不再包含=:

mode DESC;

DESC_END    : '$ENDDESCRIPTION' -> mode(DEFAULT_MODE) ;
DESC_ASSIGN : '=' -> type(ASSIGN) ;
// 匹配除$之外的所有内容(包括换行),直到遇到$ENDDESCRIPTION
TEXT        : (~'$' | '$' ~[E] | '$E' ~[N] | '$EN' ~[D] | '$END' ~[D] | '$ENDD' ~[E] | '$ENDDES' ~[C] | '$ENDDESC' ~[R] | '$ENDDESCR' ~[I] | '$ENDDESCRI' ~[P] | '$ENDDESCRIP' ~[T] | '$ENDDESCRIPT' ~[I] | '$ENDDESCRIPTIO' ~[N])+ ;
DESC_WS     : [ \t]+ -> skip ; // 只跳过空格和制表符,保留换行以维持文本格式

这样$DESCRIPTION后的=会被优先识别为ASSIGN,不会混入TEXT内容。

2. 优化CHAR正则表达式

原枚举式的CHAR规则容易遗漏字符,改为排除不允许的字符(仅排除$):

fragment CHAR      : ~[$] ; // 除$之外的所有字符,包括换行、特殊符号等

3. 收集完整格式化文本的方法

方案一:解析器层面拼接

修改解析器规则,将描述文本的片段统一捕获,后续在监听器/访问器中拼接:

keyValuePair
    : keyword ASSIGN value
    | DESCRIPTION ASSIGN? descText DESC_END
    ;

descText : TEXT+ ; // 捕获所有TEXT片段,后续可直接拼接成完整文本

方案二:词法层面直接生成完整token

在DESC模式中定义一个匹配完整描述内容的token,无需后续拼接:

mode DESC;

DESC_END    : '$ENDDESCRIPTION' -> mode(DEFAULT_MODE) ;
SKIP_ASSIGN_WS : ('='? [ \t]+) -> skip ; // 跳过可选的=和后续空白
// 匹配从当前位置到$ENDDESCRIPTION的所有内容
DESCRIPTION_FULL_TEXT : (~'$' | '$' ~[E] | '$E' ~[N] | '$EN' ~[D] | '$END' ~[D] | '$ENDD' ~[E] | '$ENDDES' ~[C] | '$ENDDESC' ~[R] | '$ENDDESCR' ~[I] | '$ENDDESCRI' ~[P] | '$ENDDESCRIP' ~[T] | '$ENDDESCRIPT' ~[I] | '$ENDDESCRIPTIO' ~[N])+ ;

此方案可直接得到完整的描述文本,简化后续处理。

4. 其他优化点

  • 移除全局的ANY : . -> skip ;规则,避免ANTLR跳过未匹配的字符,方便调试未覆盖的语法场景。
  • 保留REGULAR模式中的REGULAR_KEYWORD规则,确保单行多赋值的场景能正确切换模式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 10:27:03