如何用ANTLR4 Visitor捕获输入中here文档的全部数据?
解决ANTLR4解析Bash Here文档的匹配错误问题
核心问题拆解
line 9:4 mismatched input '<EOF>' expecting HERE_START 错误本质是:解析器进入Here文档的词法模式后,未能正确识别结束标记,导致到达文件末尾时仍处于未完成的解析状态,错误等待新的起始标记。
1. 修复词法规则的结束标记匹配逻辑
Bash Here文档要求结束标记必须是单独一行(无额外空白,除非用<<-允许前导制表符),你的词法规则可能未满足这个约束:
- 若使用普通
<<格式,结束标记规则需匹配整行:HERE_END: IDENTIFIER '\r'? '\n' -> popMode; - 若支持
<<-的前导制表符,需允许前导\t:
注意:起始标记的HERE_END: '\t'* IDENTIFIER '\r'? '\n' -> popMode;IDENTIFIER需和结束标记完全一致,确保大小写、字符完全匹配。
2. 确认词法模式切换的正确性
必须通过词法模式隔离Here文档内容,避免与其他语法冲突:
// 默认模式 HERE_START: '<<' [ \t]* IDENTIFIER -> pushMode(HERE_MODE); // Here文档专属模式 mode HERE_MODE; HERE_CONTENT: ~[\r\n]+; // 捕获单行内的所有内容(不含换行) HERE_END: IDENTIFIER '\r'? '\n' -> popMode; WS: [ \t]+ -> skip; // 若需要忽略内容内的空格,可添加此规则
确保进入HERE_MODE后,所有内部内容都被HERE_CONTENT或HERE_END捕获,不会触发默认模式的词法规则。
3. 修正解析器规则的结构
解析器规则需要明确Here文档的完整结构,同时确保顶层规则包含EOF以标记输入结束:
script: statement* EOF; statement: here_doc | command | assignment; // 其他语句类型 here_doc: HERE_START HERE_CONTENT* HERE_END;
如果顶层规则缺少EOF,解析器可能无法判断输入是否结束,导致状态异常。
4. 验证测试输入的合法性
检查测试输入的结束标记是否符合要求:
结束标记必须与起始标记完全一致,且单独占一行,前后无任何空格、制表符(除非使用
<<-格式)。例如起始标记是EOF,结束行不能是EOF或EOF,否则词法分析器无法匹配HERE_END。
5. 调试语法树的方法
使用ANTLR4的-gui选项生成可视化语法树,重点检查:
- 词法标记的分类是否正确(如
HERE_CONTENT是否捕获了所有中间内容) - 解析器是否在
HERE_START后进入here_doc分支,是否因缺少HERE_END导致分支未闭合
内容的提问来源于stack exchange,提问作者user1818726
相关产品推荐
相关产品推荐

