1 // Copyright (c) 2019, Facebook, Inc.
2 // All rights reserved.
4 // This source code is licensed under the MIT license found in the
5 // LICENSE file in the "hack" directory of this source tree.
7 use crate::declaration_parser::DeclarationParser;
8 use crate::expression_parser::ExpressionParser;
9 use crate::lexer::Lexer;
10 use crate::parser_env::ParserEnv;
11 use crate::parser_trait::Context;
12 use crate::parser_trait::ParserTrait;
13 use crate::parser_trait::SeparatedListKind;
14 use crate::smart_constructors::{NodeType, SmartConstructors};
15 use parser_core_types::lexable_token::LexableToken;
16 use parser_core_types::syntax_error::{self as Errors, SyntaxError};
17 use parser_core_types::token_kind::TokenKind;
19 pub struct TypeParser<'a, S, T>
21 S: SmartConstructors<'a, T>,
24 lexer: Lexer<'a, S::Token>,
26 context: Context<'a, S::Token>,
27 errors: Vec<SyntaxError>,
31 impl<'a, S, T: Clone> std::clone::Clone for TypeParser<'a, S, T>
33 S: SmartConstructors<'a, T>,
36 fn clone(&self) -> Self {
38 lexer: self.lexer.clone(),
39 env: self.env.clone(),
40 context: self.context.clone(),
41 errors: self.errors.clone(),
47 impl<'a, S, T: Clone> ParserTrait<'a, S, T> for TypeParser<'a, S, T>
49 S: SmartConstructors<'a, T>,
53 mut lexer: Lexer<'a, S::Token>,
55 context: Context<'a, S::Token>,
56 errors: Vec<SyntaxError>,
59 lexer.set_in_type(true);
73 Context<'a, S::Token>,
77 self.lexer.set_in_type(false);
78 (self.lexer, self.context, self.errors, self.sc)
81 fn lexer(&self) -> &Lexer<'a, S::Token> {
85 fn lexer_mut(&mut self) -> &mut Lexer<'a, S::Token> {
89 fn continue_from<P: ParserTrait<'a, S, T>>(&mut self, other: P)
93 let (mut lexer, context, errors, sc) = other.into_parts();
94 lexer.set_in_type(true);
96 self.context = context;
101 fn add_error(&mut self, error: SyntaxError) {
102 self.errors.push(error)
105 fn env(&self) -> &ParserEnv {
109 fn sc_mut(&mut self) -> &mut S {
113 fn drain_skipped_tokens(&mut self) -> std::vec::Drain<S::Token> {
114 self.context.skipped_tokens.drain(..)
117 fn skipped_tokens(&self) -> &[S::Token] {
118 &self.context.skipped_tokens
121 fn context_mut(&mut self) -> &mut Context<'a, S::Token> {
125 fn context(&self) -> &Context<'a, S::Token> {
130 impl<'a, S, T: Clone> TypeParser<'a, S, T>
132 S: SmartConstructors<'a, T>,
135 fn with_expression_parser<F, U>(&mut self, f: F) -> U
137 F: Fn(&mut ExpressionParser<'a, S, T>) -> U,
139 let mut lexer = self.lexer.clone();
140 lexer.set_in_type(false);
141 let mut expression_parser: ExpressionParser<S, T> = ExpressionParser::make(
144 self.context.clone(),
148 let res = f(&mut expression_parser);
149 self.continue_from(expression_parser);
153 fn parse_expression(&mut self) -> S::R {
154 self.with_expression_parser(|p: &mut ExpressionParser<'a, S, T>| p.parse_expression())
157 fn with_decl_parser<F, U>(&mut self, f: F) -> U
159 F: Fn(&mut DeclarationParser<'a, S, T>) -> U,
161 let mut lexer = self.lexer.clone();
162 lexer.set_in_type(false);
164 let mut declaration_parser: DeclarationParser<S, T> = DeclarationParser::make(
167 self.context.clone(),
171 let res = f(&mut declaration_parser);
172 self.continue_from(declaration_parser);
176 // TODO: What about something like for::for? Is that a legal type constant?
177 pub fn parse_type_specifier(&mut self, allow_var: bool, allow_attr: bool) -> S::R {
178 // Strictly speaking, "mixed" is a nullable type specifier. We parse it as
179 // a simple type specifier here.
180 let mut parser1 = self.clone();
181 let token = parser1.next_xhp_class_name_or_other_token();
182 let new_attr_syntax = self.env.allow_new_attribute_syntax;
184 | TokenKind::Var if allow_var => {
185 self.continue_from(parser1);
186 let token = S!(make_token, self, token);
187 S!(make_simple_type_specifier, self, token)
189 | TokenKind::This => self.parse_simple_type_or_type_constant(),
190 // Any keyword-type could be a non-keyword type, because PHP, so check whether
191 // these have generics.
192 | TokenKind::Double // TODO: Specification does not mention double; fix it.
202 | TokenKind::Arraykey
204 | TokenKind::Noreturn
205 | TokenKind::Resource
208 | TokenKind::NullLiteral
209 | TokenKind::Name => self.parse_simple_type_or_type_constant_or_generic(),
210 | TokenKind::Namespace => {
211 let name = self.scan_name_or_qualified_name();
212 self.parse_remaining_simple_type_or_type_constant_or_generic(name)
214 | TokenKind::Backslash => {
215 self.continue_from(parser1);
216 let missing = S!(make_missing, self, self.pos());
217 let token = S!(make_token, self, token);
218 let name = self.scan_qualified_name(missing, token);
219 self.parse_remaining_simple_type_or_type_constant_or_generic(name)
221 | TokenKind::SelfToken
222 | TokenKind::Parent => self.parse_simple_type_or_type_constant(),
223 | TokenKind::Category
225 | TokenKind::XHPClassName => self.parse_simple_type_or_type_constant_or_generic(),
226 | TokenKind::Array => self.parse_array_type_specifier(),
227 | TokenKind::Darray => self.parse_darray_type_specifier(),
228 | TokenKind::Varray => self.parse_varray_type_specifier(),
229 | TokenKind::Vec => self.parse_vec_type_specifier(),
230 | TokenKind::Dict => self.parse_dictionary_type_specifier(),
231 | TokenKind::Keyset => self.parse_keyset_type_specifier(),
232 | TokenKind::Tuple => self.parse_tuple_type_explicit_specifier(),
233 | TokenKind::LeftParen => self.parse_tuple_or_closure_type_specifier(),
234 | TokenKind::Shape => self.parse_shape_specifier(),
235 | TokenKind::Question => self.parse_nullable_type_specifier(),
236 | TokenKind::Tilde => self.parse_like_type_specifier(),
237 | TokenKind::At if !new_attr_syntax => self.parse_soft_type_specifier(),
238 | TokenKind::At if new_attr_syntax => self.parse_attributized_specifier(),
239 | TokenKind::LessThanLessThan if allow_attr => self.parse_attributized_specifier(),
240 | TokenKind::Classname => self.parse_classname_type_specifier(),
242 self.with_error_on_whole_token(Errors::error1007);
243 let token = self.next_xhp_class_name_or_other_token();
244 let token = S!(make_token, self, token);
245 S!(make_error, self, token)
251 // type-constant-type-name:
256 // type-constant-type-name :: name
257 fn parse_remaining_type_constant(&mut self, left: S::R) -> S::R {
258 let separator = self.fetch_token();
259 let right = self.next_token_as_name();
260 if right.kind() == TokenKind::Name {
261 let right = S!(make_token, self, right);
262 let syntax = S!(make_type_constant, self, left, separator, right);
263 let token = self.peek_token();
264 if token.kind() == TokenKind::ColonColon {
265 self.parse_remaining_type_constant(syntax)
270 // ERROR RECOVERY: Assume that the thing following the ::
271 // that is not a name belongs to the next thing to be
272 // parsed; treat the name as missing.
273 self.with_error(Errors::error1004);
274 let missing = S!(make_missing, self, self.pos());
275 S!(make_type_constant, self, left, separator, missing)
280 // pocket-universe-access:
285 // pocket-universe-access :@ name
286 fn parse_remaining_pocket_universe_access(&mut self, left: S::R) -> S::R {
287 let separator = self.fetch_token();
288 let right = self.next_token_as_name();
289 if right.kind() == TokenKind::Name {
290 let right = S!(make_token, self, right);
291 let syntax = S!(make_pu_access, self, left, separator, right);
292 let token = self.peek_token();
293 if token.kind() == TokenKind::ColonAt {
294 self.parse_remaining_pocket_universe_access(syntax)
299 // ERROR RECOVERY: Assume that the thing following the :@
300 // that is not a name belongs to the next thing to be
301 // parsed; treat the name as missing.
302 self.with_error(Errors::error1004);
303 let missing = S!(make_missing, self, self.pos());
304 S!(make_pu_access, self, left, separator, missing)
308 fn parse_remaining_generic(&mut self, name: S::R) -> S::R {
309 let (arguments, _) = self.parse_generic_type_argument_list();
310 S!(make_generic_type_specifier, self, name, arguments)
313 pub fn parse_simple_type_or_type_constant(&mut self) -> S::R {
314 let name = self.next_xhp_class_name_or_other();
315 self.parse_remaining_simple_type_or_type_constant(name)
318 pub fn parse_simple_type_or_generic(&mut self) -> S::R {
319 let name = self.next_xhp_class_name_or_other();
320 self.parse_remaining_simple_type_or_generic(name)
323 fn parse_remaining_simple_type_or_type_constant(&mut self, name: S::R) -> S::R {
324 let token = self.peek_token();
326 TokenKind::ColonColon => self.parse_remaining_type_constant(name),
327 TokenKind::ColonAt => self.parse_remaining_pocket_universe_access(name),
328 _ => S!(make_simple_type_specifier, self, name),
332 fn parse_simple_type_or_type_constant_or_generic(&mut self) -> S::R {
333 let name = self.next_xhp_class_name_or_other();
334 self.parse_remaining_simple_type_or_type_constant_or_generic(name)
337 pub fn parse_remaining_type_specifier(&mut self, name: S::R) -> S::R {
338 self.parse_remaining_simple_type_or_type_constant_or_generic(name)
341 fn parse_remaining_simple_type_or_type_constant_or_generic(&mut self, name: S::R) -> S::R {
342 match self.peek_token_kind_with_possible_attributized_type_list() {
343 TokenKind::LessThan => self.parse_remaining_generic(name),
344 _ => self.parse_remaining_simple_type_or_type_constant(name),
348 fn parse_remaining_simple_type_or_generic(&mut self, name: S::R) -> S::R {
349 match self.peek_token_kind_with_possible_attributized_type_list() {
350 TokenKind::LessThan => self.parse_remaining_generic(name),
351 _ => S!(make_simple_type_specifier, self, name),
356 // generic-type-constraint-list:
357 // generic-type-constraint
358 // generic-type-constraint generic-type-constraint-list
360 // generic-type-constraint:
362 // super type-specifier
364 // TODO: SPEC ISSUES:
365 // https://github.com/hhvm/hack-langspec/issues/83
367 // TODO: Do we also need to allow "= type-specifier" here?
368 fn parse_generic_type_constraint_opt(&mut self) -> Option<S::R> {
369 let mut parser1 = self.clone();
370 let token = parser1.next_token();
372 TokenKind::As | TokenKind::Super => {
373 self.continue_from(parser1);
374 let constraint_token = S!(make_token, self, token);
375 let matched_type = self.parse_type_specifier(false, true);
376 let type_constraint =
377 S!(make_type_constraint, self, constraint_token, matched_type);
378 Some(type_constraint)
384 fn parse_variance_opt(&mut self) -> S::R {
385 match self.peek_token_kind() {
386 TokenKind::Plus | TokenKind::Minus => self.fetch_token(),
387 _ => S!(make_missing, self, self.pos()),
392 // generic-type-parameter:
393 // generic-type-parameter-reified-opt generic-type-parameter-variance-opt
394 // name type-parameter-list? generic-type-constraint-list-opt
396 // generic-type-parameter-variance:
400 // TODO: SPEC ISSUE: We allow any number of type constraints, not just zero
401 // or one as indicated in the spec.
402 // https://github.com/hhvm/hack-langspec/issues/83
403 // TODO: Update the spec with reified
404 pub fn parse_type_parameter(&mut self) -> S::R {
405 let attributes = self.with_decl_parser(|x: &mut DeclarationParser<'a, S, T>| {
406 x.parse_attribute_specification_opt()
408 let reified = self.optional_token(TokenKind::Reify);
409 let variance = self.parse_variance_opt();
410 let type_name = self.require_name_allow_all_keywords();
411 let param_params = self.parse_generic_type_parameter_list_opt();
413 self.parse_list_until_none(|x: &mut Self| x.parse_generic_type_constraint_opt());
426 pub fn parse_generic_type_parameter_list_opt(&mut self) -> S::R {
427 match self.peek_token_kind_with_possible_attributized_type_list() {
428 TokenKind::LessThan => self.parse_generic_type_parameter_list(),
429 _ => S!(make_missing, self, self.pos()),
434 // type-parameter-list:
435 // < generic-type-parameters ,-opt >
437 // generic-type-parameters:
438 // generic-type-parameter
439 // generic-type-parameter , generic-type-parameter
442 pub fn parse_generic_type_parameter_list(&mut self) -> S::R {
443 let left = self.assert_left_angle_in_type_list_with_possible_attribute();
444 let (params, _) = self.parse_comma_list_allow_trailing(
445 TokenKind::GreaterThan,
447 |x: &mut Self| x.parse_type_parameter(),
450 let right = self.require_right_angle();
451 S!(make_type_parameters, self, left, params, right)
454 fn parse_type_list(&mut self, close_kind: TokenKind) -> S::R {
456 // type-specifier-list:
457 // type-specifiers ,opt
461 // type-specifiers , type-specifier
463 self.parse_comma_list_allow_trailing(close_kind, Errors::error1007, |x: &mut Self| {
464 x.parse_type_specifier(false, true)
471 // TODO: Add this to the specification.
472 // (This work is tracked by task T22582676.)
477 fn parse_call_convention_opt(&mut self) -> S::R {
478 match self.peek_token_kind() {
479 TokenKind::Inout => {
480 let token = self.next_token();
481 S!(make_token, self, token)
483 _ => S!(make_missing, self, self.pos()),
489 // TODO: Add this to the specification.
490 // (This work is tracked by task T22582676.)
492 // closure-param-type-specifier-list:
493 // closure-param-type-specifiers ,opt
495 // closure-param-type-specifiers:
496 // closure-param-type-specifier
497 // closure-param-type-specifiers , closure-param-type-specifier
499 fn parse_closure_param_list(&mut self, close_kind: TokenKind) -> S::R {
501 self.parse_comma_list_allow_trailing(close_kind, Errors::error1007, |x: &mut Self| {
502 x.parse_closure_param_type_or_ellipsis()
509 // TODO: Add this to the specification.
510 // (This work is tracked by task T22582676.)
512 // ERROR RECOVERY: Variadic params cannot be declared inout; this error is
513 // caught in a later pass.
515 // closure-param-type-specifier:
516 // call-convention-opt type-specifier
517 // type-specifier ...
520 fn parse_closure_param_type_or_ellipsis(&mut self) -> S::R {
521 match self.peek_token_kind() {
522 TokenKind::DotDotDot => {
523 let missing1 = S!(make_missing, self, self.pos());
524 let missing2 = S!(make_missing, self, self.pos());
525 let token = self.next_token();
526 let token = S!(make_token, self, token);
527 S!(make_variadic_parameter, self, missing1, missing2, token)
530 let callconv = self.parse_call_convention_opt();
531 let ts = self.parse_type_specifier(false, true);
532 match self.peek_token_kind() {
533 TokenKind::DotDotDot => {
534 let token = self.next_token();
535 let token = S!(make_token, self, token);
536 S!(make_variadic_parameter, self, callconv, ts, token)
538 _ => S!(make_closure_parameter_type_specifier, self, callconv, ts),
544 fn parse_optionally_reified_type(&mut self) -> S::R {
545 if self.peek_token_kind() == TokenKind::Reify {
546 let token = self.next_token();
547 let reified_kw = S!(make_token, self, token);
548 let type_argument = self.parse_type_specifier(false, true);
549 S!(make_reified_type_argument, self, reified_kw, type_argument)
551 self.parse_type_specifier(false, true)
555 pub fn parse_generic_type_argument_list(&mut self) -> (S::R, bool) {
557 // generic-type-argument-list:
558 // < generic-type-arguments ,opt >
560 // generic-type-arguments:
561 // generic-type-argument
562 // generic-type-arguments , generic-type-argument
565 // https://github.com/hhvm/hack-langspec/issues/84
566 // The specification indicates that "noreturn" is only syntactically valid
567 // as a return type hint, but this is plainly wrong because
568 // Awaitable<noreturn> is a legal type. Likely the correct rule will be to
569 // allow noreturn as a type argument, and then a later semantic analysis
570 // pass can determine when it is being used incorrectly.
572 // For now, we extend the specification to allow return types, not just
574 let open_angle = self.assert_left_angle_in_type_list_with_possible_attribute();
575 let (args, no_arg_is_missing) = self.parse_comma_list_allow_trailing(
576 TokenKind::GreaterThan,
578 |x: &mut Self| x.parse_optionally_reified_type(),
580 match self.peek_token_kind() {
581 TokenKind::GreaterThan => {
582 let close_angle = self.assert_token(TokenKind::GreaterThan);
583 let result = S!(make_type_arguments, self, open_angle, args, close_angle);
584 (result, no_arg_is_missing)
587 // ERROR RECOVERY: Don't eat the token that is in the place of the
588 // missing > or ,. TokenKind::Assume that it is the > that is missing and
589 // try to parse whatever is coming after the type.
590 self.with_error(Errors::error1014);
591 let missing = S!(make_missing, self, self.pos());
592 let result = S!(make_type_arguments, self, open_angle, args, missing);
593 (result, no_arg_is_missing)
598 fn parse_array_type_specifier(&mut self) -> S::R {
603 // TODO: Put a proper reference to the specification in here.
604 // TODO: in HHVM trailing comma is permitted only in the case with one
605 // type argument: array<type, >
606 // so now it is not really comma-separated list
607 let array_token = self.assert_token(TokenKind::Array);
608 if self.peek_token_kind_with_possible_attributized_type_list() != TokenKind::LessThan {
609 S!(make_simple_type_specifier, self, array_token)
611 let left_angle = self.assert_left_angle_in_type_list_with_possible_attribute();
612 // ERROR RECOVERY: We could improve error recovery by detecting
613 // array<, and marking the key type as missing.
614 let key_type = self.parse_type_specifier(false, true);
615 let kind = self.peek_token_kind();
616 if kind == TokenKind::GreaterThan {
617 let right_angle = self.fetch_token();
619 make_vector_array_type_specifier,
626 } else if kind == TokenKind::Comma {
627 let comma = self.fetch_token();
628 let next_token_kind = self.peek_token_kind();
629 let value_type = if next_token_kind == TokenKind::GreaterThan {
630 S!(make_missing, self, self.pos())
632 self.parse_type_specifier(false, true)
634 let right_angle = self.require_right_angle();
636 make_map_array_type_specifier,
646 // ERROR RECOVERY: TokenKind::Assume that the > is missing and keep going.
647 let right_angle = S!(make_missing, self, self.pos());
649 make_vector_array_type_specifier,
660 fn parse_darray_type_specifier(&mut self) -> S::R {
661 // darray<type, type>
662 let array_token = self.assert_token(TokenKind::Darray);
663 if self.peek_token_kind_with_possible_attributized_type_list() != TokenKind::LessThan {
664 S!(make_simple_type_specifier, self, array_token)
666 let left_angle = self.assert_left_angle_in_type_list_with_possible_attribute();
667 let key_type = self.parse_type_specifier(false, true);
668 let comma = self.require_comma();
669 let value_type = self.parse_type_specifier(false, true);
670 let optional_comma = self.optional_token(TokenKind::Comma);
671 let right_angle = self.require_right_angle();
673 make_darray_type_specifier,
686 fn parse_varray_type_specifier(&mut self) -> S::R {
688 let array_token = self.assert_token(TokenKind::Varray);
689 if self.peek_token_kind_with_possible_attributized_type_list() != TokenKind::LessThan {
690 S!(make_simple_type_specifier, self, array_token)
692 let left_angle = self.assert_left_angle_in_type_list_with_possible_attribute();
693 let value_type = self.parse_type_specifier(false, true);
694 let optional_comma = self.optional_token(TokenKind::Comma);
695 let right_angle = self.require_right_angle();
697 make_varray_type_specifier,
708 fn parse_vec_type_specifier(&mut self) -> S::R {
709 // vec < type-specifier >
710 // TODO: Should we allow a trailing comma?
711 // TODO: Add this to the specification
712 // ERROR RECOVERY: If there is no type argument list then just make
713 // this a simple type. TODO: Should this be an error at parse time? what
714 // about at type checking time?
715 let keyword = self.assert_token(TokenKind::Vec);
716 if self.peek_token_kind_with_possible_attributized_type_list() != TokenKind::LessThan {
717 S!(make_simple_type_specifier, self, keyword)
719 let left = self.assert_left_angle_in_type_list_with_possible_attribute();
720 let t = self.parse_type_specifier(false, true);
721 let optional_comma = self.optional_token(TokenKind::Comma);
722 let right = self.require_right_angle();
724 make_vector_type_specifier,
735 fn parse_keyset_type_specifier(&mut self) -> S::R {
736 // keyset < type-specifier >
737 // TODO: Should we allow a trailing comma?
738 // TODO: Add this to the specification
739 // ERROR RECOVERY: If there is no type argument list then just make
740 // this a simple type. TODO: Should this be an error at parse time? what
741 // about at type checking time?
742 let keyword = self.assert_token(TokenKind::Keyset);
743 if self.peek_token_kind_with_possible_attributized_type_list() != TokenKind::LessThan {
744 S!(make_simple_type_specifier, self, keyword)
746 let left = self.assert_left_angle_in_type_list_with_possible_attribute();
747 let t = self.parse_type_specifier(false, true);
748 let comma = self.optional_token(TokenKind::Comma);
749 let right = self.require_right_angle();
751 make_keyset_type_specifier,
762 fn parse_tuple_type_explicit_specifier(&mut self) -> S::R {
763 // tuple < type-specifier-list >
764 // TODO: Add this to the specification
765 let keyword = self.assert_token(TokenKind::Tuple);
766 let left_angle = if self.peek_next_partial_token_is_triple_left_angle() {
767 self.assert_left_angle_in_type_list_with_possible_attribute()
769 self.require_left_angle()
771 let args = self.parse_type_list(TokenKind::GreaterThan);
772 let mut parser1 = self.clone();
773 let right_angle = parser1.next_token();
774 if right_angle.kind() == TokenKind::GreaterThan {
775 self.continue_from(parser1);
776 let token = S!(make_token, self, right_angle);
778 make_tuple_type_explicit_specifier,
786 // ERROR RECOVERY: Don't eat the token that is in the place of the
787 // missing > or ,. TokenKind::Assume that it is the > that is missing and
788 // try to parse whatever is coming after the type.
789 self.with_error(Errors::error1022);
790 let right_angle = S!(make_missing, self, self.pos());
792 make_tuple_type_explicit_specifier,
802 fn parse_dictionary_type_specifier(&mut self) -> S::R {
803 // dict < type-specifier , type-specifier >
805 // TODO: Add this to the specification
807 // Though we require there to be exactly two items, we actually parse
808 // an arbitrary comma-separated list here.
810 // TODO: Give an error in a later pass if there are not exactly two members.
812 // ERROR RECOVERY: If there is no type argument list then just make this
813 // a simple type. TODO: Should this be an error at parse time? what
814 // about at type checking time?
815 let keyword = self.assert_token(TokenKind::Dict);
816 if self.peek_token_kind_with_possible_attributized_type_list() != TokenKind::LessThan {
817 S!(make_simple_type_specifier, self, keyword)
819 // TODO: This allows "noreturn" as a type argument. Should we
820 // disallow that at parse time?
821 let left = self.assert_left_angle_in_type_list_with_possible_attribute();
822 let (arguments, _) = self.parse_comma_list_allow_trailing(
823 TokenKind::GreaterThan,
825 |x: &mut Self| x.parse_return_type(),
827 let right = self.require_right_angle();
829 make_dictionary_type_specifier,
839 fn parse_tuple_or_closure_type_specifier(&mut self) -> S::R {
840 let mut parser1 = self.clone();
841 let _ = parser1.assert_token(TokenKind::LeftParen);
842 let token = parser1.peek_token();
844 TokenKind::Function | TokenKind::Coroutine => self.parse_closure_type_specifier(),
845 _ => self.parse_tuple_or_union_or_intersection_type_specifier(),
849 fn parse_closure_type_specifier(&mut self) -> S::R {
852 // TODO: Update the specification with closure-param-type-specifier-list-opt.
853 // (This work is tracked by task T22582676.)
855 // TODO: Update grammar for inout parameters.
856 // (This work is tracked by task T22582715.)
858 // closure-type-specifier:
860 // closure-param-type-specifier-list-opt \
861 // ) : type-specifier )
863 // TODO: Error recovery is pretty weak here. We could be smarter.
864 let olp = self.fetch_token();
865 let fnc = self.fetch_token();
866 let ilp = self.require_left_paren();
867 let (pts, irp) = if self.peek_token_kind() == TokenKind::RightParen {
868 let missing = S!(make_missing, self, self.pos());
869 let token = self.next_token();
870 let token = S!(make_token, self, token);
873 // TODO add second pass checking to ensure ellipsis is the last arg
874 let pts = self.parse_closure_param_list(TokenKind::RightParen);
875 let irp = self.require_right_paren();
878 let col = self.require_colon();
879 let ret = self.parse_type_specifier(false, true);
880 let orp = self.require_right_paren();
882 make_closure_type_specifier,
895 fn parse_tuple_or_union_or_intersection_type_specifier(&mut self) -> S::R {
897 // tuple-union-intersection-type-specifier:
898 // ( type-specifier , type-specifier-list )
899 // ( type-specifier & intersection-type-specifier-list )
900 // ( type-specifier | union-type-specifier-list )
901 // type-specifier-list:
902 // type-specifiers ,opt
905 // type-specifiers , type-specifier
906 // intersection-type-specifier-list:
908 // intersection-type-specifier-list & type-specifier
909 // union-type-specifier-list:
911 // union-type-specifier-list | type-specifier
913 // TODO: Here we parse a type list with one or more items, but the grammar
914 // actually requires a type list with two or more items. Give an error in
915 // a later pass if there is only one item here.
917 let left_paren = self.assert_token(TokenKind::LeftParen);
919 let (args, _, separator_kind) = self.parse_separated_list_predicate(
920 |x| x == TokenKind::Bar || x == TokenKind::Ampersand || x == TokenKind::Comma,
921 SeparatedListKind::TrailingAllowed,
922 |x| x == TokenKind::RightParen,
924 |x: &mut Self| x.parse_type_specifier(false, true),
927 if self.peek_token_kind() == TokenKind::RightParen {
928 let right_paren = self.next_token();
929 let token = S!(make_token, self, right_paren);
930 match separator_kind {
931 TokenKind::Bar => S!(make_union_type_specifier, self, left_paren, args, token),
932 TokenKind::Ampersand => S!(
933 make_intersection_type_specifier,
939 _ => S!(make_tuple_type_specifier, self, left_paren, args, token),
942 // ERROR RECOVERY: Don't eat the token that is in the place of the
943 // missing ) or ,. Assume that it is the ) that is missing and
944 // try to parse whatever is coming after the type.
945 self.with_error(Errors::error1022);
946 let missing = S!(make_missing, self, self.pos());
947 S!(make_tuple_type_specifier, self, left_paren, args, missing)
951 fn parse_nullable_type_specifier(&mut self) -> S::R {
953 // nullable-type-specifier:
957 // Note that we parse "mixed" as a simple type specifier, even though
958 // technically it is classified as a nullable type specifier by the grammar.
959 // Note that it is perfectly legal to have trivia between the ? and the
961 let question = self.assert_token(TokenKind::Question);
962 let nullable_type = self.parse_type_specifier(false, true);
963 S!(make_nullable_type_specifier, self, question, nullable_type)
966 fn parse_like_type_specifier(&mut self) -> S::R {
968 // like-type-specifier:
971 // Note that it is perfectly legal to have trivia between the ~ and the
973 let tilde = self.assert_token(TokenKind::Tilde);
974 let like_type = self.parse_type_specifier(false, true);
975 S!(make_like_type_specifier, self, tilde, like_type)
978 fn parse_soft_type_specifier(&mut self) -> S::R {
980 // soft-type-specifier:
983 // TODO: The spec does not mention this type grammar. Work out where and
984 // when it is legal, and what the exact semantics are, and put it in the spec.
985 // Add an error pass if necessary to identify illegal usages of this type.
987 // Note that it is legal for trivia to come between the @ and the type.
988 let soft_at = self.assert_token(TokenKind::At);
989 let soft_type = self.parse_type_specifier(false, true);
990 S!(make_soft_type_specifier, self, soft_at, soft_type)
993 fn parse_attributized_specifier(&mut self) -> S::R {
995 // attributized-specifier:
996 // attribute-specification-opt type-specifier
997 let attribute_spec_opt = self.with_decl_parser(|x: &mut DeclarationParser<'a, S, T>| {
998 x.parse_attribute_specification_opt()
1000 let attributized_type = self.parse_type_specifier(false, true);
1002 make_attributized_specifier,
1009 fn parse_classname_type_specifier(&mut self) -> S::R {
1011 // classname-type-specifier:
1013 // classname < qualified-name generic-type-argument-list-opt >
1015 // TODO: We parse any type as the class name type; we should write an
1016 // error detection pass later that determines when this is a bad type.
1018 // TODO: Is this grammar correct? In particular, can the name have a
1019 // scope resolution operator (::) in it? Find out and update the spec if
1020 // this is permitted.
1022 // TODO ERROR RECOVERY is unsophisticated here.
1023 let classname = self.fetch_token();
1024 match self.peek_token_kind() {
1025 TokenKind::LessThan => {
1026 let left_angle = self.require_left_angle();
1027 let classname_type = self.parse_type_specifier(false, true);
1028 let optional_comma = self.optional_token(TokenKind::Comma);
1029 let right_angle = self.require_right_angle();
1031 make_classname_type_specifier,
1041 let missing1 = S!(make_missing, self, self.pos());
1042 let missing2 = S!(make_missing, self, self.pos());
1043 let missing3 = S!(make_missing, self, self.pos());
1044 let missing4 = S!(make_missing, self, self.pos());
1046 make_classname_type_specifier,
1058 fn parse_field_specifier(&mut self) -> S::R {
1061 // ?-opt present-field-specifier
1062 // present-field-specifier:
1063 // single-quoted-string-literal => type-specifier
1064 // qualified-name => type-specifier
1065 // scope-resolution-expression => type-specifier
1067 // TODO: We require that it be either all literals or no literals in the
1068 // set of specifiers; make an error reporting pass that detects this.
1070 // ERROR RECOVERY: We allow any expression for the left-hand side.
1071 // TODO: Make an error-detecting pass that gives an error if the left-hand
1072 // side is not a literal or name.
1073 let question = if self.peek_token_kind() == TokenKind::Question {
1074 self.assert_token(TokenKind::Question)
1076 S!(make_missing, self, self.pos())
1078 let name = self.parse_expression();
1079 let arrow = self.require_arrow();
1080 let field_type = self.parse_type_specifier(false, true);
1082 make_field_specifier,
1091 fn parse_shape_specifier(&mut self) -> S::R {
1094 // shape ( field-specifier-list-opt )
1095 // field-specifier-list:
1096 // field-specifiers , ...
1097 // field-specifiers ,-opt
1098 // field-specifiers:
1100 // field-specifiers , field-specifier
1102 // TODO: ERROR RECOVERY is not very sophisticated here.
1103 let shape = self.fetch_token();
1104 let lparen = self.require_left_paren();
1105 let is_closing_token =
1106 |x: TokenKind| x == TokenKind::RightParen || x == TokenKind::DotDotDot;
1107 let fields = self.parse_comma_list_opt_allow_trailing_predicate(
1110 |x: &mut Self| x.parse_field_specifier(),
1112 let ellipsis = if self.peek_token_kind() == TokenKind::DotDotDot {
1113 self.assert_token(TokenKind::DotDotDot)
1115 S!(make_missing, self, self.pos())
1117 let rparen = self.require_right_paren();
1119 make_shape_type_specifier,
1129 pub fn parse_type_constraint_opt(&mut self) -> S::R {
1132 // as type-specifier
1133 // TODO: Is this correct? Or do we need to allow "super" as well?
1134 // TODO: What about = ?
1135 if self.peek_token_kind() == TokenKind::As {
1136 let constraint_as = self.next_token();
1137 let constraint_as = S!(make_token, self, constraint_as);
1138 let constraint_type = self.parse_type_specifier(false, true);
1139 S!(make_type_constraint, self, constraint_as, constraint_type)
1141 S!(make_missing, self, self.pos())
1145 pub fn parse_return_type(&mut self) -> S::R {
1146 if self.peek_token_kind() == TokenKind::Noreturn {
1147 let token = self.next_token();
1148 S!(make_token, self, token)
1150 self.parse_type_specifier(false, true)