Парсер против лексера и XML

Я сейчас читаю об архитектуре компиляторов и парсеров, и меня интересует одна вещь ... Когда у вас есть XML, XHTML, HTML или любой язык на основе SGML, какова будет роль лексера а какие бы токены были?

Я читал, что токены похожи на слова, подготовленные для анализа с помощью лексера. Хотя у меня нет проблем с поиском токенов для строк языков C, C ++, Pascal и т. Д., Где есть ключевые слова, имена, литералы и другие словесные строки, разделенные пробелами, с XML у меня есть проблема, потому что их нет ни слова! Это всего лишь простой текст, перемежающийся разметкой (тегами).

Я подумал про себя, что, возможно, эти теги и фрагменты обычного текста являются токенами, что-то вроде этого: [TXT][TAG][TAG][TXT][TAG][TXT][TAG][TAG][TXT].... Это было бы вполне разумно, поскольку SGML не заботится о том, что находится внутри разделителей разметки < и > (ну, он распознает специальные инструкции обработки и определения, когда находит ? или ! в качестве следующего символа; комментарии тоже относятся к этой группе), и токенизатор SGML может быть базой для парсера XML / HTML / XHTML.

Но затем я понял, что внутри разметки может быть < символов как часть другого синтаксиса: значения атрибутов: - / Даже если не совсем хорошая идея помещать < символов внутри значений атрибутов (для этого лучше использовать &lt;), многие браузеры и редакторы имеют дело с этим и рассматривают эти < как часть значения атрибута, а не как разделитель тегов.

Это немного усложняет ситуацию, потому что я не вижу способа распознать подобную разметку простым детерминированным конечным автоматом (DFA) в лексере. Похоже, что для автомата требуется отдельный контекст, когда он находится внутри тега, и другой контекст, когда он встречает значение атрибута. Я думаю, для этого потребуется стек состояний / контекстов, поэтому DFA может не справиться с этим. Я прав?

Каково ваше мнение? Можно ли делать токены из тегов (разметки) и простого текста?

Здесь: http://www.antlr.org/wiki/display/ANTLR3/Parsing+XML
использует какую-то другую технику: они рассматривают < и > (а также </ и />) как отдельные токены, а внутри тегов они используют GENERIC_ID в качестве токена и т. Д. Они обычно перемещают большую часть работа парсеру. Но они также должны изменить контексты для токенизатора: они используют другой контекст в простом тексте и разную разметку (но они забыли о контексте значений атрибутов, я думаю, потому что первое появление > завершит тег в их лексере).

Итак, каков наилучший подход к синтаксическому анализу SGML-подобных языков? Лексер там действительно используется? Если да, то какие строки составляют токены?


person SasQ    schedule 02.09.2010    source источник


Ответы (1)


Создав парсеры XML и HTML, у меня есть свое мнение.

Лексемы в целом должны быть узнаваемыми языковыми элементами.

Для XML и HTML они в основном соответствуют

  • TAGBEGIN, элементы вида ‹NAME
  • ТАГЕНД в форме >
  • TAGCLOSE вида ‹/NAME>
  • TAGENDANDCLOSE формы /> (только XML)
  • ATTRIBUTENAME в формате NAME
  • EQUALSIGN, в точности =
  • ATTRIBUTEVALUE, являющееся значением точной строки символов, представленной атрибутом, независимо от кавычек (или даже отсутствия кавычек для устаревшего HTML). Если внутри атрибута есть экранированные коды символов, этот код следует преобразовать в их фактический код символа.
  • СОДЕРЖАНИЕ, то есть текст между тегами TAGEND и TAGBEGIN. Как и ATTRIBUTEVALUES, любые экранированные символы должны быть преобразованы, поэтому КОНТЕНТ между ‹B> foobar ‹/B> преобразуется в текст foo ‹bar. Если вы хотите сохранить вызовы сущностей как отдельные токены, вы можете сделать это, создав потоки токенов CONTENT и ENTITYINVOCATION между TAGEND и TAGSTART; зависит от вашей цели.

Мы можем спорить о том, хотите ли вы создавать токен для комментариев HTML / XML или нет. Если вы это сделаете, вы это сделаете.

Если игнорировать сложности, связанные с DTD и схемами для XML, это все, что вам действительно нужно.

То, как лексер производит их, сложнее; с XML и HTML много беспорядка, связанного с экранированием во входном потоке, ‹[CDATA ...]> (если у меня есть такое право), что является просто забавной цитатой и исчезает, когда лексема CONTENT произведен. Чтобы справиться со всем этим, вам понадобится довольно сложный лексический движок. И да, с практической точки зрения вам нужны разные лексические состояния («режимы») для обработки разных частей текста. У меня почти есть один основной режим для обработки вещей внутри ... > и один основной режим для обработки CONTENT.

person Ira Baxter    schedule 02.09.2010
comment
Спасибо за очень быстрый и содержательный ответ :) ‹br/› Хм .. Звучит разумно. Еще 3 дополнительных вопроса к этому: 1. Означает ли это, что > не будет рассматриваться как TAGEND, когда он встречается внутри токена ATTRIBUTEVALUE? 2. Как эти дополнительные состояния контекста связаны с теорией NFA / DFA? Считаются ли они нормальными состояниями? Или какие-то более высокоуровневые состояния, контролирующие работу DFA? 3. Не лучше ли использовать один синтаксический анализатор для синтаксического анализа тегов SGML и выдавать его как токены для синтаксического анализатора XML / HTML / XHTML поверх него? Это разумный подход? - person SasQ; 02.09.2010
comment
@SasQ: 1. ‹FOO SIZE = ›› будет производить токены TAGBEGIN (со значением« FOO »), ATTRIBUTENAME (со значением« SIZE »), EQUALSIGN, ATTRIBUTEVALUE (со значением« ›»), TAGEND. 2. Состояния контекста (я предпочитаю называть их лексическими режимами) не относятся к теории NFA / DFA; вы используете эту теорию внутри этих состояний для построения FSA, которые распознают токены, разрешенные в этих состояниях. Мы используем конечный автомат более высокого уровня для перехода между лексическими режимами. 3. Конечно, вы можете вложить или связать парсеры, если хотите; трюк с лексическим режимом - это просто забавная версия этого, однако это очень эффективная версия. - person Ira Baxter; 02.09.2010