JavaCC配置模式匹配预期令牌时抛出错误求助
解决JavaCC嵌套配置解析的语法错误
当前问题重现
定义的词法模式
| < CONFIGURATION_PATTERN: "(" ("\n")* (" ")* ((<LETTER>)+ " = " (<LETTER> | <DIGIT>)+ ("\n") (" ")*)+ (" ") ")" > | < CONFIGURATION_SUB_PATTERN: "(" ("\n")* (" ")* ((<LETTER>)+ " = " (<LETTER> | <DIGIT> | <BOOLEAN>)+ ("\n") (" ")*)+ (" ") ")" >
待解析输入
CONFIGURATION ( INSERTVALUE = 200 PROPERTIES ( MOVETABLE = false, DOWRITE = true ) )
报错信息
Parse error: Encountered " "(" "( "" at line 25, column 29.
Was expecting one of:
"SOMETOKEN" ...
"SOMETOKEN2" ...
"SOMETOKEN3" ...
<SOME_PATTERN> ...
<SOME_PATTERN2> ...
不含PROPERTIES嵌套块的输入可正常解析,尝试过调整模式、添加递归词法规则均无效。
问题根源分析
- 词法规则无法处理递归嵌套:你把嵌套配置定义成了词法
TOKEN,但JavaCC的词法分析器是有限状态机,不支持递归结构(比如括号嵌套),必须用语法规则(递归下降解析)来处理这类嵌套场景。 - 强制换行约束不匹配输入:原模式要求每个键值对后必须跟换行符
"\n",但实际输入中PROPERTIES后直接跟了(,不符合模式要求,导致匹配中断。 - 模式匹配逻辑僵化:原模式只支持平级键值对,没有考虑"值可以是另一个配置块"的情况,无法识别
PROPERTIES后面的嵌套结构。
修正方案
1. 拆分词法与语法规则
首先定义基础词法单元,忽略空白字符:
TOKEN : { < LETTER: ["a-zA-Z"] > | < DIGIT: ["0-9"] > | < BOOLEAN: "true" | "false" > | < WHITESPACE: (" " | "\t" | "\n" | "\r")+ > : SKIP // 忽略所有空白 | < EQUALS: "=" > | < COMMA: "," > }
2. 定义递归语法规则处理嵌套
用语法规则实现递归解析,支持多层配置嵌套:
// 顶层配置入口 void configuration() : {} { "CONFIGURATION" "(" (configurationEntry())* ")" } // 配置项:可以是普通键值对,也可以是嵌套配置 void configurationEntry() : {} { // 普通键值对(如 INSERTVALUE = 200) <LETTER>+ EQUALS value() (COMMA)? // 嵌套配置(如 PROPERTIES (...)) | <LETTER>+ configuration() (COMMA)? } // 合法值类型:字母串、数字、布尔值 void value() : {} { (<LETTER>)+ | (<DIGIT>)+ | BOOLEAN }
方案说明
- 递归语法规则:通过
configuration()的递归调用,完美支持多层嵌套的配置结构。 - 空白自动忽略:通过
WHITESPACE的SKIP规则,无需手动处理换行、空格、制表符,简化模式逻辑。 - 灵活的配置项:支持普通键值对和嵌套配置两种类型,适配输入格式。
- 可选逗号:允许配置项末尾带逗号,兼容常见配置文件的书写习惯。
内容的提问来源于stack exchange,提问作者Eto
相关产品推荐
相关产品推荐

