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