1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
|
#include "nonterminal.ih"
// For an empty production, the N gets <empty>. For non-empty
// productions: add those element's first symbols, and stop if an
// element has no empty production. If, at the end, the final element
// has an empty production, add <empty> as well
void NonTerminal::setFirst(NonTerminal *nonTerminal)
{
FirstSet &firstSet = nonTerminal->d_first;
Production::Vector &prodVect = nonTerminal->d_production;
if (!prodVect.size()) // empty production
firstSet.addEpsilon(); // add epsilon to FirstSet
else
{
bool hasEpsilon = false; // include epsilon at the end?
for // visit all elements of a production
(
Production::Vector::const_iterator it = prodVect.begin();
it != prodVect.end();
++it
)
{
Production const &production = **it;
bool epsilon = true; // epsilon in this rule's elements
for
(
auto symPtrIt = production.begin();
symPtrIt != production.end();
++symPtrIt
)
{
firstSet += (*symPtrIt)->firstSet();
// add the element's firstSet
// element without <e>
if (!(*symPtrIt)->firstSet().hasEpsilon())
{
epsilon = false;
break; // and done, this productionrule
}
}
hasEpsilon |= epsilon; // once a production rule includes
// epsilon, hasEpsilon remains true
}
if (hasEpsilon)
firstSet.addEpsilon();
else
firstSet.rmEpsilon();
}
s_counter += firstSet.setSize();
}
|