===== 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; } };