Кодирам твърдо рекурсивен приличен анализатор, най-вече за учебни цели и се натъкнах на някои проблеми.
Ще използвам този кратък откъс от граматиката на 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
.
Рекурсивната рекурсия е достатъчно ясна, но моето разбиране за нея е, че трябва да направя много (поради липса на по-добра дума) проучвателна рекурсия, преди да се спра на продукция. Така че промених подписа на моите продукции, за да върна булеви стойности. По този начин можех лесно да разбера дали конкретна продукция е довела до успех или не.
Използвам структура от данни за свързан списък, за да поддържам произволен поглед напред и мога лесно да разделя този списък, за да опитам производство и след това да се върна към началната си точка, ако производството не успее. Въпреки това, докато изпробвам производство, предавам променливо състояние, опитвайки се да конструирам обектен модел на документ. Това наистина не се получава, защото няма как да знам дали продукцията ще бъде успешна или не. И ако производството не е успешно, трябва по някакъв начин да отменя всички направени промени.
Въпросът ми е следният. Трябва ли да използвам абстрактно синтактично дърво като междинно представяне и след това да продължа оттам? Това ли е нещо, което обикновено бихте направили, за да заобиколите този проблем? Тъй като проблемът изглежда е основно в обектния модел на документа, който не е подходяща дървовидна структура от данни за рекурсия.