bool Expression::infix2postfix() { Stack<Term> *operators = new Stack<Term>; Term t1, t2; // Verify all terms on queue while (!m_terms->isEmpty()) { m_terms->dequeue(t1); operators->top(t2); // If is a number, send to postfix queue if (is_number(t1)) { m_terms_postfix->enqueue(t1); // If isn't a number and the queue is empty or is // an opening parenthesis, send to operators stack } else if (operators->isEmpty() || is_opening_parenthesis(t1)) { // If the tokenize is right, this never should happen if (is_closing_parenthesis(t1)) { set_error(4, t1.col); delete operators; return false; } operators->push(t1); // If is a closing parenthesis, send all the operators // until the opening parenthesis to postfix queue } else if (is_closing_parenthesis(t1)) { while (!is_opening_parenthesis(t2)) { operators->pop(t2); m_terms_postfix->enqueue(t2); operators->top(t2); } assert(is_opening_parenthesis(t2)); operators->pop(t2); // Else, remove all operators who have a minor // precedence and push him to operators stack } else { while (get_precedence(t1) >= get_precedence(t2) && !operators->isEmpty() && !is_opening_parenthesis(t2)) { operators->pop(t2); m_terms_postfix->enqueue(t2); operators->top(t2); } operators->push(t1); } } // Remove remaining terms on Stack while (!operators->isEmpty()) { operators->pop(t2); // If the tokenize is right, this never should happen if (is_opening_parenthesis(t2)) { set_error(6, t2.col); delete operators; return false; } m_terms_postfix->enqueue(t2); } // Delete operators Stack to avoid memory leak delete operators; return true; }
void i2p(char infix[]) { int i=0,p=0,len,type,prec; char next,stack[20],postfix[20]; int get_type(char); int get_precedence(char); len=strlen(infix); while(i<len) { type=get_type(infix[i]); switch(type) { case 1: push(stack,infix[i]); break; case 2: while((next=pop(stack))!='(') postfix[p++]=next; break; case 3: postfix[p++]=infix[i]; break; case 4: prec=get_precedence(infix[i]); while(stack_empty()==False) { if(prec<=get_precedence(stack[top-1])) postfix[p++]=pop(stack); else break; } push(stack,infix[i]); break; } i++; } while(stack_empty()==False) postfix[p++]=pop(stack); postfix[p]='\0'; printf("%s\n",postfix); }
/* * Parse an infix expression from a token stream * Returns a parse tree * See https://en.wikipedia.org/wiki/Shunting-yard_algorithm */ Token parse_infix_expression(Token tokens){ Token operators = NULL; unsigned operatorsLen = 0; Token output = NULL; unsigned outputLen = 0; Token nextToken; while(tokens != NULL){ nextToken = tokens->next; tokens->next = NULL; // if it's not a builtin, stick it in output if(tokens->type != BUILTIN){ push_token_stack(tokens, &output, &outputLen); } else { // if it's a builtin, do magic // check if it's allowed to be here ERROR_UNLESS(!can_start_line(tokens->builtin), "statement operators not allowed in expressions") if(operatorsLen == 0){ push_token_stack(tokens, &operators, &operatorsLen); } else if(tokens->builtin == L_PAREN){ push_token_stack(tokens, &operators, &operatorsLen); } else if(tokens->builtin == R_PAREN){ // pop operators until L_PAREN free_token(&tokens); // we don't need the R_PAREN while(operatorsLen > 0 && operators->builtin != L_PAREN) pop_operator(&operators, &operatorsLen, &output, &outputLen); if(operatorsLen == 0){ // there was no L_PAREN, so error ERROR("mismatched parentheses") } else { // discard the L_PAREN Token discard = pop_token_stack(&operators, &operatorsLen); free_token(&discard); } } else if(get_precedence(tokens->builtin) > get_precedence(operators->builtin)){ push_token_stack(tokens, &operators, &operatorsLen); } else { // we are not a parenthesis and we're lower precedence than // the operator on the stack, so pop it and put us there pop_operator(&operators, &operatorsLen, &output, &outputLen); push_token_stack(tokens, &operators, &operatorsLen); } }
string ExpressionManager::infixToPostfix(string infixExpression){ stack<char> symbols; string out_str = ""; //do tests for the validity of the infix expression if(!isBalanced(infixExpression)){ return invalid; } if(!op_num_ratio_check(infixExpression)){ return invalid; } char exp_str[STR_BUFF_SIZE]; exp_str[0] = '\0'; //create a C string from the expression string //for use in strtok strcat(exp_str, infixExpression.c_str()); char * token; //use strtok to tokenize the string //separating by spaces token = strtok(exp_str, " "); while( 1 ){ if(token == NULL){ while(!symbols.empty()){ out_str += symbols.top(); out_str += " "; symbols.pop(); } break; } //cout << "token: " << token << "\n"; if(is_int_num(string(token))){ out_str += string(token); out_str += " "; } else if(is_paren( *token ) == OPEN_PAREN){ symbols.push( *token ); } else if(is_paren( *token ) == CLOSE_PAREN){ char top_char = symbols.top(); symbols.pop(); while(get_precedence(top_char) > OPEN_PAREN){ //symbols.pop(); out_str += top_char; out_str += " "; top_char = symbols.top(); symbols.pop(); } } else if(is_op( *token )){ if(symbols.empty()){ symbols.push( *token ); } else { char top_char = symbols.top(); int top_prec = get_precedence(top_char); int token_prec = get_precedence( *token ); while( top_prec >= token_prec ){ //go through any tokens with greater than or equal precedence symbols.pop(); out_str += top_char; out_str += " "; if(symbols.empty()){ break; } top_char = symbols.top(); top_prec = get_precedence(top_char); } symbols.push( *token ); } } //increment to the next token token = strtok(NULL, " "); } //to remove the last part of the string (the trailing space) //if using C++11 you can do out_str.pop_back(); out_str.erase(out_str.end() - 1); return out_str; }
uint32_t opp_parse(token_node * lookback_ptr, token_node * lookahead_ptr, token_node * list_begin, token_node * chunk_end, parsing_ctx * ctx) { uint32_t parse_result = 0; reduction_list *main_reduction_list, *temp_reduction_list; /* reduction_list represents where we are inside the reduction tree. */ uint32_t end_chunk_parse = __MORE_INPUT; uint32_t reduction_error = 0; uint32_t node = 0; token_node * current_list_pos = list_begin; token_node * prev_symbol_ptr = lookback_ptr; token_node * list_itr = NULL; vect_stack yields_prec_stack,parsing_stack; token_node * last_terminal = NULL; uint32_t prec=0; vect_stack stack; init_vect_stack(&stack, ctx->NODE_ALLOC_SIZE); init_vect_stack(&yields_prec_stack, ctx->PREC_ALLOC_SIZE); init_vect_stack(&parsing_stack, ctx->PREC_ALLOC_SIZE); main_reduction_list = (reduction_list *) malloc(sizeof(reduction_list)); init_reduction_list(main_reduction_list); temp_reduction_list = (reduction_list *) malloc(sizeof(reduction_list)); init_reduction_list(temp_reduction_list); /* set correctly last_terminal and current_pos */ while ( !( is_terminal(current_list_pos->token) || end_chunk_parse ) ) { end_chunk_parse = get_next_token(¤t_list_pos, &prev_symbol_ptr, chunk_end, lookahead_ptr); } last_terminal= is_terminal(lookback_ptr->token) ? lookback_ptr : current_list_pos; /* Start the parsing process. */ while (current_list_pos != NULL) { /* lookup precedence between last stack terminal token and new token. */ prec = get_precedence(current_list_pos,last_terminal); /*this was inserted by the guys: add the string terminator to the precedence table to remove this cruft */ if (lookback_ptr->token == __TERM && prec == __EQ && yields_prec_stack.top_of_stack == 0) { prec = __GT; } /* Invalid precedence value fetched from precedence table, abort parsing */ if (prec == __NOP) { parse_result = __PARSE_ERROR; break; } /* if precedence is __EQ or __LT, we should shift */ if (prec != __GT || yields_prec_stack.top_of_stack == 0) { if (end_chunk_parse == __END_OF_INPUT) { parse_result = __PARSE_IN_PROGRESS; break; } /* Push token_node on top of yields_prec_stack. */ if (prec == __LT) { vect_stack_push(&yields_prec_stack, last_terminal, ctx->PREC_REALLOC_SIZE); } /* Get next token. */ assert(is_terminal(current_list_pos->token)); vect_stack_push(&parsing_stack, last_terminal, ctx->NODE_REALLOC_SIZE); last_terminal=current_list_pos; end_chunk_parse = get_next_token(¤t_list_pos, &prev_symbol_ptr, chunk_end, lookahead_ptr); } else { /*clear reduction list */ main_reduction_list->idx_last = 0; /* node is the offset of the root of the vectorized reduction trie. */ node = vect_reduction_tree[0]; /* obtain the position of the previous yields precedence */ prev_symbol_ptr = vect_stack_pop(&yields_prec_stack); /* add pop to parsing stack to remove all the terminals up to the one which should be reduced */ while (last_terminal!= prev_symbol_ptr && last_terminal!=NULL){ last_terminal=vect_stack_pop(&parsing_stack); } /* the stack pop should always be successful, as TOS !=0 * it should_never get here*/ assert(prev_symbol_ptr !=NULL); list_itr = prev_symbol_ptr->next; /* Set the first element of the reduction list to the root. */ append_position_on_reduction_list(main_reduction_list, node); reduction_error = 0; /* starting from the previous yields precedence scan the candidate rhs and *match it against the reduction trie */ while (list_itr != NULL && list_itr != current_list_pos && list_itr != chunk_end) { /* For each available position in the reduction tree. */ uint32_t i; for (i = 0; i < main_reduction_list->idx_last; i++) { reduction_step(temp_reduction_list, get_reduction_position_at_index(main_reduction_list, i), list_itr, ctx); } swap_reduction_lists(&temp_reduction_list, &main_reduction_list); /* erase temp_reduction_list */ temp_reduction_list->idx_last = 0; list_itr = list_itr->next; /* If there is at least one available position in the reduction tree after having considered current token, go on. */ if (main_reduction_list->idx_last <= 0) { reduction_error = 1; break; } } /* Finished handle identification. */ if (!reduction_error && vect_reduction_tree[get_reduction_position_at_index(main_reduction_list, 0)] == __GRAMMAR_SIZE) { DEBUG_PRINT("Not in reducible position.\n") reduction_error = 1; } if (!reduction_error) { call_semantics(main_reduction_list, prev_symbol_ptr, &stack, ctx); } else { parse_result = __PARSE_NOT_RECOGNIZED; break; } /* if the axiom is reached and only two terminators are left reduce and exit */ if (lookback_ptr->token == __TERM && ctx->token_list->next == NULL && current_list_pos->token == __TERM && !is_terminal(ctx->token_list->token) && rewrite_to_axiom(ctx->token_list->token)) { perform_rewrite(lookback_ptr, ctx->token_list->token, __S, &stack, ctx); parse_result = __PARSE_SUCCESS; break; } } /* If next token is a nonterminal just move on. Eventually you might hit the terminator */ while ( !( is_terminal(current_list_pos->token) || end_chunk_parse ) ) { end_chunk_parse = get_next_token(¤t_list_pos, &prev_symbol_ptr, chunk_end, lookahead_ptr); } }/*end of the parsing loop */ cleanup_stack_and_lists(&yields_prec_stack, main_reduction_list, temp_reduction_list); return parse_result; }
static int compile(scriptlet *s, const char *src) { compiletime c = (compiletime)calloc(1, sizeof(struct compiletime_)); c->s = s; s->it_codes = 0; token tok; while ((src = get_token(src, tok)) != 0) { int precedence = get_precedence(tok); if (precedence) { DEBUG printf("operator '%s' precedence=%d\n", tok, precedence); } else { DEBUG printf("operand '%s'\n", tok); } if (!precedence) { push_operand(c, tok); continue; } if (!strcmp(tok, "(")) { push_operator(c, tok, precedence); continue; } int top_precedence, discard = 0, empty_list; const char *top_op; while ((top_op = head_operator(c, &top_precedence, &empty_list)), !empty_list) { if (!strcmp(top_op, "(") && !strcmp(tok, ")")) { int operand_count; pop_operator(c, &operand_count); discard = 1; continue; } DEBUG printf("top_op = '%s' with precedence = %d\n", top_op, top_precedence); if (precedence > top_precedence) break; if (!compile_operator(c)) { free(c); return 0; } if (discard) break; } if (!discard) push_operator(c, tok, precedence); } int top_precedence, empty_list; const char *top_op; while ((top_op = head_operator(c, &top_precedence, &empty_list)), !empty_list ) { DEBUG printf("top_op = '%s'\n", top_op); if (!compile_operator(c)) { free(c); return 0; } } free(c); return 1; }