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