<commit_before>
use lexer;
use rpn_calculator as calc;
use token;

pub struct ShuntingYard<'a> {
    lexer: lexer::Lexer<'a>,
    output_queue: Vec<token::Token>,
    stack: Vec<token::Token>,
    pub errors: Vec<String>
}

impl<'a> ShuntingYard<'a> {
    pub fn new(raw_input: &str) -> ShuntingYard {
        let mut yard = ShuntingYard {
            lexer: lexer::Lexer::new(raw_input),
            output_queue: vec![],
            stack: vec![],
            errors: vec![]
        };

        let lexer_errors = yard.lexer.errors.clone();
        yard.errors.extend(lexer_errors);

        yard.transform();
        yard
    }

    pub fn calculate(&self) -> f64 {
        calc::calculate(&self.output_queue)
    }

    // Transforms the input from the Lexer in to the output_queue
    // and stack based on the Shunting Yard algorithm
    fn transform(&mut self) {
        // Iterate over each token and move it based on the algorithm
        for t in self.lexer.ast.to_vec() {
            // If the token is a number, then add it to the output queue
            match t {
                token::Token::WholeNumber(_) => self.output_queue.push(t),
                token::Token::DecimalNumber(_) => self.output_queue.push(t),
                token::Token::Operator(o1, o1_associativity, o1_precedence) => {
                    while true {
                        match self.stack.last() {
                            Some(&token::Token::Operator(_, _, o2_precedence)) => {
                                if (o1_associativity == token::LEFT_ASSOCIATIVE &&
                                   o1_precedence <= o2_precedence) ||
                                   (o1_associativity == token::RIGHT_ASSOCIATIVE &&
                                   o1_precedence < o2_precedence) {
                                    self.output_queue.push(self.stack.pop().unwrap());
                                } else {
                                    self.stack.push(token::Token::Operator(o1, o1_associativity, o1_precedence));
                                    break
                                }
                            },
                            _ => { self.stack.push(token::Token::Operator(o1, o1_associativity, o1_precedence)); break; }
                        }
                    }
                },
                token::Token::LeftParenthesis => self.stack.push(token::Token::LeftParenthesis),
                token::Token::RightParenthesis => {
                    while true {
                        match self.stack.last() {
                            Some(&token::Token::LeftParenthesis) => { self.stack.pop().unwrap(); },
                            None => break,
                            _ => self.output_queue.push(self.stack.pop().unwrap()),
                        }
                    }
                },
                _ => ()
            }
        }

        // Are there any operators left on the stack?
        while self.stack.len() > 0 {
            let op = self.stack.pop();
            match op {
                Some(token::Token::Operator(o, oa, op)) => {
                    self.output_queue.push(token::Token::Operator(o, oa, op)); 
                },
                Some(token::Token::LeftParenthesis) => {
                    self.errors.push("Unbalanced parenthesis".to_string());
                    break;
                },
                Some(token::Token::RightParenthesis) => {
                    self.errors.push("Unbalanced parenthesis".to_string());
                    break;
                },
                _ => ()<commit_msg>Fixed unbalanced paren when no corresponding left paren matched<commit_after>
use lexer;
use rpn_calculator as calc;
use token;

pub struct ShuntingYard<'a> {
    lexer: lexer::Lexer<'a>,
    output_queue: Vec<token::Token>,
    stack: Vec<token::Token>,
    pub errors: Vec<String>
}

impl<'a> ShuntingYard<'a> {
    pub fn new(raw_input: &str) -> ShuntingYard {
        let mut yard = ShuntingYard {
            lexer: lexer::Lexer::new(raw_input),
            output_queue: vec![],
            stack: vec![],
            errors: vec![]
        };

        let lexer_errors = yard.lexer.errors.clone();
        yard.errors.extend(lexer_errors);

        yard.transform();
        yard
    }

    pub fn calculate(&self) -> f64 {
        calc::calculate(&self.output_queue)
    }

    // Transforms the input from the Lexer in to the output_queue
    // and stack based on the Shunting Yard algorithm
    fn transform(&mut self) {
        // Iterate over each token and move it based on the algorithm
        for t in self.lexer.ast.to_vec() {
            // If the token is a number, then add it to the output queue
            match t {
                token::Token::WholeNumber(_) => self.output_queue.push(t),
                token::Token::DecimalNumber(_) => self.output_queue.push(t),
                token::Token::Operator(o1, o1_associativity, o1_precedence) => {
                    while true {
                        match self.stack.last() {
                            Some(&token::Token::Operator(_, _, o2_precedence)) => {
                                if (o1_associativity == token::LEFT_ASSOCIATIVE &&
                                   o1_precedence <= o2_precedence) ||
                                   (o1_associativity == token::RIGHT_ASSOCIATIVE &&
                                   o1_precedence < o2_precedence) {
                                    self.output_queue.push(self.stack.pop().unwrap());
                                } else {
                                    self.stack.push(token::Token::Operator(o1, o1_associativity, o1_precedence));
                                    break
                                }
                            },
                            _ => { self.stack.push(token::Token::Operator(o1, o1_associativity, o1_precedence)); break; }
                        }
                    }
                },
                token::Token::LeftParenthesis => self.stack.push(token::Token::LeftParenthesis),
                token::Token::RightParenthesis => {
                    let mut found_left_paren = false;
                    while true {
                        match self.stack.last() {
                            Some(&token::Token::LeftParenthesis) => {
                                found_left_paren = true;
                                self.stack.pop().unwrap(); 
                            },
                            None => {
                                if !found_left_paren {
                                    self.errors.push("Unbalanced parenthesis".to_string());
                                }
                                break;
                            },
                            _ => self.output_queue.push(self.stack.pop().unwrap()),
                        }
                    }
                },
                _ => ()
            }
        }

        // Are there any operators left on the stack?
        while self.stack.len() > 0 {
            let op = self.stack.pop();
            match op {
                Some(token::Token::Operator(o, oa, op)) => {
                    self.output_queue.push(token::Token::Operator(o, oa, op)); 
                },
                Some(token::Token::LeftParenthesis) => {
                    self.errors.push("Unbalanced parenthesis".to_string());
                    break;
                },
                Some(token::Token::RightParenthesis) => {
                    self.errors.push("Unbalanced parenthesis".to_string());
                    break;
                },
                _ => ()
{'fraction_non_alphanumeric': 0.1123273390669794, 'fraction_numerical': 0.0049517852488923635, 'mean_word_length': 1.2317534166908986, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6939699', 'n_tokens_mistral': 2044, 'n_tokens_neox': 1918, 'n_words': 370}