Diese Grammatik bleibt rekursiv:
Expression ::= AdditionExpression
AdditionExpression ::=
MultiplicationExpression
| AdditionExpression '+' MultiplicationExpression
| AdditionExpression '-' MultiplicationExpression
MultiplicationExpression ::=
Term
| MultiplicationExpression '*' Term
| MultiplicationExpression '/' Term
Term ::=
Number
| '(' AdditionExpression ')'
Number ::=
[+-]?[0-9]+(\.[0-9]+)?
Theoretisch funktioniert ein rekursiver Abstieg also nicht. Durch Ausnutzen der Eigenschaften der Grammatik, dass jede linksrekursive Regel einer bestimmten Prioritätsebene entspricht und der Lookahead eines einzelnen Tokens ausreicht, um die richtige Produktion auszuwählen, können die linksrekursiven Regeln einzeln mit while-Schleifen analysiert werden.
Um beispielsweise das nicht-terminale AdditionExpression zu analysieren, reicht dieser Pseudocode aus:
function parse_addition_expression() {
num = parse_multiplication_expression()
while (has_token()) {
get_token()
if (current_token == PLUS)
num += parse_multiplication_expression()
else if (current_token == MINUS)
num -= parse_multiplication_expression()
else {
unget_token()
return num
}
}
return num
}
Wie lautet der richtige Name für diesen Parsertyp? In diesem informativen Artikel wird es nur als "klassische Lösung" bezeichnet: https://www.engr.mun.ca/~theo/Misc/exp_parsing.htm
Für diesen Parsertyp muss ein Eigenname vorhanden sein.
Antworten:
Es ist nur ein LL (1) -Parser, der mit rekursivem Abstieg implementiert ist.
Beginnt mit:
gelten links Beseitigung der Rekursion eine LL (1) Grammatik zu erhalten:
Schreiben Sie die entsprechenden Funktionen:
Schwanzrekursion entfernen:
in der Reihe:
und Sie müssen nur die semantische Verarbeitung hinzufügen, um Ihre Funktion zu erhalten.
quelle
Sehen Sie hier für einen umfassenden Überblick darüber , wie mächtig diese Klasse von Parsern ist.
quelle