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
use nom::branch::*;
use nom::character::complete::*;
#[cfg(feature = "trace")]
use nom::{AsBytes, Offset};
use nom::{IResult, InputIter, Needed, Slice};
use nom_locate::LocatedSpan;
use nom_tracable::{cumulative_histogram, histogram, tracable_parser, TracableInfo};
#[cfg(feature = "trace")]
use nom_tracable::{HasTracableInfo, Tracable};
#[derive(Clone)]
pub struct Span<'a>(LocatedSpan<&'a [u8], TracableInfo>);
#[cfg(feature = "trace")]
impl<'a> HasTracableInfo for Span<'a> {
fn get_tracable_info(&self) -> TracableInfo {
self.0.get_tracable_info()
}
fn set_tracable_info(mut self, info: TracableInfo) -> Self {
self.0 = self.0.set_tracable_info(info);
self
}
}
#[cfg(feature = "trace")]
impl<'a> Tracable for Span<'a> {
fn inc_depth(mut self) -> Self {
self.0 = self.0.inc_depth();
self
}
fn dec_depth(mut self) -> Self {
self.0 = self.0.dec_depth();
self
}
fn format(&self) -> String {
let info = self.get_tracable_info();
let fragment: String = String::from_utf8_lossy(self.0.fragment())
.lines()
.next()
.unwrap_or_else(|| "")
.chars()
.take(info.fragment_width)
.collect();
format!("{:<8} : {}", self.0.location_offset(), fragment)
}
fn header(&self) -> String {
self.0.header()
}
}
impl<'a> InputIter for Span<'a> {
type Item = u8;
type Iter = std::iter::Enumerate<Self::IterElem>;
type IterElem = std::iter::Copied<std::slice::Iter<'a, Self::Item>>;
#[inline]
fn iter_indices(&self) -> Self::Iter {
self.0.iter_indices()
}
#[inline]
fn iter_elements(&self) -> Self::IterElem {
self.0.iter_elements()
}
#[inline]
fn position<P>(&self, predicate: P) -> Option<usize>
where
P: Fn(Self::Item) -> bool,
{
self.0.position(predicate)
}
#[inline]
fn slice_index(&self, count: usize) -> Result<usize, Needed> {
self.0.slice_index(count)
}
}
impl<'a> Slice<std::ops::RangeFrom<usize>> for Span<'a> {
fn slice(&self, range: std::ops::RangeFrom<usize>) -> Self {
Span(self.0.slice(range))
}
}
#[tracable_parser]
pub fn expr(s: Span) -> IResult<Span, String> {
alt((expr_plus, expr_minus, term))(s)
}
#[tracable_parser]
pub fn expr_plus(s: Span) -> IResult<Span, String> {
let (s, x) = term(s)?;
let (s, y) = char('+')(s)?;
let (s, z) = expr(s)?;
let ret = format!("{}{}{}", x, y, z);
Ok((s, ret))
}
#[tracable_parser]
pub fn expr_minus(s: Span) -> IResult<Span, String> {
let (s, x) = term(s)?;
let (s, y) = char('-')(s)?;
let (s, z) = expr(s)?;
let ret = format!("{}{}{}", x, y, z);
Ok((s, ret))
}
#[tracable_parser]
pub fn term(s: Span) -> IResult<Span, String> {
let (s, x) = term_internal(s)?;
Ok((s, x))
}
#[tracable_parser]
pub fn term_internal(s: Span) -> IResult<Span, String> {
let (s, x) = char('1')(s)?;
Ok((s, x.to_string()))
}
fn main() {
let info = TracableInfo::new()
.parser_width(64)
.fragment_width(20)
.fold("term");
let _ret = expr(Span(LocatedSpan::new_extra("1-1+1+1-1".as_bytes(), info)));
histogram();
cumulative_histogram();
}