Рекурсивный синтаксический анализ и абстрактные синтаксические деревья

Я жестко кодирую рекурсивный приличный синтаксический анализатор, в основном для целей обучения, и у меня возникли некоторые проблемы.

Я буду использовать этот короткий отрывок из грамматики CSS3 в качестве примера:

simple_selector = type_selector | universal;
type_selector = [ namespace_prefix ]? element_name;
namespace_prefix = [ IDENT | '*' ]? '|';
element_name = IDENT;
universal = [ namespace_prefix ]? '*';

Во-первых, я не понимал, что namespace_prefix является необязательным элементом как в type_selector, так и в universal. Это приводило к тому, что type_selector всегда терпел неудачу при подаче ввода, такого как *|*, потому что он слепо рассматривался для любого ввода, который соответствовал продукции namespace_prefix.

Рекурсивный приличный достаточно прост, но я понимаю, что мне нужно сделать много (из-за отсутствия лучшего слова) исследовательской рекурсии, прежде чем остановиться на производстве. Поэтому я изменил подпись своих продуктов, чтобы они возвращали логические значения. Таким образом, я мог легко сказать, увенчалась ли конкретная постановка успехом или нет.

Я использую структуру данных связанного списка для поддержки произвольного опережающего просмотра и могу легко разрезать этот список, чтобы попытаться произвести производство, а затем вернуться к исходной точке, если производство не удастся. Однако, пробуя производство, я передаю изменяемое состояние, пытаясь построить объектную модель документа. На самом деле это не срабатывает, потому что я не знаю, будет ли производство успешным или нет. И если производство не будет успешным, мне нужно как-то отменить все сделанные изменения.

Мой вопрос заключается в следующем. Должен ли я использовать абстрактное синтаксическое дерево в качестве промежуточного представления, а затем идти оттуда? Это то, что вы обычно делаете, чтобы обойти эту проблему? Потому что проблема, по-видимому, в первую очередь связана с объектной моделью документа, которая не является подходящей древовидной структурой данных для рекурсии.


person John Leidegren    schedule 29.03.2011    source источник


Ответы (1)


Я не очень хорошо знаком с CSS, но, как правило, вы должны реорганизовать грамматику, чтобы максимально устранить двусмысленности. В вашем случае производство namespace_prefix, которое может быть в начале как type_selector, так и универсального, может быть вынесено вперед как отдельное необязательное производство:

simple_selector = [ namespace_prefix ]? (type_selector | universal);
type_selector = element_name;
namespace_prefix = [ IDENT | '*' ]? '|';
element_name = IDENT;
universal =  '*';

Однако не все грамматики можно упростить для простого просмотра вперед, как это, и для них вы можете использовать более сложные синтаксические анализаторы сдвига-уменьшения или, как вы предлагаете, откат. Для возврата вы обычно просто пытаетесь разобрать продукцию и записать путь через грамматику. Когда у вас есть продукция, соответствующая входным данным, вы используете записанный путь, чтобы фактически выполнить семантическое действие для этой продукции.

person 500 - Internal Server Error    schedule 29.03.2011
comment
Я думал об этом, но это ничего не меняет. Из-за этого грамматика не более или менее двусмысленна, постановка все еще существует. И мне очень нравится природа рекурсивного приличного синтаксического анализа. Меня больше всего интересует, как включить AST для упрощения рекурсивного приличного кода. - person John Leidegren; 29.03.2011
comment
Конечно, вы не можете быть бесконечно выразительными с любой грамматикой, вам нужно проявлять большую осторожность при разработке вашего языка. Но в данном случае это просто вопрос выбора продукции с использованием предпросмотра. - person John Leidegren; 30.03.2011