piston_meta/meta_rules/
optional.rs1use range::Range;
2use read_token::ReadToken;
3
4use super::{
5 ret_err,
6 update,
7 IndentSettings,
8};
9use {
10 DebugId,
11 MetaData,
12 ParseError,
13 Rule,
14};
15use tokenizer::TokenizerState;
16
17#[derive(Clone, Debug, PartialEq)]
19pub struct Optional {
20 pub rule: Rule,
22 pub debug_id: DebugId,
24}
25
26impl Optional {
27 pub fn parse(
30 &self,
31 tokens: &mut Vec<Range<MetaData>>,
32 state: &TokenizerState,
33 read_token: &ReadToken,
34 refs: &[Rule],
35 indent_settings: &mut IndentSettings,
36 ) -> (Range, TokenizerState, Option<Range<ParseError>>) {
37 let start = read_token;
38 let mut read_token = *start;
39 let mut success_state = state.clone();
40 let mut opt_error = None;
41 success_state = match self.rule.parse(
42 tokens, &success_state, &read_token, refs, indent_settings
43 ) {
44 Ok((range, state, err)) => {
45 update(range, err, &mut read_token, &mut opt_error);
46 state
47 }
48 Err(err) => {
49 return (start.start(), state.clone(),
50 Some(ret_err(err, opt_error)))
51 }
52 };
53 (read_token.subtract(start), success_state, opt_error)
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use all::*;
60 use all::tokenizer::*;
61 use meta_rules::{ IndentSettings, Number, Optional, Sequence, Text };
62 use range::Range;
63 use read_token::ReadToken;
64 use std::sync::Arc;
65
66 #[test]
67 fn fail_but_continue() {
68 let ref mut indent_settings = IndentSettings::default();
69 let text = "2";
70 let mut tokens = vec![];
71 let s = TokenizerState::new();
72 let num: Arc<String> = Arc::new("num".into());
73 let optional = Optional {
75 debug_id: 0,
76 rule: Rule::Sequence(Sequence {
77 debug_id: 1,
78 args: vec![
79 Rule::Text(Text {
80 debug_id: 2,
81 allow_empty: true,
82 property: None
83 }),
84 Rule::Number(Number {
85 debug_id: 3,
86 property: Some(num.clone()),
87 allow_underscore: false,
88 })
89 ]
90 }),
91 };
92 let res = optional.parse(&mut tokens, &s,
93 &ReadToken::new(&text, 0), &[], indent_settings);
94 assert_eq!(res, (Range::new(0, 0), TokenizerState(0),
95 Some(Range::new(0, 0).wrap(ParseError::ExpectedText(2)))));
96 assert_eq!(tokens.len(), 0);
97 }
98}