dynparser/parser/expression/
mod.rs

1#![warn(missing_docs)]
2//! Here we have the parser for non atomic things
3
4use super::super::idata::{
5    cont::IVec,
6    tc::{tail_call, TailCall},
7};
8use ast;
9use parser::{atom, atom::Atom, ErrPriority, Error, Result, Status};
10use std::collections::HashMap;
11use std::result;
12
13#[cfg(test)]
14mod test;
15
16//-----------------------------------------------------------------------
17//-----------------------------------------------------------------------
18//
19//  T Y P E S
20//
21//-----------------------------------------------------------------------
22//-----------------------------------------------------------------------
23
24#[derive(Clone, Copy, Debug)]
25pub(crate) struct Started(usize);
26
27pub(crate) type ResultExpr<'a> = result::Result<(Status<'a>, Vec<ast::Node>), Error>;
28
29/// The set of rules to be parsed
30/// Any rule has a name
31/// A rule can be registered just once
32/// The starting rule is main
33#[derive(Debug)]
34pub struct SetOfRules(pub(crate) HashMap<String, Expression>);
35
36impl SetOfRules {
37    /// Initialize a set of rules with a hashmap of <String, Expression>
38    /// In general, is better to use the ```rules!``` macro
39    pub fn new(mrules: HashMap<String, Expression>) -> Self {
40        SetOfRules(mrules)
41    }
42
43    /// As this is a dynamic parser, it is necessary to add rules on
44    /// runtime.
45    ///
46    /// This method, will take the owner ship, and will return itself
47    ///
48    /// In this way, you don't need to declare mutable vars.
49    /// You could need recursion in some cases
50    ///
51    /// To add several rules at once, look for merge
52    ///
53    /// ```
54    /// #[macro_use]  extern crate dynparser;
55    /// use dynparser::parse;
56    ///
57    /// fn main() {
58    ///     let rules = rules!{
59    ///        "main"   =>  and!{
60    ///                         rep!(lit!("a"), 1, 5),
61    ///                         ref_rule!("rule2")
62    ///                     }
63    ///     };
64    ///
65    ///     let rules = rules.add("rule2", lit!("bcd"));
66    ///
67    ///     assert!(parse("aabcd", &rules).is_ok())
68    /// }
69    /// ```
70    pub fn add(mut self, name: &str, expr: Expression) -> Self {
71        self.0.insert(name.to_owned(), expr);
72        self
73    }
74
75    /// As this is a dynamic parser, it is necessary to add rules on
76    /// runtime.
77    ///
78    /// This method, will take the owner ship, and will return itself
79    ///
80    /// In this way, you don't need to declare mutable vars.
81    /// You could need recursion in some cases
82    ///
83    /// It will add the rules from the parameter
84    ///
85    /// ```
86    /// #[macro_use]  extern crate dynparser;
87    /// use dynparser::parse;
88    ///
89    /// fn main() {
90    ///     let rules = rules!{
91    ///        "main"   =>  and!{
92    ///                         rep!(lit!("a"), 1, 5),
93    ///                         ref_rule!("rule2")
94    ///                     }
95    ///     };
96    ///
97    ///     let rules = rules.merge(rules!{"rule2" => lit!("bcd")});
98    ///
99    ///     assert!(parse("aabcd", &rules).is_ok())
100    /// }
101    /// ```
102    pub fn merge(self, rules2merge: Self) -> Self {
103        SetOfRules(rules2merge.0.into_iter().chain(self.0).collect())
104    }
105}
106
107#[allow(missing_docs)]
108#[derive(Debug)]
109pub enum Expression {
110    Simple(Atom),
111    And(MultiExpr),
112    Or(MultiExpr),
113    Not(Box<Expression>),
114    Repeat(RepInfo),
115    RuleName(String),
116}
117
118/// Opaque type to manage multiple expressions
119#[derive(Debug)]
120pub struct MultiExpr(pub(crate) Vec<Expression>);
121
122impl MultiExpr {
123    /// Creates a new instance of ```MultiExpr``` from a vector
124    pub fn new(v: Vec<Expression>) -> Self {
125        MultiExpr(v)
126    }
127}
128
129/// Opaque type to manage repetition subexpression
130#[derive(Debug)]
131pub struct RepInfo {
132    pub(crate) expression: Box<Expression>,
133    pub(crate) min: NRep,
134    pub(crate) max: Option<NRep>,
135}
136
137impl RepInfo {
138    /// Creates a Repeticion Info for an expression with min and
139    /// optionally max values to repeat
140    pub fn new(expression: Box<Expression>, min: usize, max: Option<usize>) -> Self {
141        RepInfo {
142            expression,
143            min: NRep(min),
144            max: max.map(NRep),
145        }
146    }
147}
148
149/// Number of repetitions of rule
150#[derive(Debug)]
151pub(crate) struct NRep(pub(crate) usize);
152
153//-----------------------------------------------------------------------
154//-----------------------------------------------------------------------
155//
156//  A P I
157//
158//-----------------------------------------------------------------------
159//-----------------------------------------------------------------------
160
161//-----------------------------------------------------------------------
162pub(crate) fn parse(status: Status) -> Result {
163    parse_rule_name(status, "main")
164}
165
166//-----------------------------------------------------------------------
167//  SUPPORT
168
169//-----------------------------------------------------------------------
170fn parse_rule_name<'a>(status: Status<'a>, rule_name: &str) -> Result<'a> {
171    // use std::time::{Duration, Instant};
172    // let start = Instant::now();
173
174    let status = if status.trace_rules {
175        status.push_rule(&format!("r:{}", rule_name))
176    } else {
177        status
178    };
179
180    let rules = &status.rules.0;
181    let expression = rules.get(rule_name).ok_or_else(|| {
182        Error::from_status(
183            &status,
184            &format!("Missing rule: {}", rule_name),
185            ErrPriority::Critical,
186        )
187    })?;
188    let (st, nodes) = parse_expr(status, &expression)?;
189
190    // let elapsed = start.elapsed();
191    // println!(
192    //     "____ elapsed time parsing {} {}.{}",
193    //     rule_name,
194    //     elapsed.as_secs(),
195    //     elapsed.subsec_millis()
196    // );
197    Ok((st, ast::Node::Rule((rule_name.to_owned(), nodes))))
198}
199
200fn parse_atom_as_expr<'a>(status: Status<'a>, a: &'a Atom) -> ResultExpr<'a> {
201    let (st, node) = atom::parse(status, a)?;
202    Ok((st, vec![node]))
203}
204
205fn parse_rule_name_as_expr<'a>(status: Status<'a>, rule_name: &str) -> ResultExpr<'a> {
206    let (st, ast) = parse_rule_name(status, rule_name)?;
207    Ok((st, vec![ast]))
208}
209
210fn parse_expr<'a>(status: Status<'a>, expression: &'a Expression) -> ResultExpr<'a> {
211    match *expression {
212        Expression::Simple(ref val) => parse_atom_as_expr(status, &val),
213        Expression::And(ref val) => parse_and(status, &val),
214        Expression::Or(ref val) => parse_or(&status, &val),
215        Expression::Not(ref val) => parse_not(status, &val),
216        Expression::Repeat(ref val) => parse_repeat(status, &val),
217        Expression::RuleName(ref val) => parse_rule_name_as_expr(status, &val),
218    }
219}
220
221//-----------------------------------------------------------------------
222fn parse_and<'a>(status: Status<'a>, multi_expr: &'a MultiExpr) -> ResultExpr<'a> {
223    let init_tc: (_, &[Expression], Vec<ast::Node>) = (status, &(multi_expr.0), vec![]);
224
225    tail_call(init_tc, |acc| {
226        if acc.1.is_empty() {
227            TailCall::Return(Ok((acc.0, acc.2)))
228        } else {
229            let result_parse = parse_expr(acc.0, &acc.1[0]);
230            match result_parse {
231                Ok((status, vnodes)) => {
232                    TailCall::Call((status, &acc.1[1..], acc.2.iappend(vnodes)))
233                }
234                Err(err) => TailCall::Return(Err(err)),
235            }
236        }
237    })
238}
239
240//-----------------------------------------------------------------------
241fn parse_or<'a>(status: &Status<'a>, multi_expr: &'a MultiExpr) -> ResultExpr<'a> {
242    let deep_err = |oe1: Option<Error>, e2: Error| match oe1 {
243        Some(e1) => match (e1.priority > e2.priority, e1.pos.n > e2.pos.n) {
244            (true, _) => Some(e1),
245            (false, true) => Some(e1),
246            (false, false) => Some(e2),
247        },
248        None => Some(e2),
249    };
250
251    // let init_tc: (_, &[Expression], Vec<Error>) = (status.clone(), &(multi_expr.0), vec![]);
252    let init_tc: (_, &[Expression], _) = (status.clone(), &(multi_expr.0), None);
253
254    tail_call(init_tc, |acc| {
255        if acc.1.is_empty() {
256            TailCall::Return(Err(match acc.2 {
257                Some(err) => err,
258                _ => Error::from_st_errs(
259                    &status,
260                    "LOGIC ERROR!!! checked all options in or with ¿NO? errors",
261                    vec![],
262                ),
263            }))
264        } else {
265            let try_parse = parse_expr(acc.0.clone(), &acc.1[0]);
266            match try_parse {
267                Ok(result) => TailCall::Return(Ok(result)),
268                Err(e) => {
269                    if e.priority == ErrPriority::Critical {
270                        TailCall::Return(Err(e))
271                    } else {
272                        TailCall::Call((acc.0, &acc.1[1..], deep_err(acc.2, e)))
273                    }
274                }
275            }
276        }
277    })
278}
279
280//-----------------------------------------------------------------------
281fn parse_not<'a>(status: Status<'a>, expression: &'a Expression) -> ResultExpr<'a> {
282    match parse_expr(status.clone(), expression) {
283        Ok(_) => Err(Error::from_status_normal(&status, "not")),
284        Err(_) => Ok((status, vec![])),
285    }
286}
287
288//-----------------------------------------------------------------------
289fn parse_repeat<'a>(status: Status<'a>, rep_info: &'a RepInfo) -> ResultExpr<'a> {
290    let big_min_bound = |counter| counter >= rep_info.min.0;
291    let touch_max_bound = |counter: usize| match rep_info.max {
292        Some(ref m) => counter + 1 == m.0,
293        None => false,
294    };
295
296    let init_tc: (_, _, Vec<ast::Node>) = (status, 0, vec![]);
297    Ok(tail_call(init_tc, |acc| {
298        let try_parse = parse_expr(acc.0.clone(), &rep_info.expression);
299        match (try_parse, big_min_bound(acc.1), touch_max_bound(acc.1)) {
300            (Err(e), true, _) => if e.priority == ErrPriority::Critical {
301                TailCall::Return(Err(e))
302            } else {
303                TailCall::Return(Ok((acc.0.set_potential_error(e), acc.2)))
304            },
305            (Err(e), false, _) => TailCall::Return(Err(e)),
306            //     Err(Error::from_status(
307            //     &acc.0,
308            //     &format!("inside repeat {:#?}", e),
309            // ))),
310            (Ok((status, vnodes)), _, false) => {
311                TailCall::Call((status, acc.1 + 1, acc.2.iappend(vnodes)))
312            }
313            (Ok((status, vnodes)), _, true) => {
314                TailCall::Return(Ok((status, acc.2.iappend(vnodes))))
315            }
316        }
317    })?)
318}
319//  SUPPORT
320//-----------------------------------------------------------------------