MismatchedTokenException в грамматике подмножества HTML - PullRequest
1 голос
/ 23 июня 2010

Я пишу грамматику ANTLR для распознавания элементов уровня блока HTML в простом тексте. Вот соответствующий фрагмент кода, ограниченный тегом div :

grammar Test;

blockElement
  : div
  ;

div
  : '<' D I V HTML_ATTRIBUTES? '>' (blockElement | TEXT)* '</' D I V '>'
  ;

D : ('d' | 'D') ;
I : ('i' | 'I') ;
V : ('v' | 'V') ;

HTML_ATTRIBUTES
  : WS (~( '<' | '\n' | '\r' | '"' | '>' ))+
  ;

TEXT
  : (. | '\r' | '\n')
  ;

fragment WS
  : (' ' | '\t')
  ;

Маркер TEXT должен представлять все, что не является элементом уровня блока, например простой текст или встроенные теги (например, <b><\b>). Когда я тестирую его на вложенных блочных элементах, например:

<div level_0><div level_1></div></div>

он их правильно анализирует. Однако, как только я добавляю некоторый случайный текст, он генерирует исключение MismatchedTokenException (0! = 0) сразу после использования первого токена TEXT , т.е. г. Столица Т в:

<div level_0>This is some random text</div>

Есть предложения? Я делаю что-то концептуально неправильно? Я использую ANTLR v. 3.2 и выполняю тестирование с ANTLRWorks v. 1.4.

Спасибо

1 Ответ

3 голосов
/ 23 июня 2010

Я рекомендую не тестировать вашу грамматику с помощью ANTLRWorks: сообщения об ошибках легко пропускаются в консоли, и это может интерпретировать ваш тестовый ввод не так, как вы ожидаете. Сделайте это с помощью пользовательского класса, подобного этому:

import org.antlr.runtime.*;

public class Main {
    public static void main(String[] args) throws Exception {
        ANTLRStringStream in = new ANTLRStringStream("<div level_0>This is some random text</div>");
        TestLexer lexer = new TestLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        TestParser parser = new TestParser(tokens);
        Sparser.parse());
    }
}

Теперь следующее правило неверно:

TEXT
  :  (. | '\r' | '\n')
  ;

. уже соответствует \r и \n, поэтому должно быть:

TEXT
  :  .
  ;

При изменении этого параметра вы можете создать парсер и лекстер, скомпилировать все файлы .java и запустить класс Main:

java -cp antlr-3.2.jar org.antlr.Tool Test.g
javac -cp antlr-3.2.jar *.java
java -cp .:antlr-3.2.jar Main

, которая выдаст следующую ошибку:

line 1:15 mismatched input 'i' expecting '</'

потому что i из This маркируется правилом I : ('i' | 'I') ;.

В вашем текущем подходе больше проблем:

  • HTML_ATTRIBUTES делает слишком много: вместо этого вы должны иметь правила ATTRIBUTE, = и VALUE и затем вместо этого переместить множественное число (атрибуты html) в свой анализатор;
  • теперь ваши атрибуты не могут содержать < и >, что неверно (может содержать их, хотя это не рекомендуется).

Я бы начал на твоем месте. Если хочешь, я готов предложить начало: просто так и говорю.

...