// FunParser.cpp: implementation of the FunParser class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "FunParser.h" #include "FunUtil.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// /***** Global and static variable *****/ int Num_Of_Bracket=0;//show number of cascaded bracket (0 base) int FunParser::f=-1; /***************************/ FunParser::FunParser() { //reset all variable TokenObj.Reset(); Num_Of_Bracket=0; OutputType=-1; //type of output of fun. (number or date) BodyType=-1; //type of body of fun. (number or date) MathBuiltFun=0; f=-1; } FunParser::~FunParser() { } void FunParser::Reset() { TokenObj.Reset(); Num_Of_Bracket=0; f=-1; } BOOL FunParser::ParseHeader(CString &FunStream,CString &Error,CCptList *pCptList) { CString Token,Cpt,Prop; int FunLength=FunStream.GetLength(); Reset(); if( TokenObj.GetToken(FunStream,Token) ==false) { Error.Format("In Column %d InValid Token",TokenObj.GetStartPos()); return false; } if(Token=='@'){ //must Parse cpt.prop if( Parse_CPT_PROP(FunStream,Cpt,Prop,Error)==false) return false; } else{ Error="The header of function must be @cpt.prop"; return false; } //////////////////////////// // check the type of cpt.prop //////////////////////////// CRule * r=new CRule; CString strType = r->GetType(Cpt,Prop,pCptList); delete r; // change the OutputType if(strType=="integer" || strType=="real") { OutputType=1; //if type is number return true; } else if(strType=="date") { OutputType=2; //if type is date return true; } Error="UnKnown type fo output of function"; return false; } BOOL FunParser::ParseBody(CString &FunStream,CString &Error,CCptList *pCptList) { CString Token,Cpt,Prop; int FunLength=FunStream.GetLength(); Reset(); FunStream.TrimLeft();FunStream.TrimRight(); if(FunStream[FunStream.GetLength()-1] !=';') { Error = "Syntax Error Function should terminate with semicolon"; return FALSE; } FunStream.Delete(FunStream.GetLength()-1,1);//remove ';' while(TokenObj.GetStartPos() < FunLength) { if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("In Column %d InValid Token",TokenObj.GetStartPos()); return false; } if(Token.IsEmpty())break; // @ if(Token=='@') { //must Parse cpt.prop if(f==0 || f==3 || f==4 || f==5){ Error.Format("In Column %d InValid Concept",TokenObj.GetStartPos()); return false; } if( Parse_CPT_PROP(FunStream,Cpt,Prop,Error)==false) return false; //////////////////////////// // check the type of cpt.prop //////////////////////////// CRule * r=new CRule; CString strType = r->GetType(Cpt,Prop,pCptList); delete r; if(strType=="integer" || strType=="real"){ if(BodyType==-1)BodyType=1; //if type is number } else if(strType=="date") BodyType=2; //if type is date else { Error.Format("Unknown type"); return false; } f=0; } // open bracket else if(Token=='(') { if(f==0 || f==3 || f==4 || f==5){ Error.Format("In Column %d Invalid Open Bracket",TokenObj.GetStartPos()); return false; } Num_Of_Bracket++; f=2; } //close bracket else if(Token==')') { if(f==-1 || f==1 || f==2){ Error.Format("In Column %d Invalid Close Bracket",TokenObj.GetStartPos()); return false; } Num_Of_Bracket--; f=3; } // #(date) else if(Token=='#') { if(f==0 || f==3 || f==4 || f==5){ Error="Invalid Date"; return false; } if(TokenObj.GetDate(FunStream,Token)==false){ Error="Invalid Date"; return false; } BodyType=2; f=5; } //number else if(IsNumber(Token[0])) { if(f==0 || f==3 || f==4 || f==5){ Error.Format("In Column %d Invalid Number",TokenObj.GetStartPos()); return false; } if(BodyType==-1)BodyType=1; f=5; } //operator else if(IsOperator(Token[0])) { if(f==-1 || f==1 || f==2){ Error.Format("In Column %d Invalid Operator",TokenObj.GetStartPos()); return false; } f=1; } //function else if(IsAlpha(Token[0])) { if(f==0 || f==3 || f==4 || f==5){ Error.Format("In Column %d Invalid Function",TokenObj.GetStartPos()); return false; } if( ParseBuilt(FunStream,Token,Error,pCptList) == false ) return false; f=4; } }// end while if(f==1 || f==2){ Error.Format("InValid end of function"); return false; } if(Num_Of_Bracket!=0){ Error.Format("In Column %d Error in Bracket",TokenObj.GetStartPos()); return false; } if( (MathBuiltFun==1 && OutputType==2) || (OutputType!=BodyType) ){ Error="Incomptable type of output and body of the function"; return false; } return true; } BOOL FunParser::Parse_CPT_PROP(CString &FunStream,CString &Cpt,CString &Prop,CString &Error) { //Parse cpt.prop CString Token; //cpt if(TokenObj.GetConcept(FunStream,Token)==false){ Error="InValid Concept"; return false; } Cpt=Token; //dot if( TokenObj.GetToken(FunStream,Token) == false){ Error.Format("In Column %d InValid Token",TokenObj.GetStartPos()); return false; } if(!IsDot(Token[0])){ Error.Format("In Column %d must there are dot after the concept",TokenObj.GetStartPos()); return false; } //prop if(TokenObj.GetProp(FunStream,Token)==false){ Error="InValid Concept"; return false; } Prop=Token; return true; } BOOL FunParser::ParseBuilt(CString &FunStream,CString &Fun,CString &Error,CCptList *pCptList) { CString Token,Cpt,Prop; int flag=0; if(Fun!="abs" && Fun!="sqrt" && Fun!="floor" && Fun!="ceil" && Fun!="now" && Fun!="day" && Fun!="month" && Fun!="year") { Error="InValid Function name"; return false; } if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("In Column %d InValid Token",TokenObj.GetStartPos()); return false; } // match the open brace of the function if(Token!='('){ Error.Format("there is no open brace for function"); return false; } //****************************** Match the function ******************** if(Fun=="abs" || Fun=="sqrt" || Fun=="floor" || Fun=="ceil") { flag=1; MathBuiltFun=1; if( ParseMath(FunStream,Error,pCptList) == false ) return false; TokenObj.ReturnBack(Token); } else if(Fun=="now") { BodyType=2; flag=1; } else if(Fun=="day" || Fun=="month" || Fun=="year") { flag=1; if( ParseDate(FunStream,Error,pCptList) == false ) return false; TokenObj.ReturnBack(Token); } if(flag==0)Error="InValid function signature"; if(flag==1){ if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("In Column %d InValid Token",TokenObj.GetStartPos()); return false; } // match the close brace of the function if(Token!=')'){ Error.Format("there is no close brace for function"); return false; } } return flag; } BOOL FunParser::ParseMath(CString &FunStream,CString &Error,CCptList *pCptList) { CString Token,Cpt,Prop; int Num_Bracket=1; int FSM=0; /*********** FSM is a finite state machine 0 initial state 1 string (@cpt.prop or date or now(),...) 2 operator 3 ( 4 ) ***********/ if(BodyType==-1)BodyType=1; do { if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("In Column %d InValid Parameter for abs function",TokenObj.GetStartPos()); return false; } if(Token.IsEmpty()){ Error="InComplete function"; return false; } //Parameter is Number if( IsNumber(Token[0]) ) { if(FSM==1 || FSM==4){ Error="Invalid Number"; return false;; } FSM=1; } ////Parameter is cpt.prop else if(Token=='@'){ if(FSM==1 || FSM==4){ Error="Invalid Concept"; return false; } FSM=1; if( Parse_CPT_PROP(FunStream,Cpt,Prop,Error)==false) return false; //////////////////////////// // check the type of cpt.prop //////////////////////////// CRule * r=new CRule; CString strType = r->GetType(Cpt,Prop,pCptList); delete r; if(strType!="integer" && strType!="real" && strType!="date"){ Error.Format("Type of property in math function must be integer or real"); return false; } //check if date if(strType=="date") { //parse the - if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("In Column %d InValid Parameter for abs function",TokenObj.GetStartPos()); return false; } if( Token != '-'){ Error.Format("The operator must be '-'"); return false; } //parse the second operand of - if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("In Column %d InValid Parameter for function",TokenObj.GetStartPos()); return false; } if(Token=='@'){ if( Parse_CPT_PROP(FunStream,Cpt,Prop,Error)==false) return false; CRule * r=new CRule; CString strType = r->GetType(Cpt,Prop,pCptList); delete r; if(strType!="date"){ Error.Format("Type of property must be date"); return false; } } else if(Token=='#'){ if(TokenObj.GetDate(FunStream,Error) ==false) {Error="Error in date";return false;} } else if(Token=="now"){ if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("now function don't take paramter"); return false; } if( Token!= '(' ){ Error.Format("In Column %d now function don't take paramter"); return false; } if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("In Column %d now function don't take paramter",TokenObj.GetStartPos()); return false; } if( Token!= ')' ){ Error.Format("In Column %d now function don't take paramter"); return false; } } else{ Error.Format("The second operand must be date or Cpt.Prop with type date"); return false; } } } //parameter is now() - date else if( Token=="now" ) { if(FSM==1 || FSM==4){ Error="Invalid calling of now function"; return false; } FSM=1; //parse the '(' and ')' if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("In Line %d now function don't take paramter",TokenObj.GetStartPos()); return false; } if( Token!= '(' ){ Error.Format("In Column %d now function don't take paramter",TokenObj.GetStartPos()); return false; } if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("In Column %d now function don't take paramter",TokenObj.GetStartPos()); return false; } if( Token!= ')' ){ Error.Format("In Column %d now function don't take paramter",TokenObj.GetStartPos()); return false; } //parse the - if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("In Column %d InValid Parameter for Math function",TokenObj.GetStartPos()); return false; } if( Token != '-'){ Error.Format("The operator must be '-'"); return false; } //parse the second operand of - if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("In Column %d InValid Parameter for function",TokenObj.GetStartPos()); return false; } if(Token=='@'){ if( Parse_CPT_PROP(FunStream,Cpt,Prop,Error)==false) return false; CRule * r=new CRule; CString strType = r->GetType(Cpt,Prop,pCptList); delete r; if(strType!="date"){ Error.Format("Type of property must be date"); return false; } } else if(Token=='#'){ if(TokenObj.GetDate(FunStream,Error) ==false) {Error="Error in date";return false;} } else{ Error="Invalid Experssion for now() - ... "; return false; } } //Parameter is date else if( Token=='#') { if(FSM==1 || FSM==4){ Error="Invalid Concep"; return false; } FSM=1; if(TokenObj.GetDate(FunStream,Error) ==false) {Error="Error in date";return false;} //parse '-' if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("In Column %d InValid Parameter for function",TokenObj.GetStartPos()); return false; } if( Token != '-'){ Error.Format("The operator must be '-'"); return false; } //parse the second operand of - if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("In Column %d InValid Parameter for abs function",TokenObj.GetStartPos()); return false; } if(Token=='@'){ if( Parse_CPT_PROP(FunStream,Cpt,Prop,Error)==false) return false; CRule * r=new CRule; CString strType = r->GetType(Cpt,Prop,pCptList); delete r; if(strType!="date"){ Error.Format("Type of property must be date"); return false; } } else if(Token=='#'){ if(TokenObj.GetDate(FunStream,Error) ==false) {Error="Error in date";return false;} } else if(Token=="now"){ if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("now function don't take paramter"); return false; } if( Token!= '(' ){ Error.Format("In Column %d now function don't take paramter"); return false; } if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("In Column %d now function don't take paramter",TokenObj.GetStartPos()); return false; } if( Token!= ')' ){ Error.Format("In Column %d now function don't take paramter"); return false; } } else{ Error.Format("The second operand must be date or Cpt.Prop with type date"); return false; } } //Parameter is another function else if( Token=="abs" || Token=="sqrt" || Token=="floor" || Token=="ceil" || Token=="day" || Token=="month" || Token=="year") { if(FSM==1 || FSM==4){ Error="Invalid call of function"; return false; } FSM=1; if( ParseBuilt(FunStream,Token,Error,pCptList) == false ){ Error="Invalid function name"; return false; } } else if( IsOperator(Token[0]) ) { if(FSM==0 || FSM==2 || FSM==3){ Error="Invalid Operator"; return false; } FSM=2; } else if( Token=='(') { if(FSM==1 || FSM==4){ Error="Invalid open bracket"; return false; } FSM=3; Num_Bracket++; while(Token != ')' ) { if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("In Column %d InValid Token",TokenObj.GetStartPos()); return false; } else{ TokenObj.ReturnBack(Token); if( ParseMath(FunStream,Error,pCptList)==false ) return false; Num_Bracket--; FSM=4; break; } }//end while } else if( Token==')'){ if(FSM==0 || FSM==2 || FSM==3){ Error="Invalid close Bracket"; return false; } FSM=4; Num_Bracket--; } else { Error="InValid Parameter of the function"; return false; } }// end do while(Token!=')' || Num_Bracket>0); return true; } BOOL FunParser::ParseDate(CString &FunStream,CString &Error,CCptList *pCptList) { CString Token,Cpt,Prop; int Num_Bracket=1; int appear_date=0;//flag show date is appear or not int FSM=0; /*********** FSM is a finite state machine 0 initial state 1 string (@cpt.prop or date or now(),...) 2 operator ***********/ if(BodyType==-1)BodyType=1; do { if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("In Column %d InValid Parameter for abs function",TokenObj.GetStartPos()); return false; } if(Token.IsEmpty()) { Error="InComplete function"; return false; } //Parameter is Number else if( IsNumber(Token[0]) ) { if(FSM == 1){ Error = "Invalid Number in the function"; return false; } FSM=1; } //Parameter is date else if( Token=='#'){ appear_date=1; if( FSM == 1){ Error = "Invalid date in the function"; return false; } FSM=1; if(TokenObj.GetDate(FunStream,Error) ==false) {Error="Error in date";return false;} } //parameter is @cpt.prop else if(Token=='@'){ if( FSM == 1){ Error = "Invalid Concept in the function"; return false; } FSM=1; if( Parse_CPT_PROP(FunStream,Cpt,Prop,Error)==false) return false; //////////////////////////// // check the type of cpt.prop //////////////////////////// CRule * r=new CRule; CString strType = r->GetType(Cpt,Prop,pCptList); delete r; if(strType!="integer" && strType!="real" && strType!="date"){ Error.Format("Type of property in math function must be data or integer"); return false; } if(strType == "date") appear_date=1; } //Parameter is now else if(Token=="now"){ if( FSM == 1){ Error = "Invalid calling of now function"; return false; } FSM=1; appear_date=1; //parse the '(' and ')' if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("now function don't take paramter"); return false; } if( Token!= '(' ){ Error.Format("In Column %d now function don't take paramter",TokenObj.GetStartPos()); return false; } if( TokenObj.GetToken(FunStream,Token) ==false){ Error.Format("In Column %d now function don't take paramter",TokenObj.GetStartPos()); return false; } if( Token!= ')' ){ Error.Format("In Column %d now function don't take paramter"); return false; } } else if( Token=='-' || Token=='+' ) { if(FSM == 0 || FSM == 2){ Error = "Invalid operator"; return false; } FSM=2; } else if( Token==')') { Num_Bracket--; } else { Error="InValid Parameter of the function"; return false; } }// end do while(Token!=')' || Num_Bracket>0); if(FSM==2){ Error = "Can't end with operator"; return false; } if(appear_date == 0){ Error=("function must be contain value from type date"); return false; } return true; }