Рекурсивно низходящ анализ и абстрактни синтактични дървета

Кодирам твърдо рекурсивен приличен анализатор, най-вече за учебни цели и се натъкнах на някои проблеми.

Ще използвам този кратък откъс от граматиката на 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, така и на universal, може да бъде изтеглена отпред като отделна незадължителна продукция:

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