我想解析纯文本注释并在其中查找某些标记。我正在寻找的标签类型如下:
<name#1234>
其中&#34;姓名&#34;是[a-z]字符串(来自固定列表)和&#34; 1234&#34;代表[0-9] +数字。这些标记可以在字符串中出现零次或多次,并被任意其他文本包围。例如,以下字符串都是有效的:
"Hello <foo#56> world!"
"<bar#1>!"
"1 < 2"
"+<baz#99>+<squid#0> and also<baz#99>.\n\nBy the way, maybe <foo#9876>"
以下字符串均无效:
"1 < 2"
"<foo>"
"<bar#>"
"Hello <notinfixedlist#1234>"
最后一个是无效的,因为&#34; notinfixedlist&#34;不是受支持的命名标识符。
我可以使用简单的正则表达式轻松解析它,例如(为了简单起见,我省略了命名组):
<[a-z]+#\d+>
或直接指定固定列表:
<(foo|bar|baz|squid)#\d+>
但是我想使用antlr有几个原因:
如何使用antlr4实现这样的语法?我见过的大多数例子都是针对整个文本的完全规则的语言,而我只希望语法适用于任意文本中的匹配模式。
我想出了这个,我认为是正确的:
grammar Tags;
parse
: ( tag | text )*
;
tag
: '<' fixedlist '#' ID '>'
;
fixedlist
: 'foo'
| 'bar'
| 'baz'
| 'squid';
text
: ~('<' | '>')+
;
ID
: [0-9]+
;
这是对的吗?
答案 0 :(得分:2)
一般而言,所识别的问题通常被描述为岛屿语法问题 - 其中单数文档的部分由两个或更多不同的,通常是相互模糊的规范描述。
ANTLR 4通过使用mode
直接支持岛语法。注意,模式仅在拆分词法分析器/解析器语法中可用。
解析器
parser grammar TagsParser ;
options {
tokenVocab = TagsLexer ;
}
parse : ( tag | text )* EOF ;
tag : LANGLE fixedlist GRIDLET ID RANGLE ;
text : . ;
fixedlist
: FOO
| BAR
| BAZ
| SQUID
;
词法分析器
lexer grammar TagsLexer ;
LANGLE : '<' -> pushMode(tag) ;
TEXT : . ;
mode tag ;
RANGLE : '>' -> popMode ;
FOO : 'foo' ;
BAR : 'bar' ;
BAZ : 'baz' ;
SQUID : 'squid' ;
GRIDLET : '#' ;
ID : [0-9]+ ;
NONTAG : . -> popMode ;
解析器中的text
规则将匹配之前未被其上的解析器规则使用的所有令牌。这将包括所有TEXT
令牌以及恰好与标记模式规则匹配但不是标记的有效部分的任何文本。