nom_lua/
function.rs

1// Copyright 2017 The nom-lua project developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use ast::ASTNode;
10use ast::ASTNode::*;
11use statement::{parse_retstat, parse_statement};
12use name::{parse_name, parse_namelist};
13
14// TODO: Needs ws! macros
15
16named!(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
32// This is here because rustc complains about lack of type annotations
33named!(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//		 function funcname funcbody |
138//		 local function Name funcbody |