u8_custom_parser/
u8_custom_parser.rs

1use nom::branch::*;
2use nom::character::complete::*;
3use nom::{IResult, InputIter, Needed, Slice};
4use nom_locate::LocatedSpan;
5use nom_tracable::{cumulative_histogram, histogram, tracable_parser, TracableInfo};
6#[cfg(feature = "trace")]
7use nom_tracable::{HasTracableInfo, Tracable};
8
9#[derive(Clone)]
10pub struct Span<'a>(LocatedSpan<&'a [u8], TracableInfo>);
11
12#[cfg(feature = "trace")]
13impl<'a> HasTracableInfo for Span<'a> {
14    fn get_tracable_info(&self) -> TracableInfo {
15        self.0.get_tracable_info()
16    }
17
18    fn set_tracable_info(mut self, info: TracableInfo) -> Self {
19        self.0 = self.0.set_tracable_info(info);
20        self
21    }
22}
23#[cfg(feature = "trace")]
24impl<'a> Tracable for Span<'a> {
25    fn inc_depth(mut self) -> Self {
26        self.0 = self.0.inc_depth();
27        self
28    }
29
30    fn dec_depth(mut self) -> Self {
31        self.0 = self.0.dec_depth();
32        self
33    }
34
35    // Customize fragment format for &[u8]
36    fn format(&self) -> String {
37        let info = self.get_tracable_info();
38        let fragment: String = String::from_utf8_lossy(self.0.fragment())
39            .lines()
40            .next()
41            .unwrap_or_else(|| "")
42            .chars()
43            .take(info.fragment_width)
44            .collect();
45        format!("{:<8} : {}", self.0.location_offset(), fragment)
46    }
47
48    fn header(&self) -> String {
49        self.0.header()
50    }
51}
52impl<'a> InputIter for Span<'a> {
53    type Item = u8;
54    type Iter = std::iter::Enumerate<Self::IterElem>;
55    type IterElem = std::iter::Copied<std::slice::Iter<'a, Self::Item>>;
56    #[inline]
57    fn iter_indices(&self) -> Self::Iter {
58        self.0.iter_indices()
59    }
60    #[inline]
61    fn iter_elements(&self) -> Self::IterElem {
62        self.0.iter_elements()
63    }
64    #[inline]
65    fn position<P>(&self, predicate: P) -> Option<usize>
66    where
67        P: Fn(Self::Item) -> bool,
68    {
69        self.0.position(predicate)
70    }
71    #[inline]
72    fn slice_index(&self, count: usize) -> Result<usize, Needed> {
73        self.0.slice_index(count)
74    }
75}
76impl<'a> Slice<std::ops::RangeFrom<usize>> for Span<'a> {
77    fn slice(&self, range: std::ops::RangeFrom<usize>) -> Self {
78        Span(self.0.slice(range))
79    }
80}
81
82// Apply tracable_parser by custom attribute
83#[tracable_parser]
84pub fn expr(s: Span) -> IResult<Span, String> {
85    alt((expr_plus, expr_minus, term))(s)
86}
87
88#[tracable_parser]
89pub fn expr_plus(s: Span) -> IResult<Span, String> {
90    let (s, x) = term(s)?;
91    let (s, y) = char('+')(s)?;
92    let (s, z) = expr(s)?;
93    let ret = format!("{}{}{}", x, y, z);
94    Ok((s, ret))
95}
96
97#[tracable_parser]
98pub fn expr_minus(s: Span) -> IResult<Span, String> {
99    let (s, x) = term(s)?;
100    let (s, y) = char('-')(s)?;
101    let (s, z) = expr(s)?;
102    let ret = format!("{}{}{}", x, y, z);
103    Ok((s, ret))
104}
105
106#[tracable_parser]
107pub fn term(s: Span) -> IResult<Span, String> {
108    let (s, x) = term_internal(s)?;
109    Ok((s, x))
110}
111
112#[tracable_parser]
113pub fn term_internal(s: Span) -> IResult<Span, String> {
114    let (s, x) = char('1')(s)?;
115    Ok((s, x.to_string()))
116}
117
118fn main() {
119    // Configure trace setting
120    let info = TracableInfo::new()
121        .parser_width(64)
122        .fragment_width(20)
123        .fold("term");
124    let _ret = expr(Span(LocatedSpan::new_extra("1-1+1+1-1".as_bytes(), info)));
125
126    // Show histogram
127    histogram();
128    cumulative_histogram();
129}