如何在ANTLR4中编写规则解析含用户自定义起止标记的字面量块
ANTLR4 自定义起止标记块语法实现方案
实现思路
这类需要配对自定义起止标识符的结构,可通过ANTLR4的词法模式+语义谓词组合实现,核心逻辑是在识别到起始标识符时暂存标记,匹配结束位置时校验是否和暂存的起始标记一致。
1. 词法规则定义
lexer grammar CustomBlockLexer; // 全局默认模式:匹配非@开头的普通文本 PLAIN_TEXT: ~[@]+ ; AT: '@' -> pushMode(AFTER_AT) ; mode AFTER_AT; // 匹配第二个@,归为AT类型,进入双@标识符匹配模式 SECOND_AT: '@' -> type(AT), pushMode(DOUBLE_AT_IDENT_MODE) ; // 匹配单@后的起始标识符,暂存到词法状态,进入块内容模式 START_IDENT: [A-Za-z0-9_]+ { getInterpreter().setUserState(_input, getCharIndex(), getText()); } -> popMode, pushMode(BLOCK_CONTENT_MODE) ; mode DOUBLE_AT_IDENT_MODE; // 匹配双@后的起始标识符,暂存到词法状态,进入块内容模式 DOUBLE_AT_START_IDENT: [A-Za-z0-9_]+ -> type(START_IDENT), { getInterpreter().setUserState(_input, getCharIndex(), getText()); } popMode, popMode, pushMode(BLOCK_CONTENT_MODE) ; mode BLOCK_CONTENT_MODE; NEWLINE: '\r'? '\n' ; // 语义谓词校验:仅当匹配内容和暂存的起始标识符一致时,才识别为结束标记 END_IDENT: [A-Za-z0-9_]+ { getText().equals(getInterpreter().getUserState(_input, getCharIndex())) }? -> popMode ; // 匹配块内普通内容 BLOCK_CONTENT: ~[\r\n]+? ;
2. 语法规则定义
parser grammar CustomBlockParser; options { tokenVocab = CustomBlockLexer; } root: (block | PLAIN_TEXT)* EOF ; block: at_prefix START_IDENT NEWLINE block_content END_IDENT ; at_prefix: AT | AT AT ; block_content: (BLOCK_CONTENT | NEWLINE)* ;
规则校验说明
- 合法场景:单
@/双@@开头的标记,结束标识符和起始标识符完全一致时,可正常识别为完整块结构。 - 非法场景:起止标识符不一致时,结束位置的字符串会被识别为普通
BLOCK_CONTENT,解析器会因找不到匹配的END_IDENT抛出语法错误,正好匹配你给出的非法样例校验要求。
内容的提问来源于stack exchange,提问作者叶雨飞
相关产品推荐
相关产品推荐

