%{/*This bison/yacc program parses the Formalised English (FE) linear format used in WebKB-1 (now superseded by WebKB-2) (see http://meganesia.int.gu.edu.au/~phmartin/WebKB/doc/grammars/) and translates it into a CG linear format (there is no official grammar for this grammar; for new/uncommon features, we used a format close to the FE format). Author: Philippe.Martin@gu.edu.au; Creation date: 25/11/99 Test: http://meganesia.int.gu.edu.au/~phmartin/WebKB/doc/grammars/kbfe.html yes:A cat is on a mat which is near a table, and has for color the white. no: A cat is on a mat which is near a table, and has for color the white, and for r a t. yes: Joe is a smoker and is a driver. no: Joe is a smoker and a driver. yes: Joe has for type Smoker and for type Driver. Compilation: fe: fe.o $(C++) $(OPTLINK) -o fe fe.o fe.o: fe.c $(C++) $(OPTIONS) -c fe.c -o fe.o fe.c: fe.y fe.lex.c bison -pfe -v -t -y fe.y -o fe.c fe.lex.c: fe.l flex -Pfe -i fe.l; /bin/mv lex.fe.c fe.lex.c To debug, set "yydebug=1;" in main() (by default: #define YYDEBUG 1) */ #ifndef __cplusplus #define __cplusplus #endif #include #include #include #include #include "String.h" #include "fe.lex.c" #define YYERROR_VERBOSE 1 #define pr printf int feerror(const char *s); extern "C" int isFormalisedEnglish (char *arg0, char *arg1); extern "C" char *formalisedEnglishToCGs (char *fe); /* at end of this file */ #ifdef _IN_WEBKB extern int WithTrace; extern char ParsingError[]; extern "C" char KsIsaRelationType (char *rTn1); int isUndeclTermEndingByING (String relName) { char *r=(char *)(relName.chars()); int l=strlen(r)-1; return ((tolower(r[l])=='g') && (tolower(r[l-1])=='n') && (tolower(r[l-2])=='i') && !KsIsaRelationType(r)); } #else int WithTrace=1; char ParsingError[500]; int isUndeclTermEndingByING (String relName) { char *r=(char *)(relName.chars()); int l=strlen(r)-1; return ((tolower(r[l])=='g') && (tolower(r[l-1])=='n') && (tolower(r[l-2])=='i')); } /* plus function main() at end of file because yydebug undeclared here */ #endif String FEinCGs; /* the result of the parsing */ static String FE_LastToken, RelType, Qualifier; static String Indiv, Coref, Set, Term, Num,N1, Perc; static String BrIndent(""); static int Of=0, IsIndiv=0; static void IndentS(int nbC) { BrIndent=" "; while (--nbC>0) BrIndent+=" "; } static String IsIt; #define MAX_DEPTH 20 static int D=0; /*Tree depth*/ static String FEinCG[MAX_DEPTH], Tree[MAX_DEPTH]; static String Concept[MAX_DEPTH], ConCore[MAX_DEPTH], Annot[MAX_DEPTH]; static String Relation[MAX_DEPTH], Elem[MAX_DEPTH], Collec[MAX_DEPTH]; static String Cq[MAX_DEPTH], Restrictor[MAX_DEPTH], ConType[MAX_DEPTH]; static String Quantif[MAX_DEPTH], CorefI[MAX_DEPTH], GroupOf[MAX_DEPTH]; static int InCollec[MAX_DEPTH]; /* static String b, Query, DefinedType, Concept[MAX_DEPTH], Relation[MAX_DEPTH]; static int IsADef=0;*/ typedef struct _StringList StringList; struct _StringList { String object; StringList *next; }; static StringList *Branch[MAX_DEPTH], *Branches[MAX_DEPTH]; /* functions to manage string lists: */ StringList *newS(); void delS(StringList *me); void pushS(StringList *me, String str); String popS(StringList *me); int isEmptyS(StringList *me); String StringRelation (String relName); void upInitial(/*varP*/char *str); void delLastS (/*varP*/char *str); static void mkFEinCG (int isNegated); static void mkTree (); static void mkBranch(int isAdef); static void mkRel (int isImplication); static void mkRelC (int isImplication); static void mkRelOp (char *oper); static void mkConcept (); static void mkConCore (int conCoreCase); static int isIdentInString(char *s); #if 0 Extended BNF grammar for Frame-CGs ("?" means 0 or 1 times, "*" means 0 to N times, "+" means 1 to N times): FE := (Tree ("."|"?"))+ Tree := Concept Branches* QuotedTree := "~"? "`" Tree "'" Context? Context := "(" Branches2 ")" Branches := With Relation1 Tree (And With? Relation Tree)* | With? Relation2 Tree (And With? Relation Tree)* | "is"("a"|"an")Tree (And "is"("a"|"an")Tree)* Branches2 := With? Relation Tree (And With? Relation Tree)* | "is"("a"|"an") Tree (And "is"("a"|"an") Tree)* With := ("with"|"at"|"has for"|"have for"|"for"|"is"|"are"| ("can"|"may")("be"|"have for")) "the"? And := "and" | "," Relation := Relation1 | Relation2 Relation1 := (RelationType|Coreference) "of"? Annotation? Context? "<="? Relation2 := ("=>" | "<=>" | "<=" ) Concept | ("=" | "!=" | "<" | "=<" | ">" | ">=" | "or") Concept RelationType := Term_or_string Coreference := "*" Term_or_number Concept := ConceptCore Annotation? ConceptCore := CorefOrIndiv Quantifier Restrictor CQ? | Quantifier Restrictor CorefOrIndiv? CQ? | GroupOf Quantifier? Restrictor CorefDecl? Collection? | GroupOf Quantifier? CorefDecl? Collection | (Number | "~"Coreference | CQ | CorefOrIndiv CQ?) CorefOrIndiv := CorefDecl | "named"? Term_or_string ("\\" ConceptType)? //Term_or_string: individual (ex: Tom) or attribute (ex: high) CorefDecl := "*"Term_or_number | "*"Term_or_number "!=" "*"Term_or_number | "*"Term_or_number "!=" Term_or_number CQ := Collection | QuotedTree Restrictor := Qualifier? ConceptType | Qualifier? "[" ConceptType Branches "]" ConceptType := Term_or_string Qualifier := "good"|"bad" | "important"|"small"|"big"|"great" | "certain" Quantifier := "a" | "an" | "some" | "the" | "any" | "every" | "most" "of"? "the"? | "at" "least" Number "%"? "of"? "the"? | "at" "most" Number "%"? "of"? "the"? | "between" Number "%"? "and" Number "%"? "of"? "the"? | Number "to" Number "%"? "of"? "the"? | "from" Number "to" Number "%"? "of"? "the"? | "mostly" | "several" "of"? "the"? | Number "%"? "of"? "the"? | ("many"|"few"|"dozens"|"hundreds" |"thousands"|"millions"|"billions") "of"? "the"? GroupOf := CorefOrIndiv?("a"|"the")("group""of" | "bag""of" | "set""of"|"sequence""of"|"alternative") | "together" Collection := "{" (Set|Bag|OrderedSet|OrderedBag|XOR_Set|OR_Bag) "}" CollSize? Set := Element ("," Element)* Bag := Element ("&" Element)* OrderedSet := Element ("<" Element)* OrderedBag := Element ("=<" Element)* XOR_Set := Element ("/" Element)* OR_Bag := Element ("|" Element)* Element := Concept | "*" CollSize := "@" Number Term_or_number:= Term | number Term_or_string:= Term | string Term := TermLetter1 TermLetter* TermLetter1 := [a-z] | "#"[a-z] TermLetter := [a-z] | "#" | "_" | "-" | "/" | "?" | "&" | "~" | Digit | [.?][a-z0-9?#~] //thus "." ok within a term but not at the end | "://" //thus a URL may be a term Number := ("+"|"-")? Digit+ ("." Digit* )? Digit := [0-9] //Additional notes on the lexical parsing: - uppercase letters are parsed as if they were lowercase letters - white spaces and the HTML imbreakable space encoding " " are ignored - Java/C++ comments ("/* ... */" and "//...") are ignored - HTML tags are ignored but the content of HTML comments is parsed - annotations are enclosed within "(^" and "^)" - strings may be double quoted or enclosed within "$(" and ")$" (because of the use of quotes and bacquotes to embedd sentences, strings cannot also be simple quoted in FE) #endif %} /* declarations for formalisedEnglish.l */ %token IDENTIFIER NUMERAL STRING ANNOTATION NAMED %token BOB WITH AT HAS_FOR CAN_HAVE_FOR MAY_HAVE_FOR IS_A A SOME THE CERTAIN %token SEVERAL EVERY ALL AT_LEAST AT_MOST BETWEEN FROM TO MANY MOST MOSTLY %token AND OF NOT_EQUAL LTE IMPLIED_BY OTHER_OPERATOR %token GROUP_OF BAG_OF SET_OF SEQUENCE_OF ALTERNATIVE TOGETHER %token DOZENS HUNDREDS THOUSANDS MILLIONS BILLIONS %token GOOD BAD IMPORTANT SMALL BIG GREAT FEW %start FE %% FE : SENTENCE EOS {++D} FE {FEinCGs=IsIt+FEinCG[--D]+";\n\n"+FEinCGs; InCollec[D]=0; FE_LastToken="";} | error EOS {++D} FE {FEinCGs="";InCollec[--D]=0;FE_LastToken="";} | {FEinCGs="";InCollec[D]=0;FE_LastToken="";} ; SENTENCE : TREE {FEinCG[D]= Tree[D]; #ifndef _IN_WEBKB pr("mkFEinCG-:%s.\n",FEinCG[D].chars()); #endif } ; Q_SENTENCE : '`' {InCollec[D]=0;} TREE '\'' _CONTEXT {mkFEinCG(0);} | '~' '`' {InCollec[D]=0;} TREE '\'' _CONTEXT {mkFEinCG(1);} ; TREE : CONCEPT EOT {Tree[D]= Concept[D];} | CONCEPT BRANCH_1 _BRANCHES_N EOT {mkTree();} ; BRANCH_1 : IS_WITH RELATION1 {++D;} TREE {--D; mkBranch(0);} BRANCH_1 : _WITH RELATION2 {++D;} TREE {--D; mkBranch(0);} | IS_A {++D;} TREE {--D; mkBranch(1);} ; BRANCH_N : BOB {/*BOB:= "_,_" | "_and_"*/} | BOB _WITH RELATION {++D;}TREE {--D; mkBranch(0);} | BOB IS_A {++D;}TREE {--D; mkBranch(1);} ; _WITH : | IS_WITH; IS_WITH : WITH | AT | HAS_FOR | CAN_HAVE_FOR | MAY_HAVE_FOR ; _BRANCHES_N: | BRANCH_N _BRANCHES_N {pushS(Branches[D],popS(Branch[D]));} ; BRANCH_1C : _WITH RELATION {++D;} TREE {--D; mkBranch(0);} | IS_A {++D;} TREE {--D; mkBranch(1);} ; _CONTEXT : | '(' {++D;} BRANCH_1C _BRANCHES_N ')' {--D;} ; RELATION : RELATION1 | RELATION2 ; RELATION1 : REL_TYPE _OF _ANNOTATION _CONTEXT {mkRel(0);} | REL_TYPE _OF _ANNOTATION _CONTEXT IMPLIED_BY {mkRel(1);} | PLAIN_COREF _OF _ANNOTATION _CONTEXT {mkRelC(0);} | PLAIN_COREF _OF _ANNOTATION _CONTEXT IMPLIED_BY {mkRelC(1);} ; RELATION2 : LTE {mkRelOp("=<");} | IMPLIED_BY {mkRelOp("<=");} | OTHER_OPERATOR {mkRelOp(fetext);} ; REL_TYPE : TERM_OR_STR {RelType=Term;} ; PLAIN_COREF: '*'TERM_OR_NUM {Coref="*"+Term;} ; _ANNOTATION: {Annot[D]="";} | ANNOTATION {Annot[D]=fetext;} ; CONCEPT : CON_CORE _ANNOTATION {mkConcept();} ; CON_CORE : COREF_I QUANTIFIER RESTRICTOR _CQ {mkConCore(1);} | QUANTIFIER RESTRICTOR _COREF_I _CQ {mkConCore(1);} | GROUPOF _QUANTIFIER RESTRICTOR _COREF _COLL {mkConCore(2);} | GROUPOF _QUANTIFIER _COREF COLL {mkConCore(2);} | COREF_I _CQ {mkConCore(4);} | CQ {mkConCore(5);} | NEG_COREF {mkConCore(6);} | NUMBER EOT {mkConCore(7);} ; _CQ : {Cq[D]="";} | CQ; CQ : COLL {Cq[D]=Collec[D];ConType[D]="Thing";IsIndiv=1;} | Q_SENTENCE {Cq[D]=FEinCG[D];ConType[D]="Description";} ; NEG_COREF : '~''*'TERM_OR_NUM {CorefI[D]="~*"+Term;} ; _COREF_I : {CorefI[D]="";} | COREF_I ; COREF_I : TERM_OR_STR'\\'CON_TYPE {IsIndiv=1;CorefI[D]=Term;} | TERM_OR_STR {IsIndiv=1;CorefI[D]=Term;} | NAMED TERM_OR_STR {IsIndiv=1;CorefI[D]=Term;} | '*'TERM_OR_NUM {CorefI[D]="*"+Term; } | '*'TERM_OR_NUM NOT_EQUAL {N1=Term;}'*'TERM_OR_NUM {CorefI[D]="*"+N1+"!=*"+Term;} | '*'TERM_OR_NUM NOT_EQUAL {N1=Term;} TERM_OR_NUM {CorefI[D]="*"+N1+"!="+Term;} ; _COREF : {CorefI[D]="";} | '*'TERM_OR_NUM {CorefI[D]="*"+Term; } | '*'TERM_OR_NUM NOT_EQUAL {N1=Term;}'*'TERM_OR_NUM {CorefI[D]="*"+N1+"!=*"+Term;} | '*'TERM_OR_NUM NOT_EQUAL {N1=Term;} TERM_OR_NUM {CorefI[D]="*"+N1+"!="+Term;} ; RESTRICTOR : _QUALIFIER CON_TYPE {Restrictor[D]=ConType[D]+Qualifier;} | _QUALIFIER '[' CON_TYPE BRANCH_1 _BRANCHES_N ']' {Restrictor[D]=ConType[D]+Qualifier;} ; CON_TYPE : TERM_OR_STR {ConType[D]=Term;} ; _QUALIFIER : {Qualifier="";} | GOOD {Qualifier=" @good";} | BAD {Qualifier=" @bad";} | IMPORTANT {Qualifier=" @important";} | SMALL {Qualifier=" @small";} | BIG {Qualifier=" @big";} | GREAT {Qualifier=" @great";} | CERTAIN {Qualifier=" @certain";} ; _QUANTIFIER: {Quantif[D]="";} | QUANTIFIER; QUANTIFIER : EXIST_QUANT {Quantif[D]="";} | FEW _OF _THE {Qualifier=" @few";} | MANY _OF _THE {Qualifier=" @many";} | EVERY {Quantif[D]="any";} | ALL {Quantif[D]="any";} | MOST _OF _THE {Quantif[D]="most";} | AT_LEAST NUMBER _PERCENT _OF _THE {Quantif[D]="@>="+Num+Perc;} | AT_MOST NUMBER _PERCENT _OF _THE {Quantif[D]="@=<"+Num+Perc;} | BETWEEN NUMBER _PERCENT {N1=Num;} AND NUMBER _PERCENT _OF _THE {Quantif[D]="@"+N1+"|"+Num+Perc;} | NUMBER _PERCENT {N1=Num;} TO NUMBER _PERCENT _OF _THE {Quantif[D]="@"+N1+"|"+Num+Perc;} | FROM NUMBER _PERCENT {N1=Num;} TO NUMBER _PERCENT _OF _THE{Quantif[D]="@"+N1+"->"+Num+Perc;} | NUMBER _PERCENT _OF _THE {Quantif[D]="@"+Num+Perc;} | SEVERAL OF _THE {Quantif[D]="@severalOf";} | SEVERAL {Quantif[D]="@several";} | MOSTLY {Quantif[D]="@mostly";} | DOZENS _OF _THE {Quantif[D]="@dozens";} | HUNDREDS _OF _THE {Quantif[D]="@hundreds";} | THOUSANDS _OF _THE {Quantif[D]="@thousands";} | MILLIONS _OF _THE {Quantif[D]="@millions";} | BILLIONS _OF _THE {Quantif[D]="@billions";} ; EXIST_QUANT: A | SOME | THE ; GROUPOF : COREF_I EXIST_QUANT GROUP_TOKEN {GroupOf[D]=CorefI[D]+ " "+GroupOf[D];} | EXIST_QUANT GROUP_TOKEN | TOGETHER {GroupOf[D]="Coll"; Restrictor[D]="Set";} ; GROUP_TOKEN: GROUP_OF {GroupOf[D]="Coll";Restrictor[D]="Set";} | SET_OF {GroupOf[D]="Coll";Restrictor[D]="Set";} | BAG_OF {GroupOf[D]="Coll";Restrictor[D]="Bag";} | SEQUENCE_OF {GroupOf[D]="Coll";Restrictor[D]="Sequence";} | ALTERNATIVE {GroupOf[D]="Coll";Restrictor[D]="Alternatives";} ; _COLL : | COLL ; COLL : '{' {InCollec[++D]=1;} COLL_ELEMS '}' {InCollec[D--]=0;} _COLL_SIZE ; _COLL_SIZE : | '@' NUMBER {Quantif[D]="@"+Num;} ; COLL_ELEMS : ELEM {Collec[D-1]="{"+Elem[D]+"}";} | ELEM ',' {InCollec[++D]=1;} SET {--D;Collec[D-1]="{"+Elem[D]+","+Set+"}";} | ELEM '&' {InCollec[++D]=1;} BAG {--D;Collec[D-1]="{"+Elem[D]+"&"+Set+"}";} | ELEM '<' {InCollec[++D]=1;} ORDERED_SET {--D;Collec[D-1]="{"+Elem[D]+"<"+Set+"}";} | ELEM LTE {InCollec[++D]=1;} ORDERED_BAG {--D;Collec[D-1]="{"+Elem[D]+"=<"+Set+"}";} | ELEM '/' {InCollec[++D]=1;} XOR_SET {--D;Collec[D-1]="{"+Elem[D]+"/"+Set+"}";} | ELEM '|' {InCollec[++D]=1;} OR_BAG {--D;Collec[D-1]="{"+Elem[D]+"|"+Set+"}";} ; SET : ELEM {Set=Elem[D];} | ELEM ',' {InCollec[++D]=1;} SET {Set=Elem[--D]+","+Set;} ; BAG : ELEM {Set=Elem[D];} | ELEM '&' {InCollec[++D]=1;} BAG {Set=Elem[--D]+","+Set;} ; ORDERED_SET: ELEM {Set=Elem[D];} | ELEM '<' {InCollec[++D]=1;} ORDERED_SET {Set=Elem[--D]+"<"+Set;} ; ORDERED_BAG: ELEM {Set=Elem[D];} | ELEM LTE {InCollec[++D]=1;} ORDERED_BAG {Set=Elem[--D]+"=<"+Set;} ; XOR_SET : ELEM {Set=Elem[D];} | ELEM '/' {InCollec[++D]=1;} XOR_SET {Set=Elem[--D]+"/"+Set;} ; OR_BAG : ELEM {Set=Elem[D];} | ELEM '|' {InCollec[++D]=1;} OR_BAG {Set=Elem[--D]+"|"+Set;} ; ELEM : CONCEPT {Elem[D]=Concept[D];} | '[' TREE ']' {Elem[D]=Tree[D];} | '*' {Elem[D]="*";} ; TERM_OR_STR: IDENTIFIER {ConType[D]="Thing"; upInitial(fetext); delLastS(fetext); Term=FE_LastToken=fetext; /*pr("term:%s.\n",fetext);*/} | STRING {ConType[D]="String"; if (isIdentInString(fetext)) { fetext[strlen(fetext)-1]='\0'; Term=FE_LastToken=(fetext+1); } else Term=FE_LastToken=fetext; } ; TERM_OR_NUM: IDENTIFIER {ConType[D]="Thing"; Term=FE_LastToken=fetext;} | NUMERAL {ConType[D]="Thing"; Term=FE_LastToken=fetext;} ; NUMBER : NUMERAL {Num=FE_LastToken= fetext;} ; _OF : {Of=0;} | OF {Of=1;} ; _THE : | THE; _PERCENT : {Perc="";} | '%' {Perc="%";} ; EOT : '.' {unput('.');} | '?' {unput('?');} | ')' {unput(')');} | ']' {unput(']');} | '\'' {unput('\'');/*==yyless(0);*/} | ',' {unput('_');unput(',');unput('_');/*BOB*/} | AND {unput('_');unput('d');unput('n'); unput('a');unput('_');/*BOB*/} ; EOS : '.' {IsIt=""; } | '?' {IsIt="";/*"spec ";*/ } ; %% void mkFEinCG (int isNegated) { if (isNegated) Tree[D]= "~[Description: "+ Tree[D] + "]"; if (isEmptyS(Branches[D+1])) FEinCG[D]= Tree[D]; else { String br1= popS(Branches[D+1]); String brN, brNs; IndentS(D+1); //? D+2 for (brN= popS(Branches[D+1]); !brN.empty(); brN= popS(Branches[D+1])) { brNs+= BrIndent+" "+brN+";\n"; } if (brNs.empty()) FEinCG[D]= "[Description: "+Tree[D]+"]"+br1; else FEinCG[D]= "[Description: "+Tree[D]+"]-\n"+ BrIndent+"{ "+br1+";\n"+ brNs +BrIndent+"}"; } #ifndef _IN_WEBKB pr("mkFEinCG:%s.\n",FEinCG[D].chars()); #endif } void mkTree () /*int withBranches*/ { /*if (!withBranches) Tree[D]= Concept[D]+popS(Branch[D]); //? Concept[D]+popS(Branches[D]) else*/ if (InCollec[D] && IsIndiv) Concept[D]= "["+Concept[D]+"]"; String br1= popS(Branch[D]); if (br1.empty()) br1= popS(Branches[D]); String brN; String brNs; if (br1.empty()) return; IndentS(D+1); if (Relation[D]=="->(Type)->") /* below is an awful hack */ { if (ConType[D]=="Thing") Tree[D]="["+CorefI[D+1]+Concept[D].after("[Thing")+Tree[D+1].after("]"); else Tree[D]="NSC for "+ConType[D]+"(x) are ["+ConType[D+1]+":*x]"+ Tree[D+1].after("]"); #ifndef _IN_WEBKB pr("ConType[%d]:%s.\n",D+1,ConType[D+1].chars()); pr("Relation[%d]:%s.\n",D,Relation[D].chars()); pr("Tree[%d]:%s.\n",D,Tree[D].chars()); #endif return; } Tree[D]= Concept[D]; for (brN= popS(Branches[D]); !brN.empty(); brN= popS(Branches[D])) { brNs+= BrIndent+" "+brN+";\n"; } if (brNs.empty()) Tree[D]+= br1; else Tree[D]+="-\n"+ BrIndent+"{ "+br1+";\n"+ brNs +BrIndent+"}"; if (InCollec[D]) Tree[D]= "\""+Tree[D]+"\""; #ifndef _IN_WEBKB pr("mkTree(%d,%d):%s.\n",InCollec[D],IsIndiv,Tree[D].chars()); #endif } void mkBranch (int isAdef) { if (isAdef) { RelType="Type"; Relation[D]="->(Type)->"; } else if ((RelType=="Subtype") || (RelType=="Partition")) { Concept[D].gsub("[Thing","[Type"); Tree[D+1].gsub("[Thing","[Type"); } pushS(Branch[D],Relation[D]+Tree[D+1]); #ifndef _IN_WEBKB pr("mkBranch(%d):%s%s.\n",isAdef,Relation[D].chars(),Tree[D+1].chars()); #endif } void mkRel (int isImplication) /*isImplication ignored at present*/ { if (isUndeclTermEndingByING(RelType)) Relation[D]= "<-(Agent)<-["+RelType+"]->(Object)->"; else Relation[D]= (Of)? "<-("+RelType+")<-" : "->("+RelType+")->"; isImplication=0; /*pr("mkRel:%s\n",Relation[D].chars());*/ } void mkRelC (int isImplication) { Relation[D]= (Of)? "<-("+Coref+")<-" : "->("+Coref+")->"; isImplication=0; } void mkRelOp (char *oper) /* => <=> <= = != < =< > >= ? */ { switch (oper[0]) { case '!': Relation[D]= "->(Different_from)->"; break; case '=': switch (oper[1]) { case '>': Relation[D]= "->(Implication)->"; break; case '<': Relation[D]= "->(LTE)->"; break; case '\0': Relation[D]= "->(Equal)->"; break; } break; case '<': switch (oper[1]) { case '=': if (!oper[2]) Relation[D]= "<-(Implication)<-"; else Relation[D]= "->(Equivalence)->"; break; case '\0': Relation[D]= "->(LT)->"; break; } break; case '>': switch (oper[1]) { case '=': Relation[D]= "<-(LTE)<-"; break; case '\0': Relation[D]= "<-(LT)<-"; break; } break; case '?': Relation[D]= "->(Relation)->"; break; } } void mkConcept () { if (InCollec[D] && IsIndiv/*&&!withBranches*/) Concept[D]=ConCore[D]+Annot[D]; else { if (Annot[D].empty()) Concept[D]= "["+ConCore[D]+"]"; else Concept[D]= "["+ConCore[D]+" "+Annot[D]+"]"; } IsIndiv=0; if (WithTrace) pr("----> Concept[%d]:%s. \n",D,Concept[D].chars()); /* unput(' '); unput('@'); unput('@'); unput(' '); EOC (End of Concept)*/ } void mkConCore (int conCoreCase) { if (WithTrace) pr("conCoreCase:%d, %d:%d-%d, Restrictor:%s, Quantif:%s.%s, Cq:%s.\n", conCoreCase,D,InCollec[D],IsIndiv,Restrictor[D].chars(), Quantif[D].chars(),Qualifier.chars(),Cq[D].chars()); //first, move the Quantif[D]=="@..." into Collec[D] or Cq[D] //if Quantif.length() not tested before accessing Quantif[0], no more output if ((conCoreCase<=3) && Quantif[D].length() && (Quantif[D][0]=='@')) { if (conCoreCase==1) Cq[D]+=Quantif[D]; else Collec[D]+=Quantif[D]; Quantif[D]=""; } switch (conCoreCase) { case 1: if (CorefI[D].length()) CorefI[D]=" "+CorefI[D]; if (Cq[D].length()) Cq[D]=" "+Cq[D]; if (Quantif[D].length()) Quantif[D]=" "+Quantif[D]; ConCore[D]= Quantif[D]+CorefI[D]+Cq[D]; if (ConCore[D].length()) ConCore[D]=Restrictor[D]+":"+ConCore[D]; else ConCore[D]= Restrictor[D]; break; case 2: if (CorefI[D].length()) CorefI[D]=" "+CorefI[D]; ConCore[D]=Restrictor[D]+": "+GroupOf[D]+CorefI[D]+" "+Collec[D]; break; case 4: if (Cq[D].length()) Cq[D]=" "+Cq[D]; if (InCollec[D]) ConCore[D]= CorefI[D]+Cq[D]; else if (!CorefI[D].length()) ConCore[D]= ConType[D]+":"+Cq[D]; else ConCore[D]= ConType[D]+": "+CorefI[D]+Cq[D]; break; case 5: if (InCollec[D]/*||(ConType[D]=="Description")*/) ConCore[D]=Cq[D]; else ConCore[D]=ConType[D]+": "+Cq[D]; break; case 6: ConCore[D]= CorefI[D]; break; case 7: ConCore[D]= "Number: "+Num; break; } } int isIdentInString (char *s) { char c= *(s+1); if (!(isalpha(c)||(c=='#'))) return 0; for ( ; *s; s++) { if (isspace(*s)||(*s=='*')) return 0; } return 1; } static int strEq (char *a, char *b) { for(;*a && *b; a++,b++) { if (*a != *b) return 0; } if (*a || *b) return 0; return 1; } int isFormalisedEnglish (char *arg0, char *arg1) { int c; if (isupper(arg0[0])) { if (arg1[0]=='(') return 0; //relation declaration switch ((c= arg1[0])) //is/has/the { case 'i': if ((arg1[1]=='s') && !arg1[2]) return 1; break; case 'h': if (strEq(arg1+1,"as")) return 1; break; case 't': if (strEq(arg1+1,"he")) return 1; } } else if (isdigit(arg0[0])) return 1; switch ((c= tolower(arg0[0]))) { case 'a': switch ((c= arg0[1])) { case '\0': return 1; /*a*/ case 'n': c=arg0[2]; if (!c) return 1; /*an*/ if ((c=='y') && !arg0[3]) return 1; /*any*/ break; case 'r': if (strEq(arg0+1,"re")) return 1; /*are*/ case 't': if (!arg0[2]) return 1; /*at*/ }break; case 'b': if (strEq(arg0+1,"etween")||strEq(arg0+1,"illions")) return 1; break; case 'd': if (arg0[1]=='o') /*do/does/dozen*/ if (!arg0[2]||strEq(arg0+2,"es")||strEq(arg0+2,"zen")) return 1; break; case 'e': if (strEq(arg0+1,"very")) return 1; /*every*/ break; case 'f': if (strEq(arg0+1,"ew")||strEq(arg0+1,"rom")) return 1;/*few/from*/ break; case 'h': if (strEq(arg0+1,"undreds")) return 1; /*hundreds*/ break; case 'i': c=arg0[1]; if ((c=='s') && !arg0[2]) return 1; /*is (there ...)*/ break; case 'm': switch ((c= arg0[1])) /*many/most(ly)/millions*/ { case 'a': if (strEq(arg0+2,"ny"))return 1; case 'o': if (strEq(arg0+2,"st")||strEq(arg0+2,"stly"))return 1; case 'i': if (strEq(arg0+2,"illions")) return 1; }break; case 's': if (strEq(arg0+1,"ome")||strEq(arg0+1,"everal")) return 1; break; case 't': if (strEq(arg0+1,"he")||strEq(arg0+1,"ogether")) return 1; break; case '*': return 1; /*reference*/ case '`': return 1; /*quoted sentence*/ case '{': return 1; /*set*/ } return 0; } int fewrap() { return 1; } int feerror(const char *s) { int l=strlen(ParsingError); ParsingError[l]='\n'; if (FE_LastToken.empty()) sprintf(ParsingError+l+1,"at \"%s\": %s.\n",fetext,s); else sprintf(ParsingError+l+1,"after \"%s\", at \"%s\": %s.\n", FE_LastToken.chars(),fetext,s); #ifndef _IN_WEBKB printf(ParsingError); #endif return 1; } char *formalisedEnglishToCGs (char *fe) { int i; if (!fe) return NULL; if (WithTrace) printf("fe:%s.\n",fe); yy_scan_string(fe); for (i=0;iobject=""; newList->next=NULL;} return newList; } void delS (StringList *me) { StringList *current; if (!me) return; while ((current=me)) { me= me->next; delete current; } } void pushS (StringList *me, String str) { StringList *newNode= new StringList; if (newNode) {newNode->object=str; newNode->next=me->next; me->next=newNode;} else feerror("Cannot store a new string"); } String popS (StringList *me) { if (me && me->next) { StringList *lastNode=me->next; String lastObject=lastNode->object; me->next=lastNode->next; delete lastNode; return lastObject; } else return String(""); /* Empty list */ } int isEmptyS (StringList *me) { if (!me) return 1; return (me->next == NULL); } void upInitial (/*varP*/char *str) { str[0]=toupper(str[0]); } void delLastS (/*varP*/char *str) { int l=strlen(str); if (l<3) return; if ((str[l-1]=='s') && (str[l-2]!='s') && (str[l-2]!='i')) str[l-1]='\0'; } #ifndef _IN_WEBKB int main() { char line[200]; printf("> "); if (WithTrace) yydebug=1; while (fgets(line,200,stdin)) { puts(formalisedEnglishToCGs(line)); printf("> "); } puts("\n"); } #endif