дизайн компилятора - нужна помощь для устранения косвенной левой рекурсии из CFG - PullRequest
0 голосов
/ 22 декабря 2018

У меня есть следующая грамматика, которая обрабатывает математическое и логическое выражение:

A ==> B A'
A' ==> | B A'
A' ==> epsilon

B ==> C B'
B' ==> ^ C B'
B' ==> epsilon

C ==> D C'
C' ==> & D C'
C' ==> epsilon

D ==> E D'
D' ==> << E D' | >> E D'
D' ==> epsilon

E ==> F E'
E' ==> + F E' | - F E'
E' ==> epsilon

F ==> G F'
F' ==> * G F' | / G F' | % G F'
F' ==> epsilon

G ==> +H | -H | ++H | --H | ~H | !H | &H 
G ==> H

H ==> (A) | A T
T ==> -- | ++ | epsilon
H ==> number

Проблема возникает, когда происходит следующее деривация:

A ==> B ==> C ==> D ==> E ==> F ==> G ==> H ==> A

И JavaCC не будет компилировать грамматикуфайл из-за косвенной левой рекурсии.

Итак, что нужно сделать, чтобы исключить эту косвенную левую рекурсию из предыдущей грамматики?

1 Ответ

0 голосов
/ 22 декабря 2018

Итак, после того, как я полчаса смотрел на эту грамматику, я понял, что в особом случае:

H ==> A

И тот же особый случай дает:

A ==> H

Итакя перефразировал грамматику таким образом, что первое производственное правило для нетерминала H вызывает левую рекурсию, а второе производственное правило не вызывает никакой левой рекурсии, поэтому вот как выглядит грамматика:

H ==> A T
T ==> -- | ++ | epsilon
H ==> (A) | number

Как уже было сказано, мы заменяем A на H в первом производственном правиле:

H ==> H T
H ==> (A) | number
T ==> -- | ++ | epsilon

Теперь тривиально устранить левую рекурсию, и вот как выглядит финальная грамматика:

H ==> (A)H' | number H'
H' ==> T H' | epsilon
T ==> -- | ++ | epsilon
...