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 136 137 138
use std::ops::{Index, RangeFrom};
/// Container for input into parsers
///
/// All parsers accept a `ParserContext` as input and [_must_](crate::Res) return one if they
/// succeed.
///
/// The structure contains [whatever input is yet to be parsed](crate::ParserContext::input) as
/// well as our [absolute position within the original input](crate::ParserContext::get_position),
/// which is useful for reporting errors.
///
/// Regular slices (i.e. `&[T]`) and string slices (i.e. `&str`) can be converted into this
/// structure by using [`ParserContext::from()`](crate::ParserContext::from), or using `.into()` in
/// contexts where the compiler can infer the type.
///
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct ParserContext<T> {
// The full input to parse
input: T,
// The input length
length: usize,
// Our current position with the input
position: usize,
}
impl<'i> From<&'i str> for ParserContext<&'i str> {
fn from(value: &'i str) -> Self {
ParserContext {
input: value,
length: value.len(),
position: 0,
}
}
}
impl<'i, T> From<&'i [T]> for ParserContext<&'i [T]> {
fn from(value: &'i [T]) -> Self {
ParserContext {
input: value,
length: value.len(),
position: 0,
}
}
}
// Note: You might be tempted to think the `Deref` trait would be cleaner to use here. However, the
// reference obtained through the `Deref` trait has the lifetime of the container. Parsers always
// accept an owned `ParserContext`, so returning a reference to it is not a allowed. We instead want
// to tell the compiler that we are returning a reference to the inner value
impl<'a, T: ?Sized> ParserContext<&'a T>
where
T: Index<RangeFrom<usize>>,
{
/// Returns the input being parsed. The first parser will see the entire input. Subsequent
/// parsers will only see whatever is left to parse
pub fn input(&self) -> &'a <T as Index<RangeFrom<usize>>>::Output {
// This is where the magic of the `ParseContext` struct comes from. It holds the entire parse
// input, but to individual parsers, will only appear to hold the part of the input they
// care about.
&self.input[self.position..]
}
}
impl<T> ParserContext<T>
where
T: Clone,
{
/// Increments the input position by `count`. If there is less than `count` elements left in
/// the input, the position will be set to the length of the input.
///
/// Advancing the position affects what subsequent calls to `.input()` return
pub(crate) fn advance_by(&mut self, count: usize) {
let offset = if self.position + count <= self.length {
count
} else {
self.length - self.position
};
self.position += offset;
}
}
impl<T> ParserContext<T> {
/// Returns `true` if this instance's position is at the end of the input
pub fn end_of_input(&self) -> bool {
self.position == self.length
}
/// Returns the current input position
pub fn get_position(&self) -> usize {
self.position
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_equality() {
let str = "A";
let ctx = ParserContext::from(str);
assert_eq!(ctx.input(), str);
assert_eq!(ctx.input(), "A");
let slice = &[0, 2, 4][..];
let ctx = ParserContext::from(slice);
assert_eq!(ctx.input(), slice);
assert_eq!(ctx.input(), &[0, 2, 4]);
}
#[test]
fn test_deref_magic() {
let str = "ABC";
let mut ctx = ParserContext::from(str);
assert_eq!(ctx.input(), "ABC");
ctx.advance_by(1);
assert_eq!(ctx.input(), "BC");
assert_eq!(&ctx.input()[0..], "BC");
ctx.advance_by(1);
assert_eq!(ctx.input(), "C");
assert_eq!(&ctx.input()[0..], "C");
ctx.advance_by(1);
assert_eq!(ctx.input(), "");
assert_eq!(&ctx.input()[0..], "");
ctx.advance_by(1);
ctx.advance_by(10);
ctx.advance_by(3);
assert_eq!(ctx.input(), "");
assert_eq!(&ctx.input()[0..], "");
}
}