1mod assignment;
11mod left_hand_side;
12mod primary;
13#[cfg(test)]
14mod tests;
15mod unary;
16mod update;
17
18pub(in crate::syntax::parser) mod await_expr;
19
20use self::assignment::ExponentiationExpression;
21pub(super) use self::{assignment::AssignmentExpression, primary::Initializer};
22use super::{AllowAwait, AllowIn, AllowYield, Cursor, ParseResult, TokenParser};
23
24use crate::{
25 profiler::BoaProfiler,
26 syntax::{
27 ast::op::LogOp,
28 ast::{
29 node::{BinOp, Node},
30 Keyword, Punctuator,
31 },
32 lexer::{InputElement, TokenKind},
33 parser::ParseError,
34 },
35};
36use std::io::Read;
37
38impl PartialEq<Keyword> for Punctuator {
41 fn eq(&self, _other: &Keyword) -> bool {
42 false
43 }
44}
45
46impl PartialEq<Punctuator> for Keyword {
49 fn eq(&self, _other: &Punctuator) -> bool {
50 false
51 }
52}
53
54macro_rules! expression { ($name:ident, $lower:ident, [$( $op:path ),*], [$( $low_param:ident ),*], $goal:expr ) => {
69 impl<R> TokenParser<R> for $name
70 where
71 R: Read
72 {
73 type Output = Node;
74
75 fn parse(self, cursor: &mut Cursor<R>)-> ParseResult {
76 let _timer = BoaProfiler::global().start_event(stringify!($name), "Parsing");
77
78 if $goal.is_some() {
79 cursor.set_goal($goal.unwrap());
80 }
81
82 let mut lhs = $lower::new($( self.$low_param ),*).parse(cursor)?;
83 while let Some(tok) = cursor.peek(0)? {
84 match *tok.kind() {
85 TokenKind::Punctuator(op) if $( op == $op )||* => {
86 let _ = cursor.next().expect("token disappeared");
87 lhs = BinOp::new(
88 op.as_binop().expect("Could not get binary operation."),
89 lhs,
90 $lower::new($( self.$low_param ),*).parse(cursor)?
91 ).into();
92 }
93 TokenKind::Keyword(op) if $( op == $op )||* => {
94 let _ = cursor.next().expect("token disappeared");
95 lhs = BinOp::new(
96 op.as_binop().expect("Could not get binary operation."),
97 lhs,
98 $lower::new($( self.$low_param ),*).parse(cursor)?
99 ).into();
100 }
101 _ => break
102 }
103 }
104
105 Ok(lhs)
106 }
107 }
108} }
109
110#[derive(Debug, Clone, Copy)]
119pub(super) struct Expression {
120 allow_in: AllowIn,
121 allow_yield: AllowYield,
122 allow_await: AllowAwait,
123}
124
125impl Expression {
126 pub(super) fn new<I, Y, A>(allow_in: I, allow_yield: Y, allow_await: A) -> Self
128 where
129 I: Into<AllowIn>,
130 Y: Into<AllowYield>,
131 A: Into<AllowAwait>,
132 {
133 Self {
134 allow_in: allow_in.into(),
135 allow_yield: allow_yield.into(),
136 allow_await: allow_await.into(),
137 }
138 }
139}
140
141expression!(
142 Expression,
143 AssignmentExpression,
144 [Punctuator::Comma],
145 [allow_in, allow_yield, allow_await],
146 None::<InputElement>
147);
148
149#[derive(Debug, Clone, Copy)]
158struct ShortCircuitExpression {
159 allow_in: AllowIn,
160 allow_yield: AllowYield,
161 allow_await: AllowAwait,
162 previous: PreviousExpr,
163}
164
165#[derive(Debug, Clone, Copy, PartialEq)]
166enum PreviousExpr {
167 None,
168 Logical,
169 Coalesce,
170}
171
172impl ShortCircuitExpression {
173 pub(super) fn new<I, Y, A>(allow_in: I, allow_yield: Y, allow_await: A) -> Self
175 where
176 I: Into<AllowIn>,
177 Y: Into<AllowYield>,
178 A: Into<AllowAwait>,
179 {
180 Self {
181 allow_in: allow_in.into(),
182 allow_yield: allow_yield.into(),
183 allow_await: allow_await.into(),
184 previous: PreviousExpr::None,
185 }
186 }
187
188 fn with_previous<I, Y, A>(
189 allow_in: I,
190 allow_yield: Y,
191 allow_await: A,
192 previous: PreviousExpr,
193 ) -> Self
194 where
195 I: Into<AllowIn>,
196 Y: Into<AllowYield>,
197 A: Into<AllowAwait>,
198 {
199 Self {
200 allow_in: allow_in.into(),
201 allow_yield: allow_yield.into(),
202 allow_await: allow_await.into(),
203 previous,
204 }
205 }
206}
207
208impl<R> TokenParser<R> for ShortCircuitExpression
209where
210 R: Read,
211{
212 type Output = Node;
213
214 fn parse(self, cursor: &mut Cursor<R>) -> ParseResult {
215 let _timer = BoaProfiler::global().start_event("ShortCircuitExpression", "Parsing");
216
217 let mut current_node =
218 BitwiseORExpression::new(self.allow_in, self.allow_yield, self.allow_await)
219 .parse(cursor)?;
220 let mut previous = self.previous;
221
222 while let Some(tok) = cursor.peek(0)? {
223 match tok.kind() {
224 TokenKind::Punctuator(Punctuator::BoolAnd) => {
225 if previous == PreviousExpr::Coalesce {
226 return Err(ParseError::expected(
227 [TokenKind::Punctuator(Punctuator::Coalesce)],
228 tok.clone(),
229 "logical expression (cannot use '??' without parentheses within '||' or '&&')",
230 ));
231 }
232 let _ = cursor.next()?.expect("'&&' expected");
233 previous = PreviousExpr::Logical;
234 let rhs =
235 BitwiseORExpression::new(self.allow_in, self.allow_yield, self.allow_await)
236 .parse(cursor)?;
237
238 current_node = BinOp::new(LogOp::And, current_node, rhs).into();
239 }
240 TokenKind::Punctuator(Punctuator::BoolOr) => {
241 if previous == PreviousExpr::Coalesce {
242 return Err(ParseError::expected(
243 [TokenKind::Punctuator(Punctuator::Coalesce)],
244 tok.clone(),
245 "logical expression (cannot use '??' without parentheses within '||' or '&&')",
246 ));
247 }
248 let _ = cursor.next()?.expect("'||' expected");
249 previous = PreviousExpr::Logical;
250 let rhs = ShortCircuitExpression::with_previous(
251 self.allow_in,
252 self.allow_yield,
253 self.allow_await,
254 PreviousExpr::Logical,
255 )
256 .parse(cursor)?;
257 current_node = BinOp::new(LogOp::Or, current_node, rhs).into();
258 }
259 TokenKind::Punctuator(Punctuator::Coalesce) => {
260 if previous == PreviousExpr::Logical {
261 return Err(ParseError::expected(
262 [
263 TokenKind::Punctuator(Punctuator::BoolAnd),
264 TokenKind::Punctuator(Punctuator::BoolOr),
265 ],
266 tok.clone(),
267 "cannot use '??' unparenthesized within '||' or '&&'",
268 ));
269 }
270 let _ = cursor.next()?.expect("'??' expected");
271 previous = PreviousExpr::Coalesce;
272 let rhs =
273 BitwiseORExpression::new(self.allow_in, self.allow_yield, self.allow_await)
274 .parse(cursor)?;
275 current_node = BinOp::new(LogOp::Coalesce, current_node, rhs).into();
276 }
277 _ => break,
278 }
279 }
280 Ok(current_node)
281 }
282}
283
284#[derive(Debug, Clone, Copy)]
293struct BitwiseORExpression {
294 allow_in: AllowIn,
295 allow_yield: AllowYield,
296 allow_await: AllowAwait,
297}
298
299impl BitwiseORExpression {
300 pub(super) fn new<I, Y, A>(allow_in: I, allow_yield: Y, allow_await: A) -> Self
302 where
303 I: Into<AllowIn>,
304 Y: Into<AllowYield>,
305 A: Into<AllowAwait>,
306 {
307 Self {
308 allow_in: allow_in.into(),
309 allow_yield: allow_yield.into(),
310 allow_await: allow_await.into(),
311 }
312 }
313}
314
315expression!(
316 BitwiseORExpression,
317 BitwiseXORExpression,
318 [Punctuator::Or],
319 [allow_in, allow_yield, allow_await],
320 None::<InputElement>
321);
322
323#[derive(Debug, Clone, Copy)]
332struct BitwiseXORExpression {
333 allow_in: AllowIn,
334 allow_yield: AllowYield,
335 allow_await: AllowAwait,
336}
337
338impl BitwiseXORExpression {
339 pub(super) fn new<I, Y, A>(allow_in: I, allow_yield: Y, allow_await: A) -> Self
341 where
342 I: Into<AllowIn>,
343 Y: Into<AllowYield>,
344 A: Into<AllowAwait>,
345 {
346 Self {
347 allow_in: allow_in.into(),
348 allow_yield: allow_yield.into(),
349 allow_await: allow_await.into(),
350 }
351 }
352}
353
354expression!(
355 BitwiseXORExpression,
356 BitwiseANDExpression,
357 [Punctuator::Xor],
358 [allow_in, allow_yield, allow_await],
359 None::<InputElement>
360);
361
362#[derive(Debug, Clone, Copy)]
371struct BitwiseANDExpression {
372 allow_in: AllowIn,
373 allow_yield: AllowYield,
374 allow_await: AllowAwait,
375}
376
377impl BitwiseANDExpression {
378 pub(super) fn new<I, Y, A>(allow_in: I, allow_yield: Y, allow_await: A) -> Self
380 where
381 I: Into<AllowIn>,
382 Y: Into<AllowYield>,
383 A: Into<AllowAwait>,
384 {
385 Self {
386 allow_in: allow_in.into(),
387 allow_yield: allow_yield.into(),
388 allow_await: allow_await.into(),
389 }
390 }
391}
392
393expression!(
394 BitwiseANDExpression,
395 EqualityExpression,
396 [Punctuator::And],
397 [allow_in, allow_yield, allow_await],
398 None::<InputElement>
399);
400
401#[derive(Debug, Clone, Copy)]
410struct EqualityExpression {
411 allow_in: AllowIn,
412 allow_yield: AllowYield,
413 allow_await: AllowAwait,
414}
415
416impl EqualityExpression {
417 pub(super) fn new<I, Y, A>(allow_in: I, allow_yield: Y, allow_await: A) -> Self
419 where
420 I: Into<AllowIn>,
421 Y: Into<AllowYield>,
422 A: Into<AllowAwait>,
423 {
424 Self {
425 allow_in: allow_in.into(),
426 allow_yield: allow_yield.into(),
427 allow_await: allow_await.into(),
428 }
429 }
430}
431
432expression!(
433 EqualityExpression,
434 RelationalExpression,
435 [
436 Punctuator::Eq,
437 Punctuator::NotEq,
438 Punctuator::StrictEq,
439 Punctuator::StrictNotEq
440 ],
441 [allow_in, allow_yield, allow_await],
442 None::<InputElement>
443);
444
445#[derive(Debug, Clone, Copy)]
454struct RelationalExpression {
455 allow_in: AllowIn,
456 allow_yield: AllowYield,
457 allow_await: AllowAwait,
458}
459
460impl RelationalExpression {
461 pub(super) fn new<I, Y, A>(allow_in: I, allow_yield: Y, allow_await: A) -> Self
463 where
464 I: Into<AllowIn>,
465 Y: Into<AllowYield>,
466 A: Into<AllowAwait>,
467 {
468 Self {
469 allow_in: allow_in.into(),
470 allow_yield: allow_yield.into(),
471 allow_await: allow_await.into(),
472 }
473 }
474}
475
476impl<R> TokenParser<R> for RelationalExpression
477where
478 R: Read,
479{
480 type Output = Node;
481
482 fn parse(self, cursor: &mut Cursor<R>) -> ParseResult {
483 let _timer = BoaProfiler::global().start_event("Relation Expression", "Parsing");
484
485 if None::<InputElement>.is_some() {
486 cursor.set_goal(None::<InputElement>.unwrap());
487 }
488
489 let mut lhs = ShiftExpression::new(self.allow_yield, self.allow_await).parse(cursor)?;
490 while let Some(tok) = cursor.peek(0)? {
491 match *tok.kind() {
492 TokenKind::Punctuator(op)
493 if op == Punctuator::LessThan
494 || op == Punctuator::GreaterThan
495 || op == Punctuator::LessThanOrEq
496 || op == Punctuator::GreaterThanOrEq =>
497 {
498 let _ = cursor.next().expect("token disappeared");
499 lhs = BinOp::new(
500 op.as_binop().expect("Could not get binary operation."),
501 lhs,
502 ShiftExpression::new(self.allow_yield, self.allow_await).parse(cursor)?,
503 )
504 .into();
505 }
506 TokenKind::Keyword(op)
507 if op == Keyword::InstanceOf
508 || (op == Keyword::In && self.allow_in == AllowIn(true)) =>
509 {
510 let _ = cursor.next().expect("token disappeared");
511 lhs = BinOp::new(
512 op.as_binop().expect("Could not get binary operation."),
513 lhs,
514 ShiftExpression::new(self.allow_yield, self.allow_await).parse(cursor)?,
515 )
516 .into();
517 }
518 _ => break,
519 }
520 }
521
522 Ok(lhs)
523 }
524}
525
526#[derive(Debug, Clone, Copy)]
535struct ShiftExpression {
536 allow_yield: AllowYield,
537 allow_await: AllowAwait,
538}
539
540impl ShiftExpression {
541 pub(super) fn new<Y, A>(allow_yield: Y, allow_await: A) -> Self
543 where
544 Y: Into<AllowYield>,
545 A: Into<AllowAwait>,
546 {
547 Self {
548 allow_yield: allow_yield.into(),
549 allow_await: allow_await.into(),
550 }
551 }
552}
553
554expression!(
555 ShiftExpression,
556 AdditiveExpression,
557 [
558 Punctuator::LeftSh,
559 Punctuator::RightSh,
560 Punctuator::URightSh
561 ],
562 [allow_yield, allow_await],
563 None::<InputElement>
564);
565
566#[derive(Debug, Clone, Copy)]
577struct AdditiveExpression {
578 allow_yield: AllowYield,
579 allow_await: AllowAwait,
580}
581
582impl AdditiveExpression {
583 pub(super) fn new<Y, A>(allow_yield: Y, allow_await: A) -> Self
585 where
586 Y: Into<AllowYield>,
587 A: Into<AllowAwait>,
588 {
589 Self {
590 allow_yield: allow_yield.into(),
591 allow_await: allow_await.into(),
592 }
593 }
594}
595
596expression!(
597 AdditiveExpression,
598 MultiplicativeExpression,
599 [Punctuator::Add, Punctuator::Sub],
600 [allow_yield, allow_await],
601 None::<InputElement>
602);
603
604#[derive(Debug, Clone, Copy)]
615struct MultiplicativeExpression {
616 allow_yield: AllowYield,
617 allow_await: AllowAwait,
618}
619
620impl MultiplicativeExpression {
621 pub(super) fn new<Y, A>(allow_yield: Y, allow_await: A) -> Self
623 where
624 Y: Into<AllowYield>,
625 A: Into<AllowAwait>,
626 {
627 Self {
628 allow_yield: allow_yield.into(),
629 allow_await: allow_await.into(),
630 }
631 }
632}
633
634expression!(
635 MultiplicativeExpression,
636 ExponentiationExpression,
637 [Punctuator::Mul, Punctuator::Div, Punctuator::Mod],
638 [allow_yield, allow_await],
639 Some(InputElement::Div)
640);