Selectn - dědičnost tříd

Klíčové slovo select před typem pravidla.

Pravidlo je tvořeno výběrem z několika jednoduchých alternativ,
které mají výsledný typ odvozený z typu zmíněného pravidla.

   stat < select TStat > :
      while_stat | if_stat | compound_stat | simple_stat | empty_stat ;

Vytvořená metoda parse_stat sama nevytváří novou instanci,
ale použije instanci dodanou metodou parse_while_stat, parse_if_stat, …

   def parse_stat (self) :
      if self.tokenText == "while" :
         result = self.parse_while_stat ()
      elif self.tokenText == "if" :
         result = self.parse_if_stat ()
      elif self.tokenText == "{" :
         result = self.parse_compound_stat ()
      elif self.token == self.identifier or self.token == self.number or self.tokenText == "(" :
         result = self.parse_simple_stat ()
      elif self.tokenText == ";" :
         result = self.parse_empty_stat ()
      else :
         self.error ("Unexpected token")
      return result

Metoda pro tisk zdrojového textu uloženého v syntaktickém stromu send_stat
otestuje skutečný typ parametru a zavolá send_while_stat, …

   def send_stat (self, param) :
      if isinstance (param, TWhileStat) :
         self.send_while_stat (param)
      elif isinstance (param, TIfStat) :
         self.send_if_stat (param)
      elif isinstance (param, TCompoundStat) :
         self.send_compound_stat (param)
      elif isinstance (param, TSimpleStat) :
         self.send_simple_stat (param)
      elif isinstance (param, TEmptyStat) :
         self.send_empty_stat (param)

Zde jsou vygenerované třídy pro uskladnění dat:

class TStat :
   pass
 
class TWhileStat (TStat) :
   def __init__ (self) :
      super (TWhileStat, self).__init__ ()
      self.cond = None
      self.code = None

Totéž v C++

CmmStat *  CmmParser::parse_stat ()
{
   CmmStat * result = NULL;
   if (isSymbol (KEYWORD_while))
      result = parse_while_stat ();
   else if (isSymbol (KEYWORD_if))
      result = parse_if_stat ();
   else if (isSymbol (LBRACE))
      result = parse_compound_stat ();
   else if (TestSymbols (set_11))
      result = parse_simple_stat ();
   else if (isSymbol (SEMICOLON))
      result = parse_empty_stat ();
   else
      error ("Unexpected symbol");
   return result;
}
 
const unsigned char set_11 [] = { ... };

Množina set_11 obsahuje symboly, kterými může začínat jednoduchý příkaz.

void CmmProduct::send_stat (CmmStat *  item)
{
    if (item->conv_CmmWhileStat () != NULL)
        send_while_stat (item->conv_CmmWhileStat ());
    else if (item->conv_CmmIfStat () != NULL)
        send_if_stat (item->conv_CmmIfStat ());
    else if (item->conv_CmmCompoundStat () != NULL)
        send_compound_stat (item->conv_CmmCompoundStat ());
    else if (item->conv_CmmSimpleStat () != NULL)
      send_simple_stat (item->conv_CmmSimpleStat ());
    else if (item->conv_CmmEmptyStat () != NULL)
       send_empty_stat (item->conv_CmmEmptyStat ());
    else
      assert (false);
}

Pro testování typu lze použít dynamic_cast.
Nebo jednoduché virtuální metody jako jsou conv_CmmIfStat, conv_CmmWhileStat

class CmmStat
{
   // conversion functions
   public:
      virtual CmmIfStat *  conv_CmmIfStat () { return NULL; }
      virtual CmmWhileStat *  conv_CmmWhileStat () { return NULL; }
};
 
class CmmWhileStat : public CmmStat
{
   public:
      CmmExpr *  cond;
      CmmStat *  body;
 
   // conversion functions
   public:
      virtual CmmWhileStat *  conv_CmmWhileStat () { return this; }
};
 
prekl/select.txt · Last modified: 2020/05/06 17:42 by 88.103.111.44
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki