static void parse_cond( cheevos_cond_t* cond, const char** memaddr ) { const char* str = *memaddr; if ( *str == 'R' && str[ 1 ] == ':' ) { cond->type = CHEEVOS_COND_TYPE_RESET_IF; str += 2; } else if ( *str == 'P' && str[ 1 ] == ':' ) { cond->type = CHEEVOS_COND_TYPE_PAUSE_IF; str += 2; } else { cond->type = CHEEVOS_COND_TYPE_STANDARD; } parse_var( &cond->source, &str ); cond->op = parse_operator( &str ); parse_var( &cond->target, &str ); cond->curr_hits = 0; cond->req_hits = read_hits( &str ); *memaddr = str; }
void Parser::compute_next() { if( !_alex.has_next() ) { _next = nullptr; return; } switch( _alex.peek().id ) { case Token::INCLUDE: _next = parse_include( _alex ); return; case Token::CATEGORY: _next = parse_category( _alex ); return; case Token::F: case Token::FX: case Token::FY: case Token::XF: case Token::YF: case Token::XFX: case Token::YFX: case Token::XFY: _next = parse_operator( _alex ); return; default: throw parse_error( "Expected include, category or operator", _alex.peek() ); } }
iterator &iterator::next( void ) { _type = TOK_UNKNOWN; _value.clear(); // Skip any whitespace while ( utf::is_pattern_whitespace( _c ) && _utf ) next_utf(); _whitespace.swap( _value ); _type = TOK_UNKNOWN; _value.clear(); if ( !_utf ) return *this; _start.set( _utf ); if ( _c == '{' ) { // Code block _type = TOK_BLOCK_START; next_utf(); } else if ( _c == '}' ) { // Code block _type = TOK_BLOCK_END; next_utf(); } else if ( _c == '(' ) { // Expression ordering _type = TOK_PAREN_START; next_utf(); } else if ( _c == ')' ) { // Expression ordering _type = TOK_PAREN_END; next_utf(); } else if ( _c == '[' ) { // Expression ordering _type = TOK_MOD_START; next_utf(); } else if ( _c == ']' ) { // Expression ordering _type = TOK_MOD_END; next_utf(); } else if ( _c == ',' ) { // Argument separator _type = TOK_COMMA; next_utf(); } else if ( _c == ';' ) { // Statement terminator _type = TOK_EXPRESSION_END; next_utf(); } else if ( _c == ':' ) { // Separator _type = TOK_SEPARATOR; next_utf(); } else if ( _c == '\"' ) parse_string(); else if ( _c == '\'' ) parse_char(); else if ( _c == 0x2AFD || _c == '#' ) // Double slash character or hash { _whitespace.push_back( _c ); parse_comment(); } else if ( _c == '/' || _c == 0x29F8 || _c == 0xFF0F || _c == 0x2044 ) // Slash, big slash, and fullwidth slash, fraction slash { char32_t comment_start = _c; skip_utf(); if ( _c == comment_start || _c == U'*' ) parse_comment(); else { _value += comment_start; parse_operator(); } } else if ( utf::is_identifier_start( _c ) ) parse_identifier(); else if ( utf::is_pattern_syntax( _c ) ) parse_operator(); else if ( utf::is_number_decimal( _c ) ) parse_number(); else next_utf(); utf::nfc( _whitespace ); utf::nfc( _value ); _end.set( _utf ); return *this; }
/** Take a string (hopefully) containing an operator and either push it to the stack or eval it depending on precedence. **/ int handle_op ( const char* op_str, Stack* op_stack, Stack* num_stack) { #if DEBUG==1 cout << "Handling operator '" << op_str << "'." << endl; #endif op_code new_op = -1; if (! (0 == op_str_len)) { new_op = parse_operator (op_str, op_str_len, check_unm); #if DEBUG==1 cout << "Operator code is: " << new_op << endl; #endif if (new_op == OP_CODE_ERR) { return PARSER_STATUS_NOP; } else { #if DEBUG==1 cout << "Comparing previous op, '" << op_stack -> top() << "' with new op '" << new_op << "'." << endl; cout << "Precedence is: " << compare_prec (new_op, op_stack -> top() ) << endl; #endif /* Only do if holding a low-precedence operator: */ while ((op_stack -> top() != OP_CODE_END) && !compare_prec (new_op, op_stack -> top()) ) { double R_arg = num_stack -> top(); num_stack -> pop(); double L_arg = 0; if ( !is_unary ( op_stack -> top() ) ) { if( num_stack -> empty() ) { cerr << "Operations remain but not enough numbers to " "evaluate." << endl; return PARSER_STATUS_SYNTAX; } #if DEBUG==1 cout << "Operator is binary." <<endl; #endif L_arg = num_stack -> top(); num_stack -> pop(); } double result = perform_op ( L_arg, R_arg, op_stack -> top(), status ); last_result = result; op_stack -> pop(); #if DEBUG==1 cout << "Result is: " << result << endl; #endif num_stack -> push (result); } /* As long as we're not holding a right-paren */ if (new_op != OP_CODE_RPN) { #if DEBUG==1 cout << "Pushing operator '" << new_op << "' to stack."<<endl; #endif op_stack -> push( new_op ); } /* only LPN has higher prec than RPN. Eliminate it. */ else if ( OP_CODE_LPN == op_stack -> top() ) { op_stack -> pop(); } #if DEBUG==1 if( !op_stack -> empty() ) cout << "Next up on stack: " << op_stack -> top() << endl; #endif } } return PARSER_STATUS_GOOD; }
int parse_expression(char *expr) { if (strlen(strtrim(expr)) == 0) return BREAK; char *token; static const char *operators = "+/*-%^"; static const char *mfuncs = "|ln|sqrt|sin|cos|tan|asin|acos|atan|"; static const char *constants = "|e|pi|"; double operand; char *ptr; while ((token = strsep(&expr, " \n"))) { if (strlen(token) == 0) continue; if (*token == ':') /* precision specified */ parse_precision(++token); else if (strchr(operators, *token) && strlen(token) == 1) { /* operator */ if (stackptr - opstack < 2) { fprintf(stderr, "!! Malformed expression -- too few operands.\n"); return CONTINUE; } if (parse_operator(*token) > 0) { return CONTINUE; } } else if ((ptr = strstr(mfuncs, strlower(token))) != NULL && *(ptr - 1) == '|' && *(ptr + strlen(token)) == '|') { /* validated trig function */ if (stackptr - opstack < 1) { fprintf(stderr, "!! Malformed expression -- too few operands.\n"); return CONTINUE; } parse_mfunc(token); } else if ((ptr = strstr(constants, strlower(token))) != NULL && *(ptr - 1) == '|' && *(ptr + strlen(token)) == '|') { /* validated constant */ parse_constant(token); } else { /* it's an operand, or it's bad input */ if (parse_operand(token, &operand) > 0) /* parsing failed on bad input */ return CONTINUE; if (stackptr == &opstack[STACK_SIZE]) { /* stack overflow */ fprintf(stderr, "!! Stack overflow. Expression too large.\n"); return CONTINUE; } *stackptr++ = operand; } } if (stackptr - opstack > 1) fprintf(stderr, "!! Malformed expression -- too many operands.\n"); else if (stackptr - opstack == 1) { if (verbose >= 1) printf(" = %.*f\n", precision, *--stackptr); else printf("%.*f\n", precision, *--stackptr); } return CONTINUE; }