Как преобразовать обычную грамматику с рекурсией и чередованиями в регулярное выражение

1

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

Регулярная грамматика обладает особым свойством: подставляя каждую нетерминальную (за исключением корневой) ее правую сторону, вы можете свести ее к единому произведению для корня с единственными терминалами и операторами с правой стороны... Сокращенное выражение терминалов и операторов можно записать в еще более компактной форме, называемой регулярным выражением

Поэтому я решил проверить эту идею и преобразовать нормальную грамматику EcmaScript для IdentifierName в регулятивные выражения:

IdentifierName ::
    IdentifierStart
    IdentifierName  IdentifierPart

Предположим, что IdentifierStart и IdentifierPart ограничены следующим:

IdentifierStart ::       IdentifierPart ::
    A                        A                 
    B                        C
    C                        &
    $                    
    _

Но я не уверен, как действовать, поскольку грамматика для IdentifierName имеет как рекурсию, так и чередование. Любая помощь?

Меня больше интересует подход, а не поиск результирующего выражения, которое, как показал @Bergi, - [ABC$_][AC&]*.

  • 1
    IdentifierName - это либо IdentifierName, за которым следует IdentifierPart, либо IdentifierStart, если IdentifierStart - S, а IdentifierPart - P, то некоторые допустимые IdentifierNames - S, SP, SPP и т. Д., Т. Е. IE, S, за которым следует некоторое количество P , Вы можете придумать регулярное выражение, чтобы соответствовать этому?
  • 0
    Просто [ABC$_][AC&]*
Показать ещё 2 комментария
Теги:
compiler-construction
compiler-design
ecmascript-next

1 ответ

2
Лучший ответ

В этом учебнике используются некоторые нестандартные (и удивительно неявные) определения.

Прежде всего, они используют операторы повторения в своей грамматике, поскольку они могут быть найдены в регулярных выражениях или EBNF. Затем они неявно определяют правильную грамматику как та, которая использует только те операторы повторения и не рекурсии. Учитывая это, тривиально превращать "регулярную грамматику" в регулярное выражение, просто вставляя все нетерминалы. Но по этому определению грамматика спецификации JS для идентификаторов не является регулярной, поскольку содержит рекурсию. Поэтому, прежде чем вы сможете встроить все, вам сначала нужно заменить рекурсию операторами повторения.

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

Теперь эти регулярные грамматики также могут быть преобразованы в регулярные выражения, но не путем простого применения метода, описанного в учебнике. Одним из способов было бы преобразование грамматики в конечный автомат, а затем применить алгоритм, описанный в этом ответе, например.

Однако на практике при выполнении преобразования вручную (вместо написания программы для этого) самым простым и наиболее распространенным способом выполнения преобразования является мысль о том, на каком языке грамматика описывает (в данном случае "язык всех слов, которые начните с символа IdentifierStart и затем укажите 0 или более символов IdentifierPart "), а затем придумайте регулярное выражение, выражающее этот язык (иначе" посмотрите на проблему очень сильно, пока не увидите решение "-algorithm).

  • 0
    спасибо, так будет ли работать этот алгоритм: 1) заменить рекурсию операторами повторения и затем 2) заменить каждый нетерминал (кроме корневого) его правой стороной? или первая часть действительно не тривиальна, применяя механический подход?
  • 0
    также я написал Грамматика правильная, если она либо линейно-правая, либо линейно-правая. Это руководство утверждает, что из-за этого ... Таким образом, кажется, что это не из-за того, что алгоритм замены будет работать, а из-за оператора повторения?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню