1use ast::ASTNode;
10use ast::ASTNode::*;
11use statement::{parse_retstat, parse_statement};
12use name::{parse_name, parse_namelist};
13
14named!(pub parse_functiondef<ASTNode>,
17 do_parse!(tag!("function") >> f: ws!(parse_funcbody) >> (astb!(Function, f))));
18
19named!(pub parse_local_function<ASTNode>, do_parse!(
20 tag!("local")
21 >> ws!(tag!("function"))
22 >> n: parse_name
23 >> f: parse_funcbody
24 >> (astb!(NamedFunction, n, f))));
25
26named!(parse_funcbody<ASTNode>, do_parse!(
27 parlist: delimited!(tag!("("), opt!(ws!(parse_parlist)), tag!(")"))
28 >> block: ws!(parse_block)
29 >> tag!("end")
30 >> (astb!(FunctionBody, parlist, block))));
31
32named!(parse_multiname<Vec<ASTNode>>, many1!(preceded!(ws!(tag!(".")), parse_name)));
34named!(parse_funcname<ASTNode>, do_parse!(
35 n: map!(parse_name, Box::new)
36 >> m: opt!(complete!(parse_multiname))
37 >> f: opt!(map!(complete!(preceded!(ws!(tag!(":")), parse_name)), Box::new))
38 >> (ASTNode::FunctionName(n, m, f))
39));
40
41named!(parse_parlist<ASTNode>, do_parse!(
42 nl: opt!(complete!(parse_namelist))
43 >> opt!(complete!(ws!(tag!(","))))
44 >> va: opt!(complete!(ws!(tag!("..."))))
45 >> (ASTNode::ParameterList(Box::new(nl), va.is_some()))
46));
47
48named!(pub parse_block<ASTNode>, do_parse!(
49 s: many0!(complete!(parse_statement))
50 >> rs: opt!(ws!(complete!(parse_retstat)))
51 >> (ast!(Block, s, Box::new(rs)))
52));
53
54#[cfg(test)]
55mod tests {
56 use ast::ASTNode::*;
57
58 ast_test!(parse_parlist_1, parse_parlist, "...",
59 ast!(ParameterList, Box::new(None), true));
60
61 ast_test!(parse_parlist_2, parse_parlist, "",
62 ast!(ParameterList, Box::new(None), false));
63
64 ast_test!(parse_parlist_3, parse_parlist, "name , ...",
65 ast!(ParameterList, Box::new(Some(ast!(NameList, vec![
66 ast!(Name, "name".into())
67 ]))), true));
68
69 ast_test!(parse_parlist_5, parse_parlist, "a,b",
70 ast!(ParameterList, Box::new(Some(ast!(NameList, vec![
71 ast!(Name, "a".into()),
72 ast!(Name, "b".into())
73 ]))), false));
74
75
76
77 ast_test!(parse_block_1, parse_block, "", ast!(Block, vec![], Box::new(None)));
78 ast_test!(parse_block_2, parse_block, "::a::", ast!(Block, vec![
79 ast!(Label, "a".into())
80 ], Box::new(None)));
81
82 ast_test!(parse_block_3, parse_block, "::b:: return 1.0", ast!(Block, vec![
83 ast!(Label, "b".into())
84 ], Box::new(Some(astb!(RetStat, Some(ast!(ExpList, vec![
85 ast!(Float, 1.0)
86 ])))))));
87
88
89 ast_test!(parse_funcbody_1, parse_funcbody, "( a, b ) ; end",
90 astb!(FunctionBody,
91 Some(ast!(ParameterList, Box::new(Some(ast!(NameList, vec![
92 ast!(Name, "a".into()),
93 ast!(Name, "b".into())
94 ]))), false)),
95 ast!(Block, vec![
96 ast!(EmptyStatement)
97 ], Box::new(None))));
98
99 ast_test!(parse_functiondef_1, parse_functiondef, "function (...) ; end",
100 astb!(Function,
101 astb!(FunctionBody,
102 Some(ast!(ParameterList, Box::new(None), true)),
103 ast!(Block, vec![ ast!(EmptyStatement) ], Box::new(None)))));
104
105 ast_test!(parse_local_function_1, parse_local_function, "local function b() ; end",
106 astb!(NamedFunction,
107 ast!(Name, "b".into()),
108 astb!(FunctionBody,
109 Some(ast!(ParameterList, Box::new(None), false)),
110 ast!(Block, vec![ ast!(EmptyStatement) ], Box::new(None)))));
111
112 ast_test!(parse_funcname_1, parse_funcname, "a",
113 ast!(FunctionName, Box::new(ast!(Name, "a".into())), None, None));
114 ast_test!(parse_funcname_2, parse_funcname, "a.b",
115 ast!(FunctionName,
116 Box::new(ast!(Name, "a".into())),
117 Some(vec![
118 ast!(Name, "b".into())
119 ]),
120 None));
121 ast_test!(parse_funcname_3, parse_funcname, "a. b . c",
122 ast!(FunctionName,
123 Box::new(ast!(Name, "a".into())),
124 Some(vec![
125 ast!(Name, "b".into()),
126 ast!(Name, "c".into())
127 ]),
128 None));
129 ast_test!(parse_funcname_4, parse_funcname, "a.b:c",
130 ast!(FunctionName,
131 Box::new(ast!(Name, "a".into())),
132 Some(vec![
133 ast!(Name, "b".into()),
134 ]),
135 Some(Box::new(ast!(Name, "c".into())))));
136}
137