%{/*************************** fs.y ******************************** Parser of commands to assert/delete knowledge in FastDB Created on the 29-Feb-2000 by philippe.martin@gu.edu.au In this Web-accessible version, all the functions have been removed except the basic ones directly related to the use of bison and flex. The parsing of control structures has also been removed. ******************************************************************/ #include "wdblib.h" #include "libFile.h" #include "dynStr.h" #include "value.h" #include #include #include //#include "String.h" #define MAX_DEPTH 20 static bool RunStack[MAX_DEPTH]; static int D=0; static bool Run; static Value V,V1; static int NbVarValues; bool LastCommandOutputIsPiped; static bool IsPipableCommand; dbArray ResultFiles; static char *addtoResultFiles (const char *str); static int MinOrigCard=0, MaxOrigCard=0, MinDestCard=0, MaxDestCard=0; static dbrTerm TheSigType; #include "lex.fs.c" #define scp strcpy #define YYERROR_VERBOSE 1 //char ParsingError[500]; //extern char ParsingError[]; int fserror(const char *); /*pm: for input files*/int fsFirst=1; void fsInit (FILE*); int fswrap(); static dbCursor TheTermCu(dbCursorForUpdate); static dbrTerm RefTerm, RefDestTerm, RefCommunity; static Partition ThePartition; static dbrUser LinkCreator; static char LinkKind, LinkKind1; //String Num,N1; //static String BrIndent; //static int Of=0, IsIndiv=0; static char GTerm[2500], Annot[5000], /*Community[100],*/ UserId[50], ModDestId[500]; static char *RelationDomain=TmpBuff, *RelationRange=TmpBuff2; //static char RelationDomain[1000],RelationRange[1000], //static bool IsRelationTypeDecl/*, AloneCT*/; static dynStr DefStr; static char *UserPasswd=""; #if 0 Extended BNF grammar for the FS notation ("?" means 0 or 1 times, "*" means 0 to N times, "+" means 1 to N times): Commands := (Command)+ Command := Assertion ";"? | Query ";" | "delGraph" Identifier ";" | TermCommand ";" | CtrlCommand ";" | CtrlStructure Assertion := Sentence Query := "?" Sentence | "spec" Sentence Sentence := TermDef | CG CG := FCG | FE | CGLF | CGIF | KIF TermDecl := Term RelSignature? Annotation? Date? (LinksOf1Kind ("," LinksOf1Kind)*)? Annotation := "(^" ... "^)" RelSignature := "(" (Term Cardinality1? ("," Term Cardinality1?)*)? ("->" Term Cardinality1?)? ")" | "(" "->" ")" Cardinality1 := "[" (Number "..")?NumOrStar "]" TermCommand := TermDecl | "?" Term ("("UserID")")? | "? userID" UserId | "e-mail" (UserId | LinkKind Term) CtrlCommand := "trace" | "no trace" | "no storage" | "storage" | "use names" | "no names" | | "unprefixed variables" | "prefixed variables" | | "default creators:" UserId* | "print" (Term|String|Number)* | "load" FileId | "run" FileId | "include" FileId | "run mode" | "load mode" LinksOf1Kind := LinkKind (DestTerm | TermPartition)+ LinkKind := ">"|"<"|"^"|":"|"="|"~"|"!"|"/"|"-"|"_"| AlphaNumChar TermPartition:= ClosedPartition | OpenPartition ClosedPartition:= "{(" DestTerm+ ")}" OpenPartition := "{" DestTerm+ "}" DestTerm := Term Cardinality2? LinkContext? LinkContext := "(" Creator Community? Date? ")" Cardinality2 := "[" (Number "..")?NumOrStar ',' (Number "..")?NumOrStar "]" NumOrStar := Number | '*' UserId := Identifier FileId := Identifier Term := Identifier String := "\"" ..."\"" | "'" ..."'" | "$(" ... ")$" Identifier := TermLetter1 TermLetter* TermLetter1 := [a-z0-9_] | "#"[a-z0-9_] TermLetter := [a-z0-9_] | "#" | "-" | "/" | "?" | "&" | "@" | "~" | "'" |"." | "://" //thus a URL may be a Term Number := ("+"|"-")? Digit+ ("." Digit* )? Digit := [0-9] Date := [0-9][0-9]"/"[0-9][0-9]"/"[0-9][0-9][0-9][0-9] AlphaNumChar := [a-zA-Z0-9] //Additional notes on the lexical parsing: - 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 single quoted, double quoted or enclosed within "$(" and ")$" Differences with C: untyped, =<, operator precedence?, '+' for string/char, no structure/object, := instead of =, = same as == '%' ... IDENT so spaces needed before some operators #endif %} %token IDENTIFIER NUMBER DATE CREATION_DATE STRING ANNOTATION CG %token SPEC "spec" MOD "mod" DEL "del" DEL_GRAPH "delGraph" PRINT "print" %token DEFAULT_CREATORS "default creator:" USER "user" %token USER_ID "userId" EMAIL "e-mail" NO_RELOAD "no reload;" %token IF "if" ELSE "else" WHILE "while" CSPB "{(" CSPE ")}" TO "->" %nonassoc VAR__SET_TO %left EQV "<=>" IMP "=>" IMPB "<=" %left OR "or" %left AND "and" %left '<' '>' '=' LTE "=<" GTE ">=" NEQ "!=" %left '+' '-' %left '*' '/' '%' %left '!' %left UMINUS %expect 1 %start COMMANDS %% COMMANDS : COMMAND | COMMANDS COMMAND ; COMM_BLOCK : COMMAND | '{' COMMANDS '}' ; COMMAND : CTRL_COMM ';' | CTRL_STRUCT | TERM_QUERY ';' {if (Run) IsPipableCommand=true;} | TERM_COMM ';' {if (Run) TheKBhasBeenModified=true;} | CG_QUERY ';' {if (Run) IsPipableCommand=true;} | CG {if (Run) {if (!parseCG()) YYERROR;} } _END_CG | DEL_GRAPH IDENTIFIER {if (Run) {if (!delGraph(fstext)) YYERROR; else TheKBhasBeenModified=true;}} ';' | NO_RELOAD {/*end parsing of current buffer*/} ';' ; _END_CG : | ';' ; CG_QUERY : '?' CG {if (Run && !prMatchingCGs('?')) YYERROR;} | "spec" CG {if (Run && !prMatchingCGs('s')) YYERROR;} ; TERM_QUERY : '?' _LK TERM_ID {if (Run) whatIsGterm("");} | '?' _LK STRING {if (Run) {scpPlusQuotesIfNecessary(GTerm,fstext); whatIsGterm("");}} | '?' _LK TERM_ID '(' UID_STR ')' {if (Run) whatIsGterm(UserId);} ; TERM_COMM : DEL TERM_ID {if (Run&& !delLinksFromGTerm())YYERROR;} | DEL TERM_ID LINK_KIND IDENTIFIER {if (Run&& !delLinkFromGTermTo(fstext)) YYERROR;} | MOD '(' TERM_ID {if (Run) strcpy(RelationDomain,GTerm);} LINK_KIND {if (Run) LinkKind1=LinkKind;} IDENTIFIER {if (Run) strcpy(RelationRange,fstext);} ')' '(' TERM_ID LINK_KIND IDENTIFIER {if (Run) ModDestId=fstext;} ')' {if (Run && !modLink()) YYERROR;} | TERM _ANNOT _CDATE _LINKS {if (Run) updateTheTermCu();} ; TERM : TERM_ID {if (Run && !getAndUpdateOrCreateTermCu(GTerm,'u', /*initP*/TheTermCu)) YYERROR;} | TERM_ID '(' {if (Run && !getAndUpdateOrCreateTermCu(GTerm,'r', /*initP*/TheTermCu)) YYERROR; TheTermCu->sigTypes.clear(); TheTermCu->sigTemplates.clear();} SIGNATURE {if (!TheTermCu->hasConformSignature()) YYERROR;} ; _ANNOT : | ANNOTATION {if (Run){Annot=fstext; TheTermCu->annotation=Annot.data;}} ; SIGNATURE : _PARAMS ')' {if (Run && !addAndCheckSig('r')) YYERROR;} | "->" R_PARAM _CARDIN1 ')' {if (Run) TheTermCu->kind='f';} | PARAMS "->" R_PARAM _CARDIN1 ')' {if (Run && !addAndCheckSig('f')) YYERROR;} ; _PARAMS : | PARAMS; PARAMS : PARAM _CARDIN1 | PARAM _CARDIN1 ',' PARAMS; PARAM : '*' {if(Run){TheTermCu->sigTypes.append(null); TheTermCu->sigTemplates.append('*');}} | RPARAM_CORE '*' {if(Run)TheTermCu->sigTemplates.append('*');} | RPARAM_CORE '+' {if(Run)TheTermCu->sigTemplates.append('+');} | '{' RPARAM_CORE '}' '*' {if(Run)TheTermCu->sigTemplates.append('s');} | '{' RPARAM_CORE '}' '+' {if(Run)TheTermCu->sigTemplates.append('S');} | R_PARAM; R_PARAM : RPARAM_CORE {if(Run)TheTermCu->sigTemplates.append('?');} | '{' RPARAM_CORE '}' {if(Run)TheTermCu->sigTemplates.append('e');} ; RPARAM_CORE: IDENTIFIER {if (Run && !addToSigTypes()) YYERROR;} | '?' {if (Run) TheTermCu->sigTypes.append(null);} ; _CARDIN1 : |'[' ORIG_CARD _MAX_O_CARD ']' {if (Run&&(MinOrigCard||MaxOrigCard)) addRelCard();} ; _CDATE : | CREATION_DATE {if(Run && !storeDate(fstext+1, TheTermCu->creationDate))YYERROR;} ; _LINKS : | LINKS; LINKS : LINKS1_S | LINKS1_S ',' LINKS ; LINKS1_S : LINK_KIND LINK_DESTS {if (Run && UserDeclarationInProgress) UserDeclarationInProgress=false;} ; LINK_DESTS : LINK_DEST | LINK_DESTS LINK_DEST /*LINK_DEST LINK_DESTS causes stack overflow*/ ; LINK_DEST : DEST_TERM | '{' {WithinSubtypePartitionDeclaration=true;} DEST_TERMS '}'_LINK_CTXT {if (Run&&!addSubtypeExcl('!'))YYERROR; WithinSubtypePartitionDeclaration=false;} | "{(" {WithinSubtypePartitionDeclaration=true;} DEST_TERMS")}"_LINK_CTXT {if(Run&&!addSubtypeExcl('/'))YYERROR; WithinSubtypePartitionDeclaration=false;} ; DEST_TERMS : DEST_TERM {if (Run) ThePartition.terms.append(RefDestTerm);} _DEST_TERMS; _DEST_TERMS: | DEST_TERMS; DEST_TERM : DEST_ID _CARDIN2 _LINK_CTXT {if (Run) addLinkToTheTermCu();} ; DEST_ID : IDENTIFIER {if (Run) GTerm=fstext;} ; _CARDIN2 : | '[' ORIG_CARD _MAX_O_CARD ',' DEST_CARD _MAX_D_CARD ']' ; ORIG_CARD : NUMBER {if (Run) {sscanf(fstext,"%d",&MinOrigCard); MaxOrigCard= MinOrigCard;} } | '*' {/*if (Run) MaxOrigCard= 0;*/} ; _MAX_O_CARD: | '.' '.' NUMBER {if (Run) sscanf(fstext,"%d",&MaxOrigCard);} | '.' '.' '*' {if (Run) MaxOrigCard= 0;} ; DEST_CARD : NUMBER {if (Run) {sscanf(fstext,"%d",&MinDestCard); MaxDestCard= MinDestCard;} } | '*' {/*if (Run) MaxDestCard= 0;*/} ; _MAX_D_CARD: | '.' '.' NUMBER {if (Run) sscanf(fstext,"%d",&MaxDestCard);} | '.' '.' '*' {if (Run) MaxDestCard= 0;} ; _LINK_CTXT : {if (Run) {LinkCreator=GdbrCurrentUser; RefCommunity=null;}} | '(' CREATOR _COMMUNITY ')' ; CREATOR : IDENTIFIER {if (Run && !mkLinkCreator()) YYERROR;} ; _COMMUNITY : {if (Run) RefCommunity=null;} | IDENTIFIER {if (Run && !mkCommunity()) YYERROR;} ; LINK_KIND : '>' {LinkKind='>';} | '<' {LinkKind='<';} | '=' {LinkKind='=';} | '~' {LinkKind='~';} | '-' {LinkKind='-';} | '!' {LinkKind='!';} | '/' {LinkKind='/';} | ':' {LinkKind=':'; if (Run && Term_UserOfThisKB_detected) { UserDeclarationInProgress=true; tr("Term_UserOfThisKB_detected\n");} } | '^' {LinkKind='^';} | '_' {LinkKind='_';} | IDENTIFIER {if (!fstext[1]) LinkKind=fstext[0]; else { LinkKind='\0'; putsErr("'%s': a link name should" " be 1 character long",fstext); YYERROR; } } ; _LK : {LinkKind='\0';} | '-' LINK_KIND ; TERM_ID : IDENTIFIER {if (Run) GTerm=fstext;} ; UID_STR : IDENTIFIER {if (fsleng>40){putsErr("UserId too long");YYERROR;} else scp(UserId,fstext);} | '*' {scp(UserId,fstext);} ; _URI : IDENTIFIER {scp(TmpBuff,fstext);/*cannot use a dynStr here*/ /*I should use scpBuff() instead*/} | {TmpBuff[0]='\0';} ; _PASSWD : {UserPasswd="";} | STRING {UserPasswd=fstext;} ; %% int fserror (const char *s) { s= moreReadableParserMessage(s,/*initP*/TmpBuff); if (GTerm[0] && !strEqual(GTerm.data,fstext)) putsErr("After \"%s\", at \"%s\": %s",GTerm.data,fstext,s); else if (!fstext[0]) if (strEqual(s,"parse error")) putsWarning("Parse error or no assertion/query has been made"); else putsErr(s); else putsErr("At \"%s\": %s",fstext,s); return 1; } void fsInit (FILE* fp) { errno=0; LineNumber=1; Run=fsCurrentBufferIsFile=true; GetComm=(RunMode==1); LastCommandOutputIsPiped=IsPipableCommand=false; NbVarValues= VariableArray.length(); ReloadingThisFile=false; if (fsFirst) fsFirst=0; else fsrestart(fp); } void fsParseStr (char *commands) { if (!commands) return; errno=0; LineNumber=1; Run=true; if (WithTrace==10) fsdebug=1; GetComm= (RunMode==1); NbVarValues= VariableArray.length(); LastCommandOutputIsPiped=IsPipableCommand=false; yy_scan_string(commands); errno=0; fsCurrentBufferIsFile=false; if ((fsparse()!=0) || ErrorDetected || NoStorage) { TheKB->rollback(); if (TheKBhasBeenModified) { fpr(ErrorFp,"\n//The knowledge base has not been modified"); if ((NoStorage==2) && !ErrorDetected) fpr(ErrorFp," (query done by the anonymous user \"u\")\n"); else fpr(ErrorFp,"\n"); } } } void fsParseFile (char *fileName) { if (!(fsin= fopen(fileName,"r"))) { putsErr("The file '%s' does not exist",fileName); return; } fsInit(fsin); if (WithTrace==10) fsdebug=1; //fsdebug=1; if ((fsparse()!=0) || ErrorDetected || NoStorage) //if (AmbiguityAcceptation<=1) { rollbackTheKB(); if (TheKBhasBeenModified) { TheKBhasBeenModified=false; fpr(ErrorFp,"\n//The knowledge base has not been modified"); if ((NoStorage==2) && !ErrorDetected) fpr(ErrorFp," (query done by the anonymous user \"u\")\n"); else fpr(ErrorFp,"\n"); } } if (fsin) fclose(fsin); //fsin tested because in run mode a string buffer //is executed and parsing errors destroy the original fsin }