%{ /**************************** fcg.y ******************************* This bison/yacc program parses the Frame-CG (FCG) linear format (see http://meganesia.int.gu.edu.au/~phmartin/WebKB/doc/grammars/) Created on the 12-Oct-2000 by philippe.martin@gu.edu.au *******************************************************************/ #include "wdblib.h" #include #include #include #include "dynStr.h" #define YYERROR_VERBOSE 1 #include "lex.fcg.c" #define MAX_NODES 100 static int NodeNum=0; static NodeWP* NodePtrs[MAX_NODES+1]; static NodeWP *ElemWP, *TheNodeWP=NULL; static RelationWP *TheRelWP=NULL; static dbCursor RelTypeC; int fcgerror(const char *); /*for input files:*/int fcgfirst=1; void fcgInit(FILE*); int fcgwrap(); //In this Web-accessible version, the following functions have been removed static void mkFirstNodeWP(); //beginning of NODE and FCG static bool mkRelWP(char *relId); //beginning of RELATION static bool mkRelNWP(const char *relId, bool isOutRel, char kind); static void mkNodeWP(); //beginning of NODE(called after mkRelWP()) static bool mkNodeType(); static bool mkFunctionCall(); static bool setFctId(); static bool mkIndividual(), mkIndividualString(); static bool mkCollNum(), mkNumber(char interv), mkToNumber(); static bool mkPTime(char interv),mkToPTime(),mkPeriod(char interv),mkToPeriod(); static void removePluralMark(char *name); static bool mkDefNodeWP(); static bool endDefNodeWP(bool isFct); static bool checkOrUpdateSignature(); static bool addParamVar(); %} FCG : '[' {mkFirstNodeWP(); } NODE _BRANCHES ']' _CONTEXT {} | '!' '[' {mkFirstNodeWP(); } NODE _BRANCHES ']' _CONTEXT {TheNodeWP->isNegated=true;} | '~' '[' {mkFirstNodeWP(); } NODE _BRANCHES ']' _CONTEXT {TheNodeWP->isNegated=true;} | '[' "if" FCG "then" FCG _ELSE_FCG ']' ; _ELSE_FCG : | "else" FCG ; _CONTEXT : | '(' CREATOR _C_DATE _REPR_STR ')' | '(' C_DATE _REPR_STR ')' ; CREATOR : IDENTIFIER {GdbrCreator= getUserWith(fcgtext); if (GdbrCreator==null) { putsErr("Unknown user: %s",fcgtext); YYERROR; } else TheNodeWP->creator= GdbrCreator; } ; _C_DATE : | C_DATE; C_DATE : POINT_IN_TIME {if (!storeDate(fcgtext,TheNodeWP->creationDate)) YYERROR;} ; _REPR_STR : | CODE_STRING {//CG_source=fcgtext; now initialized in fcg.l if (CG_source.data) GNodeWP->text=CG_source.data;} ; _BRANCHES : | BRANCHES; BRANCHES : ',' BRANCH _BRANCHES | '=' {if (!mkRelNWP("pm#equal",true,'=')) YYERROR;} NODE {TheNodeWP= NodePtrs[--NodeNum-1];} _BRANCHES | "!=" {if (!mkRelNWP("pm#different",true,'!')) YYERROR;} NODE {TheNodeWP= NodePtrs[--NodeNum-1];} _BRANCHES | "=<" {if (!mkRelNWP("pm#inferior_or_equal_to",true,'l')) YYERROR;} NODE {TheNodeWP= NodePtrs[--NodeNum-1];} _BRANCHES | '<' {if (!mkRelNWP("pm#inferior_to",true,'<')) YYERROR;} NODE {TheNodeWP= NodePtrs[--NodeNum-1];} _BRANCHES | ">=" {if (!mkRelNWP("pm#inferior_or_equal_to",false,'g')) YYERROR;} NODE {TheNodeWP= NodePtrs[--NodeNum-1];} _BRANCHES | '>' {if (!mkRelNWP("pm#inferior_to",false,'>')) YYERROR;} NODE {TheNodeWP= NodePtrs[--NodeNum-1];} _BRANCHES | "=>" {if (!mkRelNWP("pm#implication",true,'i')) YYERROR;} NODE {TheNodeWP= NodePtrs[--NodeNum-1];} _BRANCHES | "<=" {if (!mkRelNWP("pm#implication",false,'I')) YYERROR;} NODE {TheNodeWP= NodePtrs[--NodeNum-1];} _BRANCHES | "<=>"{if (!mkRelNWP("pm#equivalence",true,'~')) YYERROR;} NODE {TheNodeWP= NodePtrs[--NodeNum-1];} _BRANCHES ; BRANCH : PATH_SPECIF RELATION NODE {TheNodeWP= NodePtrs[--NodeNum-1];} | RELATION NODE {TheNodeWP= NodePtrs[--NodeNum-1];} ; PATH_SPECIF: PATH_ELEM | PATH_ELEM '|' PATH_SPECIF ; PATH_ELEM : PATH_EXPR | PATH_EXPR PATH_ELEM ; PATH_EXPR : '(' RELATION NODE ')' COUNT | '(' RELATION ')' COUNT | '(' PATH_SPECIF ')' COUNT ; COUNT : '?' | '*' | '+' | NUMBER '+' | NUMBER ; RELATION : CAN R_TYPE _R_OF _R_ANNOT _R_CONTEXT ':' {TheRelWP->kind='c';} | MAY R_TYPE _R_OF _R_ANNOT _R_CONTEXT ':' {TheRelWP->kind='m';} | R_TYPE _R_OF _R_ANNOT _R_CONTEXT IMPLIED_BY {TheRelWP->kind='m';} | R_TYPE _R_OF _R_ANNOT _R_CONTEXT ':' | '?' ':' {if (!mkRelNWP("pm#relation",true,'?')) YYERROR;} ; R_TYPE : IDENTIFIER {if (!mkRelWP(fcgtext)) YYERROR;} | '*'IDENTIFIER {if (!mkRelWP("")) YYERROR;} | '*'NUMBER {if (!mkRelWP("")) YYERROR;} ; _R_OF : {TheNodeWP->relationPtrs.append(TheRelWP); mkNodeWP();TheRelWP->destinationPtr=TheNodeWP;} | "of" {TheRelWP->isOutRel=false; TheNodeWP->relationPtrs.append(TheRelWP); mkNodeWP();TheRelWP->destinationPtr=TheNodeWP;} ; _R_ANNOT : | ANNOTATION {if (fcgtext[0]) TheRelWP->annotation=strdup(fcgtext);} ; _R_CONTEXT : | '(' {/*TheContextualisedObject=TheRelWP;*/} BRANCH _BRANCHES ')' ; NODE : NODE_EXPR _NODE_ANNOT | '(' NODE_EXPR _NODE_ANNOT BRANCHES ')' | TERM_DEF ; _NODE_ANNOT: | ANNOTATION {if (fcgtext[0]) TheNodeWP->annotation=strdup(fcgtext);} ; NODE_EXPR : '(' NODE_EXPR ')' | '-' NODE_EXPR %prec UMINUS | NODE_EXPR '-' NODE_EXPR | NODE_EXPR '+' NODE_EXPR | NODE_EXPR '*' NODE_EXPR | NODE_EXPR '/' NODE_EXPR | NODE_EXPR MOD NODE_EXPR | NODE_CORE { /* IDENTIFIER '(' NODE_CORE ')' */ } ; NODE_CORE : VARorIndiv QUANTIFIER RESTRICTORS _FCQ | VARorIndiv _FCQ | QUANTIFIER RESTRICTORS _FCQ | GROUPOF _QUANTIFIER _RESTRICTORS _COLL _QUERIED //RESTRICTORS and/or COLL | NUMBERS | TIMES | PERIODS | FCQ ; _RESTRICTORS: | RESTRICTORS ; RESTRICTORS: _ORDER _QUALIFIER VARorCATGS ; _ORDER : | ELEM_ORDER {if (!mkCollNum()) YYERROR;} | ELEM_ORDER_OCCURENCE_OF {if (!mkCollNum()) YYERROR;} ; _QUERIED : | '?'; _FCQ : | FCQ; FCQ : FCG _QUERIED {TheNodeWP= NodePtrs[--NodeNum-1];} | COLL _QUERIED | '?' ; _VARIABLE : | VARIABLE { TheNodeWP->corefVar= strdup(fcgtext); }; _VARorIndiv: | VARorIndiv; VARorIndiv : VARIABLE { TheNodeWP->corefVar= strdup(fcgtext); } _TYPE_CONST | INDIVorFCT _TERM_GUESS _TYPE_CONST | STRING {if (!mkIndividualString()) YYERROR;} ; INDIVorFCT : IDENTIFIER {IdStr=fcgtext;} _FCT_PARAMS; _FCT_PARAMS: {if (!mkIndividual()) YYERROR;} | '(' {if (!mkFunctionCall()) YYERROR;} _FCT_PRMS ')' {WithinListOf=false; if (!setFctId()) YYERROR;} ; _FCT_PRMS : | FCT_PARAMS; FCT_PARAMS : FCT_PARAM | FCT_PARAM ',' FCT_PARAMS; FCT_PARAM : NODE_CORE {ElemWP=TheNodeWP; TheNodeWP=NodePtrs[--NodeNum-1]; TheNodeWP->paramPtrs.append(ElemWP);} ; VARorCATGS : VARorCATEG | VARorCATGS VARorCATEG ; VARorCATEG : VARIABLE {if (!mkCorefVar()) YYERROR;/*to do: check uniq + order*/} | STRING {if (!mkIndividualString()) YYERROR;/*to do: check uniq*/} | NODE_CATEG | '(' {mkFirstNodeWP();/*TheNodeWP->quantifier=0;*/} NODE_TYPES ORorBRANCHS ')' {TheNodeWP= NodePtrs[--NodeNum-1];} ; ORorBRANCHS: '|' NODE_TYPES | BRANCHES ; NODE_TYPES : NODE_TYPE | '(' {mkFirstNodeWP();} NODE_TYPES ORorBRANCHS ')' {TheNodeWP= NodePtrs[--NodeNum-1];} | NODE_TYPES NODE_TYPE ; NODE_TYPE : '!' IDENTIFIER {if (!mkNodeType()) YYERROR;} | IDENTIFIER {if (!mkNodeType()) YYERROR;} ; NODE_CATEG : '!' IDENTIFIER {if (!mkNodeType()) YYERROR;} | IDENTIFIER {...} ; _TERM_GUESS: | TERM_GUESS_MARK IDENTIFIER {if (!getTermRef(fcgtext,'u',initP TheNodeWP->term)) YYERROR;} ; _TYPE_CONST: | TYPE_CONSTR_MARK IDENTIFIER {if (!TheNodeWP-> addTypeConstraint(fcgtext)) YYERROR;} ; _QUALIFIER : | "good" {TheNodeWP->qualifier='g';} | "bad" {TheNodeWP->qualifier='b';} | "important" {TheNodeWP->qualifier='i';} | "small" {TheNodeWP->qualifier='s';} | "big" {TheNodeWP->qualifier='B';} | "great" {TheNodeWP->qualifier='G';} | "certain" {TheNodeWP->qualifier='c';} ; _QUANTIFIER: {/*TheNodeWP->quantifier=0;*/} | QUANTIFIER; QUANTIFIER : EXIST_QUANT | UNIV_QUANT | NUM_QUANT _OF _THE ; EXIST_QUANT: "a" | "some" | "the" ; UNIV_QUANT : "few" {TheNodeWP->quantifier='u'; TheNodeWP->number= Q_FEW;} | "no" {TheNodeWP->quantifier='u'; TheNodeWP->number= Q_NONE;} | "any" {TheNodeWP->quantifier='u'; TheNodeWP->number= Q_ALL;} | "most" {TheNodeWP->quantifier='u'; TheNodeWP->number= Q_MOST;} | NUM1 _PERCENT {if (TheNodeWP->number==0) {TheNodeWP->quantifier='u'; TheNodeWP->number=Q_NONE;} else /*quantif=='e'/'p'*/ TheNodeWP->interval=0; } ; NUM_QUANT : "about" NUM1 _PERCENT {TheNodeWP->interval= 'a';} | "at least" NUM1 _PERCENT {TheNodeWP->interval= 'l';} | "at most" NUM1 _PERCENT {TheNodeWP->interval= 'm';} | "between" NUM1 _PERCENT "and" NUM2 _PERCENT {TheNodeWP->interval= 'b';} | NUM1 _PERCENT "to" NUM2 _PERCENT {TheNodeWP->interval= '_';} | "a few" {TheNodeWP->number= -1;} | "many" {TheNodeWP->number= -3;} | "several" {TheNodeWP->number= -3;} | "mostly" {TheNodeWP->number= -9;} | "tens" {TheNodeWP->number= -10;} | "dozens" {TheNodeWP->number= -12;} | "hundreds" {TheNodeWP->number= -20;} | "thousands" {TheNodeWP->number= -30;} | "millions" {TheNodeWP->number= -60;} | "billions" {TheNodeWP->number= -90;} ; NUMBERS : "about" NUMBER {if (!mkNumber('a')) YYERROR;} | "at least" NUMBER {if (!mkNumber('l')) YYERROR;} | "at most" NUMBER {if (!mkNumber('m')) YYERROR;} | "between" NUMBER {if (!mkNumber('b')) YYERROR;} AND_NUM NUMBER {if (!mkToNumber()) YYERROR;} | NUMBER TO_NUM {if (!mkNumber('_')) YYERROR;} NUMBER {if (!mkToNumber()) YYERROR;} | NUMBER {if (!mkNumber('\0')) YYERROR;} ; TIMES : "about" POINT_IN_TIME {if (!mkPTime('a')) YYERROR;} | "at least" POINT_IN_TIME {if (!mkPTime('l')) YYERROR;} | "at most" POINT_IN_TIME {if (!mkPTime('m')) YYERROR;} | "between" POINT_IN_TIME {if (!mkPTime('b')) YYERROR;} "and" POINT_IN_TIME {if (!mkToPTime()) YYERROR;} | POINT_IN_TIME "to" {if (!mkPTime('_')) YYERROR;} POINT_IN_TIME {if (!mkToPTime()) YYERROR;} | POINT_IN_TIME {if (!mkPTime('\0')) YYERROR;} ; PERIODS : "about" PERIOD {if (!mkPeriod('a')) YYERROR;} | "at least" PERIOD {if (!mkPeriod('l')) YYERROR;} | "at most" PERIOD {if (!mkPeriod('m')) YYERROR;} | "between" PERIOD {if (!mkPeriod('b')) YYERROR;} "and" PERIOD {if (!mkToPeriod()) YYERROR;} | PERIOD "to" {if (!mkPeriod('_')) YYERROR;} PERIOD {if (!mkToPeriod()) YYERROR;} | PERIOD {if (!mkPeriod('\0')) YYERROR;} ; GROUPOF : EXIST_QUANT GROUP_TOKEN | "together" {TheNodeWP->collKind='c';TheNodeWP->collType='s';} | "each of" {TheNodeWP->collKind='D';TheNodeWP->collType='s';} ; GROUP_TOKEN: "group of" {TheNodeWP->collKind='c';TheNodeWP->collType='s';} | "bag of" {TheNodeWP->collKind='s';TheNodeWP->collType='b';} | "set of" {TheNodeWP->collKind='s';TheNodeWP->collType='s';} | "list of" {TheNodeWP->collKind='s';TheNodeWP->collType='l';} | "sequence of" {TheNodeWP->collKind='s';TheNodeWP->collType='q';} | "alternatives" {TheNodeWP->collKind='s';TheNodeWP->collType='x';} ; _COLL : | COLL; COLL : COLL_CORE | GTYPE COLL_CORE {/*no instruction here is executed; bug of Bison?*/} ; GTYPE : "BAG" {TheNodeWP->collType='b';} | "SET" {TheNodeWP->collType='s';} | "LIST" {TheNodeWP->collType='l';} | "SEQ" {TheNodeWP->collType='q';} | "XOR" {TheNodeWP->collType='x';} | "OR" {TheNodeWP->collType='o';} | "AND" {TheNodeWP->collType='a';} ; COLL_CORE : '{' {mkNodeWP();} COLL_ELEMS '}' _COLL_SIZE | "{(" {mkNodeWP();} COLL_ELEMS ")}" _COLL_SIZE {TheNodeWP->collType= toupper(TheNodeWP->collType);} ; _COLL_SIZE : {TheNodeWP->collNum= TheNodeWP->elemPtrs.length(); if (!TheNodeWP->collKind) TheNodeWP->collKind='d';} | '@' NUMBER {if (!getNaturalInto(fcgtext,TheNodeWP->collNum)) YYERROR; if (TheNodeWP->collNum < (int)TheNodeWP->elemPtrs.length()) {putsErr("Prescribed size inferior to actual size"); YYERROR;} if (!TheNodeWP->collKind) TheNodeWP->collKind='d';} ; COLL_ELEMS : ELEM | ELEM ',' {mkNodeWP();} COLL_REST | ELEM "and" {TheNodeWP->collType='a';mkNodeWP();} COLL_AND | ELEM "or" {TheNodeWP->collType='o';mkNodeWP();} COLL_OR ; COLL_REST : ELEM | ELEM ',' {mkNodeWP();} COLL_REST; COLL_AND : ELEM | ELEM "and" {if (TheNodeWP->collType=='a') mkNodeWP(); else{putsErr("Not an \"and\" collection"); YYERROR;}} COLL_AND; COLL_OR : ELEM | ELEM "or" {if (TheNodeWP->collType=='a') mkNodeWP(); else{putsErr("Not an \"or\" collection"); YYERROR;}} COLL_OR ; ELEM : NODE {ElemWP=TheNodeWP; TheNodeWP=NodePtrs[--NodeNum-1]; TheNodeWP->elemPtrs.append(ElemWP);} | '*' {ElemWP=TheNodeWP; ElemWP->undeclaredTermName=strdup("*"); TheNodeWP=NodePtrs[--NodeNum-1]; TheNodeWP->elemPtrs.append(ElemWP);} ; TERM_DEF : "type" IDENTIFIER {if (!mkDefNodeWP()) YYERROR;} '('_PARAMS')' _DEF_ANNOT DEF_OP FCG {if (!endDefNodeWP(false)) YYERROR;} | "function" IDENTIFIER {mkDefNodeWP();} '('_PARAMS')' ":->" PARAM _DEF_ANNOT ":=" FCG {if (!endDefNodeWP(true)) YYERROR;} ; _PARAMS : | PARAMS; PARAMS : PARAM | PARAM ',' PARAMS; PARAM : _VAR_TYPE VARIABLE {if (!addParamVar()) YYERROR;} ; _VAR_TYPE : | IDENTIFIER {if (!checkOrUpdateSignature()) YYERROR;} ; DEF_OP : ":=" {TheNodeWP->relOrFct='D';} | ":=>" {TheNodeWP->relOrFct='N';} | ":<=" {TheNodeWP->relOrFct='S';} ; _DEF_ANNOT : | ANNOTATION {TheNodeWP->annotation=strdup(fcgtext);} ; NUM1 : NUMBER {//bison bug ->TmpBuff instead of fcgtext if (!getRealInto(TmpBuff,TheNodeWP->number)) YYERROR;}; NUM2 : NUMBER {if (!getRealInto(fcgtext,TheNodeWP->toNumber)) YYERROR;/*pr("NUM2:%lf\n",TheNodeWP->toNumber);*/} ; _OF : | "of"; _THE : | "the"; _PERCENT : {} | '%' {TheNodeWP->quantifier='p';} ; %% void fcgInit (FILE* fp) //uncalled { errno=0; LineNumber=0; TheNodeWP=NULL; NodeNum=0; if (fcgfirst) fcgfirst=0; else fcgrestart(fp); } int fcgwrap() { if (fcgInclBufferNum<=0) return 1; yy_delete_buffer(YY_CURRENT_BUFFER); yy_switch_to_buffer(fcgIncludedBuffers[--fcgInclBufferNum]); return 0; } int fcgerror(const char *s) /*pm: this fct */ { s= moreReadableParserMessage(s,TmpBuff); if (fcgtext[0]=='"') putsErr("At %s: %s",fcgtext,s); else putsErr("At \"%s\": %s",fcgtext,s); return 1; } bool fcgParseStr (char *fcg)//Global OutP: dbrNode GdbrNode // NodeWP *GNodeWP (not freed if query) { if (!fcg) return false; if (WithTrace) { if (ParsingQueryGraph) pr("\n\n\n ====== fcgParseStr (? %s) ======\n\n",fcg); else pr("\n\n\n ============ fcgParseStr (%s) ===========\n\n",fcg); } yy_scan_string(fcg); errno=0; NodeNum=0; TheNodeWP=NULL; if (WithTrace==11) fcgdebug=1; if (!RefsToBasicTypesInitialised) initRefsToBasicTypes(); if (!RefsToCommonLinksInitialised) initRefsToCommonLinks(); //for comparisons if (fcgparse()!=0) return false; //if (WithTrace) { GNodeWP->print(); pr("\n\n"); } return GNodeWP_checkInsertAndFree(fcg); }