// unary-expr ::= - unary expr // + unary expr // ! unary expr // primary expr Expr* parse_unary_expr(Parser& p, Token_stream& ts) { if(ts.next()) { switch (ts.next()->kind()) { // negative case minus_tok: return parse_neg(p, ts); case plus_tok: return parse_pos(p, ts); case bang_tok: return parse_not(p, ts); default: return parse_primary_expr(p, ts); } } return nullptr; }
Data* parse_expression( char **p ) { /*TODO: logic */ //return parse_aexpr(p); Data* ret = NULL; while(1) { char op; int neg ; Data* aexpr; if( ret ) {/*if it is not the first expression , a logic operator expected*/ if( p[0][0] == 'A' && p[0][1] == 'N' && p[0][2] == 'D' && ( p[0][3] = ' ' || p[0][3] == '\t' ) ) { op = 'A'; (*p)+=4; } else if( p[0][0] == 'O' && p[0][1] == 'R' && ( p[0][2] = ' ' || p[0][2] == '\t' ) ) { op = 'O'; (*p)+=3; } else break; /*if not operator */ } neg = parse_neg(p); aexpr = parse_aexpr(p); parse_ws(p); if( aexpr->type == TYPE_ERROR ) { dispose(ret); return aexpr; } if( **p == '=' || **p == '>' || **p == '<' ) { int flag; Data* right/* = parse_aexpr(p)*/; switch(**p) { case '=': #define EQ 0 flag = 0; /*EQ*/ (*p)++; break; case '>': if( p[0][1] == '=' ) { (*p)+=2; #define GE 3 flag = 3; /*GE*/ } else { #define G 1 (*p)++; flag = 1; /*G*/ } break; case '<': if( p[0][1] == '=' ) { (*p)+=2; #define LE 4 flag = 4; /*LE*/ } else if( p[0][1] == '>' ) { (*p)+=2; #define NE 5 flag = 5; /*NE*/ } else { (*p)++; #define L 2 flag = 2; /*L*/ } } right = parse_aexpr(p); if( right->type == TYPE_ERROR ) { dispose(ret); dispose(aexpr); return right; } if( right->type == TYPE_STRING ) {//String if( aexpr->type != TYPE_STRING ) { dispose(ret); dispose(aexpr); dispose(right); return Raise(TYPE_MISMATCH); } else { Data* temp = Data_new(TYPE_INTEGER,(Storage)(short)0,1); int result = strcmp( aexpr->storage.String , right->storage.String); switch(flag) { case EQ: temp->storage.Integer = (result == 0); break; case L: temp->storage.Integer = (result < 0 ); break; case LE: temp->storage.Integer = (result <= 0 ); break; case G: temp->storage.Integer = (result > 0 ); break; case GE: temp->storage.Integer = (result >= 0 ); break; case NE: temp->storage.Integer = (result != 0 ); } dispose(aexpr); dispose(right); aexpr = temp; } } else {//numeric if( aexpr->type == TYPE_STRING ) { dispose(right); dispose(aexpr); dispose(ret); return Raise(TYPE_MISMATCH); } else { Data* temp = Data_new(TYPE_INTEGER,(Storage)(short)0,1); int result ; if( aexpr->type == TYPE_INTEGER ) { aexpr->type = TYPE_REAL; aexpr->storage.Real = aexpr->storage.Integer; } if( right->type == TYPE_INTEGER ) { right->type = TYPE_REAL; right->storage.Real = right->storage.Integer; } double t = aexpr->storage.Real - right->storage.Real; if( t < 0 ) result = -1; if( t == 0 ) result = 0; if( t > 0 ) result = 1; switch(flag) { case EQ: temp->storage.Integer = (result == 0); break; case L: temp->storage.Integer = (result < 0 ); break; case LE: temp->storage.Integer = (result <= 0 ); break; case G: temp->storage.Integer = (result > 0 ); break; case GE: temp->storage.Integer = (result >= 0 ); break; case NE: temp->storage.Integer = (result != 0 ); } dispose(aexpr); dispose(right); aexpr = temp; } } } if( aexpr->type == TYPE_ERROR ) { dispose(ret); return aexpr; } if( neg ) {/*one or more NOT parsed*/ if( aexpr->type == TYPE_STRING ) /*NOT "illegal"*/ { dispose(aexpr); dispose(ret); return Raise(TYPE_MISMATCH ); } if( aexpr->type == TYPE_REAL ) { aexpr->type = TYPE_INTEGER; aexpr->storage.Integer = (int)(aexpr->storage.Real+.001); } if( aexpr->storage.Integer ) aexpr->storage.Integer = 1; else aexpr->storage.Integer = 0; if( neg < 0 ) aexpr->storage.Integer = !aexpr->storage.Integer; } if( !ret ) {/* first expression */ ret = aexpr; } else { ret = temp_var(ret); if( aexpr->type == TYPE_STRING ) { dispose(aexpr); dispose(ret); return Raise(TYPE_MISMATCH); } if( aexpr->type == TYPE_REAL ) { aexpr->type = TYPE_INTEGER; aexpr->storage.Integer = (int)(aexpr->storage.Real+.001); } if( ret->type == TYPE_REAL ) { ret->type = TYPE_INTEGER; ret->storage.Integer = (int)(ret->storage.Real+.001); } if( op == 'A' ) ret->storage.Integer &= aexpr->storage.Integer; else ret->storage.Integer |= aexpr->storage.Integer; dispose(aexpr); } } return ret; }