Граматика за език на регулярните изрази с дадена азбука

Трудно ми е да разбера откъде да започна с този въпрос. Въпросът е да се създаде граматика за езика на регулярните изрази с азбуката { ‘a’, ‘b’, ‘c’, ‘d’, ‘|’, ‘*’, ‘(‘, ‘)’ }. Да приемем 1 ред за въвеждане (единичен низ) и без интервали. Празният низ не е валиден и трябва правилно да улови приоритета на операторите, които от най-ниския до най-високия са обединение ('|'), конкатенация и kleene ('*'). Какъв би бил най-добрият начин да започнете да пишете граматиката за това? Всеки принос ще бъде много оценен.

Не търся отговор, просто не знам как да започна. Досега имам нещо като:

S -> S'('S')'S  
   | A  
A -> AA  
   | A'*'  
   | T  
T -> T'|'T  
   | X  
X -> 'a'  
   | 'b'  
   | 'c'  
   | 'd'

Но дори не съм сигурен дали съм на прав път.

РЕДАКТИРАНЕ: След като свърших още малко работа, това е заключението, до което стигнах:

START -> EXPRESSION  
EXPRESSION -> EXPRESSION'|'EXPRESSION  
EXPRESSION -> PARENTHETICAL'*'  
EXPRESSION -> PARENTHETICAL  
EXPRESSION -> EXPRESSION PARENTHETICAL  
EXPRESSION -> PARENTHETICAL EXPRESSION  
EXPRESSION -> EXPRESSION PARENTHETICAL EXPRESSION  
EXPRESSION -> REPEAT  
PARENTHETICAL -> PARENTHETICAL'*'  
PARENTHETICAL -> '('EXPRESSION')'  
REPEAT -> REPEAT REPEAT
REPEAT -> TERMINAL'*'  
REPEAT -> TERMINAL  
TERMINAL -> TERMINAL'*'  
TERMINAL -> 'a'  
TERMINAL -> 'b'  
TERMINAL -> 'c'  
TERMINAL -> 'd'  

Това може да се запише и като:

S -> E  
E -> E'|'E  
E -> P'*'  
E -> P  
E -> E P  
E -> P E 
E -> E P E  
E -> R  
P -> P'*'  
P -> '('E')'  
R -> R R
R -> T'*'  
R -> T  
T -> T'*'  
T -> 'a'  
T -> 'b'  
T -> 'c'  
T -> 'd'  

Доста съм сигурен, че това е правилно и го проверих два пъти с куп разнообразни тестови входни данни. Всяко потвърждение ще бъде оценено.


person Tony Dakhoul    schedule 22.03.2013    source източник
comment
Прилича на домашна работа. Така ли?   -  person dotNET    schedule 22.03.2013
comment
Къде по-конкретно сте заседнали?   -  person Oliver Charlesworth    schedule 22.03.2013
comment
Да това е домашното. Не търся отговор, просто не знам как да започна. Досега имам нещо като: S -› S'('S')'S | A A -› Но не съм сигурен дори дали съм на прав път.   -  person Tony Dakhoul    schedule 22.03.2013
comment
@TonyDakhoul включете последния коментар във въпроса си, така че хората да го прочетат! Винаги е добра идея да включите директно във въпроса си какво сте опитали!   -  person Hugo Dozois    schedule 22.03.2013


Отговори (2)


Това е просто въпрос на повторение. Винаги обичам да започвам с правилото Start-> NonTerminal, само за да си дам половин шанс за обикновена граматика. Вярвам, че вложените скоби ще ни сведат до граматика без контекст, но това е добре. Намирам, че прави тази стъпка по-лесна. След това трябва да започнете с оператора с НАЙ-НИСК приоритет. В скоби и съюз във вашия случай. И така, първоначално:

Start -> Expression
Expression -> Expression|Expression
Expression -> (Expression)

Обърнете внимание, че избегнах нормалното '|' нотация, защото това е един от символите във вашата азбука. Това избягва объркване. След това можем да добавим следващия оператор, конкатенация, с набор от правила, които генерират повторение.

Start -> Expression
Expression -> Expression|Expression
Expression -> (Expression)

Expression -> Repeat
Repeat -> RepeatRepeat
Repeat -> Terminal
Terminal -> a
Terminal -> b
Terminal -> c
Terminal -> d

След това всичко, което остава, е да добавите Kleene Star като оператор с най-нисък приоритет:

Start -> Expression
Expression -> Expression|Expression
Expression -> (Expression)

Expression -> Repeat
Repeat -> RepeatRepeat
Repeat -> Terminal
Terminal -> a
Terminal -> b
Terminal -> c
Terminal -> d

Repeat -> Terminal*
Expression -> (Expression)*

И имаме граматика, която генерира всички непразни регулярни изрази от желаната азбука. В по-традиционна променлива нотация може да изглежда така:

S -> E
E -> E|E
E -> (E)
E -> (E)*
E -> R
R -> RR
R -> T*
R -> T
T -> a
T -> b
T -> c
T -> d

Има една граматика, за която съм сигурен, че го прави. Надявам се някой да провери работата ми, защото минаха няколко години, откакто написах официална граматика.

РЕДАКТИРАНЕ:

В резултат на споменатата двойна проверка беше посочено, че свързването на изрази и изрази в скоби не работи. Можем обаче да добавим, че. Първата стъпка е да добавите ново правило Expression -> Parenthetical и да промените Expression -> (Expression) и Expression -> (Expression)* на Parenthetical -> (Expression) и Parenthetical -> (Expression)* След това няколко бързи правила за свързването им водят до набора от правила:

