JavaCC - Как я могу удалить все конфликты выбора в этом утверждении без предварительного просмотра? - PullRequest
1 голос
/ 24 марта 2019

В настоящее время я разрабатываю синтаксический анализатор для моей грамматики.Моя цель - сделать это без оглядки, и именно с этим я действительно борюсь.

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

void main() : {}
{
    (A())* (B())*
}

void A() : {}
{
    C() <ID>
}

void B() : {}
{
    <ID> Z()
}

void C() : {}
{
    <bah>
    | <bha>
    | <ID>
}

Это предупреждение о выходе (я хочу удалить его)

Warning: Choice conflict in (...)* construct at line 200, column 23.
         Expansion nested within construct and expansion following construct
         have common prefixes, one of which is: <ID>
         Consider using a lookahead of 2 or more for nested expansion.

1 Ответ

1 голос
/ 25 марта 2019

На самом деле нам нужно знать больше о Z.Я предполагаю, что L (Z) (то есть язык, сгенерированный Z) не содержит пустой последовательности и не содержит последовательностей, начинающихся с ID, bha или bah.Я также предполагаю, что первый токен после main не может быть ID, bha или bah.

В этой ситуации я почти наверняка использовал бы lookahead

void main() : {}
{
    AsBs()
}

void AsBs() : {}
{ 
  LOOKAHEAD( A() )
  A() AsBs() ;
|
  (B()*)
|
  {/*nothing*/}
}

с A, B и C, как в оригинальном сообщении.


Однако, постер хочет решения без использования опережающего взгляда.Вот один.Я сделал те же предположения, что и выше.

void main() : {}
{
    AsBs()
}

void AsBs() : {}
{
    C1() <ID> AsBs()
|
    <ID>  // This ID might be the start of either A or B
    ( <ID> AsBs()  // That ID started an A
    | Z() (B())* ) // That ID started a B.
|
    {/*nothing*/}
}

void B() : {}
{
    <ID> Z()
}

void C1() : {}
{
    <bah>
    | <bha>
}

Здесь нет необходимости A или C.

...