W artykule Parsing Expressions by Recursive Descent autorstwa Theodore Norvell (1999) autor zaczyna od następującej gramatyki wyrażeń arytmetycznych:
E --> E "+" E | E "-" E | "-" E | E "*" E | E "/" E | E "^" E | "(" E ")" | v
co jest dość złe, ponieważ jest dwuznaczne i lewostronne. Zaczyna więc od usunięcia lewej rekurencji, a jego wynik jest następujący:
E --> P {B P}
P --> v | "(" E ")" | U P
B --> "+" | "-" | "*" | "/" | "^"
U --> "-"
Ale nie mogę zrozumieć, jak doszedł do tego wyniku. Kiedy próbuję samodzielnie usunąć lewą rekurencję, robię to w następujący sposób:
Firs, grupuję razem produkcje, które nie opuściły rekurencji w jednej grupie, a inne (lewostronne) w innej grupie:
E --> E "+" E | E "-" E | E "*" E | E "/" E | E "^" E // L-recursive E --> v | "(" E ")" | "-" E
Następnie nazywam je i biorę pod uwagę łatwiejsze manipulacje:
E --> E B E // L-recursive; B stands for "Binary operator" E --> P // not L-recursive; P stands for "Primary Expression" P --> v | "(" E ")" | U E // U stands for "Unary operator" B --> "+" | "-" | "*" | "/" | "^" P --> "-"
Teraz muszę zajmować się tylko dwoma pierwszymi produkcjami, z którymi łatwiej sobie poradzić.
Te dwie pierwsze produkcje przepisuję, zaczynając od produkcji nierekurencyjnej (która jest po prostu
P
pierwotnym wyrażeniem), a następnie opcjonalnym ogonemT
, który definiuję jako resztę oryginalnej produkcji, pomniejszoną o pierwszą nieterminalną rekurencyjną lewą (czyli po prostuB E
), po którym następuje ogonT
, lub który może być pusty:E --> P T T --> B E T |
(zwróć uwagę na pustą alternatywę dla ogona).
Te dwie produkcje mogę teraz przepisać w EBNF w następujący sposób:
E --> P {B E}
co jest prawie tym, co dostaje autor, ale
E
zamiast tego mamP
wewnątrz wzorca zero lub więcej powtórzeń (Ogon). Inne produkcje, które otrzymuję, są takie same jak on:P --> v | "(" E ")" | U E B -> "+" | "-" | "*" | "/" | "^" U -> "-"
ale tutaj też mam
E
zamiastP
w pierwszej produkcjiP
.
Moje pytanie brzmi: czego brakuje? Jaką transformację algebraiczną w składni muszę teraz przejść, aby uzyskać dokładnie taką samą formę, jak autor? Próbowałem substytucji E
, ale prowadzi mnie to tylko do pętli. Podejrzewam, że muszę jakoś zastąpić P
za E
, ale nie znam żadnej transformacji prawnego uzasadnienia. Może wiesz, jaki jest ostatni brakujący krok?
Odpowiedzi:
Brakujący krok:
przepisz E w T:
Uprość T:
Równoważny:
I proszę bardzo
źródło
T
w jedenT
? Czy jest na to jakaś reguła? (Podejrzewam, że może to być jakoś podobne do reguły logiki algebraicznej Boolean, która mówi „aa = a”.)*
? Widziałem to w „Dragon Book” (3.3, s. 91)x** = x*
. Czy to ta sama reguła, której użyłeś?