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
use ast::ASTNode;
use nom::{alpha, digit};
use std::str;
use std::str::FromStr;
named!(recognize_keyword, alt!(
tag!("and") |
tag!("break") |
tag!("do") |
tag!("else") |
tag!("elseif") |
tag!("end") |
tag!("false") |
tag!("for") |
tag!("function") |
tag!("goto") |
tag!("if") |
tag!("in") |
tag!("local") |
tag!("nil") |
tag!("not") |
tag!("or") |
tag!("repeat") |
tag!("return") |
tag!("then") |
tag!("true") |
tag!("until") |
tag!("while")
));
named!(pub parse_name<ASTNode>, map!(parse_valid_name, ASTNode::Name));
named!(pub parse_valid_name<String>, map_res!(map_res!(do_parse!(
not!(recognize_keyword) >>
a: recognize!(preceded!(
many1!(alt!(tag!("_") | alpha)),
many0!(alt!(tag!("_") | alpha | digit)))) >> (a)),
str::from_utf8), FromStr::from_str));
named!(pub parse_label<ASTNode>, map!(delimited!(
tag!("::"),
ws!(parse_valid_name),
tag!("::")),
ASTNode::Label));
named!(pub parse_namelist<ASTNode>, map!(
map!(do_parse!(
a: parse_name
>> b: many0!(preceded!(ws!(tag!(",")), parse_name))
>> ((a,b))
), |(a, mut b): (_, Vec < ASTNode >) | { b.insert(0, a); b }),
ASTNode::NameList));
#[cfg(test)]
mod tests {
use ast::ASTNode::*;
ast_test!(parse_valid_name_1, parse_valid_name, "il", "il".to_string());
ast_test!(parse_valid_name_2, parse_valid_name, "_il3", "_il3".to_string());
ast_panic_test!(parse_valid_name_3, parse_valid_name, "3lc_");
ast_panic_test!(parse_valid_name_4, parse_valid_name, "not");
ast_test!(parse_label_1, parse_label, "::il::", ast!(Label, "il".into()));
ast_test!(parse_label_2, parse_label, ":: z ::", ast!(Label, "z".into()));
ast_test!(parse_namelist_1, parse_namelist, "name1", ast!(NameList, vec![
ast!(Name, "name1".into()),
]));
ast_test!(parse_namelist_2, parse_namelist, "name1 , name2", ast!(NameList, vec![
ast!(Name, "name1".into()),
ast!(Name, "name2".into()),
]));
ast_test!(parse_namelist_3, parse_namelist, "name1 , name2, name3", ast!(NameList, vec![
ast!(Name, "name1".into()),
ast!(Name, "name2".into()),
ast!(Name, "name3".into()),
]));
ast_test!(parse_namelist_4, parse_namelist, "a,b", ast!(NameList, vec![
ast!(Name, "a".into()),
ast!(Name, "b".into()),
]));
}