如何用ANTLR4捕获Bash Here文档起止标识间的全部数据
解决ANTLR4识别Bash Here文档内容的问题
核心问题分析
ANTLR4当前会优先匹配IDENTIFIER规则,导致Here文档起止标识间的非标识符内容被当作无关输入,无法归入hereContent。本质是ANTLR4的最长匹配规则逻辑下,IDENTIFIER的优先级高于hereContent,干扰了内容捕获。
解决方案步骤
1. 用词法模式隔离Here文档解析
ANTLR4的词法模式(Lexical Modes)能让词法分析器在进入特定上下文时切换规则集,完全避开外部的IDENTIFIER等规则干扰。在词法文件中添加专用模式:
lexer grammar BashLexer; // 默认模式 HereDocStart : '<<' IDENTIFIER -> pushMode(HERE_DOC); IDENTIFIER : [a-zA-Z_][a-zA-Z0-9_]*; // 其他默认词法规则(如运算符、空格等)... // Here文档专属模式 mode HERE_DOC; HereDocContent : ~[\r\n]+; // 匹配除换行外的所有内容 HereDocEnd : '\r'? '\n' IDENTIFIER -> popMode; // 结束标识需单独占一行,匹配后退出模式 NewLine : '\r'? '\n' -> skip; // 按需处理换行,若需保留可移除skip
2. 调整语法分析规则关联模式
在解析器文件中定义Here文档的语法规则,关联词法模式生成的token:
parser grammar BashParser; options { tokenVocab=BashLexer; } script : statement* EOF; statement : hereDoc | otherStatement; hereDoc : HereDocStart HereDocContent* HereDocEnd; // 其他语句规则(如赋值、命令调用等)...
3. 适配Bash Here文档的特殊场景
- 支持带引号的结束标识(如
<<'EOF',内容不做变量替换):
修改HereDocStart规则:HereDocStart : '<<' ( '\'' IDENTIFIER '\'' | '"' IDENTIFIER '"' | IDENTIFIER ) -> pushMode(HERE_DOC); - 处理内容中的换行保留需求:
移除NewLine规则的skip,将换行纳入HereDocContent:HereDocContent : .+?; // 非贪婪匹配所有内容,直到遇到结束标识
验证方法
用以下测试用例验证解析效果:
cat <<EOF Hello World! This is a here doc with special chars: $@ ! * EOF
检查生成的解析树,确认hereContent完整捕获起止标识间的所有内容,无截断或遗漏。
内容的提问来源于stack exchange,提问作者user1818726
相关产品推荐
相关产品推荐

