438   uint result = 0, i = 0;
   440     result += (++i) * 
qHash(cat);
   464 static void parseTreeToPmcfgSyntaxTreeUnify(
Node &dest, 
const Node &src)
   467     qFatal(
"invalid parse tree: PMCFG unification failed (mismatched nodes)");
   478     qFatal(
"invalid parse tree: PMCFG unification failed (mismatched "   479            "alternative counts)");
   480   for (
int i=0; i<s; i++) {
   483     int l = destAlternative.size();
   484     if (srcAlternative.size() != l
   485         || srcAlternative.
label() != destAlternative.
label())
   486       qFatal(
"invalid parse tree: PMCFG unification failed (mismatched "   488     for (
int j=0; j<l; j++)
   489       parseTreeToPmcfgSyntaxTreeUnify(destAlternative[j], srcAlternative.at(j));
   494 static void parseTreeToPmcfgSyntaxTreeRecurse(
const Node &parseTree,
   510     QVariant label = alternative.
label();
   514       int numArgs = componentInfo.
pmcfgRule.size();
   515       for (
int i=0; i<numArgs; i++) {
   518         const QVector<int> &argPositions = componentInfo.
argPositions.at(i);
   519         if (argPositions.isEmpty())
   522           parseTreeToPmcfgSyntaxTreeRecurse(
   523             alternative.at(argPositions.first()), newChild);
   524           int s = argPositions.size();
   525           for (
int i=1; i<s; i++) {
   527             parseTreeToPmcfgSyntaxTreeRecurse(alternative.at(
   528               argPositions.at(i)), tempChild);
   529             parseTreeToPmcfgSyntaxTreeUnify(newChild, tempChild);
   532         newAlternative.append(newChild);
   534     } 
else newAlternative = alternative; 
   541   Node syntaxTree(parseTree.
cat);
   542   parseTreeToPmcfgSyntaxTreeRecurse(parseTree, syntaxTree);
   547 QHash<QString, ActionDeserializer *> Action::deserializers;
   555   foreach (
CatArg cat, list)
   556     if (!
isToken(cat)) 
return false;
   566 Cat Parser::effectiveCat(
CatArg cat)
 const   581   initialGraph.clear();
   582   neighborhoods.clear();
   584   epsilonMatches.clear();
   589   QHashIterator<Cat, QList<Rule> > it(
rules);
   590   while (it.hasNext()) {
   593     foreach (
const Rule &rule, it.value()) {
   594       if (rule.isEmpty()) {
   595         nullable.insert(cat);
   604   unsigned newNullables;
   608     while (it.hasNext()) {
   611       if (nullable.contains(cat)) 
continue; 
   612       foreach (
const Rule &rule, it.value()) {
   613         foreach (
CatArg cati, rule) {
   614           if (!nullable.contains(effectiveCat(cati))) 
goto next_rule;
   616         nullable.insert(cat);
   623   } 
while (newNullables);
   627   while (it.hasNext()) {
   633     int n = ruleList.size();
   634     for (
int i=0; i<n; i++) {
   641       const Rule &rule = ruleList.at(i);
   642       QListIterator<Cat> it(rule);
   643       int epsilonsSkipped=0;
   644       while (it.hasNext()) {
   645         Cat cati = effectiveCat(it.next());
   646         initialGraph.insert(cati, 
FullRule(cat, rule, epsilonsSkipped,
   647                                            keepRuleNumbers ? i : 0));
   648         if (!nullable.contains(cati)) 
break;
   662 void Parser::processRule(
CatArg cat, 
const Rule &rule, 
int skip, 
int ruleno,
   663                          QQueue<Cat> &nullableQueue, 
bool &clearEpsilonMatches)
   670   QListIterator<Cat> i(rule);
   671   int epsilonsSkipped=skip;
   672   while (i.hasNext()) {
   673     Cat cati = effectiveCat(i.next());
   674     initialGraph.insert(cati, 
FullRule(cat, rule, epsilonsSkipped, ruleno));
   675     if (!nullable.contains(cati)) 
break;
   678   if (epsilonsSkipped == rule.size()) { 
   681     clearEpsilonMatches = 
true;
   682     if (!nullable.contains(cat) && !nullableQueue.contains(cat))
   683       nullableQueue.enqueue(cat);
   694   int ruleno = 
componentCats.contains(cat) ? ruleList.size() : 0;
   698   QQueue<Cat> nullableQueue; 
   699   bool clearEpsilonMatches = 
false;
   703   processRule(cat, rule, 0, ruleno, nullableQueue, clearEpsilonMatches);
   705   while (!nullableQueue.isEmpty()) {
   706     Cat newNullable = nullableQueue.dequeue();
   708     nullable.insert(newNullable);
   715     foreach (
const FullRule &rule, initialGraph.values(newNullable))
   717                   nullableQueue, clearEpsilonMatches);
   719   if (clearEpsilonMatches) {
   720     epsilonMatches.clear();
   721     neighborhoods.clear();
   722   } 
else if (!rule.isEmpty()) {
   724     typedef QPair<Cat, Cat> CatPair;
   725     QHashIterator<CatPair, QList<FullRule> > it(neighborhoods);
   727     CatArg ruleFirst = rule.first();
   728     bool firstIsNullable = nullable.contains(ruleFirst);
   729     while (it.hasNext()) {
   731       const CatPair &key = it.key();
   732       if (reachable(cat, key.second, QSet<Cat>())
   733         && (firstIsNullable || reachable(key.first, ruleFirst, QSet<Cat>()))) {
   737     foreach (
const CatPair &key, invalidate) neighborhoods.remove(key);
   743 bool Parser::computePmcfgDimension(
CatArg cat, 
const Rule &rule,
   750   int dim = 
function.size();
   753       qWarning(
"dimension mismatch: 1D function for multidimensional category");
   757     if (
rules.contains(cat)) {
   758       qWarning(
"dimension mismatch: multidimensional function for 1D category");
   763         qWarning(
"dimension mismatch: %dD function for %dD category", dim,
   769       for (
int i=0; i<dim; i++) {
   771 #ifdef DYNGENPAR_INTEGER_CATEGORIES   772         Cat component = generateCat();
   774         Cat component = QString(
"%1[%2]").arg(cat).arg(i);
   776         components.append(component);
   787 bool Parser::convertPmcfgRule(
CatArg cat, 
const Rule &rule, 
const Pmcfg &pmcfg,
   794   int dim = 
function.size();
   797     components.append(cat);
   803   foreach(
const Sequence &sequence, 
function) {
   804     foreach(
const Term &term, sequence) {
   806         numArgs = term.
arg + 1;
   811   if (rule.size() < numArgs) {
   812     qWarning(
"not enough arguments for PMCFG function");
   817   QVector<QList<Cat> > argComponents(numArgs);
   818   for (
int i=0; i<numArgs; i++) {
   822     else if (pmcfg.
rules.contains(arg) || pmcfg.
cfRules.contains(arg)
   823              || pmcfg.
tokens.contains(arg))
   824       argComponents[i].append(arg);
   832   foreach(
const Sequence &sequence, 
function) {
   833     foreach(
const Term &term, sequence) {
   835           && term.
component >= argComponents.at(term.
arg).size()) {
   836         qWarning(
"dimension mismatch: attempt to use component %d of a %dD "   837                  "category", term.
component, argComponents.at(term.
arg).size());
   844   QVector<int> usageCounts(numArgs);
   845   foreach(
const Sequence &sequence, 
function) {
   846     foreach(
const Term &term, sequence) {
   848         usageCounts[term.
arg]++;
   853   QVector<QHash<int, Cat> > newPseudoCats(numArgs);
   854   foreach(
const Sequence &sequence, 
function) {
   855     foreach(
const Term &term, sequence) {
   857         if (!newPseudoCats[term.
arg].contains(term.
component)) {
   858 #ifdef DYNGENPAR_INTEGER_CATEGORIES   859           Cat pseudoCat = generateCat();
   861           Cat pseudoCat = QString(
"Pseudo%1").arg(generateCat());
   863           newPseudoCats[term.
arg].insert(term.
component, pseudoCat);
   870   for (
int i=0; i<numArgs; i++) {
   871     const QHash<int, Cat> &pseudoCatHash = newPseudoCats.at(i);
   872     if (!pseudoCatHash.isEmpty()) {
   873       QList<Cat> pseudoCatList = pseudoCatHash.values();
   874       QHashIterator<int, Cat> it(pseudoCatHash);
   875       while (it.hasNext()) {
   877         Cat pseudoCat = it.value();
   878         pseudoCats.insert(pseudoCat, qMakePair(argComponents.at(i).at(it.key()),
   885   for (
int i=0; i<dim; i++) {
   886     const Sequence &sequence = 
function.at(i);
   888     int s = sequence.size();
   889     for (
int j=0; j<s; j++) {
   890       const Term &term = sequence.at(j);
   894     Rule internalRule(QVariant::fromValue(componentInfo));
   906     foreach (
const Term &term, sequence)
   908                           : newPseudoCats.at(term.
arg).isEmpty()
   912     CatArg catComponent = components.at(i);
   914       addRule(catComponent, internalRule);
   916       rules[catComponent].append(internalRule);
   944     QHashIterator<Cat, QList<Rule> > it(pmcfg.
rules);
   945     while (it.hasNext()) {
   946       Cat cat = it.next().key();
   947       foreach (
const Rule &rule, it.value())
   948         if (!computePmcfgDimension(cat, rule, pmcfg)) 
return false;
   952     QHashIterator<Cat, QList<Rule> > it(pmcfg.
rules);
   953     while (it.hasNext()) {
   954       Cat cat = it.next().key();
   955       foreach (
const Rule &rule, it.value())
   956         if (!convertPmcfgRule(cat, rule, pmcfg, 
false)) 
return false;
   976   if (!computePmcfgDimension(cat, rule, pmcfg)
   977       || !convertPmcfgRule(cat, rule, pmcfg, 
true)) 
return false;
   978   pmcfg.
rules[cat].append(rule);
   988 bool Parser::reachable(
CatArg cat, 
CatArg target, QSet<Cat> mark)
   990   if (cat == target) 
return true;
   992   foreach (
const FullRule &rule, initialGraph.values(cat)) {
   993     if (mark.contains(rule.
cat)) 
continue;
   994     if (reachable(rule.
cat, target, mark)) 
return true;
  1007   QPair<Cat, Cat> key(cat, target);
  1008   if (neighborhoods.contains(key)) 
return neighborhoods.value(key);
  1011   foreach (
const FullRule &rule, initialGraph.values(cat)) {
  1012     if (reachable(rule.
cat, target, QSet<Cat>())) result.append(rule);
  1015   neighborhoods.insert(key, result);
  1023   int s = matches.size();
  1024   for (
int i=0; i<s; i++) {
  1025     Match &m = matches[i];
  1039   if (scope.
isNull()) 
return; 
  1040   int s = matches.size();
  1041   for (
int i=0; i<s; i++)
  1042     matches[i].scope = scope;
  1049   bool haveNextTokenConstraints = 
false;
  1052   bool isFirst = 
true;
  1053   foreach (
const Rule &rule, 
rules.value(cat)) {
  1055     foreach (
CatArg cati, rule) {
  1056       if (!nullable.contains(cati) || mark.contains(cati)) 
goto next_rule;
  1064         haveNextTokenConstraints = 
true;
  1065         currentMatches.first().nextTokenConstraints.expect =
  1069         haveNextTokenConstraints = 
true;
  1070         currentMatches.first().nextTokenConstraints.taboo =
  1073       foreach (
CatArg cati, rule) {
  1074         int s = currentMatches.size();
  1075         for (
int i=0; i<s; ) {
  1076           Match &m = currentMatches[i];
  1078             = matchToEpsilonRecurse(cati, mark, m.
scope);
  1079           if (componentMatches.isEmpty()) {
  1080             if (i) currentMatches.swap(0, i);
  1081             currentMatches.removeFirst();
  1084             int cs = componentMatches.size();
  1085             for (
int j=1; j<cs; j++) {
  1086               const Match &cm = componentMatches.at(j);
  1092                 haveNextTokenConstraints = 
true;
  1093                 currentMatches.last().nextTokenConstraints.expect.append(
  1097                 haveNextTokenConstraints = 
true;
  1098                 currentMatches.last().nextTokenConstraints.taboo.append(
  1102             const Match &cm = componentMatches.first();
  1107               haveNextTokenConstraints = 
true;
  1112               haveNextTokenConstraints = 
true;
  1120       if (currentMatches.isEmpty()) 
goto next_rule;
  1121       if (haveNextTokenConstraints) {
  1124         int s = currentMatches.size();
  1125         for (
int i=0; i<s; i++) currentMatches[i].scope = 
PseudoCatScope();
  1126         result.append(currentMatches);
  1136       int i=0, s=currentMatches.size();
  1139         result.append(currentMatches.first());
  1143       Match &firstResult = result.first();
  1145         firstResult.
tree.
children.append(currentMatches.at(i).tree.children);
  1152   if (haveNextTokenConstraints) unify(result);
  1166     return matchCFToEpsilon(cat, mark);
  1170   int s = ruleList.size();
  1171   for (
int i=0; i<s; i++) {
  1172     const Rule &rule = ruleList.at(i);
  1174     foreach (
CatArg cati, rule) {
  1175       if (!nullable.contains(cati) || mark.contains(cati)) 
goto next_rule;
  1183       foreach (
CatArg cati, rule) {
  1184         int s = currentMatches.size();
  1185         for (
int i=0; i<s; ) {
  1186           Match &m = currentMatches[i];
  1188             = matchToEpsilonRecurse(cati, mark, m.
scope);
  1189           if (componentMatches.isEmpty()) {
  1190             if (i) currentMatches.swap(0, i);
  1191             currentMatches.removeFirst();
  1194             int cs = componentMatches.size();
  1195             for (
int j=1; j<cs; j++) {
  1196               const Match &cm = componentMatches.at(j);
  1201               currentMatches.last().nextTokenConstraints.expect.append(
  1203               currentMatches.last().nextTokenConstraints.taboo.append(
  1206             const Match &cm = componentMatches.first();
  1218       result.append(currentMatches);
  1234     QPair<QPair<Node, NextTokenConstraints>, 
int> pConstraint
  1236     if (!pConstraint.second) 
  1237       result.append(
Match(0, pConstraint.first.first, 0, scope,
  1238                           pConstraint.first.second));
  1244   Cat effCat = effectiveCat(cat);
  1246   if (effCat != cat) { 
  1247     if (mark.contains(effCat)) 
return result; 
  1252       QPair<int, PseudoCatScope> mcfgConstraint = scope.
mcfgConstraint(cat);
  1253       const Rule &rule = 
rules.value(effCat).at(mcfgConstraint.first);
  1257       foreach (
CatArg cati, rule) {
  1258         if (!nullable.contains(cati) || mark.contains(cati)) 
return result;
  1262       result.append(
Match(0, node, mcfgConstraint.first, scope,
  1264       foreach (
CatArg cati, rule) {
  1265         int s = result.size();
  1266         for (
int i=0; i<s; ) {
  1267           Match &m = result[i];
  1269             = matchToEpsilonRecurse(cati, mark, m.
scope);
  1270           if (componentMatches.isEmpty()) {
  1271             if (i) result.swap(0, i);
  1272             result.removeFirst();
  1275             int cs = componentMatches.size();
  1276             for (
int j=1; j<cs; j++) {
  1277               const Match &cm = componentMatches.at(j);
  1282               result.last().nextTokenConstraints.expect.append(
  1284               result.last().nextTokenConstraints.taboo.append(
  1287             const Match &cm = componentMatches.first();
  1299       result = matchEffectiveCatToEpsilon(effCat, mark);
  1301     finalizeMatches(result, cat, scope);
  1303     result = matchCFToEpsilon(cat, mark);
  1304     copyScope(result, scope);
  1322     QPair<QPair<Node, NextTokenConstraints>, 
int> pConstraint
  1324     if (!pConstraint.second) 
  1325       result.append(
Match(0, pConstraint.first.first, 0, scope,
  1326                           pConstraint.first.second));
  1332   Cat effCat = effectiveCat(cat);
  1334   if (effCat != cat) { 
  1337       QPair<int, PseudoCatScope> mcfgConstraint = scope.
mcfgConstraint(cat);
  1338       const Rule &rule = 
rules.value(effCat).at(mcfgConstraint.first);
  1341       foreach (
CatArg cati, rule) {
  1342         if (!nullable.contains(cati)) 
return result;
  1346       result.append(
Match(0, node, mcfgConstraint.first, scope,
  1348       foreach (
CatArg cati, rule) {
  1349         int s = result.size();
  1350         for (
int i=0; i<s; ) {
  1351           Match &m = result[i];
  1353           if (componentMatches.isEmpty()) {
  1354             if (i) result.swap(0, i);
  1355             result.removeFirst();
  1358             int cs = componentMatches.size();
  1359             for (
int j=1; j<cs; j++) {
  1360               const Match &cm = componentMatches.at(j);
  1365               result.last().nextTokenConstraints.expect.append(
  1367               result.last().nextTokenConstraints.taboo.append(
  1370             const Match &cm = componentMatches.first();
  1385       result = matchEffectiveCatToEpsilon(effCat, QSet<Cat>());
  1388     finalizeMatches(result, cat, scope);
  1393     if (epsilonMatches.contains(cat))
  1394       result = epsilonMatches.value(cat);
  1396       result = matchCFToEpsilon(cat, QSet<Cat>());
  1397       epsilonMatches.insert(cat, result);
  1399     copyScope(result, scope);
  1406 bool Parser::matchesTokenRecurse(
CatArg cat, 
CatArg token, QSet<Cat> mark)
 const  1409   if (
isToken(cat)) 
return cat == token;
  1413   foreach (
const Rule &rule, 
rules.value(cat)) {
  1415     if (rule.isEmpty()) 
continue;
  1418     int l = rule.size();
  1419     for (
int i=0; i<l; i++) {
  1420       CatArg cati = rule.at(i);
  1423       if (mark.contains(cati)) 
continue; 
  1424       for (
int j=0; j<l; j++) {
  1425         if (i == j) 
continue;
  1426         if (!nullable.contains(rule.at(j))) 
goto skip_this_i; 
  1428       if (matchesTokenRecurse(cati, token, mark)) 
return true; 
  1447 bool Parser::matchesToken(
CatArg cat, 
CatArg token)
 const  1449   return matchesTokenRecurse(cat, token, QSet<Cat>());
  1463     leaves.append(tree);
  1467       collectLeaves(node, leaves);
  1472 bool Parser::validateNextTokenConstraints(
CatArg token,
  1476     if (!matchesToken(expect, token)) 
return false;
  1478     if (matchesToken(taboo, token)) 
return false;
  1497     QPair<QPair<Node, NextTokenConstraints>, 
int> pConstraint
  1499     if (pConstraint.second) { 
  1501       collectLeaves(pConstraint.first.first, leaves);
  1506       if (validateNextTokenConstraints(leaves.first().cat,
  1507                                        nextTokenConstraints)) {
  1508         StackItem type6(stack, leaves, 0, pConstraint.first.first, scope,
  1509                         pConstraint.first.second);
  1510         nextStacks.append(type6);
  1514       newNextTokenConstraints.
expect.append(pConstraint.first.second.expect);
  1515       newNextTokenConstraints.
taboo.append(pConstraint.first.second.taboo);
  1516       result.append(
Match(0, pConstraint.first.first, 0, scope,
  1517                           newNextTokenConstraints));
  1524   Cat effCat = effectiveCat(cat);
  1528     QPair<int, PseudoCatScope> mcfgConstraint = scope.
mcfgConstraint(cat);
  1529     const Rule &rule = 
rules.value(effCat).at(mcfgConstraint.first);
  1536       result = matchRemaining(rule, 0, pos, 0, node, mcfgConstraint.second,
  1537                               mcfgConstraint.first, type5,
  1538                               nextTokenConstraints);
  1541     finalizeMatches(result, cat, scope);
  1544     if (nullable.contains(effCat)) {
  1545       result = matchToEpsilon(cat, scope);
  1546       if (!nextTokenConstraints.
expect.isEmpty()
  1547           || !nextTokenConstraints.
taboo.isEmpty()) {
  1548         int s = result.size();
  1549         for (
int i=0; i<s; i++) {
  1551             = result[i].nextTokenConstraints;
  1552           newNextTokenConstraints.
expect.append(nextTokenConstraints.
expect);
  1553           newNextTokenConstraints.
taboo.append(nextTokenConstraints.
taboo);
  1563     if (stack.
type() < 0) { 
  1565       nextStacks.append(type0);
  1568       if (scope.
isNull() && type0Indices.contains(cat))
  1569         nextStacks[type0Indices.value(cat)].addParent(stack);
  1573         StackItem type0(parents, cat, effCat, pos, scope);
  1574         if (scope.
isNull()) type0Indices.insert(cat, nextStacks.size());
  1575         nextStacks.append(type0);
  1597 bool Parser::verifyLookaheadRule(
const Rule &rule, 
int i, 
int &curr,
  1598                                  int &remaining, QSet<Cat> &mark)
  1600   while (i < rule.size()) {
  1601     Cat cati = effectiveCat(rule.at(i++));
  1606       if (lookahead != cati) {
  1609       if (!(--remaining)) {
  1613       if (!mark.contains(cati)) {
  1616         switch (catiRules.size()) {
  1621               Rule catiRule = catiRules.first();
  1622               if (!verifyLookaheadRule(catiRule, 0, curr, remaining, mark))
  1624               if (!remaining) 
return true;
  1628             foreach (
const Rule &catiRule, catiRules) {
  1631               int currCopy = curr;
  1632               int remainingCopy = remaining;
  1633               QSet<Cat> markCopy = mark;
  1634               if (!verifyLookaheadRule(catiRule, 0, currCopy, remainingCopy,
  1639               if (!remainingCopy) {
  1645               if (verifyLookaheadRule(rule, i, currCopy, remainingCopy,
  1648                 remaining = remainingCopy;
  1673 bool Parser::verifyLookahead(
const StackItem &stack, 
CatArg cat, 
int pos,
  1676   switch (stack.
type()) {
  1678       qFatal(
"type 0 items not supported by verifyLookahead");
  1684         if (parents.isEmpty()) { 
  1692         foreach (
const StackItem &parent, parents)
  1693           if (verifyLookahead(parent, cat, pos, nTokens))
  1702         return verifyLookahead(parent, cat, pos, nTokens);
  1711         int i = data->
i() + 1;
  1715         int remaining = nTokens;
  1717         bool ret = verifyLookaheadRule(rule, i, curr, remaining, mark);
  1719         if (!ret) 
return false;
  1720         if (!remaining) 
return true;
  1721         return verifyLookahead(parent, tree.
cat, curr, remaining);
  1729         Cat effCat = effectiveCat(cat);
  1730         foreach (
const FullRule &rule, neighborhood(effCat, target)) {
  1735           int remaining = nTokens;
  1737           bool ret = verifyLookaheadRule(rule.
rule, i, curr, remaining, mark);
  1740             if (!remaining) 
return true;
  1741             if (verifyLookahead(stack, rule.
cat, curr, remaining)) 
return true;
  1744         if (effCat == target)
  1745           return verifyLookahead(parent, target, pos, nTokens);
  1754         Cat dataCat = data->
cat();
  1755         return verifyLookahead(parent, dataCat, pos, nTokens);
  1758       qFatal(
"type 6 items not supported by verifyLookahead");
  1760       qFatal(
"invalid stack item type");
  1770 QList<Match> Parser::matchRemaining(
const Rule &rule, 
int len, 
int curr, 
int i,
  1775                                       &nextTokenConstraints)
  1778   if (i < rule.size()) {
  1781       StackItem type3(stack, rule, len, curr, i, tree, ruleno,
  1782                       nextTokenConstraints);
  1783       matches = match(rule.at(i), curr, scope, type3, nextTokenConstraints);
  1785     foreach (
const Match &m, matches) {
  1786       Node newTree = tree;
  1788       result.append(matchRemaining(rule, len+m.
len, curr+m.
len, i+1, newTree,
  1789                                    m.
scope, ruleno, stack,
  1795       if (lookaheadTokens <= 0 
  1800       } 
else return result; 
  1806     result.append(
Match(len, tree, ruleno, scope, newNextTokenConstraints));
  1815 Cat Parser::findFirstToken(
const Node &tree)
  1823       Cat result = findFirstToken(node);
  1834   int l = matches.size();
  1839     QHash<QPair<QPair<QPair<int, Cat>, QPair<int, PseudoCatScope> >,
  1843       const Match &m = matches.first();
  1844       indexOfLenCat.insert(qMakePair(qMakePair(qMakePair(m.
len, m.
tree.
cat),
  1848     for (
int i=1; i<l; ) {
  1849       const Match &m = matches.at(i);
  1850       QPair<QPair<QPair<int, Cat>, QPair<int, PseudoCatScope> >,
  1851             NextTokenConstraints> key(qMakePair(qMakePair(m.
len, m.
tree.
cat),
  1854       if (indexOfLenCat.contains(key)) {
  1855         matches[indexOfLenCat.value(key)].tree.children.append(m.
tree.
children);
  1856         matches.removeAt(i);
  1858       } 
else indexOfLenCat.insert(key, i++);
  1880   if (cat == target) result.append(
Match(len, tree, ruleno, scope,
  1881                                          nextTokenConstraints));
  1884     StackItem type4(stack, target, pos, len);
  1886     foreach (
const FullRule &rule, neighborhood(cat, target)) {
  1893       CatArg pseudoCat = rule.
rule.at(epsilonsSkipped);
  1894       if (pseudoCat != cat) {
  1896           qMakePair(qMakePair(tree, nextTokenConstraints), len));
  1900       currentMatches.append(
Match(0, node, rule.
ruleno, newScope,
  1901                                   nextTokenConstraints));
  1908       if (epsilonsSkipped)
  1909         firstToken = findFirstToken(tree);
  1911       for (
int k=0; k<epsilonsSkipped; k++) {
  1912         int s = currentMatches.size();
  1913         for (
int i=0; i<s; ) {
  1914           Match &m = currentMatches[i];
  1924             int cs = componentMatches.size();
  1925             for (
int j=0; j<cs; ) {
  1926               if (validateNextTokenConstraints(firstToken,
  1927                     componentMatches.at(j).nextTokenConstraints)) j++; 
else {
  1928                 if (j) componentMatches.swap(0, j);
  1929                 componentMatches.removeFirst();
  1934           if (componentMatches.isEmpty()) {
  1935             if (i) currentMatches.swap(0, i);
  1936             currentMatches.removeFirst();
  1939             int cs = componentMatches.size();
  1940             for (
int j=1; j<cs; j++) {
  1941               const Match &cm = componentMatches.at(j);
  1948               = 
static_cast<const QList<Match> &
>(componentMatches).first();
  1956       foreach (
const Match &m, currentMatches) {
  1958         newTree.
children.first().append(tree);
  1960         matches.append(matchRemaining(rule.
rule, 0, pos, epsilonsSkipped+1,
  1970     foreach (
const Match &m, matches) {
  1973         qFatal(
"length of a reduction increased in a non-shift codepath");
  1978       if (mark.contains(newCat)) 
continue;
  1980       result.append(reduce(newCat, target, pos, len, m.
tree, type2, m.
scope,
  2003     if (matches.isEmpty()) 
return matches;
  2004     switch (item.
type()) {
  2006         qFatal(
"type 0 items not supported by processStackItem");
  2017             finalizeMatches(nextMatches, cat, scope);
  2019             copyScope(nextMatches, scope);
  2021           if (parents.isEmpty()) 
  2023           else if (parents.count() == 1) {
  2024             nextItem = parents.first();
  2029             foreach (
const StackItem &parent, parents)
  2030               result.append(processStackItem(parent, nextMatches));
  2045             present = collectedMatches.contains(data);
  2047             if (priorityQueue.isEmpty()) {
  2052             int headDepth = priorityQueue.head().depth();
  2053             int depth = data->
depth();
  2054             if (headDepth < depth) 
goto type_2_skip;
  2055             if (headDepth == depth) {
  2056               present = collectedMatches.contains(data);
  2057               if (!present) 
goto type_2_skip;
  2058             } 
else present = collectedMatches.contains(data);
  2063             QPair<bool, QList<Match> > &entry = collectedMatches[data];
  2065             entry.second.append(matches);
  2067             collectedMatches[data] = qMakePair(
false, matches);
  2068             priorityQueue.enqueue(item);
  2079           int len = data->
len();
  2080           int curr = data->
curr();
  2083           int ruleno = data->
ruleno();
  2086           foreach (
const Match &m, matches) {
  2087             Node newTree = tree;
  2089             result.append(matchRemaining(rule, len+m.
len, curr+m.
len, i+1,
  2090                                          newTree, m.
scope, ruleno, parent,
  2094           nextMatches = result;
  2105           int pos = data->
pos();
  2106           int len = data->
len();
  2112             present = collectedMatches.contains(data);
  2114             if (priorityQueue.isEmpty()) {
  2119                 foreach (
const Match &m, matches) {
  2122                     qFatal(
"reduction with unchanged length was deferred");
  2124                   result.append(reduce(newCat, target, pos+m.
len, len+m.
len,
  2132               nextMatches = result;
  2136             int headDepth = priorityQueue.head().depth();
  2137             int depth = data->
depth();
  2138             if (headDepth < depth) 
goto type_4_skip;
  2139             if (headDepth == depth) {
  2140               present = collectedMatches.contains(data);
  2141               if (!present) 
goto type_4_skip;
  2142             } 
else present = collectedMatches.contains(data);
  2147             QPair<bool, QList<Match> > &entry = collectedMatches[data];
  2149             entry.second.append(matches);
  2151             collectedMatches[data] = qMakePair(
false, matches);
  2152             priorityQueue.enqueue(item);
  2164           finalizeMatches(nextMatches, cat, scope);
  2171         qFatal(
"type 6 items not supported by processStackItem");
  2173         qFatal(
"invalid stack item type");
  2189   switch (stack.
type()) {
  2198         int pos = data->
pos();
  2209           StackItem type1(parents, cat, effCat, scope);
  2215             finalizeMatches(matches, cat, scope);
  2217             copyScope(matches, scope);
  2220         if (parents.isEmpty()) 
  2224           if (parents.count() > 1) branched = 
true;
  2225           foreach (
const StackItem &parent, parents)
  2226             result.append(processStackItem(parent, matches));
  2246           int l = leaves.size();
  2248             matches.append(
Match(l, tree, 0, scope, nextTokenConstraints));
  2250             StackItem type6(parent, leaves, i, tree, scope,
  2251                             nextTokenConstraints);
  2252             nextStacks.append(type6);
  2256         return processStackItem(parent, matches);
  2265         QPair<bool, QList<Match> > entry = collectedMatches.take(stack.
data());
  2267           unify(entry.second);
  2268         return processStackItem(stack, entry.second);
  2271       qFatal(
"invalid stack (expected toplevel item or unification point)");
  2281 bool Parser::shift(
int pos)
  2284     qWarning(
"invalid input position");
  2293     int l = nextStacks.size();
  2294     for (
int i=0; i<l; ) {
  2297       if (stack.
type()) i++; 
else {
  2302         if (parents.empty()) i++; 
else {
  2303           int n = parents.size();
  2304           for (
int j=0; j<n; ) {
  2305             const StackItem &parent = parents.at(j);
  2308             if (validateNextTokenConstraints(token,
  2310               if (j) parents.swap(0, j);
  2311               parents.removeFirst();
  2316           if (parents.isEmpty()) {
  2317             if (i) nextStacks.swap(0, i);
  2318             nextStacks.removeFirst();
  2332   if (nextStacks.isEmpty()) {
  2339   currentMatches.clear();
  2342   priorityQueue = Private::PriorityQueue<StackItem>(currentStacks);
  2343   while (!priorityQueue.isEmpty())
  2344     currentMatches.append(processStack(priorityQueue.dequeue(), token));
  2345   type0Indices.clear();
  2350   if (nextStacks.isEmpty() && currentMatches.isEmpty()) {
  2353     nextStacks = currentStacks;
  2444   if (!incrementalPos || *incrementalPos < 0) 
  2448     pos = *incrementalPos;
  2449     if (incrementalMatches) currentMatches = *incrementalMatches;
  2450     if (incrementalStacks) nextStacks = *incrementalStacks;
  2454     currentLexerState = *lexerState;
  2456     currentLexerState.
clear();
  2460   while (shift(pos)) pos++;
  2464     if (errorPos) *errorPos = errPos;
  2465     if (errorToken) *errorToken = errToken;
  2466     if (incrementalPos) *incrementalPos = errPos;
  2467     if (incrementalStacks) *incrementalStacks = nextStacks;
  2468     if (incrementalMatches) incrementalMatches->clear();
  2469     if (lexerState) *lexerState = currentLexerState;
  2473     currentMatches.clear();
  2474     currentLexerState.
clear();
  2477   if (errorPos) *errorPos = -1;
  2478   if (errorToken) *errorToken = 
Cat();
  2482     int s = currentMatches.size();
  2483     for (
int i=0; i<s; ) {
  2484       Match &m = currentMatches[i];
  2486         if (i) currentMatches.swap(0, i);
  2487         currentMatches.removeFirst();
  2494   if (incrementalPos) *incrementalPos = pos;
  2495   if (incrementalMatches) *incrementalMatches = currentMatches;
  2496   if (incrementalStacks) *incrementalStacks = nextStacks;
  2497   if (lexerState) *lexerState = currentLexerState;
  2499   currentLexerState.
clear();
  2503   currentMatches.clear();
  2518   foreach (
const StackItem &stack, stacks) {
  2522       predict.insert(data->
leaves().at(data->
i()).cat);
  2524       predict.insert(static_cast<const StackItemType0 *>(stack.
data())
  2531 void Parser::expandNonterminalPredictionRecurse(
CatArg cat,
  2532                                                 QHash<
Cat, QSet<Cat> > &result,
  2533                                                 QSet<Cat> &mark)
 const  2536   foreach (
const Rule &rule, 
rules.value(cat)) {
  2537     QListIterator<Cat> i(rule);
  2548     while (i.hasNext()) {
  2549       Cat cati = effectiveCat(i.next());
  2551         result[cat].insert(cati); 
  2555       if (!mark.contains(cati))
  2556         expandNonterminalPredictionRecurse(cati, result, mark);
  2557       if (!nullable.contains(cati)) 
break;
  2577   QHash<Cat, QSet<Cat> > result;
  2580     qWarning(
"trying to expand terminal prediction");
  2582     expandNonterminalPredictionRecurse(cat, result, mark);
  2587 void Parser::expandNonterminalPredictionRecurseC(
CatArg cat,
  2588                                                  QHash<
Cat, QSet<Cat> > &result,
  2589                                                  QSet<Cat> mark, 
int ruleno,
  2592                                                    &nextTokenConstraints)
  2596   int firstRule = ruleno >= 0 ? ruleno : 0;
  2597   int lastRule = ruleno >= 0 ? ruleno : ruleList.size() - 1;
  2598   for (
int currRule = firstRule; currRule <= lastRule; currRule++) {
  2599     const Rule &rule = ruleList.at(currRule);
  2600     QListIterator<Cat> i(rule);
  2614       Cat effCat1 = effectiveCat(cat1);
  2616         if (validateNextTokenConstraints(effCat1, nextTokenConstraints))
  2617           result[cat].insert(effCat1); 
  2624       if (!mark.contains(effCat1)
  2626         int mcfgRuleno = -1;
  2629           QPair<int, PseudoCatScope> mcfgConstraint
  2631           mcfgRuleno = mcfgConstraint.first;
  2632           mcfgScope = mcfgConstraint.second;
  2634         expandNonterminalPredictionRecurseC(effCat1, result, mark, mcfgRuleno,
  2635                                             mcfgScope, nextTokenConstraints);
  2637       if (!nullable.contains(effCat1)) 
continue;
  2645       const QList<Match> componentMatches = matchToEpsilon(cat1, scope);
  2646       if (componentMatches.isEmpty())
  2650       bool haveUnconstrained = 
false;
  2651       foreach (
const Match &cm, componentMatches) {
  2654           haveUnconstrained = 
true;
  2658       if (haveUnconstrained)
  2659         currentMatches.append(
Match(0, 
Node(), 0, scope, nextTokenConstraints));
  2661         foreach (
const Match &cm, componentMatches) {
  2663                                       nextTokenConstraints));
  2665             currentMatches.last().nextTokenConstraints.expect.append(
  2668             currentMatches.last().nextTokenConstraints.taboo.append(
  2672       while (i.hasNext()) {
  2674         Cat cati = i.next();
  2675         Cat effCati = effectiveCat(cati);
  2677           bool nextTokenConstraintsPass = 
false;
  2678           foreach (
const Match &m, currentMatches)
  2680               nextTokenConstraintsPass = 
true;
  2683           if (nextTokenConstraintsPass)
  2684             result[cat].insert(effCati); 
  2688         if (!mark.contains(effCati)) {
  2689           foreach (
const Match &m, currentMatches)
  2695               int mcfgRuleno = -1;
  2698                 QPair<int, PseudoCatScope> mcfgConstraint
  2700                 mcfgRuleno = mcfgConstraint.first;
  2701                 mcfgScope = mcfgConstraint.second;
  2703               expandNonterminalPredictionRecurseC(effCati, result, mark,
  2704                                                   mcfgRuleno, mcfgScope,
  2708         if (!nullable.contains(effCati)) 
break;
  2709         int s = currentMatches.size();
  2710         for (
int j=0; j<s; ) {
  2711           Match &m = currentMatches[j];
  2715           const QList<Match> componentMatches = matchToEpsilon(effCati,
  2717           if (componentMatches.isEmpty()) {
  2718             if (j) currentMatches.swap(0, j);
  2719             currentMatches.removeFirst();
  2722             int cs = componentMatches.size();
  2725             bool haveUnconstrained = 
false;
  2726             for (
int k=0; k<cs; k++) {
  2727               const Match &cm = componentMatches.at(k);
  2730                 haveUnconstrained = 
true;
  2734             if (!haveUnconstrained) {
  2735               for (
int k=1; k<cs; k++) {
  2736                 const Match &cm = componentMatches.at(k);
  2740                   currentMatches.last().nextTokenConstraints.expect.append(
  2743                   currentMatches.last().nextTokenConstraints.taboo.append(
  2746               const Match &cm = componentMatches.first();
  2758         if (currentMatches.isEmpty())
  2776   QHash<Cat, QSet<Cat> > result;
  2778     qWarning(
"trying to expand terminal prediction");
  2780     expandNonterminalPredictionRecurseC(cat, result, QSet<Cat>(), -1,
  2810   foreach (
const StackItem &stack, stacks) {
  2822       int l = leaves.size();
  2823       for (
int j=i; j<l; j++)
  2824         prediction.append(leaves.at(j).cat);
  2825       literal = prediction;
  2826       for (
int j=i-1; j>=0; j--)
  2827         literal.prepend(leaves.at(j).cat);
  2829       if (!predictMulti.contains(prediction, multiPrediction))
  2830         predictMulti.insert(prediction, multiPrediction);
  2837         if (parents.isEmpty()) { 
  2841           if (!predictMulti.contains(list, multiPrediction))
  2842             predictMulti.insert(list, multiPrediction);
  2844           foreach (
const StackItem &parent, parents) {
  2848             int i = parentData->
i();
  2850             while (i+len < rule.size() && 
isToken(rule.at(i+len))) len++;
  2852             while (i > 0 && 
isToken(rule.at(i-1))) i--, len++;
  2855             if (!predictMulti.contains(literal, multiPrediction))
  2856               predictMulti.insert(literal, multiPrediction);
  2863         if (!predictMulti.contains(list, multiPrediction))
  2864           predictMulti.insert(list, multiPrediction);
  2868   return predictMulti;
  2872 void Parser::expandNonterminalPredictionMultiRecurse(
CatArg cat,
  2873  QHash<
Cat, QSet<
QList<Cat> > > &result, QSet<Cat> &mark)
 const  2876   foreach (
const Rule &rule, 
rules.value(cat)) {
  2877     int l = rule.size();
  2888     for (
int i = 0; i < l; i++) {
  2889       Cat cati = effectiveCat(rule.at(i));
  2892         while (i+len < l && 
isToken(rule.at(i+len))) len++;
  2893         result[cat].insert(rule.mid(i, len)); 
  2897       if (!mark.contains(cati))
  2898         expandNonterminalPredictionMultiRecurse(cati, result, mark);
  2899       if (!nullable.contains(cati)) 
break;
  2917 QHash<Cat, QSet<QList<Cat> > >
  2920   QHash<Cat, QSet<QList<Cat> > > result;
  2923     qWarning(
"trying to expand terminal prediction");
  2925     expandNonterminalPredictionMultiRecurse(cat, result, mark);
  2930 void Parser::expandNonterminalPredictionMultiRecurseC(
CatArg cat,
  2931   QHash<
Cat, QSet<
QList<Cat> > > &result, QSet<Cat> mark, 
int ruleno,
  2936   int firstRule = ruleno >= 0 ? ruleno : 0;
  2937   int lastRule = ruleno >= 0 ? ruleno : ruleList.size() - 1;
  2938   for (
int currRule = firstRule; currRule <= lastRule; currRule++) {
  2939     const Rule &rule = ruleList.at(currRule);
  2940     int l = rule.size();
  2953       cat1 = rule.first();
  2954       Cat effCat1 = effectiveCat(cat1);
  2956         if (validateNextTokenConstraints(effCat1, nextTokenConstraints)) {
  2958           while (len < l && 
isToken(rule.at(len))) len++;
  2960           result[cat].insert(rule.mid(0, len));
  2968       if (!mark.contains(effCat1)
  2970         int mcfgRuleno = -1;
  2973           QPair<int, PseudoCatScope> mcfgConstraint
  2975           mcfgRuleno = mcfgConstraint.first;
  2976           mcfgScope = mcfgConstraint.second;
  2978         expandNonterminalPredictionMultiRecurseC(effCat1, result, mark,
  2979                                                  mcfgRuleno, mcfgScope,
  2980                                                  nextTokenConstraints);
  2982       if (!nullable.contains(effCat1)) 
continue;
  2990       const QList<Match> componentMatches = matchToEpsilon(cat1, scope);
  2991       if (componentMatches.isEmpty())
  2995       bool haveUnconstrained = 
false;
  2996       foreach (
const Match &cm, componentMatches) {
  2999           haveUnconstrained = 
true;
  3003       if (haveUnconstrained)
  3004         currentMatches.append(
Match(0, 
Node(), 0, scope, nextTokenConstraints));
  3006         foreach (
const Match &cm, componentMatches) {
  3008                                       nextTokenConstraints));
  3010             currentMatches.last().nextTokenConstraints.expect.append(
  3013             currentMatches.last().nextTokenConstraints.taboo.append(
  3017       for (
int i = 1; i < l; i++) {
  3019         Cat cati = rule.at(i);
  3020         Cat effCati = effectiveCat(cati);
  3022           bool nextTokenConstraintsPass = 
false;
  3023           foreach (
const Match &m, currentMatches)
  3025               nextTokenConstraintsPass = 
true;
  3028           if (nextTokenConstraintsPass) {
  3030             while (i+len < l && 
isToken(rule.at(i+len))) len++;
  3032             result[cat].insert(rule.mid(i, len));
  3037         if (!mark.contains(effCati)) {
  3038           foreach (
const Match &m, currentMatches)
  3044               int mcfgRuleno = -1;
  3047                 QPair<int, PseudoCatScope> mcfgConstraint
  3049                 mcfgRuleno = mcfgConstraint.first;
  3050                 mcfgScope = mcfgConstraint.second;
  3052               expandNonterminalPredictionMultiRecurseC(effCati, result, mark,
  3053                                                        mcfgRuleno, mcfgScope,
  3057         if (!nullable.contains(effCati)) 
break;
  3058         int s = currentMatches.size();
  3059         for (
int j=0; j<s; ) {
  3060           Match &m = currentMatches[j];
  3064           const QList<Match> componentMatches = matchToEpsilon(effCati,
  3066           if (componentMatches.isEmpty()) {
  3067             if (j) currentMatches.swap(0, j);
  3068             currentMatches.removeFirst();
  3071             int cs = componentMatches.size();
  3074             bool haveUnconstrained = 
false;
  3075             for (
int k=0; k<cs; k++) {
  3076               const Match &cm = componentMatches.at(k);
  3079                 haveUnconstrained = 
true;
  3083             if (!haveUnconstrained) {
  3084               for (
int k=1; k<cs; k++) {
  3085                 const Match &cm = componentMatches.at(k);
  3089                   currentMatches.last().nextTokenConstraints.expect.append(
  3092                   currentMatches.last().nextTokenConstraints.taboo.append(
  3095               const Match &cm = componentMatches.first();
  3107         if (currentMatches.isEmpty())
  3123 QHash<Cat, QSet<QList<Cat> > >
  3126   QHash<Cat, QSet<QList<Cat> > > result;
  3128     qWarning(
"trying to expand terminal prediction");
  3130     expandNonterminalPredictionMultiRecurseC(cat, result, QSet<Cat>(), -1,
  3151   foreach (
const StackItem &stack, stacks) {
  3157       if (!predict.contains(cat, nextTokenConstraints))
  3158         predict.insert(cat, nextTokenConstraints);
  3164       if (parents.isEmpty()) { 
  3166         if (!predict.contains(cat, nextTokenConstraints))
  3167           predict.insert(cat, nextTokenConstraints);
  3171           bool nextTokenConstraintsPass = 
false;
  3172           foreach (
const StackItem &parent, parents) {
  3177             if (validateNextTokenConstraints(cat, nextTokenConstraints)) {
  3178               nextTokenConstraintsPass = 
true;
  3182           if (nextTokenConstraintsPass) {
  3184             if (!predict.contains(cat, nextTokenConstraints))
  3185               predict.insert(cat, nextTokenConstraints);
  3188           foreach (
const StackItem &parent, parents) {
  3193             if (!predict.contains(cat, nextTokenConstraints))
  3194               predict.insert(cat, nextTokenConstraints);
  3218   QHash<Cat, QSet<Cat> > result;
  3220     qWarning(
"trying to expand terminal prediction");
  3222     expandNonterminalPredictionRecurseC(cat, result, QSet<Cat>(), -1,
  3224                                         nextTokenConstraints);
  3245   switch (nextTokenConstraintsList.size()) {
  3247       qWarning(
"list of next token constraints is empty");
  3248       return QHash<Cat, QSet<Cat> >();
  3251                                           nextTokenConstraintsList.first());
  3255         QHash<Cat, QSet<Cat> > filteredResult;
  3256         QHashIterator<Cat, QSet<Cat> > it(result);
  3257         while (it.hasNext()) {
  3259           foreach (
CatArg cati, it.value()) {
  3260             bool nextTokenConstraintsPass = 
false;
  3262                      nextTokenConstraintsList) {
  3263               if (validateNextTokenConstraints(cati, nextTokenConstraints)) {
  3264                 nextTokenConstraintsPass = 
true;
  3268             if (nextTokenConstraintsPass)
  3269               filteredResult[it.key()].insert(cati);
  3272         return filteredResult;
  3303   foreach (
const StackItem &stack, stacks) {
  3315       int l = leaves.size();
  3316       for (
int j=i; j<l; j++)
  3317         prediction.append(leaves.at(j).cat);
  3318       literal = prediction;
  3319       for (
int j=i-1; j>=0; j--)
  3320         literal.prepend(leaves.at(j).cat);
  3322       if (!predictMulti.contains(prediction, multiPrediction))
  3323         predictMulti.insert(prediction, multiPrediction);
  3330         if (parents.isEmpty()) { 
  3334           if (!predictMulti.contains(list, multiPrediction))
  3335             predictMulti.insert(list, multiPrediction);
  3337           foreach (
const StackItem &parent, parents) {
  3343             if (!validateNextTokenConstraints(cat, nextTokenConstraints))
  3346             int i = parentData->
i();
  3348             while (i+len < rule.size() && 
isToken(rule.at(i+len))) len++;
  3350             while (i > 0 && 
isToken(rule.at(i-1))) i--, len++;
  3353             if (!predictMulti.contains(literal, multiPrediction))
  3354               predictMulti.insert(literal, multiPrediction);
  3358         if (parents.isEmpty()) { 
  3362           if (!predictMulti.contains(list, multiPrediction))
  3363             predictMulti.insert(list, multiPrediction);
  3365           foreach (
const StackItem &parent, parents) {
  3373                                                        nextTokenConstraints);
  3374             if (!predictMulti.contains(list, multiPrediction))
  3375               predictMulti.insert(list, multiPrediction);
  3381   return predictMulti;
  3396 QHash<Cat, QSet<QList<Cat> > >
  3400   QHash<Cat, QSet<QList<Cat> > > result;
  3402     qWarning(
"trying to expand terminal prediction");
  3404     expandNonterminalPredictionMultiRecurseC(cat, result, QSet<Cat>(), -1,
  3406                                              nextTokenConstraints);
  3424 QHash<Cat, QSet<QList<Cat> > >
  3428   switch (nextTokenConstraintsList.size()) {
  3430       qWarning(
"list of next token constraints is empty");
  3431       return QHash<Cat, QSet<QList<Cat> > >();
  3434                nextTokenConstraintsList.first());
  3437         QHash<Cat, QSet<QList<Cat> > > result
  3439         QHash<Cat, QSet<QList<Cat> > > filteredResult;
  3440         QHashIterator<Cat, QSet<QList<Cat> > > it(result);
  3441         while (it.hasNext()) {
  3443           foreach (
const QList<Cat> &literal, it.value()) {
  3444             CatArg cati = literal.first();
  3445             bool nextTokenConstraintsPass = 
false;
  3447                      nextTokenConstraintsList) {
  3448               if (validateNextTokenConstraints(cati, nextTokenConstraints)) {
  3449                 nextTokenConstraintsPass = 
true;
  3453             if (nextTokenConstraintsPass)
  3454               filteredResult[it.key()].insert(literal);
  3457         return filteredResult;
 const StackItem & parent() const
 
PseudoCatScope scope() const
 
ConstrainedMultiPredictions computeConstrainedMultiPredictions(const QList< StackItem > &stacks) const
compute a set of multi-token predictions from the stacks produced by an incremental parse ...
 
QHash< Cat, QPair< Cat, int > > componentCats
maps categories which represent components of a multi-component category to the category and componen...
 
const StackItem & parent() const
 
PseudoCatScope scope() const
 
type 6 item: during match, we're matching a P constraint 
 
virtual LexerState saveState()
saves the current lexer state, by default a null LexerState 
 
QPair< QPair< Node, NextTokenConstraints >, int > pConstraint(CatArg cat) const
 
MultiPredictions computeMultiPredictions(const QList< StackItem > &stacks) const
compute a set of multi-token predictions from the stacks produced by an incremental parse ...
 
const QList< StackItem > & parents() const
 
QHash< Cat, QSet< Cat > > expandNonterminalPrediction(CatArg cat) const
expand a nonterminal prediction to the possible initial tokens and the nonterminals they immediately ...
 
data passed to parser actions 
 
uint qHash(const NextTokenConstraints &nextTokenConstraints)
simple hash function for next token constraints 
 
bool hasPConstraint(CatArg cat) const
 
virtual int lookaheadTokens() const
the number of tokens to look ahead before deciding to execute the action 
 
NextTokenConstraints nextTokenConstraints
 
QList< Cat > expect
list of context-free categories the next token MUST match 
 
QString Cat
Category type: string or integer depending on DYNGENPAR_INTEGER_CATEGORIES. 
 
QHash< Cat, QPair< QPair< Node, NextTokenConstraints >, int > > & pConstraints()
 
NextTokenConstraints nextTokenConstraints() const
 
type 0 item: during match, we're waiting for a token to shift 
 
term in the expression of a component of a PMCFG function 
 
component of a PMCFG function, a sequence of terms 
 
const QList< StackItem > & parents() const
 
QList< Match > parse(int *errorPos=0, Cat *errorToken=0, int *incrementalPos=0, QList< StackItem > *incrementalStacks=0, QList< Match > *incrementalMatches=0, LexerState *lexerState=0)
parse the input string 
 
RuleSet cfRules
optional context-free rules 
 
QHash< Cat, QSet< Cat > > expandNonterminalPredictionC(CatArg cat)
expand a nonterminal prediction to the possible initial tokens and the nonterminals they immediately ...
 
Node parseTree()
get the parse tree for the last shifted token 
 
QHash< Cat, QPair< int, PseudoCatScope > > & mcfgConstraints()
 
const StackItem & parent() const
 
TokenSet tokens
set of true tokens 
 
void addRule(CatArg cat, const Rule &rule)
adds a new rule to the grammar, updates the nullable categories and the initial graph and clears the ...
 
QHash< Cat, QList< Cat > > catComponents
maps multi-component categories to the list of their components 
 
static bool serializeActions
whether the operator<<(QDataStream &, const Rule &) should serialize actions 
 
Function lookupFunction(const QVariant &id) const
 
virtual void execute(const ActionInfo &info)=0
 
Cat startCat
start category 
 
type 3 item: during matchRemaining, we're executing a match 
 
uint qHash(const QList< DynGenPar::Cat > &list)
simple hash function for lists of categories 
 
attached to the parse trees as rule labels to allow obtaining syntax trees 
 
bool isToken(CatArg cat) const
 
type 1 item: during type 0 item processing, we're executing a reduce 
 
bool hasMcfgConstraint(CatArg cat) const
 
QList< Cat > taboo
list of context-free categories the next token MUST NOT match 
 
virtual bool rewindTo(int pos, const LexerState &=LexerState())
rewind to an older position (requires buffering) 
 
QHash< Cat, QSet< QList< Cat > > > expandNonterminalPredictionMulti(CatArg cat) const
expand a nonterminal prediction to the possible initial nonempty literals (strings of one or more tok...
 
PseudoCatScope scope() const
 
TokenSource * inputSource
input source 
 
bool isLiteral(const QList< Cat > &list) const
is a given list of categories a literal? 
 
QMultiHash< QList< Cat >, ConstrainedMultiPrediction > ConstrainedMultiPredictions
 
QMultiHash< Cat, NextTokenConstraints > ConstrainedPredictions
 
QHash< Cat, QSet< QList< Cat > > > expandNonterminalPredictionMultiC(CatArg cat)
expand a nonterminal prediction to the possible initial nonempty literals (strings of one or more tok...
 
RuleSet rules
set of PMCFG rules 
 
int currentPosition()
get the current input position 
 
Cat startCat
start category 
 
int ruleno
used for PMCFGs 
 
bool loadPmcfg(const Pmcfg &pmcfg)
loads a PMCFG in standard form, converting it to the internal representation 
 
QMultiHash< QList< Cat >, MultiPrediction > MultiPredictions
 
type 4 item: during reduce, we're executing a matchRemaining 
 
RuleSet rules
grammar rules 
 
multi-token predictions with next token constraints 
 
type 2 item: during reduce, we're recursively executing another reduce 
 
const StackItem & parent() const
 
const Cat & CatArg
Category type (string or integer) when passed as an argument. 
 
virtual bool matchParseTree(const Node &treeToMatch)
match the parse tree for the last shifted token against the given tree 
 
Predictions computePredictions(const QList< StackItem > &stacks) const
compute a set of predictions from the stacks produced by an incremental parse 
 
QHash< Cat, QPair< Cat, QList< Cat > > > pseudoCats
pseudo-categories, used to represent PMCFGs internally 
 
void setLabel(const QVariant &label)
 
ConstrainedPredictions computeConstrainedPredictions(const QList< StackItem > &stacks) const
compute a set of predictions from the stacks produced by an incremental parse 
 
QList< Node > leaves() const
 
void setParents(const QList< StackItem > &parents)
 
int ruleno
needed for PMCFGs (to match components of rules to each other) 
 
void initCaches()
clears all caches, then computes the nullable categories and the initial graph 
 
PseudoCatScope scope() const
 
QVector< QVector< int > > argPositions
 
full rule as found in the initial graph 
 
const StackItemData * data() const
 
static bool serializeLabels
whether the operator<<(QDataStream &, const Rule &) should serialize labels 
 
NextTokenConstraints nextTokenConstraints
 
type 5 item: during match (of an MCFG constraint), we're executing a matchRemaining ...
 
rule constraints affecting the next token, for scannerless parsing 
 
QList< Alternative > children
 
Node parseTreeToPmcfgSyntaxTree(const Node &parseTree)
converts a parse tree obtained from a PMCFG to a PMCFG syntax tree 
 
QPair< int, PseudoCatScope > mcfgConstraint(CatArg cat) const
 
Cat nextToken()
get the next token from the input, increment current position, save parse tree 
 
bool addPmcfgRule(Pmcfg &pmcfg, CatArg cat, const Rule &rule)
adds a new rule to the grammar (both the PMCFG and the internal representation), updates the nullable...
 
const StackItem & parent() const
 
NextTokenConstraints nextTokenConstraints
 
NextTokenConstraints nextTokenConstraints() const