boa/syntax/parser/expression/assignment/
arrow_function.rs1use super::AssignmentExpression;
11use crate::{
12 syntax::{
13 ast::{
14 node::{ArrowFunctionDecl, FormalParameter, Node, Return, StatementList},
15 Punctuator,
16 },
17 lexer::{Error as LexError, Position, TokenKind},
18 parser::{
19 error::{ErrorContext, ParseError, ParseResult},
20 function::{FormalParameters, FunctionBody},
21 statement::BindingIdentifier,
22 AllowAwait, AllowIn, AllowYield, Cursor, TokenParser,
23 },
24 },
25 BoaProfiler,
26};
27
28use std::io::Read;
29
30#[derive(Debug, Clone, Copy)]
39pub(in crate::syntax::parser) struct ArrowFunction {
40 allow_in: AllowIn,
41 allow_yield: AllowYield,
42 allow_await: AllowAwait,
43}
44
45impl ArrowFunction {
46 pub(in crate::syntax::parser) fn new<I, Y, A>(
48 allow_in: I,
49 allow_yield: Y,
50 allow_await: A,
51 ) -> Self
52 where
53 I: Into<AllowIn>,
54 Y: Into<AllowYield>,
55 A: Into<AllowAwait>,
56 {
57 Self {
58 allow_in: allow_in.into(),
59 allow_yield: allow_yield.into(),
60 allow_await: allow_await.into(),
61 }
62 }
63}
64
65impl<R> TokenParser<R> for ArrowFunction
66where
67 R: Read,
68{
69 type Output = ArrowFunctionDecl;
70
71 fn parse(self, cursor: &mut Cursor<R>) -> Result<Self::Output, ParseError> {
72 let _timer = BoaProfiler::global().start_event("ArrowFunction", "Parsing");
73 let next_token = cursor.peek(0)?.ok_or(ParseError::AbruptEnd)?;
74
75 let params = if let TokenKind::Punctuator(Punctuator::OpenParen) = &next_token.kind() {
76 cursor.expect(Punctuator::OpenParen, "arrow function")?;
78
79 let params = FormalParameters::new(self.allow_yield, self.allow_await).parse(cursor)?;
80 cursor.expect(Punctuator::CloseParen, "arrow function")?;
81 params
82 } else {
83 let param = BindingIdentifier::new(self.allow_yield, self.allow_await)
84 .parse(cursor)
85 .context("arrow function")?;
86 Box::new([FormalParameter::new(param, None, false)])
87 };
88
89 cursor.peek_expect_no_lineterminator(0, "arrow function")?;
90
91 cursor.expect(TokenKind::Punctuator(Punctuator::Arrow), "arrow function")?;
92 let body = ConciseBody::new(self.allow_in).parse(cursor)?;
93
94 {
98 let lexically_declared_names = body.lexically_declared_names();
99 for param in params.as_ref() {
100 if lexically_declared_names.contains(param.name()) {
101 return Err(ParseError::lex(LexError::Syntax(
102 format!("Redeclaration of formal parameter `{}`", param.name()).into(),
103 match cursor.peek(0)? {
104 Some(token) => token.span().end(),
105 None => Position::new(1, 1),
106 },
107 )));
108 }
109 }
110 }
111
112 Ok(ArrowFunctionDecl::new(params, body))
113 }
114}
115
116#[derive(Debug, Clone, Copy)]
118struct ConciseBody {
119 allow_in: AllowIn,
120}
121
122impl ConciseBody {
123 fn new<I>(allow_in: I) -> Self
125 where
126 I: Into<AllowIn>,
127 {
128 Self {
129 allow_in: allow_in.into(),
130 }
131 }
132}
133
134impl<R> TokenParser<R> for ConciseBody
135where
136 R: Read,
137{
138 type Output = StatementList;
139
140 fn parse(self, cursor: &mut Cursor<R>) -> Result<Self::Output, ParseError> {
141 match cursor.peek(0)?.ok_or(ParseError::AbruptEnd)?.kind() {
142 TokenKind::Punctuator(Punctuator::OpenBlock) => {
143 let _ = cursor.next();
144 let body = FunctionBody::new(false, false).parse(cursor)?;
145 cursor.expect(Punctuator::CloseBlock, "arrow function")?;
146 Ok(body)
147 }
148 _ => Ok(StatementList::from(vec![Return::new(
149 ExpressionBody::new(self.allow_in, false).parse(cursor)?,
150 None,
151 )
152 .into()])),
153 }
154 }
155}
156
157#[derive(Debug, Clone, Copy)]
159struct ExpressionBody {
160 allow_in: AllowIn,
161 allow_await: AllowAwait,
162}
163
164impl ExpressionBody {
165 fn new<I, A>(allow_in: I, allow_await: A) -> Self
167 where
168 I: Into<AllowIn>,
169 A: Into<AllowAwait>,
170 {
171 Self {
172 allow_in: allow_in.into(),
173 allow_await: allow_await.into(),
174 }
175 }
176}
177
178impl<R> TokenParser<R> for ExpressionBody
179where
180 R: Read,
181{
182 type Output = Node;
183
184 fn parse(self, cursor: &mut Cursor<R>) -> ParseResult {
185 AssignmentExpression::new(self.allow_in, false, self.allow_await).parse(cursor)
186 }
187}