我将如何使用 antlr 解析其值中带有 space 的标签?
How will I parse a tag with space in its value using antlr?
我有以下语法。
meta
: '<' NAME '>' TEXT '</' NAME '>'
| '<' NAME S* attribute* '>';
dl : '<' NAME '><' TEXT '>' dt* '</' NAME '><' TEXT '>';
dt : '<' NAME '><' NAME S* attribute* S* '>' TEXT '</' NAME '>';
attribute : attributeName '=' attributeValue;
attributeName : NAME;
attributeValue : VAL;
NAME : [A-Z0-9_-]+;
VAL : '"'.*?'"';
TEXT : [A-Za-z0-9:\/\.@\-;\s*]+;
S : [ \t\r\n]+ -> skip;
字符串是
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
<TITLE>Abcd</TITLE>
<H1>Abcd</H1>
<DL><p>
<DT><H3 ADD_DATE="1481473849" LAST_MODIFIED="1481473992" PERSONAL_XYZ_FOLDER="true">Foo bar</H3>
</DL><p>
我收到以下错误:
ParseError extraneous input 'bar' expecting '</' clj-antlr.common/parse-error (common.clj:146)
问题是 space 被跳过,所以当 Foo bar
有一个 space 时它给出了一个错误。但是,如果我没有跳过 space,我会在 META
解析中遇到另一个错误。 (跳过 spaces 时不需要 S*
)。
ParseError extraneous input ' ' expecting {'>', NAME}
mismatched input '>' expecting '><'
mismatched input '<' expecting {<EOF>, COMMENT, S} clj-antlr.common/parse-error (common.clj:146)
这是我用 antlr 生成的令牌文件:
T__0=1
T__1=2
T__2=3
T__3=4
T__4=5
DTD=6
COMMENT=7
NAME=8
VAL=9
TEXT=10
S=11
'<'=1
'>'=2
'</'=3
'><'=4
'='=5
当我 运行 使用 grun
时,我得到以下信息,但我没有看到报告的令牌中有任何错误。它类似于我定义的语法。我如何接受标签值中的 spaces?
$ grun MyGrammer r -tokens
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
[@0,0:0='<',<1>,1:0]
[@1,1:4='META',<8>,1:1]
[@2,5:5=' ',<11>,1:5]
[@3,6:15='HTTP-EQUIV',<8>,1:6]
[@4,16:16='=',<5>,1:16]
[@5,17:30='"Content-Type"',<9>,1:17]
[@6,31:31=' ',<11>,1:31]
[@7,32:38='CONTENT',<8>,1:32]
[@8,39:39='=',<5>,1:39]
[@9,40:65='"text/html; charset=UTF-8"',<9>,1:40]
[@10,66:66='>',<2>,1:66]
[@11,67:67='\n',<11>,1:67]
[@12,68:67='<EOF>',<-1>,2:0]
No method for rule r or it has arguments
谢谢。
如果你在 foo
和 bar
之间放置一个 space 词法分析器将其生成为两个标记(TEXT
类型)但语法指出只有一个名称允许使用令牌。要解决您的问题,您只需通过加号运算符在序列中允许一些文本:
dt : '<' NAME '><' NAME S* attribute* S* '>' TEXT+ '</' NAME '>';
另请注意,您可能 运行 会遇到问题,因为 Lexer 会转换相当多的名称输入而不是文本输入,因为它们都可以匹配模式 [A-Z0-9]+
我有以下语法。
meta
: '<' NAME '>' TEXT '</' NAME '>'
| '<' NAME S* attribute* '>';
dl : '<' NAME '><' TEXT '>' dt* '</' NAME '><' TEXT '>';
dt : '<' NAME '><' NAME S* attribute* S* '>' TEXT '</' NAME '>';
attribute : attributeName '=' attributeValue;
attributeName : NAME;
attributeValue : VAL;
NAME : [A-Z0-9_-]+;
VAL : '"'.*?'"';
TEXT : [A-Za-z0-9:\/\.@\-;\s*]+;
S : [ \t\r\n]+ -> skip;
字符串是
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
<TITLE>Abcd</TITLE>
<H1>Abcd</H1>
<DL><p>
<DT><H3 ADD_DATE="1481473849" LAST_MODIFIED="1481473992" PERSONAL_XYZ_FOLDER="true">Foo bar</H3>
</DL><p>
我收到以下错误:
ParseError extraneous input 'bar' expecting '</' clj-antlr.common/parse-error (common.clj:146)
问题是 space 被跳过,所以当 Foo bar
有一个 space 时它给出了一个错误。但是,如果我没有跳过 space,我会在 META
解析中遇到另一个错误。 (跳过 spaces 时不需要 S*
)。
ParseError extraneous input ' ' expecting {'>', NAME}
mismatched input '>' expecting '><'
mismatched input '<' expecting {<EOF>, COMMENT, S} clj-antlr.common/parse-error (common.clj:146)
这是我用 antlr 生成的令牌文件:
T__0=1
T__1=2
T__2=3
T__3=4
T__4=5
DTD=6
COMMENT=7
NAME=8
VAL=9
TEXT=10
S=11
'<'=1
'>'=2
'</'=3
'><'=4
'='=5
当我 运行 使用 grun
时,我得到以下信息,但我没有看到报告的令牌中有任何错误。它类似于我定义的语法。我如何接受标签值中的 spaces?
$ grun MyGrammer r -tokens
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
[@0,0:0='<',<1>,1:0]
[@1,1:4='META',<8>,1:1]
[@2,5:5=' ',<11>,1:5]
[@3,6:15='HTTP-EQUIV',<8>,1:6]
[@4,16:16='=',<5>,1:16]
[@5,17:30='"Content-Type"',<9>,1:17]
[@6,31:31=' ',<11>,1:31]
[@7,32:38='CONTENT',<8>,1:32]
[@8,39:39='=',<5>,1:39]
[@9,40:65='"text/html; charset=UTF-8"',<9>,1:40]
[@10,66:66='>',<2>,1:66]
[@11,67:67='\n',<11>,1:67]
[@12,68:67='<EOF>',<-1>,2:0]
No method for rule r or it has arguments
谢谢。
如果你在 foo
和 bar
之间放置一个 space 词法分析器将其生成为两个标记(TEXT
类型)但语法指出只有一个名称允许使用令牌。要解决您的问题,您只需通过加号运算符在序列中允许一些文本:
dt : '<' NAME '><' NAME S* attribute* S* '>' TEXT+ '</' NAME '>';
另请注意,您可能 运行 会遇到问题,因为 Lexer 会转换相当多的名称输入而不是文本输入,因为它们都可以匹配模式 [A-Z0-9]+