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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use std::fmt::Debug;
use std::fmt::{Display, Error, Formatter};
use std::hash::Hash;

///
/// Position within a Cfg
/// Immutable struct
///
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
pub struct Pos {
    /// Index of the production
    pr_index: usize,

    /// Index of the symbol within the production
    /// 0: Always the index of the left-hand-side of the production
    /// >0: Index of a symbol on the hight-hand-side of the production
    sy_index: usize,
}

impl Pos {
    /// Creates an immutable Pos instance
    /// Panics on invalid index values.
    pub fn new(pr_index: usize, sy_index: usize) -> Self {
        Self { pr_index, sy_index }
    }

    pub fn pr_index(&self) -> usize {
        self.pr_index
    }

    pub fn sy_index(&self) -> usize {
        self.sy_index
    }

    pub fn as_tuple(&self) -> (usize, usize) {
        (self.pr_index, self.sy_index)
    }

    pub fn no_pos() -> Self {
        Self {
            pr_index: usize::MAX,
            sy_index: usize::MAX,
        }
    }
    pub fn is_no_pos(&self) -> bool {
        self.pr_index == usize::MAX && self.sy_index == usize::MAX
    }

    pub fn next_pos(&self) -> Self {
        Self {
            pr_index: self.pr_index,
            sy_index: self.sy_index + 1,
        }
    }

    pub fn next_pos_mut(&mut self) {
        self.sy_index += 1;
    }

    ///
    /// Returns true if self is the immediate successor of the given Pos.
    /// The relation holds only within a single production, i.e. the pr_index must be equal.
    ///
    /// ```
    /// use parol::Pos;
    ///
    /// let this : Pos = (0, 2).into();
    /// let that : Pos = (0, 1).into();
    /// assert!(this.follows(&that));
    /// assert!(!that.follows(&this));
    ///
    /// let this : Pos = (0, 1).into();
    /// let that : Pos = (0, 1).into();
    /// assert!(!this.follows(&that));
    /// assert!(!that.follows(&this));
    ///
    /// let this : Pos = (0, 2).into();
    /// let that : Pos = (1, 1).into();
    /// assert!(!this.preceds(&that));
    /// assert!(!that.preceds(&this));
    ///
    /// let this : Pos = (0, 1).into();
    /// let that : Pos = (0, 2).into();
    /// assert!(!this.follows(&that));
    /// assert!(that.follows(&this));
    /// ```
    ///
    pub fn follows(&self, that: &Self) -> bool {
        self.pr_index == that.pr_index && self.sy_index == that.sy_index + 1
    }

    ///
    /// Returns true if self is the immediate predecessor of the given Pos.
    /// The relation holds only within a single production, i.e. the pr_index must be equal.
    ///
    /// ```
    /// use parol::Pos;
    ///
    /// let this : Pos = (0, 2).into();
    /// let that : Pos = (0, 1).into();
    /// assert!(!this.preceds(&that));
    /// assert!(that.preceds(&this));
    ///
    /// let this : Pos = (0, 1).into();
    /// let that : Pos = (0, 1).into();
    /// assert!(!this.preceds(&that));
    /// assert!(!that.preceds(&this));
    ///
    /// let this : Pos = (0, 1).into();
    /// let that : Pos = (1, 2).into();
    /// assert!(!this.preceds(&that));
    /// assert!(!that.preceds(&this));
    ///
    /// let this : Pos = (0, 1).into();
    /// let that : Pos = (0, 2).into();
    /// assert!(this.preceds(&that));
    /// assert!(!that.preceds(&this));
    /// ```
    ///
    pub fn preceds(&self, that: &Self) -> bool {
        self.pr_index == that.pr_index && self.sy_index + 1 == that.sy_index
    }
}

impl From<(usize, usize)> for Pos {
    fn from(p: (usize, usize)) -> Self {
        Self::new(p.0, p.1)
    }
}

impl Display for Pos {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
        write!(f, "({},{})", self.pr_index, self.sy_index)
    }
}