Мне кажется, я понимаю (примерно), как работают парсеры рекурсивного спуска (например, Scala's Parbin Combinators): Вы анализируете входную строку одним парсером, и этот парсер вызывает другие, меньшие парсеры для каждой "части" всего ввода, ии так далее, пока вы не достигнете синтаксических анализаторов низкого уровня, которые непосредственно генерируют AST из фрагментов входной строки
. Я также думаю, что понимаю, как работает Lexing / Parsing: сначала вы запускаете лексер, чтобы разбить весь ввод наплоский список токенов, и затем вы запускаете парсер, чтобы взять список токенов и сгенерировать AST.
Однако я не понимаю, как стратегия Lex / Parse работает со случаями, когда именно от того, как вы токенизируете что-то, зависитна токены, которые были токенизированы ранее.Например, если я возьму кусок XML:
"<tag attr='moo' omg='wtf'>attr='moo' omg='wtf'</tag>"
Парсер рекурсивного спуска может взять это и разбить его (каждый последующий отступ представляет декомпозицию родительской строки)
"<tag attr='moo' omg='wtf'>attr='moo' omg='wtf'</tag>"
-> "<tag attr='moo' omg='wtf'>"
-> "<tag"
-> "attr='moo'"
-> "attr"
-> "="
-> "moo"
-> "omg='wtf'"
-> "omg"
-> "="
-> "wtf"
-> ">"
-> "attr='moo' omg='wtf'"
-> "</tag>"
И небольшие парсеры, которые по отдельности разбирают <tag
, attr="moo"
и т. Д., Будут затем создавать представление XML-тега и добавлять к нему атрибуты.
Однако, как работает одношаговый Lex /Разбирать работу?Откуда Lexer знает, что строка после <tag
и до >
должна быть разбита на отдельные атрибуты, в то время как строка между >
и </tag>
не должна быть?Не нужно ли парсеру сказать, что первая строка находится внутри тела тега, а вторая - вне тела тега?
РЕДАКТИРОВАТЬ: Изменен пример, чтобы сделать его более понятным