Table of Contents

Choose - opožděné rozhodnutí

Při zpracování aritmetických výrazů není vhodné vytvářet novou instanci pro každé zpracovávané pravidlo

simple_expr :          identifier | number  | "(" expr ")" ;
multiplicative_expr :  simple_expr ( ("*"|"/") simple_expr )* ;
additive_expr :        multiplicative_expr ( ("+"|"-") multiplicative_expr )* ;
expr :                 additive_expr ( "=" expr )? ;

Pokud např. zpracováváme výraz A + B - C,
zajímají nás uzly odpovídající aditivnímu výrazu a listy s idetifikátory.

Uzly, které neskladují žádnou aritmetickou operaci, většinou znepřehledňují strom.

Klíčové slovo choose před typem pravidla

additive_expr <choose CmmExpr> :
   multiplicative_expr
   (
      <new CmmAddExpr:CmmExpr>
      <store left:CmmExpr>
      ( '+' <set kind=addExp> |
        '-' <set kind=subExp> )
      right:multiplicative_expr
   )* ;

Požadavky na použité typy

Vygenerovaná metoda syntaktického analyzátoru

   def parse_additive_expr (self) :
      result = self.parse_multiplicative_expr ()
      while self.tokenText == "+" or self.tokenText == "-" :
            store = result
            result = CmmAddExpr ()
 
            result.left = store
 
            if self.tokenText == "+" :
               self.check ("+")
               result.kind = result.addExp
            elif self.tokenText == "-" :
               self.check ("-")
               result.kind = result.subExp
            else :
               self.error ("Unexpected token")
 
            result.right = self.parse_multiplicative_expr ()
      return result

Pokud bude na vstupu např. A + B - C, vznikne strom

          "-"
           |
       .------.
       |      |
      "+"      C
       |
   .------.
   |      |
   A      B

Do proměnné result se nejprve voláním parse_multiplicative_expr uloží A.

Jelikož následuje plus, původní hodnotu result uschováme do proměnné store.
Do result uložíme nový uzel pro aritmetickou operaci typu CmmAddExpr.
Původní hodnotu (A) uložíme do result.left.
Nastavíme result.kind na addExp nebo subExp.
Pravý operand (B) uložíme do result.right.

Nyní se while cyklus opakuje.
Jelikož následuje minus, současný výsledek (A+B) uschováme,
a vytvoříme novou instanci, tentokrát pro minus.

Pokud nenásleduje další plus nebo minus, tak funkce skončí a výsledkem bude načrtnutý strom.
Můžete porovnat s úvodní kapitolou syntaktická analýza výrazů.

Vygenerovaná metoda pro tisk zdrojového textu

Metoda pro tisk nejprve vyzkouší zda parametr není typem pro naší variantu CmmAddExpr. Pro tisk levého parametru rekurzivně použije stejnou metodu.

Nakonci metody je else pro případ, že naše varianta nenastala.

   def send_additive_expr (self, param) :
      if isinstance (param, CmmAddExpr) :
         self.send_additive_expr (param.left)
         if param.kind == param.addExp :
            self.send ("+")
         elif param.kind == param.subExp :
            self.send ("-")
         self.send_multiplicative_expr (param.right)
      else :
         self.send_multiplicative_expr (param)