// pest. The Elegant Parser
// Copyright (c) 2018 Dragoș Tiselice
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

#[macro_use]
extern crate pest;

use pest::error::Error;
use pest::iterators::{Pair, Pairs};
use pest::prec_climber::{Assoc, Operator, PrecClimber};
use pest::{state, ParseResult, Parser, ParserState};

#[allow(dead_code, non_camel_case_types)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
enum Rule {
    expression,
    primary,
    number,
    plus,
    minus,
    times,
    divide,
    modulus,
    power,
}

struct CalculatorParser;

impl Parser<Rule> for CalculatorParser {
    fn parse(rule: Rule, input: &str) -> Result<Pairs<Rule>, Error<Rule>> {
        fn expression(state: Box<ParserState<Rule>>) -> ParseResult<Box<ParserState<Rule>>> {
            state.rule(Rule::expression, |s| {
                s.sequence(|s| {
                    primary(s).and_then(|s| {
                        s.repeat(|s| {
                            s.sequence(|s| {
                                plus(s)
                                    .or_else(|s| minus(s))
                                    .or_else(|s| times(s))
                                    .or_else(|s| divide(s))
                                    .or_else(|s| modulus(s))
                                    .or_else(|s| power(s))
                                    .and_then(|s| primary(s))
                            })
                        })
                    })
                })
            })
        }

        fn primary(state: Box<ParserState<Rule>>) -> ParseResult<Box<ParserState<Rule>>> {
            state
                .sequence(|s| {
                    s.match_string("(")
                        .and_then(|s| expression(s))
                        .and_then(|s| s.match_string(")"))
                })
                .or_else(|s| number(s))
        }

        fn number(state: Box<ParserState<Rule>>) -> ParseResult<Box<ParserState<Rule>>> {
            state.rule(Rule::number, |s| {
                s.sequence(|s| {
                    s.optional(|s| s.match_string("-")).and_then(|s| {
                        s.match_string("0").or_else(|s| {
                            s.sequence(|s| {
                                s.match_range('1'..'9')
                                    .and_then(|s| s.repeat(|s| s.match_range('0'..'9')))
                            })
                        })
                    })
                })
            })
        }

        fn plus(state: Box<ParserState<Rule>>) -> ParseResult<Box<ParserState<Rule>>> {
            state.rule(Rule::plus, |s| s.match_string("+"))
        }

        fn minus(state: Box<ParserState<Rule>>) -> ParseResult<Box<ParserState<Rule>>> {
            state.rule(Rule::minus, |s| s.match_string("-"))
        }

        fn times(state: Box<ParserState<Rule>>) -> ParseResult<Box<ParserState<Rule>>> {
            state.rule(Rule::times, |s| s.match_string("*"))
        }

        fn divide(state: Box<ParserState<Rule>>) -> ParseResult<Box<ParserState<Rule>>> {
            state.rule(Rule::divide, |s| s.match_string("/"))
        }

        fn modulus(state: Box<ParserState<Rule>>) -> ParseResult<Box<ParserState<Rule>>> {
            state.rule(Rule::modulus, |s| s.match_string("%"))
        }

        fn power(state: Box<ParserState<Rule>>) -> ParseResult<Box<ParserState<Rule>>> {
            state.rule(Rule::power, |s| s.match_string("^"))
        }

        state(input, |state| match rule {
            Rule::expression => expression(state),
            _ => unreachable!(),
        })
    }
}

fn consume<'i>(pair: Pair<'i, Rule>, climber: &PrecClimber<Rule>) -> i32 {
    let primary = |pair| consume(pair, climber);
    let infix = |lhs: i32, op: Pair<Rule>, rhs: i32| match op.as_rule() {
        Rule::plus => lhs + rhs,
        Rule::minus => lhs - rhs,
        Rule::times => lhs * rhs,
        Rule::divide => lhs / rhs,
        Rule::modulus => lhs % rhs,
        Rule::power => lhs.pow(rhs as u32),
        _ => unreachable!(),
    };

    match pair.as_rule() {
        Rule::expression => climber.climb(pair.into_inner(), primary, infix),
        Rule::number => pair.as_str().parse().unwrap(),
        _ => unreachable!(),
    }
}

#[test]
fn number() {
    parses_to! {
        parser: CalculatorParser,
        input: "-12",
        rule: Rule::expression,
        tokens: [
            expression(0, 3, [
                number(0, 3)
            ])
        ]
    };
}

#[test]
fn parens() {
    parses_to! {
        parser: CalculatorParser,
        input: "((-12))",
        rule: Rule::expression,
        tokens: [
            expression(0, 7, [
                expression(1, 6, [
                    expression(2, 5, [
                        number(2, 5)
                    ])
                ])
            ])
        ]
    };
}

#[test]
fn expression() {
    parses_to! {
        parser: CalculatorParser,
        input: "-12+3*(4-9)^7^2",
        rule: Rule::expression,
        tokens: [
            expression(0, 15, [
                number(0, 3),
                plus(3, 4),
                number(4, 5),
                times(5, 6),
                expression(7, 10, [
                    number(7, 8),
                    minus(8, 9),
                    number(9, 10)
                ]),
                power(11, 12),
                number(12, 13),
                power(13, 14),
                number(14, 15)
            ])
        ]
    };
}

#[test]
fn prec_climb() {
    let climber = PrecClimber::new(vec![
        Operator::new(Rule::plus, Assoc::Left) | Operator::new(Rule::minus, Assoc::Left),
        Operator::new(Rule::times, Assoc::Left)
            | Operator::new(Rule::divide, Assoc::Left)
            | Operator::new(Rule::modulus, Assoc::Left),
        Operator::new(Rule::power, Assoc::Right),
    ]);

    let pairs = CalculatorParser::parse(Rule::expression, "-12+3*(4-9)^3^2/9%7381");
    assert_eq!(-1_525, consume(pairs.unwrap().next().unwrap(), &climber));
}
