1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
// Copyright 2017 The nom-operator project developers
//
// 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. This file may not be copied, modified, or distributed
// except according to those terms.

//! An Operator wrapper with extra info for parsing

use std::fmt;
use IResult;
use Parser;

/// An Operator wrapper with extra info for parsing
pub struct Operator<O> {
    /// The underlying operator enum
    pub op: O,

    /// The associativity of the operator
    pub associativity: Associativity,

    /// Size of the operator, Unary, Binary, etc...
    pub size: OperatorSize,

    /// The precedence of the operator
    /// If * has precedence 10 and - has precedence 9
    /// the following expression 1 * 2 - 3
    /// would parse as (1 * 2) - 3
    pub precedence: usize,

    /// The nom parser function
    pub parser: Parser,
}


impl<O> Operator<O> {
    /// Creates a new operator
    pub fn new(op: O,
               assoc: Associativity,
               size: OperatorSize,
               prec: usize,
               parser: Parser) -> Self {
        Operator {
            op: op,
            associativity: assoc,
            size: size,
            precedence: prec,
            parser: parser,
        }
    }
}

impl<O: fmt::Debug> fmt::Debug for Operator<O> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "Operator<{:?}>: \n\tAssociativity: {:?}\n\tPrecedence: {}",
               self.op,
               self.associativity,
               self.precedence)
    }
}

impl<O: PartialEq> PartialEq for Operator<O> {
    // TODO: Should we compare the parser?
    fn eq(&self, other: &Operator<O>) -> bool {
        self.op == other.op &&
            self.associativity == other.associativity &&
            self.precedence == other.precedence
    }
}

/// Size of the operator
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum OperatorSize {
    /// Unary operator
    ///
    /// ++x
    Unary,

    /// Binary operator
    ///
    /// 5 ^ 5
    Binary,
}


/// Associativity of the operator
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Associativity {
    /// Left associative operator
    ///
    /// 5 * 5 * 7 = (5 * 5) * 7
    Left,

    /// Right associative operator
    ///
    /// 5 ^ 5 ^ 9 = 5 ^ (5 ^ 9)
    Right,
}