/src/grammar.cpp
C++ | 916 lines | 790 code | 74 blank | 52 comment | 179 complexity | decf0554d5d6cf003c2350b4815f74b2 MD5 | raw file
- #include "grammar.h"
- #include <QFile>
- #include <QString>
- #include <QTextStream>
- #include <QHash>
- #include <QHashIterator>
- #include <QStringList>
- #include <QRegExp>
- #include <QTreeWidget>
- #include <QTreeWidgetItem>
- #include <QDebug>
- #include <QTime>
- #include <lexem.h>
- #include <lexer.h>
- Grammar::Grammar()
- {
- lastNonTerminal = QString();
- axiom = QString();
- hash = QHash<QString, QList<QList<term> > >();
- hash_NoEpsilon = QHash<QString, QList<QList<term> > >();
- firstSets = new QHash<QString, QList<QStringList> >;
- followSets = new QHash<QString, QList<QStringList> >;
- epsilonNonTerminals = QStringList();
- K = 1;
- K2 = 1;
- lex = Lexer();
- errorAt = -1;
- errorInd = -1;
- unattainableNonTerminals = QStringList();
- rightRecursion = QStringList();
- }
- int Grammar::ReadFromFile(QString fileName)
- {
- // returns 0 - if okay
- // line number - if errors
- this->allNonTerminals.clear();
- this->allTerminals.clear();
- this->axiom.clear();
- this->hash.clear();
- this->hash_NoEpsilon.clear();
- this->epsilonNonTerminals.clear();
- this->firstSets->clear();
- this->followSets->clear();
- this->K = 1;
- QFile file(fileName);
- if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
- return -1;
- QTextStream in(&file);
- int lineNum = 1;
- // process first line and ramember the axiom
- QString line = in.readLine();
- if(!ProcessLine(line))
- return lineNum;
- QHashIterator<QString, QList<QList<term> > > it(hash);
- if(!it.hasNext())
- return -1;
- it.next();
- this->axiom = it.key();
- while (!in.atEnd()) {
- QString line = in.readLine();
- if(!ProcessLine(line))
- return lineNum;
- lineNum++;
- }
- file.close();
- return 0;
- }
- bool Grammar::ProcessLine(QString line)
- {
- /* returns true if line was processed without errors; */
- if(line.trimmed().isEmpty() || line.startsWith(";"))
- return true;
- bool continueLastLine = false;
- // *parse left part*
- int ind = 1;
- if(line.startsWith('#')) {
- ind = line.indexOf('#', 1) + 1;
- lastNonTerminal = UnShield(line.mid(0,ind));
- if(!this->allNonTerminals.contains(lastNonTerminal))
- this->allNonTerminals.append(lastNonTerminal);
- }
- else if(line[0].isSpace()) {
- continueLastLine = true;
- }
- line = line.mid(ind).trimmed();
- // *parse right part*
- // split apart
- QStringList parts = line.split(QRegExp("\\s"), QString::SkipEmptyParts);
- for(int i=0; i<parts.length(); i++) {
- if(parts[i].startsWith('#') && !parts[i].endsWith('#')) {
- while(i<parts.length()-1 &&
- (!parts[i].endsWith('#') || parts[i].endsWith("\\#")))
- {
- parts[i].append(" "+parts[i+1]);
- parts.removeAt(i+1);
- }
- if(!parts[i].endsWith('#') || parts[i].endsWith("\\#"))
- return false;
- }
- }
- // make list of [non]terminals form right part
- QList<term> right;
- foreach(QString part, parts) {
- QString s = UnShield(part);
- if(part.startsWith('#')) { // NonTerminal
- right.append(MakeNonTerm(s));
- if(!this->allNonTerminals.contains(s))
- this->allNonTerminals.append(s);
- }
- else { // Terminal
- right.append(MakeTerm(s));
- if(!this->allTerminals.contains(s))
- this->allTerminals.append(s);
- }
- }
- if(right.isEmpty())
- right.append(MakeTerm(""));
- //QHash<QString, QList<QList<Term> > >::iterator it = ;
- QList<QList<term> > list = hash.take(lastNonTerminal);
- if(continueLastLine && !list.isEmpty()) {
- list.last().append(right);
- }
- else {
- list.append(right);
- }
- hash.insert(lastNonTerminal, list);
- return true;
- }
- QString Grammar::ToText()
- {
- QString res;
- QHashIterator<QString, QList<QList<term> > > it(hash);
- while (it.hasNext()) {
- it.next();
- foreach(QList<term> termList, it.value()) {
- res.append(it.key()+" -> ");
- foreach(term t, termList)
- res.append(t.s + " ");
- res.append('\n');
- }
- }
- return res;
- }
- QString Grammar::ToText2(QHash<QString, QList<QStringList> > * F)
- {
- QString res;
- foreach(QString A, hash.uniqueKeys()) {
- QString a = A.mid(1, A.length()-2);
- res.append(a+"\t[");
- foreach(QStringList sl, F->value(A)) {
- res.append("[");
- foreach(QString s, sl) {
- res.append("'"+s+"'"+", ");
- }
- if(res.endsWith(", "))
- res = res.mid(0, res.length() -2);
- res.append("], ");
- }
- if(res.endsWith(", "))
- res = res.mid(0, res.length() -2);
- res.append("]\n");
- }
- return res;
- }
- QList<QTreeWidgetItem *> Grammar::GetTreeItems(QTreeWidget *treeWidget)
- {
- QList<QTreeWidgetItem *> treeItems;
- QHashIterator<QString, QList<QList<term> > > it(hash);
- while (it.hasNext()) {
- it.next();
- QTreeWidgetItem *parent = new QTreeWidgetItem(treeWidget, QStringList(it.key()));
- if(this->unattainableNonTerminals.contains(it.key())) {
- parent->setBackgroundColor(0, QColor("blue"));
- }
- if(this->rightRecursion.contains(it.key())) {
- if(this->unattainableNonTerminals.contains(it.key()))
- parent->setBackgroundColor(0, QColor("green"));
- else
- parent->setBackgroundColor(0, QColor("yellow"));
- }
- QList<QTreeWidgetItem *> alternatives;
- foreach(QList<term> termList, it.value()) {
- QString rule;
- foreach(term t, termList) {
- rule.append(" " + t.s);
- }
- alternatives.append(new QTreeWidgetItem(parent, QStringList(rule)));
- }
- treeItems.append(alternatives);
- }
- return treeItems;
- }
- QList<QTreeWidgetItem *> Grammar::GetFIRSTOrFOLLOWTreeItems(QTreeWidget *treeWidget,
- QHash<QString, QList<QStringList> > * set)
- {
- QList<QTreeWidgetItem *> treeItems;
- QHashIterator<QString, QList<QStringList> > it(*set);
- while (it.hasNext()) {
- it.next();
- QTreeWidgetItem *parent = new QTreeWidgetItem(treeWidget, QStringList(it.key()));
- QList<QTreeWidgetItem *> alternatives;
- foreach(QStringList sl, it.value()) {
- QString rule;
- foreach(QString s, sl) {
- rule.append(" " + s);
- }
- alternatives.append(new QTreeWidgetItem(parent, QStringList(rule)));
- }
- treeItems.append(alternatives);
- }
- return treeItems;
- }
- term Grammar::MakeTerm(QString str)
- {
- term t(str, true);
- return t;
- }
- term Grammar::MakeNonTerm(QString str)
- {
- term t(str, false);
- return t;
- }
- QStringList Grammar::GetNonProductiveNonTerminals()
- {
- // Get names of non-productive nonterminals
- QList<QString> nonTerminals = hash.uniqueKeys();
- //QSet<QString> ...; // better performance but uncomfortable, use QStringList
- QStringList productive, maybeProductive, nonProductive;
- // build the list of non-terminals that produce terminals: "productive"
- // and the list of all others non-terminals: "maybeProductive"
- bool allTerms = true;
- foreach(QString s, nonTerminals) {
- QList<QList<term> > lists = hash.find(s).value();
- foreach(QList<term> list, lists) {
- allTerms = true;
- foreach(term t, list) {
- if(!t.isTerminal) {
- allTerms = false;
- break;
- }
- }
- if(allTerms)
- productive.append(s);
- else
- maybeProductive.append(s);
- }
- }
- productive.removeDuplicates();
- maybeProductive.removeDuplicates();
- bool changes = true;
- while (changes) {
- changes = false;
- foreach(QString tn, maybeProductive) {
- if(productive.contains(tn)) { // just for confidence
- maybeProductive.removeAll(tn);
- continue;
- }
- QList<QList<term> > lists = hash.find(tn).value();
- foreach(QList<term> list, lists) {
- bool flag = true;
- foreach(term t, list) {
- if(!t.isTerminal && !productive.contains(t.s)) {
- flag = false;
- break;
- }
- }
- if(flag) {
- productive.append(tn);
- maybeProductive.removeAll(tn);
- changes = true;
- break;
- }
- }
- }
- }
- // Select non-terminals in RIGHT part that have got no rules
- // in hash (in grammar) at all
- QHashIterator<QString, QList<QList<term> > > it(hash);
- while (it.hasNext()) {
- it.next();
- foreach(QList<term> list, it.value()) {
- foreach(term t, list) {
- if(!t.isTerminal && !hash.contains(t.s))
- nonProductive.append(t.s);
- }
- }
- }
- nonProductive += maybeProductive;
- nonProductive.removeDuplicates();
- return nonProductive;
- }
- QStringList Grammar::GetUnattainableNonTerminals()
- {
- /* no recursion here */
- // build the list of attainable nonterminals
- int i = 0;
- QStringList attainable(this->axiom); // list of attainable nonterminals
- while(i < attainable.length()) {
- QList<QList<term> > lists = hash.find(attainable[i]).value();
- foreach(QList<term> list, lists) {
- foreach(term t, list) {
- if(!t.isTerminal && !attainable.contains(t.s))
- attainable.append(t.s);
- }
- }
- i++;
- }
- // all nonterminals minus attainable
- QSet<QString> unattainable(this->allNonTerminals.toSet());
- unattainable.subtract(attainable.toSet());
- this->unattainableNonTerminals = unattainable.toList();
- return this->unattainableNonTerminals;
- }
- void Grammar::RemoveEpsilonRules()
- {
- this->hash_NoEpsilon = this->GetGrammarWithoutEpsilonRules();
- }
- QHash<QString, QList<QList<term> > > Grammar::GetGrammarWithoutEpsilonRules()
- {
- QHash<QString, QList<QList<term> > > res(hash);
- bool noEpsilon = false;
- while(!noEpsilon) {
- noEpsilon = true;
- QStringList keys = res.uniqueKeys();
- foreach(QString key, keys) {
- QList<QList<term> > lists = res.find(key).value();
- foreach(QList<term> list, lists) {
- if(list.isEmpty()) { // epsilon rule found
- noEpsilon = false;
- this->_EpsilonRuleFound(key, &res);
- break;
- }
- }
- if(!noEpsilon)
- break;
- }
- }
- return res;
- }
- void Grammar::_EpsilonRuleFound(QString s, QHash<QString, QList<QList<term> > > *newHash)
- {
- bool flag = false;
- QStringList keys = newHash->uniqueKeys();
- QList<QList<term> > a = newHash->find(s).value();
- if(a.length() == 1 && a[0].isEmpty()) {
- newHash->remove(s);
- flag = true;
- }
- else {
- int i = 0;
- while(i<a.length()) {
- if(a[i].isEmpty()) {
- a.removeAt(i);
- }
- else
- i++;
- }
- newHash->insert(s, a);
- }
- foreach(QString key, keys) {
- if(key == s)
- continue;
- QList<QList<term> > lists = newHash->find(key).value();
- for(int i=0; i<lists.length(); i++) {
- if(lists[i].contains(MakeNonTerm(s))) {
- QList<term> l = lists[i];
- l.removeAll(MakeNonTerm(s));
- if(flag)
- lists.replace(i, l);
- else
- lists.append(l);
- newHash->insert(key, lists);
- }
- }
- }
- }
- QStringList Grammar::FindRightRecursion()
- {
- QStringList res;
- foreach(QString N, this->hash.uniqueKeys()) {
- if(TestForRightRecursion(N))
- res.append(N);
- }
- this->rightRecursion = res;
- return this->rightRecursion;
- }
- bool Grammar::TestForRightRecursion(QString X)
- {
- if(this->epsilonNonTerminals.isEmpty())
- this->FindEpsilonNonTerminals();
- if(_isTerminal(X))
- return false;
- QStringList l; // TODO!!
- // S0
- foreach(QList<term> rule, this->hash.value(X)) {
- QStringList strRule = this->Rule2StringList(rule);
- for(int i=rule.length()-1; i>=0; i--) {
- if( !this->TurnsIntoEpsilon(rule.mid(i+1)) )
- break;
- if( !rule[i].isTerminal ) {
- l.append(rule[i].s);
- }
- }
- }
- if( l.contains(X) )
- return true;
- // Si
- QStringList newL;
- foreach(QString S, l) {
- newL.clear();
- foreach(QList<term> rule, this->hash.value(S)) {
- QStringList strRule = this->Rule2StringList(rule);
- for(int i=rule.length()-1; i>=0; i--) {
- if( i<rule.length()-1 && !this->TurnsIntoEpsilon(rule.mid(i+1, 1)) )
- break;
- if( !rule[i].isTerminal ) {
- newL.append(rule[i].s);
- }
- }
- }
- if( newL.contains(X) )
- return true;
- l.append(newL);
- }
- return false;
- }
- QString Grammar::UnShield(QString s)
- {
- return s.replace("\\#", "#").replace("\\\\","\\").replace("\\!", "!");
- }
- bool Grammar::BuildFIRST(unsigned K)
- {
- this->K = (int)K;
- firstSets->clear();
- foreach(QString nonTerminal, this->allNonTerminals)
- firstSets->insert(nonTerminal, MakeF0(nonTerminal, K));
- bool changes = true;
- while(changes) {
- changes = false;
- QHash<QString, QList<QStringList> > newFirst = *firstSets;
- foreach(QString nonTerminal, this->allNonTerminals) {
- QList<QStringList> Fn = MakeFn(nonTerminal, K);
- newFirst.insert(nonTerminal, Fn);
- if(!_cmpFirsts(firstSets->value(nonTerminal), Fn))
- changes = true;
- }
- *firstSets = newFirst; // ?
- }
- // For K==1 only:
- // bool changes = true;
- // while(changes) {
- // changes = false;
- // QHash<QString, QList<QStringList> > * newFirstSets = new
- // QHash<QString, QList<QStringList> >;
- //
- // foreach(QString key, this->allNonTerminals) {
- // QList<QStringList> *newSet = new QList<QStringList>;
- // foreach(QList<term> rule, hash[key]) { // ???
- // QList<QStringList> newSubSet = firstSets->value(key);
- // bool stop = false;
- // for(int i=0; i<rule.length() && !stop; i++) {
- // if(rule[i].isTerminal)
- // newSubSet = _terminalExpansion(newSubSet, rule[i].s, K, &stop);
- // else
- // newSubSet = _nonTerminalExpansion(newSubSet,
- // firstSets->value(rule[i].s),
- // firstSets->value(key), K, &stop);
- // }
- // newSet->append(newSubSet);
- // }
- // newFirstSets->insert(key, *newSet);
- // }
- // this->firstSets = newFirstSets;
- // }
- return true;
- }
- bool Grammar::_cmpFirsts(QList<QStringList> F1, QList<QStringList> F2)
- {
- if(F1.length() != F2.length())
- return false;
- foreach(QStringList f1, F1) {
- if(!F2.contains(f1))
- return false;
- F2.removeAll(f1);
- }
- foreach(QStringList f2, F2)
- if(!F1.contains(f2))
- return false;
- return true;
- }
- QList<QStringList> Grammar::MakeF0(QString A, int K)
- {
- QList<QStringList> res;
- if(this->_isTerminal(A)) {
- res.append(QStringList(A));
- return res;
- }
- foreach(QList<term> rule, hash[A]) {
- int count = 0;
- while(count<rule.length() && rule[count].isTerminal && count <= K)
- count++;
- bool eps = (rule.length() == count)? true:false ;
- if((count==K && !eps) || (count<=K && eps)) {
- res.append(Rule2StringList(rule.mid(0, count)));
- }
- }
- return res;
- }
- QList<QStringList> Grammar::MakeFn(QString A, int K)
- {
- QList<QStringList> res;
- foreach(QList<term> rule, hash[A]) {
- QList<QStringList> ruleRes;
- bool undef = false;
- int i;
- for(i=0; i<rule.length(); i++) {
- QList<QStringList> F = FIRST(rule[i].s);
- if(F.isEmpty()) {
- undef = true;
- break;
- }
- int flag = 0;
- ruleRes = SumK(ruleRes, F, K, &flag); // ?
- if(flag)
- break;
- }
- if(!undef)
- res.append(ruleRes);
- }
- res.append(FIRST(A));
- return this->_removeDuplicates(res);
- }
- QList<QStringList> Grammar::SumK(QList<QStringList> L1, QList<QStringList> L2,
- int K, int *flag)
- {
- QList<QStringList> res;
- if(flag != NULL) *flag = 1;
- foreach(QStringList l1, L1)
- foreach(QStringList l2, L2)
- res.append(l1+l2);
- if(L2.isEmpty())
- res = L1;
- if(L1.isEmpty())
- res = L2;
- for(int i=0; i<res.length(); i++) {
- if(res[i].length() > 1) {
- if(res[i].count("") == res[i].length()) {
- res[i].clear();
- res[i].append("");
- }
- else
- res[i].removeAll("");
- }
- while(res[i].length() > K)
- res[i].removeLast();
- if( flag != NULL && res[i].length() != K && !res[i].first().isEmpty() )
- *flag = 0;
- }
- res = this->_removeDuplicates(res);
- return res;
- }
- bool Grammar::BuildFOLLOW(unsigned K2)
- {
- this->K2 = (int)K2;
- this->followSets->clear();
- foreach(QString nonTerminal, this->allNonTerminals)
- followSets->insert(nonTerminal, QList<QStringList>() );
- QList<QStringList> eps;
- eps.append(QStringList(""));
- followSets->insert(this->axiom, eps);
- bool changes = true;
- while(changes) {
- changes = false;
- QHash<QString, QList<QStringList> > newFollow = *followSets;
- foreach(QString nonTerminal, this->allNonTerminals) {
- QList<QStringList> followAj = followSets->value(nonTerminal);
- if(followAj.isEmpty())
- continue;
- foreach(QList<term> rule, hash[nonTerminal]) {
- for(int i=0; i<rule.length(); i++) {
- if(rule[i].isTerminal)// || rule[i].s == nonTerminal) // !!
- continue;
- QList<QStringList> firstW2 = FIRST(Rule2StringList(rule.mid(i+1)), K2);
- for(int i=0; i<firstW2.length(); i++) {
- while(firstW2[i].length() > (int)K2)
- firstW2[i].removeLast();
- }
- firstW2 = this->_removeDuplicates(firstW2);
- QList<QStringList> toInsert = SumK(firstW2, followAj, (int)K2, NULL);
- toInsert.append(followSets->value(rule[i].s)); // todo
- toInsert = this->_removeDuplicates(toInsert);
- if(!_cmpFirsts(followSets->value(rule[i].s), toInsert)) {
- changes = true;
- newFollow.insert(rule[i].s, toInsert );
- }
- }
- }
- }
- *followSets = newFollow;
- }
- return true;
- }
- QStringList Grammar::Rule2StringList(QList<term> rule)
- {
- QStringList res;
- for(int i=0; i<rule.length(); i++) {
- res.append(rule[i].s);
- }
- return res;
- }
- bool Grammar::FindEpsilonNonTerminals()
- {
- QStringList res;
- QStringList keys = this->hash.uniqueKeys();
- // S0
- foreach(QString key, keys) {
- foreach(QList<term> rule, this->hash.value(key)) {
- if(rule.length() == 1 && rule[0].isTerminal && rule[0].s.isEmpty()) {
- res.append(key);
- continue;
- }
- }
- }
- //Si
- bool flag = true;
- bool changes = true;
- while(changes) {
- changes = false;
- QStringList toAppend;
- foreach(QString key, keys) {
- foreach(QList<term> rule, this->hash.value(key)) {
- flag = true;
- if( rule.length() == 1 && rule[0].s == "") {
- flag = false; // the key is allreary in res list
- }
- foreach(term t, rule) {
- if((t.isTerminal && !t.s.isEmpty()) ||
- (!t.isTerminal && !res.contains(t.s)) )
- {
- flag = false;
- break;
- }
- }
- if(flag && !res.contains(key) && !toAppend.contains(key)) {
- toAppend.append(key);
- changes = true;
- }
- }
- }
- res.append(toAppend);
- }
- res.removeDuplicates();
- this->epsilonNonTerminals = res;
- return true;
- }
- bool Grammar::TurnsIntoEpsilon(QString X)
- {
- if(this->_isTerminal(X))
- return X.isEmpty();
- return this->epsilonNonTerminals.contains(X);
- }
- bool Grammar::TurnsIntoEpsilon(QList<term> X)
- {
- foreach(term t, X) {
- if( (t.isTerminal && !t.s.isEmpty()) ||
- (!t.isTerminal && !this->epsilonNonTerminals.contains(t.s)) )
- {
- return false;
- }
- }
- return true;
- }
- QList<QStringList> Grammar::FIRST(QString X)
- {
- if(_isTerminal(X)) {
- QList<QStringList> res;
- res.append(QStringList(X));
- return res;
- }
- return firstSets->value(X);
- }
- QList<QStringList> Grammar::FIRST(QStringList L, int K) // test it
- {
- if(K == -1)
- K = this->K;
- QList<QStringList> res;
- int q = 0;
- foreach(QString s, L) {
- res = SumK(res, FIRST(s), K, &q);
- // if(q == 1)
- // break;
- }
- return res;
- }
- bool Grammar::_isNonTerminal(QString s)
- {
- if(s.startsWith('#') && s.endsWith('#'))
- return true;
- return false;
- }
- bool Grammar::_isTerminal(QString s)
- {
- if(!s.startsWith('#') && !s.endsWith('#'))
- return true;
- return false;
- }
- QList<QStringList> Grammar::_removeDuplicates(QList<QStringList> L)
- {
- int k = 0;
- while(k<L.length()-1) {
- int l = k+1;
- while(l<L.length()) {
- if(L[k] == L[l])
- L.removeAt(l);
- else
- l++;
- }
- k++;
- }
- return L;
- }
- int Grammar::FindK()
- {
- QStringList keys = this->hash.uniqueKeys();
- int K = 1;
- bool flag = true;
- for(K = 1; K < 3 && flag;) {
- flag = false;
- foreach(QString key, keys) {
- QList<QList<term> > rules = this->hash.value(key);
- for(int i=0; i<rules.length() && !flag; i++) {
- if(!rules.isEmpty() && rules[i].first().s.isEmpty())
- continue;
- for(int j=i+1; j<rules.length() && !flag; j++) {
- if(!rules.isEmpty() && rules[j].first().s.isEmpty())
- continue;
- QList<QStringList> follow = followSets->value(key);
- QList<QStringList> sumk1 = SumK(FIRST(Rule2StringList(rules[i]), 2), follow, K, NULL);
- QList<QStringList> sumk2 = SumK(FIRST(Rule2StringList(rules[j]), 2), follow, K, NULL);
- bool flag2 = false;
- foreach(QStringList sl1, sumk1) {
- foreach(QStringList sl2, sumk2) {
- bool flag3 = true;
- for(int q=0; q<=K && q<sl1.length() && q<sl2.length(); q++) {
- if(sl1[q] != sl2[q]) {
- flag3 = false;
- break;
- }
- else {
- qDebug()<<"----------------1-"<<sumk1;
- qDebug()<<"----------------2-"<<sumk2;
- }
- }
- if(flag3) {
- flag2 = true;
- break;
- }
- if(flag2) break;
- }
- if(flag2) break;
- }
- if(flag2) {
- flag = true;
- break;
- }
- }
- }
- if(flag) {break;}
- }
- if(flag) {K++;break;}
- if(!flag) flag = true;
- }
-
- return K;
- }
- int Grammar::Go(int i, QString nonterm)
- {
- int lexInd = i;
- if(lexInd == -1 || lexInd>=lex.lexemes_list.length()) return -1;
- QStringList rule;
- bool hasEps = false;
- foreach(QList<term> rule1, hash.value(nonterm)) {
- if(rule1.length()>0 && rule1[0].s == "") {
- hasEps = true;
- continue;
- }
- QList<QStringList> sumk = SumK(FIRST(Rule2StringList(rule1), 1), followSets->value(nonterm), 1, NULL);
- if(sumk.isEmpty() || sumk[0].isEmpty()) {
- hasEps = true;
- continue;
- }
- bool f = false;
- foreach(QStringList sl, sumk) {
- if(sl.length() == 0) {
- continue; // ?
- }
- if(lex.lexemes_list[lexInd].terminal.compare(sl[0], Qt::CaseInsensitive) == 0) { //rule1[0].s) { // ?
- rule = Rule2StringList(rule1);
- f = true;
- break;
- }
- }
- if(f) break;
- }
- if(rule.isEmpty()) {
- if(hasEps) return lexInd;
- qDebug()<<">> No suitable rule found; "<<QString(lex.lexemes_list.at(lexInd).text);
- qDebug()<<" "<<nonterm;
- //this->errorAt = lexInd;
- this->errorAt = lex.lexemes_list.at(lexInd).lineNum;
- this->errorInd = lexInd;
- Error(lexInd);
- return -1;
- }
- foreach(QString term, rule) {
- if(_isNonTerminal(term)) {
- qDebug()<<">> Go() for "<<term;
- lexInd = Go(lexInd, term);
- if(lexInd == -1 || lexInd>=lex.lexemes_list.length())
- return -1;
- }
- else {
- if(lex.lexemes_list[lexInd].terminal.compare(term, Qt::CaseInsensitive) == 0) {
- qDebug()<<">> Match: "<<lex.lexemes_list[lexInd].terminal<<" == "<<term;
- lexInd++;
- }
- else {
- //this->errorAt = lexInd;
- if(hasEps) return lexInd;
- qDebug()<<">> NO Match: "<<lex.lexemes_list[lexInd].terminal<<" != "<<term;
- this->errorAt = lex.lexemes_list.at(lexInd).lineNum;
- this->errorInd = lexInd;
- Error(lexInd);
- return -1;
- }
- }
- }
- return lexInd;
- }
- void Grammar::Error(int lexInd)
- {
- qDebug()<<"Error at line"<<this->errorAt<<"; Lexem number "<<lexInd;
- }