1use crate::parse::ast::AST;
2use crate::parse::ast::Node;
3use crate::parse::definition::parse_fun_arg;
4use crate::parse::expression::parse_inner_expression;
5use crate::parse::iterator::LexIterator;
6use crate::parse::lex::token::Token;
7use crate::parse::operation::parse_expression;
8use crate::parse::result::{expected_one_of, ParseResult};
9
10pub fn parse_anon_fun(it: &mut LexIterator) -> ParseResult {
11 let start = it.start_pos("anonymous function")?;
12 it.eat(&Token::BSlash, "anonymous function")?;
13
14 let mut args: Vec<AST> = vec![];
15 it.peek_while_not_token(&Token::BTo, &mut |it, _| {
16 args.push(*it.parse(&parse_fun_arg, "anonymous function", start)?);
17 it.eat_if(&Token::Comma);
18 Ok(())
19 })?;
20
21 it.eat(&Token::BTo, "anonymous function")?;
22
23 let body = it.parse(&parse_expression, "anonymous function", start)?;
24 let node = Node::AnonFun { args, body: body.clone() };
25 Ok(Box::from(AST::new(start.union(body.pos), node)))
26}
27
28pub fn parse_call(pre: &AST, it: &mut LexIterator) -> ParseResult {
29 it.peek_or_err(
30 &|it, ast| match ast.token {
31 Token::Point => {
32 it.eat(&Token::Point, "call")?;
33 let property = it.parse(&parse_inner_expression, "call", pre.pos)?;
34 let node = Node::PropertyCall {
35 instance: Box::from(pre.clone()),
36 property: property.clone(),
37 };
38 Ok(Box::from(AST::new(pre.pos.union(property.pos), node)))
39 }
40 Token::LRBrack => {
41 it.eat(&Token::LRBrack, "direct call")?;
42 let args = it.parse_vec(&parse_arguments, "direct call", pre.pos)?;
43 let end = it.eat(&Token::RRBrack, "direct call")?;
44 let node = Node::FunctionCall { name: Box::from(pre.clone()), args };
45 Ok(Box::from(AST::new(pre.pos.union(end), node)))
46 }
47 _ => Err(Box::from(expected_one_of(&[Token::Point, Token::LRBrack], ast, "function call"))),
48 },
49 &[Token::Point, Token::LRBrack],
50 "function call",
51 )
52}
53
54fn parse_arguments(it: &mut LexIterator) -> ParseResult<Vec<AST>> {
55 let start = it.start_pos("arguments")?;
56 let mut arguments = vec![];
57 it.peek_while_not_token(&Token::RRBrack, &mut |it, _| {
58 arguments.push(*it.parse(&parse_expression, "arguments", start)?);
59 it.eat_if(&Token::Comma);
60 Ok(())
61 })?;
62 Ok(arguments)
63}
64
65#[cfg(test)]
66mod test {
67 use crate::parse::{parse, parse_direct};
68 use crate::parse::ast::{AST, Node};
69 use crate::parse::ast::node_op::NodeOp;
70
71 #[test]
72 fn op_assign() {
73 let source = String::from("a:=1\nb+=2\nc-=3\nd*=4\ne/=5\nf^=6\ng<<=7\nh>>=8\n");
74 let statements = parse_direct(&source).unwrap();
75
76 let ops: Vec<NodeOp> = statements
77 .iter()
78 .map(|ast| match &ast.node {
79 Node::Reassign { op, .. } => op.clone(),
80 other => panic!("Expected reassign {:?}", other)
81 })
82 .collect();
83
84 assert_eq!(ops[0], NodeOp::Assign);
85 assert_eq!(ops[1], NodeOp::Add);
86 assert_eq!(ops[2], NodeOp::Sub);
87 assert_eq!(ops[3], NodeOp::Mul);
88 assert_eq!(ops[4], NodeOp::Div);
89 assert_eq!(ops[5], NodeOp::Pow);
90 assert_eq!(ops[6], NodeOp::BLShift);
91 assert_eq!(ops[7], NodeOp::BRShift);
92 }
93
94 #[test]
95 fn anon_fun_no_args_verify() {
96 let source = String::from("\\ => c");
97 let statements = parse_direct(&source).unwrap();
98
99 let Node::AnonFun { args, body } = &statements.first().expect("script empty.").node else {
100 panic!("first element script was anon fun.")
101 };
102
103 assert_eq!(args.len(), 0);
104 assert_eq!(body.node, Node::Id { lit: String::from("c") });
105 }
106
107 #[test]
108 fn anon_fun_verify() {
109 let source = String::from("\\a,b => c");
110 let statements = parse_direct(&source).unwrap();
111
112 let Node::AnonFun { args, body } = &statements.first().expect("script empty.").node else {
113 panic!("first element script was anon fun.")
114 };
115
116 assert_eq!(args.len(), 2);
117 let (id1, id2) = match (&args[0], &args[1]) {
118 (
119 AST { node: Node::FunArg { var: id1, ty: None, mutable: true, .. }, .. },
120 AST { node: Node::FunArg { var: id2, ty: None, mutable: true, .. }, .. },
121 ) => (id1.clone(), id2.clone()),
122 other => panic!("Id's of anon fun not expression type: {:?}", other),
123 };
124
125 assert_eq!(id1.node, Node::Id { lit: String::from("a") });
126 assert_eq!(id2.node, Node::Id { lit: String::from("b") });
127
128 assert_eq!(body.node, Node::Id { lit: String::from("c") });
129 }
130
131 #[test]
132 fn direct_call_verify() {
133 let source = String::from("a(b, c)");
134 let statements = parse_direct(&source).unwrap();
135
136 let Node::FunctionCall { name, args } = &statements.first().expect("script empty.").node else {
137 panic!("first element script was anon fun.")
138 };
139
140 assert_eq!(name.node, Node::Id { lit: String::from("a") });
141 assert_eq!(args.len(), 2);
142 assert_eq!(args[0].node, Node::Id { lit: String::from("b") });
143 assert_eq!(args[1].node, Node::Id { lit: String::from("c") });
144 }
145
146 #[test]
147 fn method_call_verify() {
148 let source = String::from("instance.a(b, c)");
149 let statements = parse_direct(&source).unwrap();
150
151 let (instance, name, args) = match &statements.first().expect("script empty.").node {
152 Node::PropertyCall { instance, property } => match &property.node {
153 Node::FunctionCall { name, args } => (instance.clone(), name.clone(), args.clone()),
154 other => panic!("not function call in property call {:?}", other),
155 },
156 other => panic!("first element script was property call {:?}", other),
157 };
158
159 assert_eq!(instance.node, Node::Id { lit: String::from("instance") });
160 assert_eq!(name.node, Node::Id { lit: String::from("a") });
161
162 assert_eq!(args.len(), 2);
163 assert_eq!(args[0].node, Node::Id { lit: String::from("b") });
164 assert_eq!(args[1].node, Node::Id { lit: String::from("c") });
165 }
166
167 #[test]
168 fn direct_call_missing_closing_bracket() {
169 let source = String::from("a(b");
170 parse(&source).unwrap_err();
171 }
172
173 #[test]
174 fn regular_call_missing_closing_bracket() {
175 let source = String::from("instance.a(b");
176 parse(&source).unwrap_err();
177 }
178}