Как я буду анализировать тег с пробелом в его значении, используя 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)

Проблема в том, что пространство пропускается так, когда Foo bar имеет пробел, это дает ошибку. Но если я не пропускаю место, я получаю еще одну ошибку в META разбор. (The 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 Я получаю следующее, но не вижу ошибок в сообщаемом токене. Это похоже на грамматику, которую я определил. Как я могу принять пробелы в значениях тегов?

$ 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

Благодарю.

1 ответ

Решение

Если вы поставите пробел между foo а также bar лексер выдает его как два токена (типа TEXT) но грамматика гласит, что разрешен только один маркер имени. Чтобы решить вашу проблему, вы просто должны разрешить несколько текстов последовательно через оператор плюс:

dt : '<' NAME '><' NAME S* attribute* S* '>' TEXT+ '</' NAME '>';

Также обратите внимание, что вы можете столкнуться с проблемами, поскольку Lexer преобразует довольно много входных данных в NAMEs, а не в TEXTs, поскольку они оба могут соответствовать шаблону. [A-Z0-9]+

Другие вопросы по тегам