Start -> Expression
Expression -> Expression|Expression
Expression -> Parenthetical

Parenthetical -> (Expression)
Parenthetical -> (Expression)*

Expression -> Expression Parenthetical
Expression -> Parenthetical Expression
Expression -> Expression Parenthetical Expression

Expression -> Repeat
Repeat -> Repeat Repeat
Repeat -> Terminal
Terminal -> a
Terminal -> b
Terminal -> c
Terminal -> d

Repeat -> Terminal*
person FrankieTheKneeMan    schedule 22.03.2013
comment
хм Това не поддържа (E)*, но това е лесно решение. Ще го направя след малко. - person FrankieTheKneeMan; 22.03.2013
comment
Въпрос: Тази граматика, която сте написали, не позволява нещо като a(b|c)*d правилно? Освен това скобите няма ли технически да бъдат най-високият приоритет? Знам, че не е посочено в проблема, но например това твърдение: abc|d Може да се мисли така: (a(b)c)|(d) - person Tony Dakhoul; 22.03.2013
comment
Това може да се коригира чрез промяна на E->(E) and E->(E)* на E->P, P->(E) и P->(E)*, след което се добавят правилата E->EP, E->PE и E->EPE. Това вероятно може да бъде намалено. - person FrankieTheKneeMan; 22.03.2013
comment
А, разбирам, има смисъл. Моят основен извод от вашия отговор е винаги да започвате с най-ниския приоритет, нали? Нека се опитам да пренапиша моята граматика и скоро ще я публикувам отново. Благодаря отново за отговора, оценявам много! - person Tony Dakhoul; 22.03.2013
comment
Мда. Не се притеснявайте да се опитвате да направите минимална граматика първоначално, със сигурност не го направих. Просто накарайте всяко парче да работи, без да счупите всички предишни парчета. Винаги можете да намалите граматиката си по-късно. - person FrankieTheKneeMan; 22.03.2013
comment
Благодарение на вашия съвет, смятам, че имам правилна граматика за езика на регулярните изрази. Ако можете да го проверите два пъти само заради мен, ще е страхотно, но така или иначе наистина оценявам помощта ви. =] - person Tony Dakhoul; 22.03.2013
comment
@TonyDakhoul Внимавайте! EXPRESSION -> PARENTHETICAL'*' и PARENTHETICAL -> PARENTHETICAL'*' могат да се комбинират за генериране на безкрайни звезди - което не е валидно в регулярните изрази. Всъщност второто правило може да направи това само по себе си. - person FrankieTheKneeMan; 22.03.2013
comment
Същото нещо с TERMINAL -> TERMINAL'*' - person FrankieTheKneeMan; 22.03.2013
comment
Доколкото учителят ми спомена, може да има колкото искате звезди, просто е излишно. Нещо като abc**** е валидно на езика, който той иска да измислим. Но освен това има ли вашето одобрение? - person Tony Dakhoul; 22.03.2013
comment
@TonyDakhoul - Да, така мисля. Отново минаха години, откакто трябваше да пиша формални граматики. Бих направил две неща: Проверете отново с вашия учител за излишните звезди, след което (ако ви е позволено) го раздайте на някои други съученици или приятели, които са ходили на курса преди. - person FrankieTheKneeMan; 22.03.2013

Това, което на новодошлите в компилаторите им е трудно да разберат, е, че граматика, която е само способна да анализира валиден вход, е безполезна.

Една добра граматика трябва да отразява йерархичната структура на входа, за да можем да прикачим семантика към него.

Всичко опира до смисъл.

Въпреки това Grako има преводач на регулярен израз към CFG като единственият примерен проект.

person Apalala    schedule 23.03.2013
comment
Това има много малко общо с въпроса, зададен тук. Зададеният въпрос беше за граматика, която създава всички низове, които са валидни регулярни изрази, предвид предоставената азбука, а не за създаване на граматика от регулярен израз. Този въпрос не е за компилаторите и вашият отговор (без значение от истинната стойност на твърденията, направени в него) е неподходящ тук. - person FrankieTheKneeMan; 25.03.2013
comment
@FrankieTheKneeMan От първоначалния въпрос... за създаване на граматика за езика на регулярните изрази..., ...трябва да улови правилно приоритета на операторите.... Точно това е отговорът ми. - person Apalala; 25.03.2013
comment
Изобщо не е за това отговорът ти. Вашият отговор е да вземете регулярен израз и да го превърнете в граматика без контекст. Или поне това прави примерният проект, към който се свързвате. Това не беше попитано. Това, което беше попитано, е как да напишем граматика, която генерира всички валидни регулярни изрази. Това е много различен процес. - person FrankieTheKneeMan; 25.03.2013
comment
Езикът, генериран от граматика, е теоретична концепция с малка практическа полза, тъй като повечето интересни езици са безкрайни. На практика с използване на граматики за изграждане на синтактични анализатори, които могат да проверят дали дадено изречение принадлежи на езика, и ние пишем граматики, които ни позволяват да възстановим абстрактната структура на изреченията, така че може да им придаде семантика. Във всеки случай граматиката, която публикувах като пример, генерира езика на регулярните изрази и може да се използва за всяка задача за анализиране или може да бъде преведена в нотацията на различен инструмент за генериране на анализатор, ако така пожела. - person Apalala; 26.03.2013