/********************************************************************** Verish.cpp - a program for checking logical reasoning version 0.95 ------------------- begin : circa August 1997 release date : 31 January 2013 copyright : (C) 1997 - 2013 by Chris Austin email : chris@chrisaustin.info **********************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #include "Verish.h" using namespace std; // argc is total number of words in command line // argv[] is array of pointers to the command line words int main(const int argc, const char* argv[]) { size_t pos; string infile = "", requestTit = ""; string notQnt, buf, Wrd; char c; bool check_reasoning_flag = false; try { if ( argc == 2 ) check_reasoning_flag = true; if ( argc == 3 ) { buf = ""; pos = 0; do { c = argv[2][pos++]; if ( ( c >= '!' ) && ( c < 0x7f ) ) buf += c; } while (c); if (argv[2][0] == '+') { pos = 1; while ( pos < buf.length() ) { c = buf[pos++]; if ( isCapital(c) ) throw 3; } requestTit = buf; check_reasoning_flag = true; } } if ( check_reasoning_flag ) { buildDev(argv[1], infile); chkreas(infile, requestTit); } else VUtilsMain(argc, argv); } catch (int e) { if ( e == 0 ) cout << endl << endl; if ( e == 1 ) cout << endl; if ( e == 2 ) cout << endl << "Cannot Open " << argv[1] << endl << endl; if ( e == 3 ) cout << endl << "Command not recognised" << endl << endl; } catch (bad_alloc&) { cout << "Error allocating memory." << endl; } catch (exception& e) { cout << "Standard exception: " << e.what() << endl; } return 0; } // the first entry in strts[STSSZ] is 0, and the last entry that is not string::npos is an // effective start position, for getSent, of the current Paragraph. Any entries between // that entry and the first entry are effective start positions of Method Applications // that have not ended at least one Paragraph before the start of the current Paragraph void initstrts(size_t strts[STSSZ]) { int n = 2; strts[0] = strts[1] = 0; while ( n < STSSZ ) strts[n++] = string::npos; } // return the index of the first occurrence of string::npos in strts[STSSZ] int nxtstrt(const size_t strts[STSSZ]) { int n = 0; while ( n < STSSZ ) { if ( strts[n] == string::npos ) break; n++; } if ( n == STSSZ ) { cout << "\nNumber of nested Method Applications is at least " << (STSSZ - 1); throw 0; } return n; } void buildDev(const char* flnm, string& infile) { char c; ifstream sourcefile; bool openflag = false; sourcefile.open(flnm, ios::binary); if ( sourcefile ) openflag = true; else throw 2; while (sourcefile.get(c) != 0) if (c >= '!' && c <= '~') infile += c; cout << endl << "infile.length() = " << infile.length() << endl; if ( openflag ) sourcefile.close(); } // prepare infile and strts[STSSZ] for reasoning checking, starting at the position that is // initially pos. Includes the actions at the end of the chkreas loop, without the reas check void prpflsts(string& infile, size_t strts[STSSZ], const size_t pos) { } // prepare the list of Names. It contains a - to mark the start of each Method Application void prpNms(const string infile, const size_t stpos, string& Names) { size_t pos = 0; while ( pos < stpos ) { reviseNms(pos, infile, Names); nxtPar(infile, pos); } } // seek last Title occurrence of Tit in infile starting at pos, and set pos to that position if // found, and otherwise set pos to string::npos void sklstTit(const string infile, const string Tit, size_t& pos) { size_t savepos, fpos = infile.length(); seekTit(pos, infile, Tit, fpos); savepos = pos; while ( pos < fpos ) { savepos = pos; seekTit(pos, infile, Tit, fpos); } pos = savepos; if ( pos == fpos ) pos = string::npos; } void chkreas(string& infile, const string requestTit) { size_t pos = 0, strts[STSSZ], lpos; int n; string Sent, Names = ""; initstrts(strts); if ( requestTit != "" ) { sklstTit(infile, requestTit, pos); if ( pos == string::npos ) { cout << endl << "Error seeking Title"; throw 0; } prpflsts(infile, strts, pos); pos = strts[nxtstrt(strts) - 1]; prpNms(infile, pos, Names); } do { pos = strts[nxtstrt(strts) - 1]; getSent(Sent, pos, infile); if ( Sent == "" ) break; chkPar(infile, strts, Names); pos = strts[nxtstrt(strts) - 1]; reviseNms(pos, infile, Names); if ( ( Sent != "+Df" ) && ( Sent != "+1Df" ) ) { n = (nxtstrt(strts) - 1) - cntMthnfbAo(infile, pos); lpos = strts[n]; infile.erase(lpos, pos - lpos); n++; while ( n < STSSZ ) { if ( strts[n] == string::npos ) break; strts[n++] = string::npos; } getSent(Sent, lpos, infile); pos = lpos; getSent(Sent, pos, infile); while ( !isReason(Sent) ) { infile.erase(lpos, pos - lpos); pos = lpos; getSent(Sent, pos, infile); } } n = nxtstrt(strts) - 1; lpos = pos = strts[n]; nxtPar(infile, pos); getSent(Sent, lpos, infile); if ( isOpnTit(Sent) ) strts[n + 1] = pos; else strts[n] = pos; } while ( true ); cout << endl; } // return the number of Methods not followed by +Ao in the Paragraph that starts at pos int cntMthnfbAo(const string infile, const size_t pos) { size_t getpos = pos; string Sent, Tit; int n = 0; getSent(Tit, getpos, infile); while ( getpos < infile.length() ) { getSent(Sent, getpos, infile); if ( Sent == "" ) { cout << "\nNo Reason found after Title\n\n" << Tit; throw 0; } if ( nmSbjBrf(Sent) < 0 ) { cout << "\nNot a Brief where Brief expected after Title\n\n" << Tit; throw 0; } if ( isReason(Sent) ) break; n++; } if ( Sent == "+Ao" ) n--; if ( n < 0 ) { cout << "\nReason +Ao not following Method found while counting Methods"; throw 0; } return n; } // check the Paragraph for which an effective start position is strts[nxtstrt(strts) - 1] void chkPar(const string infile, const size_t strts[STSSZ], const string Names) { const int ns = nxtstrt(strts); int n1; const size_t stpos = strts[ns - 1]; size_t pos = stpos, stscp[STSSZ]; string Brf, chkSent, Sbjs[MXSBJ]; getSent(Brf, pos, infile); display(Brf); if ( !isNoun(Brf) ) { cout << endl << "Not a Title"; throw 0; } if ( ( Brf != "+Df" ) && ( Brf != "+1Df" ) ) { cout << endl << "Title" << endl; n1 = cntMthnfbAo(infile, stpos); if ( ( n1 == (ns - 2) ) && !isOpnTit(Brf) ) { // this Paragraph is not in a Method Application initstrts(stscp); stscp[2] = strts[2]; if ( skTitsts(infile, Brf, stscp) != string::npos ) { cout << "\nRepeated Title not in a Method Application"; throw 0; } } n1 = 0; while ( pos < infile.length() ) { getSent(Brf, pos, infile); if ( Brf != "" ) display(Brf); if ( Brf == "" ) { cout << "\nNo Reason found"; throw 0; } if ( nmSbjBrf(Brf) < 0 ) { cout << "\nNot a Brief where Brief expected"; throw 0; } if ( isReason(Brf) ) break; cout << endl << "Method" << endl; n1++; if ( n1 == ns ) { cout << "\nNumber of Methods not followed by +Ao exceeds number of Opening Titles by 2"; throw 0; } } if ( Brf == "+Ao" ) { if ( n1 == 0 ) cout << "\nReason +Ao not preceded by a Method"; else cout << "\nApplication of preceding Method is omitted"; throw 0; } if ( n1 == (ns - 1) ) { cout << "\nNumber of Methods not followed by +Ao exceeded number of Opening Titles"; throw 0; } cout << endl << "Reason" << endl; getSbjs(Brf, Sbjs); TittoFact(infile, Sbjs, strts); getSent(chkSent, pos, infile); if ( chkSent == "" ) { cout << "\nNo Statement found"; throw 0; } display(chkSent); pos = strts[(ns - 1) - cntMthnfbAo(infile, stpos)]; while ( pos < stpos ) { seekDef(pos, infile, stpos); if ( pos == stpos ) break; if ( hasRelocAb(infile, pos, chkSent) ) { cout << "\nStatement has a Relevant occurrence of a Word Defined by a Definition\n"; cout << "Paragraph within a Method Application that ended immediately before this\n"; cout << "Paragraph. The Abbreviation and Definition in that Definition Paragraph are\n"; getSent(Brf, pos, infile); getSent(Brf, pos, infile); display(Brf); getSent(chkSent, pos, infile); display(chkSent); throw 1; } nxtPar(infile, pos); } if ( isTb(Brf) >= 0 ) chkTb(chkSent, Sbjs); try { if ( isGn(Brf) >= 0 ) chkGn(chkSent, Sbjs, Names); } catch (int e) { if ( e == 4 ) { pos = 0; putWord(chkSent, pos, Brf); Brf[0] = '+'; pos = seekDfNm(infile, Brf, stpos); getSent(Brf, pos, infile); getSent(Brf, pos, infile); getSent(chkSent, pos, infile); cout << "\nThe Adverb Agrees with a Name, in consequence of the Definition"; cout << "\nParagraph whose Abbreviation is\n"; display(Brf); cout << "\nand whose Definition is\n"; display(chkSent); throw 1; } throw; } if ( isSm(Brf) >= 0 ) chkSm(chkSent, Sbjs); if ( Brf == "+Ex" ) chkEx(chkSent, Sbjs); if ( isFc(Brf) >= 0 ) chkFc(chkSent, Sbjs); if ( isAb(Brf) >= 0 ) chkAb(chkSent, Sbjs, infile, stpos); if ( Brf == "+Ao" ) { cout << "\nReason used after a Method whose Application is omitted"; throw 0; } cout << endl << "Fact" << endl; } else { // Definition Paragraph cout << endl << "Title of Definition Paragraph" << endl; getSent(Brf, pos, infile); if ( Brf != "" ) display(Brf); if ( Brf == "" ) { cout << "\nNo Abbreviation found"; throw 0; } if ( nmSbjBrf(Brf) < 0 ) { cout << "\nNot an Abbreviation"; throw 0; } cout << endl << "Abbreviation" << endl; getSbjs(Brf, Sbjs); getSent(chkSent, pos, infile); if ( chkSent == "" ) { cout << "\nNo Definition found"; throw 0; } display(chkSent); chkDef(infile, stpos, Brf, chkSent); cout << endl << "Definition" << endl; } } // if the first Letter at or after getpos is an Initial, set Sent to the first Sentence // starting at or after getpos, if there is one, with all non-Letters removed, and // otherwise to the null string. This is where all syntax checking is done. getpos is // called an effective start position of that Sentence, and is set to an effective start // position of the next Sentence, if there is one, and otherwise to infile.length() void getSent(string& Sent, size_t& getpos, const string infile) { char c = ' ', firstchar = ' ', secondchar = ' '; bool inSentence = false, goodSentence = false, incomplete = false; bool inPhrase = false, needFormative = false, needCapital = false; long atstart = 2, endcomment = 0, Scount = 1, Pcount = 1; Sent = ""; while ( ( !goodSentence ) && ( !incomplete ) && ( getpos < infile.length() ) ) { c = ' '; while ( !( ( c >= '!' ) && ( c <= '~' ) ) && ( getpos < infile.length() ) ) c = infile[getpos++]; if ( ( c >= '!' ) && ( c <= '~' ) ) { if ( atstart == 2 ) { inSentence = inPhrase = needFormative = needCapital = false; endcomment = 0; firstchar = c; // provisionally assume it's a Sentence if first Letter is an Initial // change mind later if second Letter results in bad grammar if ( isInitial(c) ) inSentence = true; else { cout << endl << c << endl; cout << endl << "Not an Initial"; throw 0; } Scount = 1; Sent = ""; } if ( inSentence ) { if ( needFormative && isCapital(c) ) incomplete = true; if ( needCapital && !isCapital(c) ) incomplete = true; needFormative = needCapital = false; if (c == '+' || c == '[' || c == ']') needFormative = true; if (c == '=' || c == '-' || c == '(' || c == ')' || c == '/') needCapital = true; if ( ( !inPhrase ) && c == '/') incomplete = true; if ( inPhrase && ( Pcount != 0 ) ) { if (c == '=' || c == '-' || c == '(' || c == ')') incomplete = true; if (c == '[' || c == ']') incomplete = true; } if ( inPhrase && ( Pcount == 0 ) && isInitial(c) ) inPhrase = false; if ( ( !inPhrase ) && ( c == '+' ) ) { inPhrase = true; Pcount = 1; } if ( inPhrase ) { if (c == '=' || c == '(' || c == ')' || c == '/') Pcount++; if (c == '+') Pcount--; } if ( (Scount == 0 ) && ( !incomplete ) && isInitial(c) ) goodSentence = true; if ( ( !goodSentence ) && ( !incomplete ) ) { if (c == '=' || c == '(' || c == ')' || c == '/') Scount++; if (c == '+') Scount--; } if ( ( atstart == 1 ) && incomplete ) { inSentence = incomplete = false; secondchar = c; } } if ( ( !inSentence ) && ( atstart == 0 ) ) { if ( endcomment == 1 ) { if ( c == possreverse(firstchar) ) endcomment++; else endcomment = 0; } if ( endcomment == 0 ) if ( c == possreverse(secondchar) ) endcomment++; } if ( inSentence && ( !goodSentence ) && ( !incomplete ) ) Sent += c; if ( atstart > 0 ) atstart--; if ( endcomment == 2 ) atstart = 2; } else { if ( atstart == 2 ) { inSentence = false; Sent = ""; } if ( inSentence ) { if ( needFormative || needCapital || ( Scount != 0 ) ) incomplete = true; else goodSentence = true; } } } if ( atstart == 2 ) Sent = ""; else if ( ( c >= '!' ) && ( c <= '~' ) && ( getpos < infile.length() ) ) getpos--; if ( incomplete ) { display(Sent); cout << endl << "Incomplete Sentence"; throw 0; } } // if getpos is start of a Statement Paragraph, get the Reason into Sent and set getpos to // start of the Statement if the Reason is found, and otherwise set Sent to "" void getReason(string& Sent, size_t& getpos, const string infile) { string Tit; getSent(Tit, getpos, infile); do { getSent(Sent, getpos, infile); if ( Sent == "" ) break; if ( nmSbjBrf(Sent) < 0 ) { cout << "Brief not found where Brief expected after Title\n\n" << Tit; throw 0; } } while ( !isReason(Sent) ); } // if pos is an effective start position of a Paragraph, set pos to an effective start // position of the next Paragraph if all expected Sentences in the current Paragraph are // found, and otherwise to string::npos void nxtPar(const string infile, size_t& pos) { size_t savepos = pos; string Sent; getSent(Sent, pos, infile); if ( ( Sent != "+Df" ) && ( Sent != "+1Df" ) ) { pos = savepos; getReason(Sent, pos, infile); } else getSent(Sent, pos, infile); getSent(Sent, pos, infile); if ( Sent == "" ) pos = string::npos; } // return true if an occurrence of a Noun or Prep starting at pos is an Object occurrence, // and otherwise false bool isObjoc(const string Sent, const size_t pos) { size_t getpos = 0, savepos; bool flag = false; string buf; while ( getpos < pos ) { savepos = getpos; putWord(Sent, getpos, buf); if ( buf[0] == '+' ) if ( pos < afterScope(Sent, savepos) ) flag = true; } return flag; } // return true if Sent has an Object occurrence of Noun that is not Governed, and otherwise false bool hasnGovObjoc(const string Noun, const string Sent) { size_t pos = 0, savepos; bool flag = false; string buf; while ( ( pos < Sent.length() ) && !flag ) { savepos = pos; putWord(Sent, pos, buf); if ( buf == Noun ) if ( isObjoc(Sent, savepos) && ( !isGovpos(Sent, savepos) ) ) flag = true; } return flag; } // return true if Sent has an Object occurrence of Preposition Prep, and otherwise false bool hasObjoc(const string Prep, const string Sent) { size_t pos = 0, savepos; bool flag = false; string buf; while ( ( pos < Sent.length() ) && !flag ) { savepos = pos; putWord(Sent, pos, buf); if ( buf == Prep ) if ( isObjoc(Sent, savepos) ) flag = true; } return flag; } // return true if Sent has a Verb occurrence of the Noun or Preposition Wrd, and otherwise false bool hasVrboc(const string Wrd, const string Sent) { string buf; size_t pos1 = 0, pos2; bool flag = false; while ( pos1 < Sent.length() ) { if (Sent[pos1] == '+') { pos2 = pos1; putWord(Sent, pos2, buf); pos1 = afterScope(Sent, pos1); if ( buf == Wrd ) flag = 1; } else pos1++; } return flag; } // return true if Sentence Sent has a Relevant occurrence of the Abbreviation Defined by the // Definition Paragraph that starts at pos in infile, and false otherwise bool hasRelocAb(const string infile, const size_t pos, const string Sent) { size_t getpos = pos; bool flag = false; string Abb, Def, Wrd; getSent(Abb, getpos, infile); getSent(Abb, getpos, infile); if ( Abb == "" ) { cout << "\nAbbreviation not found"; throw 0; } getSent(Def, getpos, infile); if ( Def == "" ) { cout << "\nDefinition not found"; throw 0; } getpos = 0; putWord(Abb, getpos, Wrd); if ( nmSbjPhrs(Def) >= 0 ) { if ( isNoun(Wrd) ) { if ( hasnGovObjoc(Wrd, Sent) ) flag = true; } else if ( hasObjoc(Wrd, Sent) ) flag = true; } if ( hasVrboc(Wrd, Sent) ) flag = true; return flag; } // return true if Sentence Sent1 is a Subject of Sentence Sent2, and otherwise false bool isSbj(const string Sent1, const string Sent2) { size_t pos = Sent2.find_first_of("=-()+[]", 1); bool flag = false; string Subj; if ( pos == string::npos ) pos = Sent2.length(); while ( pos < Sent2.length() ) { getSent(Subj, pos, Sent2); if ( Sent1 == Subj ) flag = true; } return flag; } // return -1 if Sent is not a Phrase, and its number of Subjects otherwise int nmSbjPhrs(const string Sent) { size_t pos = 0; int count = -1; if ( Sent.length() >= 2 ) { if (Sent[pos++] == '+') { count++; while ( pos < Sent.length() ) { if (Sent[pos] == '/') count++; if (Sent[pos++] == '+') break; } } } return count; } // return -1 if Sent is not a Brief, and the number of /'s otherwise. int nmSbjBrf(const string Sent) { size_t pos = 0; int count = -1; bool flag = false; if ( Sent.length() >= 2 ) { if (Sent[pos++] == '+') { count++; while ( pos < Sent.length() ) { if (Sent[pos] == '/') { if ( !flag ) count++; else count = -1; } if (Sent[pos++] == '+') flag = true; } } } return count; } // return -1 if the Sentence is not a +Tb/.../ Reason, and the number of /'s otherwise int isTb(const string Sent) { int count = nmSbjBrf(Sent); if ( Sent.length() >= 3 ) { if ( Sent.substr(0, 3) != "+Tb" ) count = -1; if ( Sent.length() > 3 ) if ( Sent[3] != '/' ) count = -1; } else count = -1; return count; } // return -1 if the Sentence is not a +Gn/ Reason, and 1 otherwise int isGn(const string Sent) { int count = nmSbjBrf(Sent); if (count != 1) count = -1; if ( Sent.length() < 4 ) count = -1; else if ( Sent.substr(0, 4) != "+Gn/" ) count = -1; return count; } // return -1 if the Sentence is not a +Sm/ Reason, and 1 otherwise int isSm(const string Sent) { int count = nmSbjBrf(Sent); if (count != 1) count = -1; if ( Sent.length() < 4 ) count = -1; else if ( Sent.substr(0, 4) != "+Sm/" ) count = -1; return count; } // return -1 if the Sentence is not a +Fc/ Reason, and 1 otherwise int isFc(const string Sent) { int count = nmSbjBrf(Sent); if (count != 1) count = -1; if ( Sent.length() < 4 ) count = -1; else if ( Sent.substr(0, 4) != "+Fc/" ) count = -1; return count; } // return -1 if the Sentence is not a +Ab/ Reason, and 1 otherwise int isAb(const string Sent) { int count = nmSbjBrf(Sent); if (count != 1) count = -1; if ( Sent.length() < 4 ) count = -1; else if ( Sent.substr(0, 4) != "+Ab/" ) count = -1; return count; } // return true if Sent is a Reason, otherwise false bool isReason(const string Sent) { int flag = false; if (isTb(Sent) != -1) flag = true; if (isGn(Sent) != -1) flag = true; if (isSm(Sent) != -1) flag = true; if ( Sent == "+Ex" ) flag = true; if (isFc(Sent) != -1) flag = true; if (isAb(Sent) != -1) flag = true; if ( Sent == "+Ao" ) flag = true; return flag; } // if buf is a Word or a Sentence, return true if buf is a Noun, and otherwise false bool isNoun(const string buf) { size_t pos = 1; bool flag = false; if ( buf.length() >= 2 ) { if (buf[0] == '+') { flag = true; while ( pos < buf.length() ) if ( buf[pos++] == '/' ) flag = false; } } return flag; } // if Sent is a Noun, return true if Sent is an Opening Title, and otherwise false bool isOpnTit(const string Sent) { char c; bool flag = true; if ( Sent[1] != '1' ) flag = false; if ( Sent.length() > 2 ) { c = Sent[2]; if ( ( c >= '0' ) && ( c <= '9' ) ) flag = false; } return flag; } // return true if Noun is a Name, and otherwise false bool isName(const string Names, const string Noun) { size_t pos = 0; bool flag = false; string buf; while ( pos < Names.length() ) { putWord(Names, pos, buf); if ( buf == Noun ) flag = true; } return flag; } // return the first position after the Scope that starts at startpos size_t afterScope(const string Sent, size_t startpos) { char c; int Scount = 1; bool flag = true; while ( flag ) { c = Sent[startpos]; if ( ( Scount == 0 ) && isInitial(c) ) flag = false; if (c == 0) flag = false; if ( flag ) { if (c == '=' || c == '(' || c == ')' || c == '/') Scount++; if (c == '+') Scount--; startpos++; } } return startpos; } // copy Word starting at Sent[pos] into buf, and set pos to first position after Word void putWord(const string Sent, size_t& pos, string& buf) { char c; bool flag = true; buf = ""; if ( pos < Sent.length() ) buf += Sent[pos++]; while (flag) { if ( pos < Sent.length() ) { c = Sent[pos]; flag = !isInitial(c); } else flag = false; if (flag) { pos++; buf += c; } } } // if pos is the start of a Noun, return true if that Noun is Governed, else false bool isGovpos(const string Sent, const size_t pos) { string Wrd, buf; size_t n = pos, m; bool flag = false; putWord(Sent, n, Wrd); n = 0; while ( !flag && n < pos ) { if (Sent[n] == '[' || Sent[n] == ']') { m = n; putWord(Sent, m, buf); buf[0] = '+'; if ( ( buf == Wrd ) && ( pos < afterScope(Sent, n) ) ) flag = true; n = m; } else n++; } return flag; } // if pos is the position of a + Capital in Sent, return true if // that is the start of a Noun, and false otherwise. bool isNounpos(const string Sent, size_t pos) { char c; bool wflag = true, rflag = true; pos++; while ( wflag && ( pos < Sent.length() ) ) { c = Sent[pos++]; if (c == '/') rflag = false; if ( isInitial(c) ) wflag = false; } return rflag; } // display Sent without endls void dispNoNdl(const string Sent) { size_t pos = 0; char c; if ( Sent != "" ) { c = Sent[pos++]; cout << c; } while ( pos < Sent.length() ) { c = Sent[pos++]; if ( isInitial(c) ) cout << " "; cout << c; } } // display Sent with initial and final endl void display(const string Sent) { cout << endl; dispNoNdl(Sent); cout << endl; } // search for Tit starting at pos and going up to immediately before fpos. Set pos to // start position of Tit if successful, and otherwise to fpos void seekTit(size_t& pos, const string infile, const string Tit, const size_t fpos) { size_t savepos; string Sent; while ( pos < fpos ) { savepos = pos; getSent(Sent, pos, infile); pos = savepos; if ( ( Sent == Tit ) || ( Sent == "" ) ) break; nxtPar(infile, pos); if ( pos == string::npos ) break; } if ( ( Sent == "" ) || ( pos == string::npos ) ) pos = fpos; } // search for first Definition Paragraph starting at pos and going up to immediately before // fpos. Set pos to start position of that Paragraph if successful, and otherwise to fpos void seekDef(size_t& pos, const string infile, const size_t fpos) { size_t savepos1 = pos, savepos2; seekTit(pos, infile, "+Df", fpos); savepos2 = pos; pos = savepos1; seekTit(pos, infile, "+1Df", savepos2); } // search for Tit starting at the second last entry in strts[STSSZ] that is not string::npos // and going up to immediately before the last entry, then if necessary starting at the third // from last entry, and so on, and finally if necessary starting at the first entry. Return // position of start of Tit if successful, and otherwise string::npos size_t skTitsts(const string infile, const string Tit, const size_t strts[STSSZ]) { size_t pos, fpos; int n = nxtstrt(strts) - 2; while ( n >= 0 ) { pos = strts[n]; fpos = strts[n + 1]; seekTit(pos, infile, Tit, fpos); if ( pos < fpos ) break; n--; } if ( n < 0 ) pos = string::npos; return pos; } // initialize Sbjs[MXSBJ] to null strings, then copy the Subjects of Brief Brf into Sbjs[MXSBJ] void getSbjs(const string Brf, string Sbjs[MXSBJ]) { size_t pos = Brf.find_first_of("+", 1); int n1, n2; for (n1 = 0; n1 < MXSBJ; n1++) Sbjs[n1].resize(0); n2 = nmSbjPhrs(Brf); if ( n2 < 0 ) { cout << "\nNot a Phrase"; throw 0; } if ( n2 > MXSBJ ) { cout << "\nReason, Method, or Abbreviation has more than " << MXSBJ << " Subjects"; throw 0; } n1 = 0; while ( n1 < n2 ) getSent(Sbjs[n1++], pos, Brf); } // for each entry in Sbjs[MXSBJ] that is a Title that is not +Df or +1Df, as opposed to null, // search for that Title, and if found, replace that entry in Sbjs[] by the Sentence after the // next Reason void TittoFact(const string infile, string Sbjs[MXSBJ], const size_t strts[STSSZ]) { size_t pos; int n = 0; string Tit; while ( n < MXSBJ ) { Tit = Sbjs[n]; if ( Tit == "" ) break; if ( ( Tit == "+Df" ) || ( Tit == "+1Df" ) ) { cout << endl << Tit << " is a Title of a Definition Paragraph"; throw 0; } pos = skTitsts(infile, Tit, strts); if ( pos == string::npos ) { cout << "\nTitle\n\n" << Tit << "\n\nnot found"; throw 0; } getReason(Sbjs[n], pos, infile); if ( Sbjs[n] == "" ) { cout << "No Reason found after Title\n\n" << Tit; throw 0; } getSent(Sbjs[n], pos, infile); if ( Sbjs[n] == "" ) { cout << "No Statement found after Title\n\n" << Tit; throw 0; } n++; } } // if Sbjs[0] is the Statement referred to by a +Ab/ Reason, then search through Definition // Paragraphs until the Definition of the Abbreviation by which chkSent differs from // Sbjs[0] is found, and copy the Abbreviation into Sbjs[1] and the Definition into Sbjs[2]. // Swap chkSent and Sbjs[0] if no suitable Definition Paragraph can be found otherwise void getDef(const size_t stpos, const string infile, string& chkSent, string Sbjs[MXSBJ]) { size_t pos1, pos2, savepos; bool sameflag = true, endflag = false, swapflag = false; string buf1, buf2; // identify the first Word at which chkSent differs from Sbjs[0] pos1 = pos2 = 0; while ( sameflag && !endflag ) { if ( ( pos1 >= chkSent.length() ) || ( pos2 >= Sbjs[0].length() ) ) endflag = true; else { putWord(chkSent, pos1, buf1); putWord(Sbjs[0], pos2, buf2); if ( buf1 != buf2 ) sameflag = false; } } if ( endflag ) { cout << "\nFact\n\nNo substitution made"; throw 0; } if ( buf1[0] != '+' ) { if ( buf2[0] == '+' ) { chkSent.swap(Sbjs[0]); buf1.swap(buf2); swapflag = true; } else { cout << "\nThe earlier Statement differs from this Statement before the start of the"; cout << "\nfirst Phrase of either Statement"; throw 0; } } while ( true ) { // seek the Definition Paragraph that Defines the Abbreviation in buf1 savepos = pos1 = 0; while ( pos1 < stpos ) { seekDef(pos1, infile, stpos); savepos = pos1; if ( pos1 < stpos ) { getSent(Sbjs[1], pos1, infile); getSent(Sbjs[1], pos1, infile); getSent(Sbjs[2], pos1, infile); pos2 = 0; putWord(Sbjs[1], pos2, buf2); if ( buf1 == buf2 ) { if ( nmSbjBrf(Sbjs[1]) != -1 ) break; else { cout << "\nErroneous Definition Paragraph found. Its Abbreviation is\n\n"; cout << Sbjs[1]; throw 0; } } } } if ( savepos != stpos ) break; if ( ( swapflag ) || ( buf2[0] != '+' ) ) { cout << "\nNo Definition of the Abbreviation found"; throw 0; } chkSent.swap(Sbjs[0]); buf1.swap(buf2); swapflag = true; } } // return the Sentence obtained from Defn by replacing each unGoverned Noun occurrence // in Defn, of any Word in DefSbjs, by the corresponding Phrase in DfSbjReps string buildsubsDefn(string Defn, const string DefSbjs[MXSBJ], const string DfSbjReps[MXSBJ]) { string buildbuf, tempbuf; size_t n = 0, afterPhrase, newpos, aftr; int i; buildbuf = ""; while ( n < Defn.length() ) { afterPhrase = afterScope(Defn, n); putWord(Defn, n, tempbuf); buildbuf += tempbuf; if (tempbuf[0] == '+') while ( n < afterPhrase ) { newpos = n; putWord(Defn, newpos, tempbuf); if (isNounpos(Defn, n)) if (!isGovpos(Defn, n)) { aftr = 0; for (i = 0; ( i < MXSBJ ) && ( aftr == 0 ); i++) if ( DefSbjs[i] == tempbuf ) getSent(tempbuf, aftr, DfSbjReps[i]); } buildbuf += tempbuf; n = newpos; } } return buildbuf; } // check whether chkSent can be obtained from Sbjs[0] by precisely one // +Ab/ application of the Definition contained in Sbjs[1] and Sbjs[2] void chkAb(string chkSent, string Sbjs[MXSBJ], const string infile, const size_t stpos) { size_t pos1 = 0, pos2 = 0, savepos; int n; string buf1, buf2; bool flag = true, swapflag = false; string Abbrv, Phrs, DefSbjs[MXSBJ], DfSbjReps[MXSBJ]; while ( true ) { buf1 = chkSent; getDef(stpos, infile, chkSent, Sbjs); // will not return if chkSent == Sbjs[0] if ( buf1 != chkSent ) swapflag = true; while ( flag && ( pos1 < Sbjs[0].length() ) && ( pos2 < chkSent.length() ) ) { savepos = pos1; putWord(Sbjs[0], pos1, buf1); putWord(chkSent, pos2, buf2); if ( buf1 != buf2 ) flag = false; } Abbrv = Sbjs[1]; // copy the Subjects of the Abbreviation in the Definition Paragraph into DefSbjs getSbjs(Sbjs[1], DefSbjs); pos2 = savepos; // copy the Abbreviation Phrase in chkSent into Sbjs[1] getSent(Sbjs[1], pos2, chkSent); Phrs = Sbjs[1]; // copy the Subjects of the Abbreviation Phrase in chkSent into DfSbjReps getSbjs(Sbjs[1], DfSbjReps); Sbjs[1] = buildsubsDefn(Sbjs[2], DefSbjs, DfSbjReps); pos1 = savepos; getSent(buf1, pos1, Sbjs[0]); if ( Sbjs[1] != buf1 ) { if ( swapflag ) { cout << "\nInvalid substitution"; throw 0; } chkSent.swap(Sbjs[0]); swapflag = true; continue; } flag = true; if ( ( pos1 < Sbjs[0].length() ) && ( pos2 == chkSent.length() ) ) flag = false; if ( ( pos1 == Sbjs[0].length() ) && ( pos2 < chkSent.length() ) ) flag = false; if ( ( pos1 < Sbjs[0].length() ) && ( pos2 < chkSent.length() ) ) if ( Sbjs[0].substr(pos1) != chkSent.substr(pos2) ) flag = false; if ( !flag ) { cout << "\nSentence altered after the Abbreviation"; throw 0; } n = 0; while ( n < MXSBJ ) { if ( DefSbjs[n] != "" ) { if ( !nGovforPhrs(Sbjs[2], DefSbjs[n], DfSbjReps[n]) ) { cout << "\nThe formation of the Sentence\n"; display(Sbjs[1]); cout << "\nfrom the Phrase\n\n"; dispNoNdl(Phrs); cout << ",\n\nin Accordance with the Definition\n"; display(Sbjs[2]); cout << "\nof the Abbreviation\n\n"; dispNoNdl(Abbrv); cout << ",\n\nis not Legitimate, because in the Definition, there is an "; cout << "Object occurrence\nof the Noun\n"; display(DefSbjs[n]); cout << "\nthat is not Governed, and lies within the Scope of an Adverb "; cout << "that Agrees with\na Noun in the Phrase\n"; display(DfSbjReps[n]); throw 1; } } n++; } break; } } // if pos is an effective start of a Statement Paragraph that contains Methods, remove the // last - and what follows it from the end of Names, as many times as there are Methods not // followed by +Ao in that Paragraph. Then if the Title at or after pos is an Opening Title, // add - to Names. Then if pos is an effective start of a Definition Paragraph, add each // Name created by that Definition Paragraph to Names, if it is not already present void reviseNms(const size_t pos, const string infile, string& Names) { size_t getpos = pos, newpos, afterPhrase; bool flag; int n; string Wrd, Abb, Def, Sbjs[MXSBJ]; getSent(Wrd, getpos, infile); if ( ( Wrd != "+Df" ) && ( Wrd != "+1Df" ) ) { n = cntMthnfbAo(infile, pos); while ( n > 0 ) { newpos = Names.rfind("-"); Names.resize(newpos); n--; } } if ( isOpnTit(Wrd) ) Names += "-"; if ( ( Wrd == "+Df" ) || ( Wrd == "+1Df" ) ) { getSent(Abb, getpos, infile); if ( Abb == "" ) { cout << "\nAbbreviation not found"; throw 0; } getSent(Def, getpos, infile); if ( Def == "" ) { cout << "\nDefinition not found"; throw 0; } if ( isNoun(Abb) ) if ( !isName(Names, Abb) ) Names += Abb; getSbjs(Abb, Sbjs); getpos = 0; while ( getpos < Def.length() ) { getpos = Def.find_first_of("+", getpos); afterPhrase = afterScope(Def, getpos); putWord(Def, getpos, Wrd); while ( getpos < afterPhrase ) { newpos = getpos; putWord(Def, newpos, Wrd); if (isNounpos(Def, getpos)) if (!isGovpos(Def, getpos)) { flag = true; for (n = 0; n < MXSBJ; n++) if ( Sbjs[n] == Wrd ) flag = false; if ( flag && !isName(Names, Wrd) ) Names += Wrd; } getpos = newpos; } } } } // if Abb has one or more Subjects, check they are all different. And if stpos is an // effective start position of a Definition Paragraph, whose Abbreviation and Definition // are Abb and Def, check the 2nd, 3rd, and 4th requirements for a Regular Development void chkDef(const string infile, const size_t stpos, const string Abb, const string Def) { size_t pos = 0, getpos = 0; int n1, n2; bool flag = false; string Sbjs[MXSBJ], Wrd1, Wrd2, Brf, prvDf; getSbjs(Abb, Sbjs); for(n1 = 1; n1 < MXSBJ; n1++) { if ( Sbjs[n1] == "" ) break; for (n2 = 0; n2 < n1 ; n2++) if ( Sbjs[n2] == Sbjs[n1] ) { cout << "\nSubjects of Abbreviation are not all different"; throw 0; } } if ( isNoun(Def) ) { display(Def); cout << "\nDefinition is a Noun"; throw 0; } if ( hasRelocAb(infile, stpos, Def) ) { display(Def); cout << "\nWord being Defined has a Relevant occurrence in its Definition"; throw 0; } putWord(Abb, pos, Wrd1); while ( getpos < stpos ) { seekDef(getpos, infile, stpos); if ( getpos == stpos ) break; getSent(Brf, getpos, infile); getSent(Brf, getpos, infile); if ( Brf == "" ) { cout << "\nAn earlier Definition Paragraph is missing its Abbreviation"; throw 0; } getSent(prvDf, getpos, infile); if ( prvDf == "" ) { cout << "\nAn earlier Definition Paragraph is missing its Definition"; throw 0; } pos = 0; putWord(Brf, pos, Wrd2); if ( Wrd1 == Wrd2 ) { cout << "\nThe Word being Defined was Defined by an earlier Definition Paragraph\n"; cout << "\nThe Abbreviation and Definition in that earlier Definition Paragraph are\n"; display(Brf); display(prvDf); throw 1; } n1 = nmSbjBrf(Brf); if ( n1 < 0 ) { cout << "\nThe second Sentence of an earlier Definition Paragraph is not a Brief"; throw 0; } if ( n1 > MXSBJ ) { cout << "\nThe Abbreviation in an earlier Definition Paragraph has more than "; cout << MXSBJ << " Subjects"; throw 0; } getSbjs(Brf, Sbjs); if ( nmSbjPhrs(Def) >= 0 ) { if ( isNoun(Wrd1) ) { if ( hasnGovObjoc(Wrd1, prvDf) ) { flag = true; for (n1 = 0; n1 < MXSBJ; n1++) if ( Sbjs[n1] == Wrd1 ) flag = false; } } else if ( hasObjoc(Wrd1, prvDf) ) flag = true; } if ( hasVrboc(Wrd1, prvDf) ) flag = true; if ( flag ) { display(Def); if ( isNoun(Wrd1) ) { cout << "\nThe Noun being Defined has a Relevant occurrence in the Definition of an"; cout << "\nearlier Definition Paragraph, such that either the Noun being Defined is"; cout << "\nnot a Subject of the Abbreviation of that earlier Definition Paragraph, or"; cout << "\nthe Relevant occurrence is a Verb occurrence\n"; } else { cout << "\nThe Preposition being Defined has a Relevant occurrence in the Definition"; cout << "\nof an earlier Definition Paragraph\n"; } cout << "\nThe Abbreviation and Definition in that earlier Definition Paragraph are\n"; display(Brf); display(prvDf); throw 1; } } } // if Nm is a Name, return the start position of the first Definition Paragraph such that // either the Abbreviation is Nm and the Definition is a Phrase, or Nm has an Object // occurrence in the Definition that is not Governed, but is not a Subject of the Abbreviation size_t seekDfNm(const string infile, const string Nm, const size_t stpos) { size_t pos = 0, savepos = 0; string Brf, Def, Sbjs[MXSBJ]; int n; bool flag = false; while ( pos < stpos ) { seekDef(pos, infile, stpos); savepos = pos; getSent(Brf, pos, infile); getSent(Brf, pos, infile); getSent(Def, pos, infile); if ( ( Brf == Nm ) && ( nmSbjPhrs(Def) >= 0 ) ) break; getSbjs(Brf, Sbjs); for (n = 0; n < MXSBJ; n++) if ( Sbjs[n] == Nm ) flag = true; if ( !flag && hasnGovObjoc(Nm, Def) ) break; } return savepos; } // get the distinct Clauses in Sent into Cls[], if they are not already there void oneSentgetCls(string Sent, string Cls[MXCLS]) { size_t pos = 0; string buf; int i; bool sflag, nflag; while ( pos < Sent.length() ) { pos = Sent.find_first_of("+[]", pos); getSent(buf, pos, Sent); nflag = sflag = false; i = 0; while ( ( !nflag ) && ( !sflag ) && ( i < MXCLS ) ) { if ( Cls[i] == buf ) sflag = true; if ( Cls[i] == "" ) nflag = true; else i++; } if ( !sflag ) { if ( nflag ) Cls[i] = buf; else { cout << "\nMore than " << MXCLS << " distinct Clauses"; throw 0; } } } } // get the distinct Clauses in chkSent, and in the Sentences in Sbjs[], into Cls[] void getClauses(string chkSent, string Sbjs[MXSBJ], string Cls[MXCLS]) { int i; oneSentgetCls(chkSent, Cls); for (i = 0; i < MXSBJ; i++) if ( Sbjs[i] != "" ) oneSentgetCls(Sbjs[i], Cls); } // get the Clause summary of srcSent into Clsform[]. Each Clause is represented by // the index of that Clause in Cls[], = is represented by -4, - by -5, ( by -6, // and ) by -7, and the first position after the end by -1. void makeClsform(string srcSent, string Cls[MXCLS], int Clsform[CLSSZ]) { size_t pos = 0; char c; string buf; int n = 0, Clfrm = -1; while ( pos < srcSent.length() ) { c = srcSent[pos]; if (c == '=') Clfrm = -4; if (c == '-') Clfrm = -5; if (c == '(') Clfrm = -6; if (c == ')') Clfrm = -7; if (c == '+' || c == '[' || c == ']') { getSent(buf, pos, srcSent); Clfrm = 0; while ( Clfrm < MXCLS ) { if ( Cls[Clfrm] == buf ) break; Clfrm++; } } else pos++; Clsform[n++] = Clfrm; if ( n == CLSSZ ) { cout << "\nLength of Clause form will exceed " << CLSSZ; throw 0; } } Clsform[n] = -1; } // for each entry i >= 0 in Clsform[], from the beginning until -1 is found, // this function replaces i by TFvals[i]. Negative entries are unchanged. void subsTFvals(int Clsform[CLSSZ], int TFvals[MXCLS]) { int m = 0; while (Clsform[m] != -1) { if (Clsform[m] >= 0 && Clsform[m] < MXCLS) Clsform[m] = TFvals[Clsform[m]]; m++; } } // for each non-null Clause in Cls[], the corresponding entry in TFvals[] is // initialised to 1, representing True, and any remaining entries are // initialised to 2. void initTFvals(string Cls[MXCLS], int TFvals[MXCLS]) { int i = 0; while (i < MXCLS) { if ( Cls[i] != "" ) TFvals[i] = 1; else TFvals[i] = 2; i++; } } // if there are any 1 entries in TFvals[], then the first 1 entry is set to // 0, all the 0 entries before that are set to 1, and 1 is returned, while if // there are no 1 entries, then 0 is returned. int newTFvals(int TFvals[MXCLS]) { int i = 0, j = 0, flag = 0; while (!flag && i < MXCLS) { if (TFvals[i] == 1) { TFvals[i] = 0; flag = 1; } else i++; } if (flag) while (j < i) { if (TFvals[j] == 0) TFvals[j] = 1; j++; } return flag; } // if Clsform[] contains the result of substituting the current Truth values of the // Clauses, for the corresponding Clause numbers in the Clause summary of a Sentence, // then return the truth value of that Sentence for the current Truth values of the // Clauses. The entries in Clsform[] initially consist of -4, -5, -6, and -7, coding // for =, -, (, and ) respectively, 1, coding for True, 0, coding for False, and // finally a -1 to indicate the first position after the end. When a 1 or 0 is "used", // it is replaced by -2, and when a -4, -5, -6, or -7 is "evaluated", it is replaced // by 1 or 0 as appropriate. An evaluation step consists of starting from the // beginning of Clsform[], finding the first coded Sign such that sufficient 0's or // 1's to serve as its Subjects are found before any further coded Sign occurs, // evaluating that coded Sign and replacing it by 0 or 1 as appropriate, and // replacing its Subjects by -2. This step is repeated until Clsform[0] is evaluated, // and then Clsform[0] is returned int evalClsform(int Clsform[CLSSZ]) { int flag, s, x, y = 1; // initializations of y and k are not used, they are to avoid int i; // index of Sign compiler warnings int j; // index of first Subject int k = 0; // index of second Subject do { i = 0; do { s = Clsform[i]; flag = 0; j = i + 1; if (Clsform[j] <= -4) flag = 1; if (flag == 0 && s != -5) { k = j + 1; while (Clsform[k] == -2) k++; if (Clsform[k] <= -4) flag = 1; } if (flag == 1) { do i++; while (Clsform[i] > -4); } } while (flag); x = Clsform[j]; if (s != -5) y = Clsform[k]; if (s == -4) Clsform[i] = x * y + (1 - x) * (1 - y); // equivalence if (s == -5) Clsform[i] = 1 - x; // not if (s == -6) Clsform[i] = x * y; // and if (s == -7) Clsform[i] = 1 - (1 - x) * (1 - y); // or Clsform[j] = -2; if (s != -5) Clsform[k] = -2; } while (i != 0); return Clsform[0]; } // for each independent assignment of truth values to the distinct Clauses in chkSent, // and in the Sentences in Sbjs[], the truth value of each Sentence in Sbjs[] is // calculated. If all of these evaluate as true, then the truth value of chkSent is // evaluated for that assignment of truth values to the Clauses. The function returns if // the truth value of chkSent is true for each such assignment of truth values to the // Clauses, while if the truth value of chkSent is found to be false for some such // assignment of truth values to the Clauses, the function displays those truth values // of the Clauses then throws an exception void chkTb(string chkSent, string Sbjs[MXSBJ]) { string Cls[MXCLS]; int TFvals[MXCLS]; int i, tflag, Clsform[CLSSZ], numCls = 0; int wflag = 1; // the following 22 lines of code are a work-around for a seg fault that sometimes // occurred at a random point during the execution of makeClsform(...), when there // were about 10 or more Clauses, and the first of the previous Statements had only // one Clause, for example +sm// +a +a int n1, n2, n3, n4; for ( i = 0, n1 = 0; i < MXSBJ; i++) if ( Sbjs[i] != "" ) n1++; if ( n1 > 1 ) { i = n1 = n2 = 0; while ( i < MXSBJ ) { if ( Sbjs[i] != "" ) { for (n3 = 0; n3 < MXCLS; n3++) Cls[n3].resize(0); oneSentgetCls(Sbjs[i], Cls); for ( n3 = 0, n4 = 0; n3 < MXCLS; n3++) if ( Cls[n3] != "" ) n4++; if ( n4 > n2 ) { n2 = n4; n1 = i; } } i++; } if ( n1 != 0 ) Sbjs[0].swap(Sbjs[n1]); } for (i = 0; i < MXCLS; i++) Cls[i].resize(0); getClauses(chkSent, Sbjs, Cls); for (i = 0; i < MXCLS; i++) if ( Cls[i] != "" ) numCls++; if ( numCls >= WNCLS ) { cout << "\nThere are " << numCls << " distinct Clauses.\n"; cout << "\nThe time required to check a use of Tabulate approximately doubles with each\n"; cout << "extra distinct Clause\n"; } initTFvals(Cls, TFvals); while ( wflag ) { i = 0; tflag = 1; while (tflag && i < MXSBJ) { if ( Sbjs[i] != "" ) { makeClsform(Sbjs[i], Cls, Clsform); subsTFvals(Clsform, TFvals); tflag = evalClsform(Clsform); } i++; } if (tflag) { makeClsform(chkSent, Cls, Clsform); subsTFvals(Clsform, TFvals); tflag = evalClsform(Clsform); if ( !tflag ) { cout << "\nThis Sentence is False, while all the Facts referred to in the Reason "; cout << "\nare True, when the truth values of the Clauses are as follows:"; for(i = 0;i < MXCLS;i++) if ( Cls[i] != "" ) { cout << "\n"; display(Cls[i]); if ( TFvals[i] ) cout << "\ntrue"; else cout << "\nfalse"; } throw 0; } } wflag = newTFvals(TFvals); } } // check chkSent is equal to Sbjs[0], preceded by an Adverb that starts with [. Check no Name // Agrees with the first Adverb in chkSent void chkGn(const string chkSent, const string Sbjs[MXSBJ], const string Names) { size_t pos = 0; string buf, temp; if (chkSent[0] != '[') { cout << "\nStatement does not begin with ["; throw 0; } putWord(chkSent, pos, buf); buf[0] = '+'; if ( isName(Names, buf) ) throw 4; buf[0] = '['; buf += Sbjs[0]; if ( buf != chkSent ) { cout << "\nSentence after the Adverb differs from the earlier Sentence"; throw 0; } } // check that chkSent and Sbjs[0] are related by replacing exactly one sequence of the // form - A - in one of them, where A is an Adverb that starts with [, by the Adverb // obtained from A by replacing its initial [ by ], in the other of them void chkSm(string chkSent, string Sbjs[MXSBJ]) { size_t pos1 = 0, pos2 = 0, savepos; string buf1, buf2; bool flag = true; while ( flag && ( pos1 < Sbjs[0].length() ) && ( pos2 < chkSent.length() ) ) { putWord(Sbjs[0], pos1, buf1); putWord(chkSent, pos2, buf2); flag = ( buf1 == buf2 ); } if ( flag ) { cout << "\nFact\n\nNo substitution made"; throw 0; } if ( buf1 != "-") { if (buf2 != "-" ) { cout << "\nThe first Word where the Statements differ is not - in either case"; throw 0; } else { chkSent.swap(Sbjs[0]); buf2.swap(buf1); savepos = pos1; pos1 = pos2; pos2 = savepos; } } if ( buf2[0] != ']' ) { cout << "\nThe first Letter where the Statements differ is not ] in either case"; throw 0; } // Sbjs[0] has another Word, because Sbjs[0] is a Sentence putWord(Sbjs[0], pos1, buf1); if ( buf1[0] != '[' ) { cout << "\nThe first Letter after the first - where the Statements differ is not ["; throw 0; } buf1[0] = ']'; if ( buf1 != buf2 ) { cout << "\nThe [ Adverb and the ] Adverb differ after their first Letters"; throw 0; } putWord(Sbjs[0], pos1, buf1); if ( buf1 != "-" ) { cout << "\nThe first Word after the replaced or substituted [ Adverb is not -"; throw 0; } flag = true; if ( ( pos1 < Sbjs[0].length() ) && ( pos2 == chkSent.length() ) ) flag = false; if ( ( pos1 == Sbjs[0].length() ) && ( pos2 < chkSent.length() ) ) flag = false; if ( ( pos1 < Sbjs[0].length() ) && ( pos2 < chkSent.length() ) ) if ( Sbjs[0].substr(pos1) != chkSent.substr(pos2) ) flag = false; if ( !flag ) { cout << "\nSentence altered after the Some substitution"; throw 0; } } // return true if no Object occurrence of Noun1 in chkSent, that is not Governed, occurs // within the Scope of an Adverb that Agrees with Noun2, and otherwise false bool nGovforNoun(string chkSent, string Noun1, string Noun2) { size_t pos1 = 0, newpos, pos2, afterPhrase, aftScpAdv; string buf; bool flag = true; while ( flag && ( pos1 < chkSent.length() ) ) { afterPhrase = afterScope(chkSent, pos1); putWord(chkSent, pos1, buf); if ( buf[0] == '+' ) while ( flag && ( pos1 < afterPhrase ) ) { newpos = pos1; putWord(chkSent, newpos, buf); if ( buf == Noun1 ) if ( !isGovpos(chkSent, pos1) ) { pos2 = 0; while ( flag && ( pos2 < pos1 ) ) { aftScpAdv = afterScope(chkSent, pos2); putWord(chkSent, pos2, buf); if (buf[0] == '[' || buf[0] == ']') { buf[0] = '+'; if ( ( buf == Noun2 ) && ( pos1 < aftScpAdv ) ) flag = false; } } } pos1 = newpos; } } return flag; } // return true if no Object occurrence of Noun1 in chkSent, that is not Governed, occurs // within the Scope of any Adverb that Agrees with a Noun in Phrase, and otherwise false bool nGovforPhrs(const string chkSent, const string Noun1, const string Phrase) { size_t pos = 0; bool flag = true; string Wrd; while ( pos < Phrase.length() ) { putWord(Phrase, pos, Wrd); if ( isNoun(Wrd) ) if ( !nGovforNoun(chkSent, Noun1, Wrd) ) flag = false; } return flag; } // check that chkSent has the form ) - A B C, where A is an Adverb that begins with [, // B is a Sentence, and C is obtained from B by replacing every Object occurrence that // is not Governed, of the Noun that Agrees with A, by a Phrase D, such that no Noun in // D becomes Governed, when D replaces an occurrence in B of the Noun that Agrees with A void chkEx(string chkSent, string Sbjs[MXSBJ]) { string Noun, Sent; size_t pos1 = 2, pos2 = 0, savepos; int n; string buf1, buf2; bool flag = true; string DefSbjs[MXSBJ], DfSbjReps[MXSBJ]; for (n = 0; n < MXSBJ; n++) DefSbjs[n].resize(0); for (n = 0; n < MXSBJ; n++) DfSbjReps[n].resize(0); if ( chkSent.length() < 4 ) { cout << "\nNot a Fact of type +Ex"; throw 0; } if ( ( chkSent[0] != ')' ) || ( chkSent[1] != '-' ) || ( chkSent[2] != '[' ) ) { cout << "\nNot a Fact of type +Ex"; throw 0; } putWord(chkSent, pos1, Noun); Noun[0] = '+'; getSent(Sbjs[0], pos1, chkSent); getSent(Sent, pos1, chkSent); pos1 = 0; while ( flag && ( pos1 < Sent.length() ) && ( pos2 < Sbjs[0].length() ) ) { savepos = pos1; putWord(Sent, pos1, buf1); putWord(Sbjs[0], pos2, buf2); flag = ( buf1 == buf2 ); } if (!flag) { if ( buf2 != Noun ) { Noun[0] = '['; cout << "\nThe first Word in the Subject of\n\n" << Noun << endl << endl; Noun[0] = '+'; cout << "that is replaced is not\n\n" << Noun; throw 0; } if ( ( !isObjoc(Sbjs[0], savepos) ) || isGovpos(Sbjs[0], savepos) ) { cout << "\nThe first occurrence of\n\n" << Noun << endl << endl; Noun[0] = '['; cout << "in the Subject of\n\n" << Noun << endl << endl; cout << "that is replaced is not an Object occurrence that is not Governed"; throw 0; } Sbjs[1] = buf2; DefSbjs[0] = buf2; pos1 = savepos; getSent(buf1, pos1, Sent); Sbjs[2] = buf1; DfSbjReps[0] = buf1; Sbjs[3] = buildsubsDefn(Sbjs[0], DefSbjs, DfSbjReps); if ( Sbjs[3] == "" ) { Noun[0] = '['; cout << "\nFailed to build Subject of\n\n" << Noun; cout << "\n\nwith the appropriate substitutions"; throw 0; } if ( !( Sent == Sbjs[3] ) ) { cout << "\nInvalid substitution"; throw 0; } // if this stage is reached, Sbjs[2] is a Phrase if ( !nGovforPhrs(Sbjs[0], Sbjs[1], Sbjs[2]) ) { Sbjs[1].replace(0, 1, "["); cout << "\nIn the Subject of the Adverb\n\n"<< Sbjs[1]; cout << ",\n\nthere is an Object occurrence of the Noun that Agrees with "; cout << "that Adverb, that is\nnot Governed within the Subject, and lies within"; cout << " the Scope of an Adverb in the\n"; cout << "Subject that Agrees with a Noun in the Phrase\n\n"; cout << Sbjs[2]; throw 0; } } } // check that chkSent has the form ) B A C, and Sbjs[0] has the form A ) B C, where A is // an Adverb that begins with [, and B and C are Sentences such that the Noun that Agrees // with A has no Object occurrence in B that is not Governed void chkFc(const string chkSent, const string Sbjs[MXSBJ]) { size_t pos = 0; string Wrd, SbjB, SbjC, buf; putWord(chkSent, pos, buf); if ( buf != ")" ) { cout << "\nThe first Word of the Statement is not )"; throw 0; } getSent(SbjB, pos, chkSent); putWord(chkSent, pos, Wrd); if ( Wrd[0] != '[' ) { cout << "\nThe first Letter of the second Subject of the first ) is not ["; throw 0; } getSent(SbjC, pos, chkSent); pos = 0; putWord(Sbjs[0], pos, buf); if ( buf != Wrd ) { cout << "\nThe first Word of the earlier Statement is not the same as the Adverb at the"; cout << "\nstart of the second Subject of the first ) in the current Statement"; throw 0; } putWord(Sbjs[0], pos, buf); if ( buf != ")" ) { cout << "\nThe second Word of the earlier Statement is not )"; throw 0; } getSent(buf, pos, Sbjs[0]); if ( buf != SbjB ) { cout << "\nThe first Subject of the first ) in the earlier Statement is not the same as"; cout << "\nthe first Subject of the first ) in the current Statement"; throw 0; } getSent(buf, pos, Sbjs[0]); if ( buf != SbjC ) { cout << "\nThe second Subject of the first ) in the earlier Statement is not the same as"; cout << "\nthe Subject in the current Statement of the Adverb that moved"; throw 0; } Wrd[0] = '+'; if ( hasnGovObjoc(Wrd, SbjB) ) { cout << "\nIn the first Subject of the first ), there is an Object occurrence, that is"; cout << "\nnot Governed, of the Noun that Agrees with the Adverb that moved"; throw 0; } } bool isInitial(char c) { bool tst = false; if (c == '=' || c == '-' || c == '(' || c == ')') tst = true; if (c == '+' || c == '[' || c == ']') tst = true; return tst; } bool isCapital(char c) { bool tst = false; if (c == '=' || c == '-' || c == '(' || c == ')') tst = true; if (c == '+' || c == '/' || c == '[' || c == ']') tst = true; return tst; } char possreverse(char c) { char ch = c; if ( c == '(' ) ch = ')'; if ( c == ')' ) ch = '('; if ( c == '[' ) ch = ']'; if ( c == ']' ) ch = '['; if ( c == '<' ) ch = '>'; if ( c == '>' ) ch = '<'; if ( c == '{' ) ch = '}'; if ( c == '}' ) ch = '{'; return ch; }