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
use range::Range;
use read_token::ReadToken;
use super::{
err_update,
ParseResult,
};
use {
DebugId,
MetaData,
ParseError,
Rule,
};
use tokenizer::TokenizerState;
#[derive(Clone, Debug, PartialEq)]
pub struct Select {
pub args: Vec<Rule>,
pub debug_id: DebugId,
}
impl Select {
pub fn parse(
&self,
tokens: &mut Vec<Range<MetaData>>,
state: &TokenizerState,
read_token: &ReadToken,
refs: &[Rule]
) -> ParseResult<TokenizerState> {
let mut opt_error: Option<Range<ParseError>> = None;
for sub_rule in &self.args {
match sub_rule.parse(tokens, state, read_token, refs) {
Ok((range, state, err)) => {
err_update(err, &mut opt_error);
return Ok((read_token.peek(range.length),
state, opt_error));
}
Err(err) => {
err_update(Some(err), &mut opt_error);
}
}
}
match opt_error {
None => Err(read_token.start().wrap(
ParseError::InvalidRule(
"`Select` requires at least one sub rule", self.debug_id))),
Some(err) => Err(err),
}
}
}
#[cfg(test)]
mod tests {
use all::*;
use meta_rules::{ Number, Select, Text };
use range::Range;
use std::sync::Arc;
#[test]
fn invalid_rule() {
let text = "";
let select = Rule::Select(Select {
debug_id: 0,
args: vec![]
});
let mut syntax = Syntax::new();
syntax.push(Arc::new("".into()), select);
let mut tokens = vec![];
let res = parse(&syntax, &text, &mut tokens);
let invalid_rule = match &res {
&Err(ref range_err) => {
match range_err.data {
ParseError::InvalidRule(_, _) => true,
_ => false
}
}
_ => false
};
assert!(invalid_rule);
}
#[test]
fn fail_first() {
let text = "2";
let num: Arc<String> = Arc::new("num".into());
let select = Rule::Select(Select {
debug_id: 0,
args: vec![
Rule::Text(Text {
debug_id: 1,
allow_empty: true,
property: None
}),
Rule::Number(Number {
debug_id: 2,
property: Some(num.clone()),
allow_underscore: false,
})
]
});
let mut syntax = Syntax::new();
syntax.push(Arc::new("".into()), select);
let mut tokens = vec![];
let res = parse(&syntax, &text, &mut tokens);
assert_eq!(res, Ok(()));
assert_eq!(tokens, vec![
Range::new(0, 1).wrap(MetaData::F64(num.clone(), 2.0))
]);
}
}