1use crate::ast::*;
4use crate::parser::util::*;
5use crate::parser::*;
6use nom_locate::position;
7
8pub fn parse_expr(s: Span) -> ParseResult<Node> {
10 context("expression", |s| parse_expr_bp(s, 0, false))(s)
11}
12
13pub fn parse_expr_no_seq(s: Span) -> ParseResult<Node> {
16 context("expression no seq", |s| parse_expr_bp(s, 1, false))(s)
17}
18
19pub fn parse_primary_expr(s: Span) -> ParseResult<Node> {
22 alt((
23 parse_identifier,
24 literal::parse_literal,
25 parse_this_expr,
26 parse_function_expr,
27 parse_paren_expr,
28 ))(s)
29}
30
31pub fn parse_primary_expr_allow_reserved(s: Span) -> ParseResult<Node> {
38 alt((
39 parse_identifier_name, literal::parse_literal,
41 parse_this_expr,
42 parse_function_expr,
43 parse_paren_expr,
44 ))(s)
45}
46
47pub fn parse_this_expr(s: Span) -> ParseResult<Node> {
48 map(
49 spanned(ws0(pair(tag("this"), not(identifier_continue)))),
50 |(_, start, end)| NodeKind::ThisExpression.with_pos(start, end),
51 )(s)
52}
53
54pub fn parse_paren_expr(s: Span) -> ParseResult<Node> {
55 context(
56 "paren expression",
57 delimited(ws0(char('(')), parse_expr, ws0(char(')'))),
58 )(s)
59}
60
61fn parse_opt_expr_in_list(s: Span) -> ParseResult<Option<Node>> {
62 alt((value(None, peek(char(','))), map(parse_expr_no_seq, Some)))(s)
63}
64
65pub fn parse_expr_list_with_opt_expr(s: Span) -> ParseResult<Vec<Option<Node>>> {
66 context(
67 "expression list with optional expression",
68 terminated(
69 separated_list0(ws0(char(',')), parse_opt_expr_in_list),
70 ws0(opt(char(','))),
72 ),
73 )(s)
74}
75
76pub fn parse_expr_list(s: Span) -> ParseResult<Vec<Node>> {
77 context(
78 "expression list",
79 terminated(
80 separated_list0(ws0(char(',')), parse_expr_no_seq),
81 ws0(opt(char(','))),
83 ),
84 )(s)
85}
86
87fn parse_prefix_expr(s: Span) -> ParseResult<Node> {
89 let (s, start) = position(s)?;
90 let (s, (prefix_op, BindingPower(_, right_bp))) = parse_prefix_operator(s)?;
91 let (s, rhs) = parse_expr_bp(
92 s, right_bp, false,
93 )?;
94
95 let (mut s, mut end) = position(s)?;
96
97 let node_kind = match prefix_op {
98 PrefixOperator::Unary(prefix_op) => NodeKind::UnaryExpression {
99 argument: Box::new(rhs),
100 operator: prefix_op,
101 prefix: true,
102 },
103 PrefixOperator::Update(prefix_op) => NodeKind::UpdateExpression {
104 argument: Box::new(rhs),
105 operator: prefix_op,
106 prefix: true,
107 },
108 PrefixOperator::New => {
109 let (s_tmp, arguments) = opt(delimited(ws0(char('(')), parse_expr_list, char(')')))(s)?;
110 s = s_tmp;
111 let (s_tmp, end_tmp) = position(s)?;
112 s = s_tmp;
113 end = end_tmp;
114
115 let (s_tmp, _) = sp0(s)?;
116 s = s_tmp;
117
118 NodeKind::NewExpression {
119 callee: Box::new(rhs),
120 arguments: arguments.unwrap_or_default(),
121 }
122 }
123 PrefixOperator::Await => NodeKind::AwaitExpression {
124 argument: Box::new(rhs),
125 },
126 };
127 Ok((s, node_kind.with_pos(start, end)))
128}
129
130pub fn parse_expr_bp(s: Span, min_bp: i32, allow_reserved: bool) -> ParseResult<Node> {
136 let (mut s, mut lhs) = alt((
137 parse_prefix_expr,
138 if allow_reserved {
139 parse_primary_expr_allow_reserved
140 } else {
141 parse_primary_expr
142 },
143 ))(s)?;
144
145 loop {
146 if let Ok((s_tmp, (postfix_op, BindingPower(left_bp, _), mut end))) =
147 parse_postfix_operator(s)
148 {
149 if left_bp < min_bp {
150 break;
151 }
152 s = s_tmp;
153 let start = lhs.start.clone();
154
155 let node_kind = match postfix_op {
156 PostfixOperator::Update(postfix_op) => NodeKind::UpdateExpression {
157 argument: Box::new(lhs),
158 operator: postfix_op,
159 prefix: false,
160 },
161 PostfixOperator::ComputedMember => {
162 let (s_tmp, property) = terminated(parse_expr, char(']'))(s)?;
164 s = s_tmp;
165
166 let (s_tmp, end_tmp) = position(s)?;
167 s = s_tmp;
168 end = end_tmp;
169
170 let (s_tmp, _) = sp0(s)?;
171 s = s_tmp;
172
173 NodeKind::MemberExpression {
174 object: Box::new(lhs),
175 property: Box::new(property),
176 computed: true,
177 }
178 }
179 PostfixOperator::FuncCall => {
180 let (s_tmp, arguments) = terminated(parse_expr_list, char(')'))(s)?;
182 s = s_tmp;
183
184 let (s_tmp, end_tmp) = position(s)?;
185 s = s_tmp;
186 end = end_tmp;
187
188 let (s_tmp, _) = sp0(s)?;
189 s = s_tmp;
190
191 NodeKind::CallExpression {
192 callee: Box::new(lhs),
193 arguments,
194 }
195 }
196 };
197
198 lhs = node_kind.with_pos(start, end);
199
200 continue;
201 }
202
203 let (s_tmp, (op, BindingPower(left_bp, right_bp))) = match parse_infix_operator(s) {
205 Ok(res) => res,
206 Err(_) => break, };
208
209 if left_bp < min_bp {
210 break;
211 }
212
213 s = s_tmp;
215
216 if let InfixOperator::TernaryOperator = op {
217 let (s_tmp, mhs) = parse_expr_bp(s, right_bp, false)?;
218 s = s_tmp;
219
220 let (s_tmp, _) = ws0(tag(":"))(s)?;
221 s = s_tmp;
222
223 let (s_tmp, rhs) = parse_expr_bp(s, right_bp, false)?;
224 s = s_tmp;
225
226 let start = lhs.start.clone();
227 let end = rhs.end.clone();
228
229 let node_kind = NodeKind::ConditionalExpression {
230 test: Box::new(lhs),
231 consequent: Box::new(mhs),
232 alternate: Box::new(rhs),
233 };
234
235 lhs = node_kind.with_pos(start, end);
236 continue;
237 }
238
239 let (s_tmp, rhs) = parse_expr_bp(s, right_bp, op == InfixOperator::DotOperator)?;
240 s = s_tmp;
241
242 let start = lhs.start.clone();
243 let end = rhs.end.clone();
244
245 let node_kind = match op {
246 InfixOperator::Binary(op) => NodeKind::BinaryExpression {
247 left: Box::new(lhs),
248 right: Box::new(rhs),
249 operator: op,
250 },
251 InfixOperator::Logical(op) => NodeKind::LogicalExpression {
252 left: Box::new(lhs),
253 right: Box::new(rhs),
254 operator: op,
255 },
256 InfixOperator::Assignment(op) => NodeKind::AssignmentExpression {
257 left: Box::new(lhs),
258 right: Box::new(rhs),
259 operator: op,
260 },
261 InfixOperator::DotOperator => NodeKind::MemberExpression {
262 object: Box::new(lhs),
263 property: Box::new(rhs),
264 computed: false,
265 },
266 InfixOperator::SequenceOperator => NodeKind::SequenceExpression {
267 expressions: match &lhs.kind {
268 NodeKind::SequenceExpression { expressions } => {
269 let mut expressions = expressions.clone();
270 expressions.push(rhs);
271 expressions
272 }
273 _ => vec![lhs, rhs],
274 },
275 },
276 InfixOperator::TernaryOperator => unreachable!("handled earlier"),
277 };
278 lhs = node_kind.with_pos(start, end);
279 }
280
281 Ok((s, lhs))
282}
283
284#[cfg(test)]
285mod tests {
286 use super::*;
287 use insta::assert_json_snapshot;
288
289 #[test]
290 fn smoke_test_this_expr() {
291 parse_this_expr("this".into()).unwrap();
292 parse_this_expr("notthis".into()).unwrap_err();
293 }
294
295 #[test]
296 fn smoke_test_primary_expr() {
297 parse_primary_expr("this".into()).unwrap();
298 parse_primary_expr("myVar".into()).unwrap();
299 }
300
301 #[test]
302 fn test_identifier_expr() {
303 assert_json_snapshot!(parse_expr("myIdentifier".into()).unwrap().1);
304 }
305
306 #[test]
307 fn test_expr_bp_guard_in() {
308 assert_json_snapshot!(
309 parse_expr_bp("myIdentifier in foo".into(), 25, false)
310 .unwrap()
311 .1
312 );
313 }
315
316 #[test]
317 fn test_paren_expr() {
318 assert_json_snapshot!(parse_expr("(1)".into()).unwrap().1);
319 assert_json_snapshot!(parse_expr("(((1)))".into()).unwrap().1);
320 assert_json_snapshot!(parse_expr("(((1 + 1)))".into()).unwrap().1);
321 }
322
323 #[test]
324 fn test_member_expr() {
325 assert_json_snapshot!(parse_expr("a.b".into()).unwrap().1);
326 assert_json_snapshot!(parse_expr("a.b.c".into()).unwrap().1);
327 assert_json_snapshot!(parse_expr("a[1]".into()).unwrap().1);
328 assert_json_snapshot!(parse_expr("a[0]".into()).unwrap().1);
329 assert_json_snapshot!(parse_expr("a[[]]".into()).unwrap().1);
330 }
331
332 #[test]
333 fn test_new_expr() {
334 assert_json_snapshot!(parse_expr("new Array()".into()).unwrap().1);
335 assert_json_snapshot!(parse_expr("new Array".into()).unwrap().1); assert_json_snapshot!(parse_expr("new Array(1)".into()).unwrap().1);
337 assert_json_snapshot!(parse_expr("new Array(1,)".into()).unwrap().1);
338 assert_json_snapshot!(parse_expr("new Array(1,2)".into()).unwrap().1);
339 assert_json_snapshot!(parse_expr("new Foo.Bar(true)".into()).unwrap().1);
340 }
341
342 #[test]
343 fn test_call_expr() {
344 assert_json_snapshot!(parse_expr("foo()".into()).unwrap().1);
345 assert_json_snapshot!(parse_expr("foo.bar()".into()).unwrap().1);
346 assert_json_snapshot!(parse_expr("foo.bar.baz()".into()).unwrap().1);
347 assert_json_snapshot!(parse_expr("foo.bar(baz)".into()).unwrap().1);
348 assert_json_snapshot!(parse_expr("foo.bar(baz, 1, 2, 3)".into()).unwrap().1);
349
350 assert_json_snapshot!(
351 parse_expr("console.log(\"Hello World!\")".into())
352 .unwrap()
353 .1
354 );
355 }
356
357 #[test]
358 fn test_sequence_expr() {
359 assert_json_snapshot!(parse_expr("1,2,3".into()).unwrap().1);
360 assert_json_snapshot!(parse_expr("(1,2,3)".into()).unwrap().1);
361 }
362
363 #[test]
364 fn test_ternary_expr() {
365 assert_json_snapshot!(parse_expr("true ? x : y".into()).unwrap().1);
366 assert_json_snapshot!(parse_expr("a ? x : b ? y : z".into()).unwrap().1);
367 }
369
370 #[test]
371 fn test_expr_bp_infix() {
372 assert_json_snapshot!(parse_expr("1 + 2".into()).unwrap().1);
373 assert_json_snapshot!(parse_expr("1 - 2 - 3".into()).unwrap().1);
374 assert_json_snapshot!(parse_expr("1 * 2 + 3".into()).unwrap().1);
375 assert_json_snapshot!(parse_expr("1 + 2 * 3".into()).unwrap().1);
376 assert_json_snapshot!(parse_expr("1 * 2 + 3 * 4".into()).unwrap().1);
377 assert_json_snapshot!(parse_expr("(1 + 2) * 3".into()).unwrap().1);
378
379 assert_json_snapshot!(parse_expr("true && false".into()).unwrap().1);
380 assert_json_snapshot!(parse_expr("x < y".into()).unwrap().1);
381
382 assert_json_snapshot!(parse_expr("x == 1".into()).unwrap().1);
384 assert_json_snapshot!(parse_expr("x != 1".into()).unwrap().1);
385 assert_json_snapshot!(parse_expr("x === 1".into()).unwrap().1);
386 assert_json_snapshot!(parse_expr("x !== 1".into()).unwrap().1);
387
388 assert_json_snapshot!(parse_expr("x < 1".into()).unwrap().1);
390 assert_json_snapshot!(parse_expr("x > 1".into()).unwrap().1);
391 assert_json_snapshot!(parse_expr("x <= 1".into()).unwrap().1);
392 assert_json_snapshot!(parse_expr("x >= 1".into()).unwrap().1);
393
394 assert_json_snapshot!(parse_expr("x << 1".into()).unwrap().1);
396 assert_json_snapshot!(parse_expr("x >> 1".into()).unwrap().1);
397 assert_json_snapshot!(parse_expr("x >>> 1".into()).unwrap().1);
398
399 assert_json_snapshot!(parse_expr("x && y".into()).unwrap().1);
401 assert_json_snapshot!(parse_expr("x || y".into()).unwrap().1);
402
403 assert_json_snapshot!("exponentiation", parse_expr("x ** y".into()).unwrap().1);
405 assert_json_snapshot!(
406 "exponentiation-2",
407 parse_expr("x ** y ** z".into()).unwrap().1
408 );
409 }
410
411 #[test]
412 fn test_expr_bp_infix_str_concat() {
413 assert_json_snapshot!(parse_expr(r#""a" + "b""#.into()).unwrap().1);
414 assert_json_snapshot!(parse_expr(r#""a" + 123"#.into()).unwrap().1);
415 assert_json_snapshot!(parse_expr(r#""a" + {}"#.into()).unwrap().1);
416 assert_json_snapshot!(parse_expr(r#"[] + {}"#.into()).unwrap().1);
417 }
418
419 #[test]
420 fn test_expr_bp_prefix() {
421 assert_json_snapshot!(parse_expr("-1".into()).unwrap().1);
422 assert_json_snapshot!(parse_expr("+1".into()).unwrap().1);
423 assert_json_snapshot!(parse_expr("+(+1)".into()).unwrap().1);
424 assert_json_snapshot!(parse_expr("1 + -2".into()).unwrap().1); assert_json_snapshot!(parse_expr("++x".into()).unwrap().1);
426
427 assert_json_snapshot!(parse_expr("typeof x".into()).unwrap().1);
428 assert_json_snapshot!(parse_expr("typeof module === \"object\"".into()).unwrap().1);
429
430 assert_json_snapshot!(parse_expr("!x".into()).unwrap().1);
431 assert_json_snapshot!(parse_expr("!(x && y)".into()).unwrap().1);
432
433 assert_json_snapshot!(parse_expr("await foo".into()).unwrap().1);
434 assert_json_snapshot!(parse_expr("await foo".into()).unwrap().1);
435 }
436
437 #[test]
438 fn test_expr_bp_postfix() {
439 assert_json_snapshot!(parse_expr("x++".into()).unwrap().1);
440 assert_json_snapshot!(parse_expr("x++\t".into()).unwrap().1); assert_json_snapshot!(parse_expr("x--".into()).unwrap().1);
442 assert_json_snapshot!(parse_expr("x++ + 1".into()).unwrap().1); }
444
445 #[test]
446 fn test_expr_bp_assignment() {
447 assert_json_snapshot!(parse_expr("x = 1".into()).unwrap().1);
448 assert_json_snapshot!(parse_expr("x = 1 + 2".into()).unwrap().1);
449 assert_json_snapshot!(parse_expr("x += 1".into()).unwrap().1);
450 assert_json_snapshot!(parse_expr("x += y += 1".into()).unwrap().1);
451 assert_json_snapshot!(parse_expr("x += x * x".into()).unwrap().1);
452 assert_json_snapshot!(parse_expr("x = a ? b : c".into()).unwrap().1);
453 assert_json_snapshot!(
454 parse_expr("x = a ? myFunc : function () { return c; }".into())
455 .unwrap()
456 .1
457 );
458
459 assert_json_snapshot!(parse_expr("hello.value = \"world\"".into()).unwrap().1);
460 assert_json_snapshot!(
461 parse_expr("myFunc = function () { return 0; }".into())
462 .unwrap()
463 .1
464 );
465 assert_json_snapshot!(parse_expr("a = b = c;".into()).unwrap().1);
466
467 assert_json_snapshot!(parse_expr("x -= x * x".into()).unwrap().1);
468 assert_json_snapshot!(parse_expr("x **= y".into()).unwrap().1);
469 assert_json_snapshot!(parse_expr("x *= x * x".into()).unwrap().1);
470 assert_json_snapshot!(parse_expr("x /= x * x".into()).unwrap().1);
471 assert_json_snapshot!(parse_expr("x %= x * x".into()).unwrap().1);
472 assert_json_snapshot!(parse_expr("x <<= 1".into()).unwrap().1);
473 assert_json_snapshot!(parse_expr("x >>= 1".into()).unwrap().1);
474 assert_json_snapshot!(parse_expr("x >>>= 1".into()).unwrap().1);
475 assert_json_snapshot!(parse_expr("x |= 1".into()).unwrap().1);
476 assert_json_snapshot!(parse_expr("x ^= 1".into()).unwrap().1);
477 assert_json_snapshot!(parse_expr("x &= 1".into()).unwrap().1);
478
479 assert_json_snapshot!(parse_expr("x[1] = a".into()).unwrap().1);
480 assert_json_snapshot!(parse_expr("x[\"foo\"] = a".into()).unwrap().1);
481
482 assert_json_snapshot!(
483 parse_expr(
484 r#"identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace +
485 "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+""#
486 .into()
487 )
488 .unwrap()
489 .1
490 );
491 }
492
493 #[test]
494 fn test_expr_bp_member_expr() {
495 assert_json_snapshot!(parse_expr("x.y".into()).unwrap().1);
496 assert_json_snapshot!(parse_expr("x.y.z".into()).unwrap().1);
497 assert_json_snapshot!(parse_expr("x.y[z]".into()).unwrap().1);
498 assert_json_snapshot!(parse_expr("x.y[\"z\"]".into()).unwrap().1);
499 assert_json_snapshot!(parse_expr("x.y[arr.length - 1]".into()).unwrap().1);
500
501 assert_json_snapshot!(
502 parse_expr("x.y()\n// abc\n/* 123 */\n.z()".into())
503 .unwrap()
504 .1
505 );
506 assert_json_snapshot!(
507 parse_expr("x.y(123)\n// abc\n/* 123 */\n.z(abc)".into())
508 .unwrap()
509 .1
510 );
511 assert_json_snapshot!(
512 parse_expr(
513 r#"test
514 .then(fn)
515 // properties can be reserved words ("catch" keyword)
516 .catch(function (error) {
517 console.error(error);
518 });"#
519 .into()
520 )
521 .unwrap()
522 .1
523 );
524 }
525
526 #[test]
527 fn test_expr_bp_no_seq() {
528 assert_json_snapshot!(parse_expr_no_seq("x, y".into()).unwrap().1); assert_json_snapshot!(
530 parse_expr_no_seq(
531 "test() ? function () { return 0; } : function() { return 1; }, y".into()
532 )
533 .unwrap()
534 .1
535 ); }
537}