/************************************************************************/ /* */ /* RCPP - Resource Compiler Pre-Processor for NT system */ /* */ /* P0EXPR.C - Expression routines for Pre-Processor */ /* */ /* AUTHOR - Ralph Ryan, Sept. 16, 1982 */ /* 06-Dec-90 w-BrianM Update for NT from PM SDK RCPP */ /* */ /************************************************************************/ /* * DESCRIPTION * Evaluate the constant expression. Since these routines are * all recursively coupled, it is clearer NOT to document them * with the standard header. Instead, BML (British Meta Language, * a BNF like meta language) will be given for each "production" * of this recursive descent parser. * * Note - Sure, yeah, right. Frankly, I'm frightened! (w-BrianM) ************************************************************************/ #include #include "rcpptype.h" #include "rcppdecl.h" #include "rcppext.h" #include "grammar.h" /************************************************************************/ /* Local Function Prototypes */ /************************************************************************/ long and(void); long andif(void); long constant(void); long constexpr(void); long eqset(void); long mult(void); long or(void); long orelse(void); long plus(void); long prim(void); long relation(void); long shift(void); long xor(void); /************************************************************************/ /* File Global Variables */ /************************************************************************/ long Currval = 0; static int Parencnt = 0; /************************************************************************/ /* do_constexpr() */ /************************************************************************/ long do_constexpr(void) { REG long val; Parencnt = 0; Currtok = L_NOTOKEN; val = constexpr(); if( Currtok == L_RPAREN ) { if( Parencnt-- == 0 ) { Msg_Temp = GET_MSG(1012); SET_MSG (Msg_Text, Msg_Temp, "("); fatal(1012); /* missing left paren */ } } else if( Currtok != L_NOTOKEN ) { Msg_Temp = GET_MSG(4067); SET_MSG (Msg_Text, Msg_Temp, PPifel_str); warning(4067); } if( Parencnt > 0 ) { Msg_Temp = GET_MSG(4012); SET_MSG (Msg_Text, Msg_Temp, ")"); fatal(4012); /* missing right paren */ } return(val); } /************************************************************************/ /* constexpr ::= orelse [ '?' orelse ':' orelse ]; */ /************************************************************************/ long constexpr(void) { REG long val; REG long val1; long val2; val = orelse(); if( nextis(L_QUEST) ) { val1 = orelse(); if( nextis(L_COLON) ) val2 = orelse(); return(val ? val1 : val2); } return(val); } /************************************************************************/ /* orelse ::= andif [ '||' andif ]* ; */ /************************************************************************/ long orelse(void) { REG long val; val = andif(); while(nextis(L_OROR)) val = andif() || val; return(val); } /************************************************************************/ /* andif ::= or [ '&&' or ]* ; */ /************************************************************************/ long andif(void) { REG long val; val = or(); while(nextis(L_ANDAND)) val = or() && val; return(val); } /************************************************************************/ /* or ::= xor [ '|' xor]* ; */ /************************************************************************/ long or(void) { REG long val; val = xor(); while( nextis(L_OR) ) val |= xor(); return(val); } /************************************************************************/ /* xor ::= and [ '^' and]* ; */ /************************************************************************/ long xor(void) { REG long val; val = and(); while( nextis(L_XOR) ) val ^= and(); return(val); } /************************************************************************/ /* and ::= eqset [ '&' eqset]* ; */ /************************************************************************/ long and(void) { REG long val; val = eqset(); while( nextis(L_AND) ) val &= eqset(); return(val); } /************************************************************************/ /* eqset ::= relation [ ('==' | '!=') eqset] ; */ /************************************************************************/ long eqset(void) { REG long val; val = relation(); if( nextis(L_EQUALS) ) return(val == relation()); if( nextis(L_NOTEQ) ) return(val != relation()); return(val); } /************************************************************************/ /* relation ::= shift [ ('<' | '>' | '<=' | '>=' ) shift] ; */ /************************************************************************/ long relation(void) { REG long val; val = shift(); if( nextis(L_LT) ) return(val < shift()); if( nextis(L_GT) ) return(val > shift()); if( nextis(L_LTEQ) ) return(val <= shift()); if( nextis(L_GTEQ) ) return(val >= shift()); return(val); } /************************************************************************/ /* shift ::= plus [ ('<< | '>>') plus] ; */ /************************************************************************/ long shift(void) { REG long val; val = plus(); if( nextis(L_RSHIFT) ) return(val >> plus()); if( nextis(L_LSHIFT) ) return(val << plus()); return(val); } /************************************************************************/ /* plus ::= mult [ ('+' | '-') mult ]* ; */ /************************************************************************/ long plus(void) { REG long val; val = mult(); for(;;) { if( nextis(L_PLUS) ) val += mult(); else if( nextis(L_MINUS) ) val -= mult(); else break; } return(val); } /************************************************************************/ /* mult ::= prim [ ('*' | '/' | '%' ) prim ]* ; */ /************************************************************************/ long mult(void) { REG long val; val = prim(); for(;;) { if( nextis(L_MULT) ) val *= prim(); else if( nextis(L_DIV) ) val /= prim(); else if( nextis(L_MOD) ) val %= prim(); else break; } return(val); } /************************************************************************/ /* prim ::= constant | ( '!' | '~' | '-' ) constant */ /************************************************************************/ long prim(void) { if( nextis(L_EXCLAIM) ) return( ! constant()); else if( nextis(L_TILDE) ) return( ~ constant() ); else if( nextis(L_MINUS) ) return(-constant()); else return(constant()); } /************************************************************************/ /* constant - at last, a terminal symbol | '(' constexpr ')' */ /************************************************************************/ long constant(void) { REG long val; if( nextis(L_LPAREN) ) { Parencnt++; val = constexpr(); if( nextis(L_RPAREN) ) { Parencnt--; return(val); } else { Msg_Temp = GET_MSG(1012); SET_MSG (Msg_Text, Msg_Temp, ")"); fatal (1012); } } else if( ! nextis(L_CINTEGER) ) { Msg_Temp = GET_MSG(1017); SET_MSG (Msg_Text, Msg_Temp); fatal(1017); /* invalid integer constant expression */ } return(Currval); }