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::expression_parser::ExpressionParser;
8 use crate::lexer::Lexer;
9 use crate::parser_env::ParserEnv;
10 use crate::parser_trait::{Context, ExpectedTokens, ParserTrait, SeparatedListKind};
11 use crate::smart_constructors::{NodeType, SmartConstructors};
12 use crate::statement_parser::StatementParser;
13 use crate::type_parser::TypeParser;
14 use parser_core_types::lexable_token::LexableToken;
15 use parser_core_types::lexable_trivia::LexableTrivia;
16 use parser_core_types::syntax_error::{self as Errors, SyntaxError};
17 use parser_core_types::token_kind::TokenKind;
18 use parser_core_types::trivia_kind::TriviaKind;
21 pub struct DeclarationParser<'a, S, T>
23 S: SmartConstructors<'a, T>,
26 lexer: Lexer<'a, S::Token>,
28 context: Context<'a, S::Token>,
29 errors: Vec<SyntaxError>,
33 impl<'a, S, T: Clone> Clone for DeclarationParser<'a, S, T>
35 S: SmartConstructors<'a, T>,
38 fn clone(&self) -> Self {
40 lexer: self.lexer.clone(),
41 env: self.env.clone(),
42 context: self.context.clone(),
43 errors: self.errors.clone(),
49 impl<'a, S, T: Clone> ParserTrait<'a, S, T> for DeclarationParser<'a, S, T>
51 S: SmartConstructors<'a, T>,
55 lexer: Lexer<'a, S::Token>,
57 context: Context<'a, S::Token>,
58 errors: Vec<SyntaxError>,
74 Context<'a, S::Token>,
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 (lexer, context, errors, sc) = other.into_parts();
95 self.context = context;
100 fn add_error(&mut self, error: SyntaxError) {
101 self.errors.push(error)
104 fn env(&self) -> &ParserEnv {
108 fn sc_mut(&mut self) -> &mut S {
112 fn skipped_tokens_mut(&mut self) -> &mut Vec<S::Token> {
113 &mut self.context.skipped_tokens
116 fn skipped_tokens(&self) -> &[S::Token] {
117 &self.context.skipped_tokens
120 fn context_mut(&mut self) -> &mut Context<'a, S::Token> {
124 fn context(&self) -> &Context<'a, S::Token> {
129 impl<'a, S, T: Clone> DeclarationParser<'a, S, T>
131 S: SmartConstructors<'a, T>,
134 fn with_type_parser<F, U>(&mut self, f: F) -> U
137 F: Fn(&mut TypeParser<'a, S, T>) -> U,
139 let mut type_parser: TypeParser<S, T> = TypeParser::make(
142 self.context.clone(),
146 let res = f(&mut type_parser);
147 self.continue_from(type_parser);
151 fn parse_type_specifier(&mut self, allow_var: bool, allow_attr: bool) -> S::R {
152 self.with_type_parser(|p: &mut TypeParser<'a, S, T>| {
153 p.parse_type_specifier(allow_var, allow_attr)
157 fn with_statement_parser<F, U>(&mut self, f: F) -> U
160 F: Fn(&mut StatementParser<'a, S, T>) -> U,
162 let mut statement_parser: StatementParser<S, T> = StatementParser::make(
165 self.context.clone(),
169 let res = f(&mut statement_parser);
170 self.continue_from(statement_parser);
174 fn parse_simple_type_or_type_constant(&mut self) -> S::R {
175 self.with_type_parser(|x: &mut TypeParser<'a, S, T>| x.parse_simple_type_or_type_constant())
178 fn parse_simple_type_or_generic(&mut self) -> S::R {
179 self.with_type_parser(|p: &mut TypeParser<'a, S, T>| p.parse_simple_type_or_generic())
182 fn with_expression_parser<F, U>(&mut self, f: F) -> U
185 F: Fn(&mut ExpressionParser<'a, S, T>) -> U,
187 let mut expression_parser: ExpressionParser<S, T> = ExpressionParser::make(
190 self.context.clone(),
194 let res = f(&mut expression_parser);
195 self.continue_from(expression_parser);
199 fn parse_expression(&mut self) -> S::R {
200 self.with_expression_parser(|p: &mut ExpressionParser<'a, S, T>| p.parse_expression())
203 fn parse_compound_statement(&mut self) -> S::R {
204 self.with_statement_parser(|p: &mut StatementParser<'a, S, T>| p.parse_compound_statement())
207 fn parse_enumerator_list_opt(&mut self) -> S::R {
211 // enumerator-list enumerator
213 self.parse_terminated_list(|x: &mut Self| x.parse_enumerator(), TokenKind::RightBrace)
216 fn parse_enum_declaration(&mut self, attrs: S::R) -> S::R {
219 // attribute-specification-opt enum name enum-base type-constraint-opt /
220 // { enumerator-list-opt }
225 // TODO: SPEC ERROR: The spec states that the only legal enum types
226 // are "int" and "string", but Hack allows any type, and apparently
227 // some of those are meaningful and desired. Figure out what types
228 // are actually legal and illegal as enum base types; put them in the
229 // spec, and add an error pass that says when they are wrong.
230 let enum_ = self.assert_token(TokenKind::Enum);
231 let name = self.require_name();
232 let colon = self.require_colon();
234 self.parse_type_specifier(false /* allow_var */, true /* allow_attr */);
235 let enum_type = self.parse_type_constraint_opt();
236 let (left_brace, enumerators, right_brace) =
237 self.parse_braced_list(|x: &mut Self| x.parse_enumerator_list_opt());
239 make_enum_declaration,
253 fn parse_record_field(&mut self) -> S::R {
256 // record-constant : type field-initializer-opt,
259 // field-initializer:
261 let name = self.require_name_allow_non_reserved();
262 let colon = self.require_colon();
263 let field_type = self.parse_type_specifier(false, true);
264 let init = self.parse_simple_initializer_opt();
265 let comma = self.require_comma();
277 fn parse_record_fields(&mut self) -> S::R {
281 // record-list record-field
282 self.parse_terminated_list(|x| x.parse_record_field(), TokenKind::RightBrace)
285 fn parse_record_declaration(&mut self, attrs: S::R) -> S::R {
286 // record-declaration:
287 // abstract? record name { record-list }
288 let abstract_ = self.optional_token(TokenKind::Abstract);
289 let record = self.require_token(TokenKind::RecordDec, Errors::error1037);
290 let name = self.require_name();
291 let (record_extends, record_extends_list) = self.parse_extends_opt();
292 let (left_brace, record_fields, right_brace) =
293 self.parse_braced_list(|x| x.parse_record_fields());
295 make_record_declaration,
309 pub fn parse_leading_markup_section(&mut self) -> Option<S::R> {
310 let mut parser1 = self.clone();
311 let (markup_section, has_suffix) =
312 parser1.with_statement_parser(|p: &mut StatementParser<'a, S, T>| p.parse_header());
313 // proceed successfully if we've consumed <?..., or dont need it
314 // We purposefully ignore leading trivia before the <?hh, and handle
315 // the error on a later pass
317 self.continue_from(parser1);
320 if self.lexer().source().length() > 0
321 && self.lexer().source().file_path().has_extension("php")
323 self.with_error(Errors::error1001);
329 fn parse_namespace_body(&mut self) -> S::R {
330 match self.peek_token_kind() {
331 TokenKind::Semicolon => {
332 let token = self.fetch_token();
333 S!(make_namespace_empty_body, self, token)
335 TokenKind::LeftBrace => {
336 let left = self.fetch_token();
337 let body = self.parse_terminated_list(
338 |x: &mut Self| x.parse_declaration(),
339 TokenKind::RightBrace,
341 let right = self.require_right_brace();
342 S!(make_namespace_body, self, left, body, right)
345 // ERROR RECOVERY: return an inert namespace (one with all of its
346 // components 'missing'), and recover--without advancing the parser--
347 // back to the level that the namespace was declared in.
348 self.with_error(Errors::error1038);
349 let missing1 = S!(make_missing, self, self.pos());
350 let missing2 = S!(make_missing, self, self.pos());
351 let missing3 = S!(make_missing, self, self.pos());
352 S!(make_namespace_body, self, missing1, missing2, missing3)
357 fn is_group_use(&self) -> bool {
358 let mut parser = self.clone();
359 // We want a heuristic to determine whether to parse the use clause as
360 // a group use or normal use clause. We distinguish the two by (1) whether
361 // there is a namespace prefix -- in this case it is definitely a group use
362 // clause -- or, if there is a name followed by a curly. That's illegal, but
363 // we should give an informative error message about that.
364 parser.assert_token(TokenKind::Use);
365 parser.parse_namespace_use_kind_opt();
366 let token = parser.next_token();
368 TokenKind::Backslash => {
369 let missing = S!(make_missing, parser, parser.pos());
370 let backslash = S!(make_token, parser, token);
371 let (_name, is_backslash) = parser.scan_qualified_name_extended(missing, backslash);
372 is_backslash || parser.peek_token_kind() == TokenKind::LeftBrace
375 let token = S!(make_token, parser, token);
376 let roken_ref = &token as *const _;
377 let (name, is_backslash) = parser.scan_remaining_qualified_name_extended(token);
378 // Here we rely on the implementation details of
379 // scan_remaining_qualified_name_extended. It's returning
380 // *exactly* token if there is nothing except it in the name.
381 is_backslash && (&name as *const _ == roken_ref)
382 || parser.peek_token_kind() == TokenKind::LeftBrace
388 fn parse_namespace_use_kind_opt(&mut self) -> S::R {
390 // namespace-use-kind:
394 let mut parser1 = self.clone();
395 let token = parser1.next_token();
397 TokenKind::Type | TokenKind::Namespace | TokenKind::Function | TokenKind::Const => {
398 self.continue_from(parser1);
399 S!(make_token, self, token)
401 _ => S!(make_missing, self, self.pos()),
405 fn parse_group_use(&mut self) -> S::R {
406 // See below for grammar.
407 let use_token = self.assert_token(TokenKind::Use);
408 let use_kind = self.parse_namespace_use_kind_opt();
409 // We already know that this is a name, qualified name, or prefix.
410 // If this is not a prefix, it will be detected as an error in a later pass
411 let prefix = self.scan_name_or_qualified_name();
412 let (left, clauses, right) =
413 self.parse_braced_comma_list_opt_allow_trailing(|x: &mut Self| {
414 x.parse_namespace_use_clause()
416 let semi = self.require_semicolon();
418 make_namespace_group_use_declaration,
430 fn parse_namespace_use_clause(&mut self) -> S::R {
432 // namespace-use-clause:
433 // qualified-name namespace-aliasing-clauseopt
434 // namespace-use-kind-clause:
435 // namespace-use-kind-opt qualified-name namespace-aliasing-clauseopt
436 // namespace-aliasing-clause:
439 let use_kind = self.parse_namespace_use_kind_opt();
440 let name = self.require_qualified_name();
441 let (as_token, alias) = if self.peek_token_kind() == TokenKind::As {
442 let as_token = self.next_token();
443 let as_token = S!(make_token, self, as_token);
444 let alias = self.require_name();
447 let missing1 = S!(make_missing, self, self.pos());
448 let missing2 = S!(make_missing, self, self.pos());
452 make_namespace_use_clause,
461 fn parse_namespace_use_declaration(&mut self) -> S::R {
463 // namespace-use-declaration:
464 // use namespace-use-kind-opt namespace-use-clauses ;
465 // use namespace-use-kind namespace-name-as-a-prefix
466 // { namespace-use-clauses } ;
467 // use namespace-name-as-a-prefix { namespace-use-kind-clauses } ;
469 // TODO: Add the grammar for the namespace-use-clauses; ensure that it
470 // indicates that trailing commas are allowed in the list.
473 // In the "simple" format, the kind may only be specified up front.
475 // The grammar in the specification says that in the "group"
476 // format, if the kind is specified up front then it may not
477 // be specified in each clause. However, HHVM's parser disallows
478 // the kind in each clause regardless of whether it is specified up front.
479 // We will fix the specification to match HHVM.
481 // The grammar in the specification also says that in the "simple" format,
482 // the kind may only be specified up front. But HHVM allows the kind to
483 // be specified in each clause. Again, we will fix the specification to match
486 // TODO: Update the grammar comment above when the specification is fixed.
487 // (This work is being tracked by spec work items 102, 103 and 104.)
489 // We do not enforce these rules here. Rather, we allow the kind to be anywhere,
490 // and detect the errors in a later pass.
491 if self.is_group_use() {
492 self.parse_group_use()
494 let use_token = self.assert_token(TokenKind::Use);
495 let use_kind = self.parse_namespace_use_kind_opt();
496 let (clauses, _) = self.parse_comma_list_allow_trailing(
497 TokenKind::Semicolon,
499 |x: &mut Self| x.parse_namespace_use_clause(),
501 let semi = self.require_semicolon();
503 make_namespace_use_declaration,
513 fn parse_namespace_declaration(&mut self) -> S::R {
515 // namespace-definition:
516 // namespace namespace-name ;
517 // namespace namespace-name-opt { declaration-list }
519 // TODO: An error case not caught by the parser that should be caught
521 // Qualified names are a superset of legal namespace names.
522 let namespace_token = self.assert_token(TokenKind::Namespace);
523 let name = match self.peek_token_kind() {
525 let token = self.next_token();
526 let token = S!(make_token, self, token);
527 self.scan_remaining_qualified_name(token)
529 TokenKind::LeftBrace => S!(make_missing, self, self.pos()),
530 TokenKind::Semicolon => {
531 // ERROR RECOVERY Plainly the name is missing.
532 self.with_error(Errors::error1004);
533 S!(make_missing, self, self.pos())
536 // TODO: Death to PHPisms; keywords as namespace names
538 self.require_name_allow_non_reserved()
541 let body = self.parse_namespace_body();
543 make_namespace_declaration,
551 pub fn parse_classish_declaration(&mut self, attribute_spec: S::R) -> S::R {
552 let modifiers = self.parse_classish_modifiers();
553 let token = self.parse_classish_token();
554 let name = self.require_class_name();
555 let generic_type_parameter_list = self.parse_generic_type_parameter_list_opt();
556 let (classish_extends, classish_extends_list) = self.parse_extends_opt();
557 let (classish_implements, classish_implements_list) = self.parse_classish_implements_opt();
558 let classish_where_clause = self.parse_classish_where_clause_opt();
559 let body = self.parse_classish_body();
561 make_classish_declaration,
567 generic_type_parameter_list,
569 classish_extends_list,
571 classish_implements_list,
572 classish_where_clause,
577 fn parse_classish_where_clause_opt(&mut self) -> S::R {
578 if self.peek_token_kind() == TokenKind::Where {
579 self.parse_where_clause()
581 S!(make_missing, self, self.pos())
585 fn parse_classish_implements_opt(&mut self) -> (S::R, S::R) {
586 if self.peek_token_kind() != TokenKind::Implements {
587 let missing1 = S!(make_missing, self, self.pos());
588 let missing2 = S!(make_missing, self, self.pos());
591 let implements_token = self.next_token();
592 let implements_token = S!(make_token, self, implements_token);
593 let implements_list = self.parse_special_type_list();
594 (implements_token, implements_list)
598 fn parse_classish_modifiers(&mut self) -> S::R {
599 let mut acc = vec![];
601 match self.peek_token_kind() {
602 TokenKind::Abstract | TokenKind::Final => {
604 let token = self.next_token();
605 let token = S!(make_token, self, token);
608 _ => return S!(make_list, self, acc, self.pos()),
613 fn parse_classish_token(&mut self) -> S::R {
614 let spellcheck_tokens = vec![TokenKind::Class, TokenKind::Trait, TokenKind::Interface];
615 let token_str = &self.current_token_text();
616 let token_kind = self.peek_token_kind();
618 TokenKind::Class | TokenKind::Trait | TokenKind::Interface => {
619 let token = self.next_token();
620 S!(make_token, self, token)
623 TokenKind::Name if Self::is_misspelled_from(&spellcheck_tokens, token_str) => {
624 // Default won't be used, since we already checked is_misspelled_from
625 let suggested_kind = Self::suggested_kind_from(&spellcheck_tokens, token_str)
626 .unwrap_or(TokenKind::Name);
627 self.skip_and_log_misspelled_token(suggested_kind);
628 S!(make_missing, self, self.pos())
631 self.with_error(Errors::error1035);
632 S!(make_missing, self, self.pos())
637 fn parse_special_type(&mut self) -> (S::R, bool) {
638 let mut parser1 = self.clone();
639 let token = parser1.next_xhp_class_name_or_other_token();
641 TokenKind::Comma => {
642 // ERROR RECOVERY. We expected a type but we got a comma.
643 // Give the error that we expected a type, not a name, even though
644 // not every type is legal here.
645 self.continue_from(parser1);
646 self.with_error(Errors::error1007);
647 let comma = S!(make_token, self, token);
648 let missing = S!(make_missing, self, self.pos());
649 let list_item = S!(make_list_item, self, missing, comma);
653 | TokenKind::Namespace
655 | TokenKind::XHPClassName => {
657 .parse_type_specifier(false /* allow_var */, true /* allow_attr */);
658 let comma = self.optional_token(TokenKind::Comma);
659 let is_missing = comma.is_missing();
660 let list_item = S!(make_list_item, self, item, comma);
661 (list_item, is_missing)
665 | TokenKind::RecordDec
667 | TokenKind::SelfToken
668 if self.env.hhvm_compat_mode =>
670 // HHVM allows these keywords here for some reason
671 let item = self.parse_simple_type_or_type_constant();
672 let comma = self.optional_token(TokenKind::Comma);
673 let is_missing = comma.is_missing();
674 let list_item = S!(make_list_item, self, item, comma);
675 (list_item, is_missing)
678 // ERROR RECOVERY: We are expecting a type; give an error as above.
679 // Don't eat the offending token.
680 self.with_error(Errors::error1007);
681 let missing1 = S!(make_missing, self, self.pos());
682 let missing2 = S!(make_missing, self, self.pos());
683 let list_item = S!(make_list_item, self, missing1, missing2);
689 fn parse_special_type_list(&mut self) -> S::R {
690 // An extends / implements list is a comma-separated list of types, but
691 // very special types; we want the types to consist of a name and an
692 // optional generic type argument list.
694 // TODO: Can the type name be of the form "foo::bar"? Those do not
695 // necessarily start with names. Investigate this.
697 // Normally we'd use one of the separated list helpers, but there is no
698 // specific end token we could use to detect the end of the list, and we
699 // want to bail out if we get something that is not a type of the right form.
700 // So we have custom logic here.
702 // TODO: This is one of the rare cases in Hack where a comma-separated list
703 // may not have a trailing comma. Is that desirable, or was that an
704 // oversight when the trailing comma rules were added? If possible we
705 // should keep the rule as-is, and disallow the trailing comma; it makes
706 // parsing and error recovery easier.
707 let mut items = vec![];
709 let (item, is_missing) = self.parse_special_type();
716 S!(make_list, self, items, self.pos())
719 fn parse_extends_opt(&mut self) -> (S::R, S::R) {
720 let token_kind = self.peek_token_kind();
721 if token_kind != TokenKind::Extends {
722 let missing1 = S!(make_missing, self, self.pos());
723 let missing2 = S!(make_missing, self, self.pos());
726 let token = self.next_token();
727 let extends_token = S!(make_token, self, token);
728 let extends_list = self.parse_special_type_list();
729 (extends_token, extends_list)
733 fn parse_classish_body(&mut self) -> S::R {
734 let left_brace_token = self.require_left_brace();
735 let classish_element_list = self.parse_classish_element_list_opt();
736 let right_brace_token = self.require_right_brace();
741 classish_element_list,
746 fn parse_classish_element_list_opt(&mut self) -> S::R {
747 // TODO: ERROR RECOVERY: consider bailing if the token cannot possibly
748 // start a classish element.
749 // ERROR RECOVERY: we're in the body of a classish, so we add visibility
750 // modifiers to our context.
751 self.expect_in_new_scope(ExpectedTokens::Visibility);
752 let element_list = self.parse_terminated_list(
753 |x: &mut Self| x.parse_classish_element(),
754 TokenKind::RightBrace,
756 self.pop_scope(ExpectedTokens::Visibility);
760 fn parse_xhp_children_paren(&mut self) -> S::R {
762 // ( xhp-children-expressions )
764 // xhp-children-expressions:
765 // xhp-children-expression
766 // xhp-children-expressions , xhp-children-expression
768 // TODO: The parenthesized list of children expressions is NOT allowed
769 // to be comma-terminated. Is this intentional? It is inconsistent with
770 // practice throughout the rest of Hack. There is no syntactic difficulty
771 // in allowing a comma before the close paren. Consider allowing it.
772 let (left, exprs, right) =
773 self.parse_parenthesized_comma_list(|x: &mut Self| x.parse_xhp_children_expression());
775 make_xhp_children_parenthesized_list,
783 fn parse_xhp_children_term(&mut self) -> S::R {
785 // xhp-children-term:
786 // ( xhp-children-expressions ) trailing-opt
788 // xhp-class-name trailing-opt
789 // xhp-category-name trailing-opt
792 // Note that there may be only zero or one trailing unary operator.
793 // "foo*?" is not a legal xhp child expression.
795 let mut parser1 = self.clone();
796 let token = parser1.next_xhp_children_name_or_other();
797 let kind = token.kind();
798 let name = S!(make_token, parser1, token);
800 TokenKind::Name | TokenKind::XHPClassName | TokenKind::XHPCategoryName => {
801 self.continue_from(parser1);
802 self.parse_xhp_children_trailing(name)
804 TokenKind::LeftParen => {
805 let term = self.parse_xhp_children_paren();
806 self.parse_xhp_children_trailing(term)
809 // ERROR RECOVERY: Eat the offending token, keep going.
810 self.with_error(Errors::error1053);
816 fn parse_xhp_children_trailing(&mut self, term: S::R) -> S::R {
817 let token_kind = self.peek_token_kind();
819 TokenKind::Star | TokenKind::Plus | TokenKind::Question => {
820 let token = self.next_token();
821 let token = S!(make_token, self, token);
822 S!(make_postfix_unary_expression, self, term, token)
828 fn parse_xhp_children_bar(&mut self, left: S::R) -> S::R {
829 let token_kind = self.peek_token_kind();
832 let token = self.next_token();
833 let token = S!(make_token, self, token);
834 let right = self.parse_xhp_children_term();
835 let result = S!(make_binary_expression, self, left, token, right);
836 self.parse_xhp_children_bar(result)
842 fn parse_xhp_children_expression(&mut self) -> S::R {
844 // xhp-children-expression:
846 // xhp-children-expression | xhp-children-term
848 // Note that the bar operator is left-associative. (Not that it matters
850 let term = self.parse_xhp_children_term();
851 self.parse_xhp_children_bar(term)
854 fn parse_xhp_children_declaration(&mut self) -> S::R {
856 // xhp-children-declaration:
858 // children xhp-children-expression ;
859 let children = self.assert_token(TokenKind::Children);
860 let token_kind = self.peek_token_kind();
861 let expr = match token_kind {
862 TokenKind::Empty => {
863 let token = self.next_token();
864 S!(make_token, self, token)
866 _ => self.parse_xhp_children_expression(),
868 let semi = self.require_semicolon();
869 S!(make_xhp_children_declaration, self, children, expr, semi)
872 fn parse_xhp_category(&mut self) -> S::R {
873 let token = self.next_xhp_category_name();
874 let token_kind = token.kind();
875 let category = S!(make_token, self, token);
877 TokenKind::XHPCategoryName => category,
879 self.with_error(Errors::error1052);
885 fn parse_xhp_type_specifier(&mut self) -> S::R {
887 // xhp-type-specifier:
888 // enum { xhp-attribute-enum-list ,-opt }
891 // The list of enum values must have at least one value and can be
895 // xhp-attribute-enum-value
896 // xhp-enum-list , xhp-attribute-enum-value
898 // xhp-attribute-enum-value:
899 // any integer literal
900 // any single-quoted-string literal
901 // any double-quoted-string literal
903 // TODO: What are the semantics of encapsulated expressions in double-quoted
904 // string literals here?
905 // ERROR RECOVERY: We parse any expressions here;
906 // TODO: give an error in a later pass if the expressions are not literals.
907 // (This work is tracked by task T21175355)
909 // An empty list is illegal, but we allow it here and give an error in
911 let mut parser1 = self.clone();
912 let token = parser1.next_token();
913 let (token, optional) = match token.kind() {
914 TokenKind::Question => {
915 let enum_token = parser1.next_token();
916 let token = S!(make_token, parser1, token);
920 let missing = S!(make_missing, parser1, self.pos());
926 self.continue_from(parser1);
927 let enum_token = S!(make_token, self, token);
928 let (left_brace, values, right_brace) = self
929 .parse_braced_comma_list_opt_allow_trailing(|x: &mut Self| {
942 _ => self.parse_type_specifier(true, true),
946 fn parse_xhp_required_opt(&mut self) -> S::R {
949 // @ (required | lateinit)
951 // Note that these are two tokens. They can have whitespace between them.
952 if self.peek_token_kind() == TokenKind::At {
953 let at = self.assert_token(TokenKind::At);
954 let req_kind = self.next_token();
955 let kind = req_kind.kind();
956 let req = S!(make_token, self, req_kind);
958 TokenKind::Required => S!(make_xhp_required, self, at, req),
959 TokenKind::Lateinit => S!(make_xhp_lateinit, self, at, req),
961 self.with_error(Errors::error1051);
962 S!(make_missing, self, self.pos())
966 S!(make_missing, self, self.pos())
970 fn parse_xhp_class_attribute_typed(&mut self) -> S::R {
971 // xhp-type-specifier xhp-name initializer-opt xhp-required-opt
972 let ty = self.parse_xhp_type_specifier();
973 let name = self.require_xhp_name();
974 let init = self.parse_simple_initializer_opt();
975 let req = self.parse_xhp_required_opt();
976 S!(make_xhp_class_attribute, self, ty, name, init, req)
979 fn parse_xhp_category_declaration(&mut self) -> S::R {
981 // xhp-category-declaration:
982 // category xhp-category-list ,-opt ;
984 // xhp-category-list:
986 // xhp-category-list , xhp-category-name
987 let category = self.assert_token(TokenKind::Category);
988 let (items, _) = self.parse_comma_list_allow_trailing(
989 TokenKind::Semicolon,
991 |x: &mut Self| x.parse_xhp_category(),
993 let semi = self.require_semicolon();
994 S!(make_xhp_category_declaration, self, category, items, semi)
997 fn parse_xhp_class_attribute(&mut self) -> S::R {
999 // xhp-attribute-declaration:
1001 // xhp-type-specifier xhp-name initializer-opt xhp-required-opt
1004 // The xhp type specifier could be an xhp class name. To disambiguate we peek
1005 // ahead a token; if it's a comma or semi, we're done. If not, then we assume
1006 // that we are in the more complex case.
1007 if self.is_next_xhp_class_name() {
1008 let mut parser1 = self.clone();
1009 let class_name = parser1.require_class_name();
1010 match parser1.peek_token_kind() {
1011 TokenKind::Comma | TokenKind::Semicolon => {
1012 self.continue_from(parser1);
1013 let type_specifier = S!(make_simple_type_specifier, self, class_name);
1014 S!(make_xhp_simple_class_attribute, self, type_specifier)
1016 _ => self.parse_xhp_class_attribute_typed(),
1019 self.parse_xhp_class_attribute_typed()
1023 fn parse_xhp_class_attribute_declaration(&mut self) -> S::R {
1025 // xhp-class-attribute-declaration :
1026 // attribute xhp-attribute-declaration-list ;
1028 // xhp-attribute-declaration-list:
1029 // xhp-attribute-declaration
1030 // xhp-attribute-declaration-list , xhp-attribute-declaration
1032 // TODO: The list of attributes may NOT be terminated with a trailing comma
1033 // before the semicolon. This is inconsistent with the rest of Hack.
1034 // Allowing a comma before the semi does not introduce any syntactic
1035 // difficulty; consider allowing it.
1036 let attr_token = self.assert_token(TokenKind::Attribute);
1037 // TODO: Better error message.
1039 self.parse_comma_list(TokenKind::Semicolon, Errors::error1004, |x: &mut Self| {
1040 x.parse_xhp_class_attribute()
1042 let semi = self.require_semicolon();
1044 make_xhp_class_attribute_declaration,
1052 fn parse_qualified_name_type(&mut self) -> S::R {
1053 // Here we're parsing a name followed by an optional generic type
1054 // argument list; if we don't have a name, give an error.
1055 match self.peek_token_kind() {
1056 TokenKind::Backslash | TokenKind::Name => self.parse_simple_type_or_generic(),
1057 _ => self.require_qualified_name(),
1061 fn parse_qualified_name_type_opt(&mut self) -> S::R {
1062 // Here we're parsing a name followed by an optional generic type
1063 // argument list; if we don't have a name, give an error.
1064 match self.peek_token_kind() {
1065 TokenKind::Backslash | TokenKind::Construct | TokenKind::Name => {
1066 self.parse_simple_type_or_generic()
1068 _ => S!(make_missing, self, self.pos()),
1072 fn parse_require_clause(&mut self) -> S::R {
1074 // require-extends-clause:
1075 // require extends qualified-name ;
1077 // require-implements-clause:
1078 // require implements qualified-name ;
1080 // We must also parse "require extends :foo;"
1081 // TODO: What about "require extends :foo<int>;" ?
1082 // TODO: The spec is incomplete; we need to be able to parse
1083 // require extends Foo<int>;
1084 // (This work is being tracked by spec issue 105.)
1085 // TODO: Check whether we also need to handle
1086 // require extends foo::bar
1089 // ERROR RECOVERY: Detect if the implements/extends, name and semi are
1091 let req = self.assert_token(TokenKind::Require);
1092 let token_kind = self.peek_token_kind();
1093 let req_kind = match token_kind {
1094 TokenKind::Implements | TokenKind::Extends => {
1095 let req_kind_token = self.next_token();
1096 S!(make_token, self, req_kind_token)
1099 self.with_error(Errors::error1045);
1100 S!(make_missing, self, self.pos())
1103 let name = if self.is_next_xhp_class_name() {
1104 self.parse_simple_type_or_generic()
1106 self.parse_qualified_name_type()
1108 let semi = self.require_semicolon();
1109 S!(make_require_clause, self, req, req_kind, name, semi)
1112 // This duplicates work from parse_methodish_or_const_or_type_const,
1113 // but this function is only invoked after an attribute spec, while
1114 // parse_methodish_or_const_or_type_const is called after a modifier.
1115 // Having this function prevents constants from having attributes as
1116 // this cannot be checked in parser_errors as there is no field in constant
1117 // declaration to store 'attributes'.
1118 fn parse_methodish_or_property_or_type_constant(&mut self, attribute_spec: S::R) -> S::R {
1119 let mut parser1 = self.clone();
1120 let modifiers = parser1.parse_modifiers();
1121 let current_token_kind = parser1.peek_token_kind();
1122 let next_token = parser1.peek_token_with_lookahead(1);
1123 let next_token_kind = next_token.kind();
1124 match (current_token_kind, next_token_kind) {
1125 (TokenKind::Const, TokenKind::Type) => {
1126 self.continue_from(parser1);
1127 let const_ = self.assert_token(TokenKind::Const);
1128 self.parse_type_const_declaration(attribute_spec, modifiers, const_)
1130 _ => self.parse_methodish_or_property(attribute_spec),
1134 fn has_leading_trivia(token: &S::Token, kind: TriviaKind) -> bool {
1135 token.leading().iter().any(|x| x.kind() == kind)
1138 fn parse_methodish_or_property(&mut self, attribute_spec: S::R) -> S::R {
1139 let modifiers = self.parse_modifiers();
1140 // ERROR RECOVERY: match against two tokens, because if one token is
1141 // in error but the next isn't, then it's likely that the user is
1142 // simply still typing. Throw an error on what's being typed, then eat
1143 // it and keep going.
1144 let current_token_kind = self.peek_token_kind();
1145 let next_token = self.peek_token_with_lookahead(1);
1146 let next_token_kind = next_token.kind();
1147 match (current_token_kind, next_token_kind) {
1148 // Detected the usual start to a method, so continue parsing as method.
1149 (TokenKind::Async, _) | (TokenKind::Coroutine, _) | (TokenKind::Function, _) => {
1150 self.parse_methodish(attribute_spec, modifiers)
1152 (TokenKind::LeftParen, _) => self.parse_property_declaration(attribute_spec, modifiers),
1154 // We encountered one unexpected token, but the next still indicates that
1155 // we should be parsing a methodish. Throw an error, process the token
1156 // as an extra, and keep going.
1157 (_, TokenKind::Async) | (_, TokenKind::Coroutine) | (_, TokenKind::Function)
1158 if !(Self::has_leading_trivia(&next_token, TriviaKind::EndOfLine)) =>
1160 self.with_error_on_whole_token(Errors::error1056);
1161 self.skip_and_log_unexpected_token(false);
1162 self.parse_methodish(attribute_spec, modifiers)
1164 // Otherwise, continue parsing as a property (which might be a lambda).
1165 _ => self.parse_property_declaration(attribute_spec, modifiers),
1169 fn parse_trait_use_precedence_item(&mut self, name: S::R) -> S::R {
1170 let keyword = self.assert_token(TokenKind::Insteadof);
1171 let removed_names = self.parse_trait_name_list(|x: TokenKind| x == TokenKind::Semicolon);
1173 make_trait_use_precedence_item,
1181 fn parse_trait_use_alias_item(&mut self, aliasing_name: S::R) -> S::R {
1182 let keyword = self.require_token(TokenKind::As, Errors::expected_as_or_insteadof);
1183 let modifiers = self.parse_modifiers();
1184 let aliased_name = self.parse_qualified_name_type_opt();
1186 make_trait_use_alias_item,
1195 fn parse_trait_use_conflict_resolution_item(&mut self) -> S::R {
1196 let qualifier = self.parse_qualified_name_type();
1197 let name = if self.peek_token_kind() == TokenKind::ColonColon {
1198 // scope resolution expression case
1199 let cc_token = self.require_coloncolon();
1201 .require_token_one_of(&[TokenKind::Name, TokenKind::Construct], Errors::error1004);
1203 make_scope_resolution_expression,
1210 // plain qualified name case
1213 match self.peek_token_kind() {
1214 TokenKind::Insteadof => self.parse_trait_use_precedence_item(name),
1215 TokenKind::As | _ => self.parse_trait_use_alias_item(name),
1220 // trait-use-conflict-resolution:
1221 // use trait-name-list { trait-use-conflict-resolution-list }
1223 // trait-use-conflict-resolution-list:
1224 // trait-use-conflict-resolution-item
1225 // trait-use-conflict-resolution-item trait-use-conflict-resolution-list
1227 // trait-use-conflict-resolution-item:
1228 // trait-use-alias-item
1229 // trait-use-precedence-item
1231 // trait-use-alias-item:
1232 // trait-use-conflict-resolution-item-name as name;
1233 // trait-use-conflict-resolution-item-name as visibility-modifier name;
1234 // trait-use-conflict-resolution-item-name as visibility-modifier;
1236 // trait-use-precedence-item:
1237 // scope-resolution-expression insteadof trait-name-list
1239 // trait-use-conflict-resolution-item-name:
1241 // scope-resolution-expression
1242 fn parse_trait_use_conflict_resolution(
1245 trait_name_list: S::R,
1247 let left_brace = self.assert_token(TokenKind::LeftBrace);
1248 let clauses = self.parse_separated_list_opt(
1249 TokenKind::Semicolon,
1250 SeparatedListKind::TrailingAllowed,
1251 TokenKind::RightBrace,
1253 |x: &mut Self| x.parse_trait_use_conflict_resolution_item(),
1255 let right_brace = self.require_token(TokenKind::RightBrace, Errors::error1006);
1257 make_trait_use_conflict_resolution,
1268 // trait-use-clause:
1269 // use trait-name-list ;
1272 // qualified-name generic-type-parameter-listopt
1273 // trait-name-list , qualified-name generic-type-parameter-listopt
1274 fn parse_trait_name_list<P>(&mut self, predicate: P) -> S::R
1276 P: Fn(TokenKind) -> bool,
1278 let (items, _, _) = self.parse_separated_list_predicate(
1279 |x| x == TokenKind::Comma,
1280 SeparatedListKind::NoTrailing,
1283 |x: &mut Self| x.parse_qualified_name_type(),
1288 fn parse_trait_use(&mut self) -> S::R {
1289 let use_token = self.assert_token(TokenKind::Use);
1290 let trait_name_list =
1291 self.parse_trait_name_list(|x| x == TokenKind::Semicolon || x == TokenKind::LeftBrace);
1292 if self.peek_token_kind() == TokenKind::LeftBrace {
1293 self.parse_trait_use_conflict_resolution(use_token, trait_name_list)
1295 let semi = self.require_semicolon();
1296 S!(make_trait_use, self, use_token, trait_name_list, semi)
1300 fn parse_property_declaration(&mut self, attribute_spec: S::R, modifiers: S::R) -> S::R {
1302 // property-declaration:
1303 // attribute-spec-opt property-modifier type-specifier
1304 // property-declarator-list ;
1306 // property-declarator-list:
1307 // property-declarator
1308 // property-declarator-list , property-declarator
1310 // The type specifier is optional in non-strict mode and required in
1311 // strict mode. We give an error in a later pass.
1312 let prop_type = match self.peek_token_kind() {
1313 TokenKind::Variable => S!(make_missing, self, self.pos()),
1314 _ => self.parse_type_specifier(false /* allow_var */, false /* allow_attr */),
1317 self.parse_comma_list(TokenKind::Semicolon, Errors::error1008, |x: &mut Self| {
1318 x.parse_property_declarator()
1320 let semi = self.require_semicolon();
1322 make_property_declaration,
1332 fn parse_property_declarator(&mut self) -> S::R {
1334 // property-declarator:
1335 // variable-name property-initializer-opt
1336 // property-initializer:
1338 let name = self.require_variable();
1339 let simple_init = self.parse_simple_initializer_opt();
1340 S!(make_property_declarator, self, name, simple_init)
1343 fn is_type_in_const(&self) -> bool {
1344 let mut parser1 = self.clone();
1345 let _ = parser1.parse_type_specifier(false, true);
1346 let _ = parser1.require_name_allow_all_keywords();
1347 self.errors.len() == parser1.errors.len()
1351 // const-declaration:
1352 // abstract_opt const type-specifier_opt constant-declarator-list ;
1353 // visibility const type-specifier_opt constant-declarator-list ;
1354 // constant-declarator-list:
1355 // constant-declarator
1356 // constant-declarator-list , constant-declarator
1357 // constant-declarator:
1358 // name constant-initializer_opt
1359 // constant-initializer:
1360 // = const-expression
1361 fn parse_const_declaration(&mut self, modifiers: S::R, const_: S::R) -> S::R {
1362 let type_spec = if self.is_type_in_const() {
1363 self.parse_type_specifier(/* allow_var = */ false, /* allow_attr = */ true)
1365 S!(make_missing, self, self.pos())
1369 self.parse_comma_list(TokenKind::Semicolon, Errors::error1004, |x: &mut Self| {
1370 x.parse_constant_declarator()
1372 let semi = self.require_semicolon();
1374 make_const_declaration,
1384 fn parse_constant_declarator(&mut self) -> S::R {
1385 // TODO: We allow const names to be keywords here; in particular we
1386 // require that const string TRUE = "true"; be legal. Likely this
1387 // should be more strict. What are the rules for which keywords are
1388 // legal constant names and which are not?
1389 // Note that if this logic is changed, it should be changed in
1390 // is_type_in_const above as well.
1392 // This permits abstract variables to have an initializer, and vice-versa.
1393 // This is deliberate, and those errors will be detected after the syntax
1395 let const_name = self.require_name_allow_all_keywords();
1396 let initializer_ = self.parse_simple_initializer_opt();
1397 S!(make_constant_declarator, self, const_name, initializer_)
1401 // type-constant-declaration:
1402 // abstract-type-constant-declaration
1403 // concrete-type-constant-declaration
1404 // abstract-type-constant-declaration:
1405 // abstract const type name type-constraintopt ;
1406 // concrete-type-constant-declaration:
1407 // const type name type-constraintopt = type-specifier ;
1411 // An abstract type constant may only occur in an interface or an abstract
1412 // class. We allow that to be parsed here, and the type checker detects the
1414 // CONSIDER: We could detect this error in a post-parse pass; it is entirely
1415 // syntactic. Consider moving the error detection out of the type checker.
1417 // An interface may not contain a non-abstract type constant that has a
1418 // type constraint. We allow that to be parsed here, and the type checker
1419 // detects the error.
1420 // CONSIDER: We could detect this error in a post-parse pass; it is entirely
1421 // syntactic. Consider moving the error detection out of the type checker.
1422 fn parse_type_const_declaration(
1428 let type_token = self.assert_token(TokenKind::Type);
1429 let name = self.require_name_allow_non_reserved();
1430 let generic_type_parameter_list = self.parse_generic_type_parameter_list_opt();
1431 let type_constraint = self.parse_type_constraint_opt();
1432 let (equal_token, type_specifier) = if self.peek_token_kind() == TokenKind::Equal {
1433 let equal_token = self.assert_token(TokenKind::Equal);
1434 let type_spec = self
1435 .parse_type_specifier(/* allow_var = */ false, /* allow_attr = */ true);
1436 (equal_token, type_spec)
1438 let missing1 = S!(make_missing, self, self.pos());
1439 let missing2 = S!(make_missing, self, self.pos());
1440 (missing1, missing2)
1442 let semicolon = self.require_semicolon();
1444 make_type_const_declaration,
1451 generic_type_parameter_list,
1460 // attribute_specification :=
1462 // old_attribute_specification
1463 // attribute_list :=
1465 // attribute_list attribute
1466 // attribute := @ attribute_name attribute_value_list_opt
1467 // old_attribute_specification := << old_attribute_list >>
1468 // old_attribute_list :=
1470 // old_attribute_list , old_attribute
1471 // old_attribute := attribute_name attribute_value_list_opt
1472 // attribute_name := name
1473 // attribute_value_list := ( attribute_values_opt )
1474 // attribute_values :=
1476 // attribute_values , attribute_value
1477 // attribute_value := expression
1479 // TODO: The list of attrs can have a trailing comma. Update the spec.
1480 // TODO: The list of values can have a trailing comma. Update the spec.
1481 // (Both these work items are tracked by spec issue 106.)
1482 pub fn parse_old_attribute_specification_opt(&mut self) -> S::R {
1483 if self.peek_token_kind() == TokenKind::LessThanLessThan {
1484 let (left, items, right) =
1485 self.parse_double_angled_comma_list_allow_trailing(|x: &mut Self| {
1486 x.parse_old_attribute()
1488 S!(make_old_attribute_specification, self, left, items, right)
1490 S!(make_missing, self, self.pos())
1494 fn parse_file_attribute_specification_opt(&mut self) -> S::R {
1495 if self.peek_token_kind() == TokenKind::LessThanLessThan {
1496 let left = self.assert_token(TokenKind::LessThanLessThan);
1497 let keyword = self.assert_token(TokenKind::File);
1498 let colon = self.require_colon();
1499 let (items, _) = self.parse_comma_list_allow_trailing(
1500 TokenKind::GreaterThanGreaterThan,
1501 Errors::expected_user_attribute,
1502 |x: &mut Self| x.parse_old_attribute(),
1504 let right = self.require_token(TokenKind::GreaterThanGreaterThan, Errors::error1029);
1506 make_file_attribute_specification,
1515 S!(make_missing, self, self.pos())
1519 fn parse_return_type_hint_opt(&mut self) -> (S::R, S::R) {
1520 let token_kind = self.peek_token_kind();
1521 if token_kind == TokenKind::Colon {
1522 let token = self.next_token();
1523 let colon_token = S!(make_token, self, token);
1525 self.with_type_parser(|p: &mut TypeParser<'a, S, T>| p.parse_return_type());
1526 (colon_token, return_type)
1528 let missing1 = S!(make_missing, self, self.pos());
1529 let missing2 = S!(make_missing, self, self.pos());
1530 (missing1, missing2)
1534 pub fn parse_parameter_list_opt(&mut self) -> (S::R, S::R, S::R) {
1536 // TODO: The specification is wrong in several respects concerning
1537 // variadic parameters. Variadic parameters are permitted to have a
1538 // type and name but this is not mentioned in the spec. And variadic
1539 // parameters are not mentioned at all in the grammar for constructor
1540 // parameter lists. (This is tracked by spec issue 107.)
1543 // variadic-parameter
1544 // parameter-declaration-list
1545 // parameter-declaration-list ,
1546 // parameter-declaration-list , variadic-parameter
1548 // parameter-declaration-list:
1549 // parameter-declaration
1550 // parameter-declaration-list , parameter-declaration
1552 // variadic-parameter:
1554 // attribute-specification-opt visiblity-modifier-opt type-specifier \
1555 // ... variable-name
1557 // This function parses the parens as well.
1558 // ERROR RECOVERY: We allow variadic parameters in all positions; a later
1559 // pass gives an error if a variadic parameter is in an incorrect position
1560 // or followed by a trailing comma, or if the parameter has a
1562 self.parse_parenthesized_comma_list_opt_allow_trailing(|x: &mut Self| x.parse_parameter())
1565 fn parse_parameter(&mut self) -> S::R {
1566 let mut parser1 = self.clone();
1567 let token = parser1.next_token();
1568 match token.kind() {
1569 TokenKind::DotDotDot => {
1570 let next_kind = parser1.peek_token_kind();
1571 if next_kind == TokenKind::Variable {
1572 self.parse_parameter_declaration()
1574 let missing1 = S!(make_missing, parser1, self.pos());
1575 let missing2 = S!(make_missing, parser1, self.pos());
1576 self.continue_from(parser1);
1577 let token = S!(make_token, self, token);
1578 S!(make_variadic_parameter, self, missing1, missing2, token)
1581 _ => self.parse_parameter_declaration(),
1585 fn parse_parameter_declaration(&mut self) -> S::R {
1588 // TODO: Add call-convention-opt to the specification.
1589 // (This work is tracked by task T22582676.)
1591 // TODO: Update grammar for inout parameters.
1592 // (This work is tracked by task T22582715.)
1594 // parameter-declaration:
1595 // attribute-specification-opt \
1596 // call-convention-opt \
1597 // type-specifier variable-name \
1598 // default-argument-specifier-opt
1601 // In strict mode, we require a type specifier. This error is not caught
1602 // at parse time but rather by a later pass.
1603 // Visibility modifiers are only legal in constructor parameter
1604 // lists; we give an error in a later pass.
1605 // Variadic params cannot be declared inout; we permit that here but
1606 // give an error in a later pass.
1607 // Variadic params and inout params cannot have default values; these
1608 // errors are also reported in a later pass.
1609 let attrs = self.parse_attribute_specification_opt();
1610 let visibility = self.parse_visibility_modifier_opt();
1611 let callconv = self.parse_call_convention_opt();
1612 let token = self.peek_token();
1613 let type_specifier = match token.kind() {
1614 TokenKind::Variable | TokenKind::DotDotDot => S!(make_missing, self, self.pos()),
1616 self.parse_type_specifier(/* allow_var = */ false, /* allow_attr */ false)
1619 let name = self.parse_decorated_variable_opt();
1620 let default = self.parse_simple_initializer_opt();
1622 make_parameter_declaration,
1633 fn parse_decorated_variable_opt(&mut self) -> S::R {
1634 match self.peek_token_kind() {
1635 TokenKind::DotDotDot => self.parse_decorated_variable(),
1636 _ => self.require_variable(),
1640 // TODO: This is wrong. The variable here is not anexpression* that has
1641 // an optional decoration on it. It's a declaration. We shouldn't be using the
1642 // same data structure for a decorated expression as a declaration; one
1643 // is ause* and the other is a *definition*.
1644 fn parse_decorated_variable(&mut self) -> S::R {
1646 // Detection of (variadic, byRef) inout params happens in post-parsing.
1647 // Although a parameter can have at most one variadic/reference decorator,
1648 // we deliberately allow multiple decorators in the initial parse and produce
1649 // an error in a later pass.
1650 let decorator = self.fetch_token();
1651 let variable = match self.peek_token_kind() {
1652 TokenKind::DotDotDot => self.parse_decorated_variable(),
1653 _ => self.require_variable(),
1655 S!(make_decorated_expression, self, decorator, variable)
1658 fn parse_visibility_modifier_opt(&mut self) -> S::R {
1659 let token_kind = self.peek_token_kind();
1661 TokenKind::Public | TokenKind::Protected | TokenKind::Private => {
1662 let token = self.next_token();
1663 S!(make_token, self, token)
1665 _ => S!(make_missing, self, self.pos()),
1671 // TODO: Add this to the specification.
1672 // (This work is tracked by task T22582676.)
1676 fn parse_call_convention_opt(&mut self) -> S::R {
1677 let token_kind = self.peek_token_kind();
1679 TokenKind::Inout => {
1680 let token = self.next_token();
1681 S!(make_token, self, token)
1683 _ => S!(make_missing, self, self.pos()),
1688 // default-argument-specifier:
1689 // = const-expression
1691 // constant-initializer:
1692 // = const-expression
1693 fn parse_simple_initializer_opt(&mut self) -> S::R {
1694 let token_kind = self.peek_token_kind();
1696 TokenKind::Equal => {
1697 let token = self.next_token();
1698 // TODO: Detect if expression is not const
1699 let token = S!(make_token, self, token);
1700 let default_value = self.parse_expression();
1701 S!(make_simple_initializer, self, token, default_value)
1703 _ => S!(make_missing, self, self.pos()),
1707 pub fn parse_function_declaration(&mut self, attribute_specification: S::R) -> S::R {
1708 let modifiers = self.parse_modifiers();
1710 self.parse_function_declaration_header(modifiers, /* is_methodish =*/ false);
1711 let body = self.parse_compound_statement();
1713 make_function_declaration,
1715 attribute_specification,
1721 fn parse_constraint_operator(&mut self) -> S::R {
1722 // TODO: Put this in the specification
1723 // (This work is tracked by spec issue 100.)
1724 // constraint-operator:
1728 let token_kind = self.peek_token_kind();
1730 TokenKind::Equal | TokenKind::As | TokenKind::Super => {
1731 let token = self.next_token();
1732 S!(make_token, self, token)
1735 // ERROR RECOVERY: don't eat the offending token.
1736 // TODO: Give parse error
1738 S!(make_missing, self, self.pos())
1743 fn parse_where_constraint(&mut self) -> S::R {
1744 // TODO: Put this in the specification
1745 // (This work is tracked by spec issue 100.)
1747 // type-specifier constraint-operator type-specifier
1749 self.parse_type_specifier(/* allow_var = */ false, /* allow_attr = */ true);
1750 let op = self.parse_constraint_operator();
1752 self.parse_type_specifier(/* allow_var = */ false, /* allow_attr = */ true);
1753 S!(make_where_constraint, self, left, op, right)
1756 fn parse_where_constraint_list_item(&mut self) -> Option<S::R> {
1757 match self.peek_token_kind() {
1758 TokenKind::Semicolon | TokenKind::LeftBrace => None,
1760 let where_constraint = self.parse_where_constraint();
1761 let comma = self.optional_token(TokenKind::Comma);
1762 let result = S!(make_list_item, self, where_constraint, comma);
1768 fn parse_where_clause(&mut self) -> S::R {
1769 // TODO: Add this to the specification
1770 // (This work is tracked by spec issue 100.)
1772 // where constraint-list
1776 // constraint-list , constraint
1777 let keyword = self.assert_token(TokenKind::Where);
1779 self.parse_list_until_none(|x: &mut Self| x.parse_where_constraint_list_item());
1780 S!(make_where_clause, self, keyword, constraints)
1783 fn parse_where_clause_opt(&mut self) -> S::R {
1784 if self.peek_token_kind() != TokenKind::Where {
1785 S!(make_missing, self, self.pos())
1787 self.parse_where_clause()
1791 fn parse_function_declaration_header(&mut self, modifiers: S::R, is_methodish: bool) -> S::R {
1793 // function-definition-header:
1794 // attribute-specification-opt async-opt coroutine-opt function name /
1795 // generic-type-parameter-list-opt ( parameter-list-opt ) : /
1796 // return-type where-clause-opt
1797 // TODO: The spec does not specify "where" clauses. Add them.
1798 // (This work is tracked by spec issue 100.)
1800 // In strict mode, we require a type specifier. This error is not caught
1801 // at parse time but rather by a later pass.
1802 let function_token = self.require_function();
1803 let label = self.parse_function_label_opt(is_methodish);
1804 let generic_type_parameter_list = self.parse_generic_type_parameter_list_opt();
1805 let (left_paren_token, parameter_list, right_paren_token) = self.parse_parameter_list_opt();
1806 let (colon_token, return_type) = self.parse_return_type_hint_opt();
1807 let where_clause = self.parse_where_clause_opt();
1809 make_function_declaration_header,
1814 generic_type_parameter_list,
1824 // A function label is either a function name or a __construct label.
1825 fn parse_function_label_opt(&mut self, is_methodish: bool) -> S::R {
1826 let report_error = |x: &mut Self, token: S::Token| {
1827 x.with_error(Errors::error1044);
1828 let token = S!(make_token, x, token);
1829 S!(make_error, x, token)
1831 let token_kind = self.peek_token_kind();
1833 TokenKind::Name | TokenKind::Construct => {
1834 let token = self.next_token();
1835 S!(make_token, self, token)
1837 TokenKind::LeftParen => {
1838 // It turns out, it was just a verbose lambda; YOLO PHP
1839 S!(make_missing, self, self.pos())
1841 TokenKind::Isset | TokenKind::Unset | TokenKind::Empty => {
1842 // We need to parse those as names as they are defined in hhi
1843 let token = self.next_token_as_name();
1844 S!(make_token, self, token)
1847 let token = if is_methodish {
1848 self.next_token_as_name()
1850 self.next_token_non_reserved_as_name()
1852 if token.kind() == TokenKind::Name {
1853 S!(make_token, self, token)
1855 // ERROR RECOVERY: Eat the offending token.
1856 report_error(self, token)
1862 fn parse_old_attribute(&mut self) -> S::R {
1863 self.with_expression_parser(|p: &mut ExpressionParser<'a, S, T>| p.parse_constructor_call())
1866 pub fn parse_attribute_specification_opt(&mut self) -> S::R {
1867 match self.peek_token_kind() {
1868 TokenKind::At if self.env.allow_new_attribute_syntax => {
1869 self.parse_new_attribute_specification_opt()
1871 TokenKind::LessThanLessThan => self.parse_old_attribute_specification_opt(),
1872 _ => S!(make_missing, self, self.pos()),
1876 fn parse_new_attribute_specification_opt(&mut self) -> S::R {
1877 let attributes = self.parse_list_while(
1878 |p: &mut Self| p.parse_new_attribute(),
1879 |p: &Self| p.peek_token_kind() == TokenKind::At,
1881 S!(make_attribute_specification, self, attributes)
1884 fn parse_new_attribute(&mut self) -> S::R {
1885 let at = self.assert_token(TokenKind::At);
1886 let token = self.peek_token();
1887 let constructor_call = match token.kind() {
1888 TokenKind::Name => self.with_expression_parser(|p: &mut ExpressionParser<'a, S, T>| {
1889 p.parse_constructor_call()
1892 self.with_error(Errors::expected_user_attribute);
1893 S!(make_missing, self, self.pos())
1896 S!(make_attribute, self, at, constructor_call)
1899 // Parses modifiers and passes them into the parse methods for the
1900 // respective class body element.
1901 fn parse_methodish_or_property_or_const_or_type_const(&mut self) -> S::R {
1902 let mut parser1 = self.clone();
1903 let modifiers = parser1.parse_modifiers();
1904 let kind0 = parser1.peek_token_kind_with_lookahead(0);
1905 let kind1 = parser1.peek_token_kind_with_lookahead(1);
1906 let kind2 = parser1.peek_token_kind_with_lookahead(2);
1907 match (kind0, kind1, kind2) {
1908 (TokenKind::Const, TokenKind::Type, TokenKind::Semicolon) => {
1909 self.continue_from(parser1);
1910 let const_ = self.assert_token(TokenKind::Const);
1911 self.parse_const_declaration(modifiers, const_)
1913 (TokenKind::Const, TokenKind::Type, _) if kind2 != TokenKind::Equal => {
1914 let attributes = S!(make_missing, self, self.pos());
1915 let modifiers = self.parse_modifiers();
1916 let const_ = self.assert_token(TokenKind::Const);
1917 self.parse_type_const_declaration(attributes, modifiers, const_)
1919 (TokenKind::Const, _, _) => {
1920 self.continue_from(parser1);
1921 let const_ = self.assert_token(TokenKind::Const);
1922 self.parse_const_declaration(modifiers, const_)
1925 let missing = S!(make_missing, self, self.pos());
1926 self.parse_methodish_or_property(missing)
1932 // method-declaration:
1933 // attribute-spec-opt method-modifiers function-definition
1934 // attribute-spec-opt method-modifiers function-definition-header ;
1935 // method-modifiers:
1937 // method-modifiers method-modifier
1939 // visibility-modifier (i.e. private, public, protected)
1943 fn parse_methodish(&mut self, attribute_spec: S::R, modifiers: S::R) -> S::R {
1945 self.parse_function_declaration_header(modifiers, /* is_methodish:*/ true);
1946 let token_kind = self.peek_token_kind();
1948 TokenKind::LeftBrace => {
1949 let body = self.parse_compound_statement();
1950 let missing = S!(make_missing, self, self.pos());
1952 make_methodish_declaration,
1960 TokenKind::Semicolon => {
1961 let pos = self.pos();
1962 let token = self.next_token();
1963 let missing = S!(make_missing, self, pos);
1964 let semicolon = S!(make_token, self, token);
1966 make_methodish_declaration,
1974 TokenKind::Equal => {
1975 let equal = self.assert_token(TokenKind::Equal);
1976 let qualifier = self.parse_qualified_name_type();
1977 let cc_token = self.require_coloncolon();
1978 let name = self.require_token_one_of(
1979 &[TokenKind::Name, TokenKind::Construct],
1983 make_scope_resolution_expression,
1989 let semi = self.require_semicolon();
1991 make_methodish_trait_resolution,
2001 // ERROR RECOVERY: We expected either a block or a semicolon; we got
2002 // neither. Use the offending token as the body of the method.
2003 // TODO: Is this the right error recovery?
2004 let pos = self.pos();
2005 let token = self.next_token();
2006 self.with_error(Errors::error1041);
2007 let token = S!(make_token, self, token);
2008 let error = S!(make_error, self, token);
2009 let missing = S!(make_missing, self, pos);
2011 make_methodish_declaration,
2021 fn parse_modifiers(&mut self) -> S::R {
2022 let mut items = vec![];
2024 let token_kind = self.peek_token_kind();
2029 | TokenKind::Protected
2030 | TokenKind::Private
2032 | TokenKind::Coroutine
2033 | TokenKind::Final => {
2034 let token = self.next_token();
2035 let item = S!(make_token, self, token);
2041 S!(make_list, self, items, self.pos())
2044 fn parse_enum_or_classish_or_function_declaration(&mut self) -> S::R {
2045 // An enum, type alias, function, interface, trait or class may all
2046 // begin with an attribute.
2047 let mut parser1 = self.clone();
2048 let attribute_specification = parser1.parse_attribute_specification_opt();
2050 let mut parser2 = parser1.clone();
2051 let token = parser2.next_token();
2052 match token.kind() {
2053 TokenKind::Enum => {
2054 self.continue_from(parser1);
2055 self.parse_enum_declaration(attribute_specification)
2057 TokenKind::Type | TokenKind::Newtype => {
2058 self.continue_from(parser1);
2060 self.parse_alias_declaration(attribute_specification)
2062 TokenKind::Async | TokenKind::Coroutine | TokenKind::Function => {
2063 if attribute_specification.is_missing() {
2064 // if attribute section is missing - it might be either
2065 // function declaration or expression statement containing
2066 // anonymous function - use statement parser to determine in which case
2067 // we are currently in
2068 self.with_statement_parser(|p: &mut StatementParser<'a, S, T>| {
2069 p.parse_possible_php_function(/* toplevel=*/ true)
2072 self.continue_from(parser1);
2073 self.parse_function_declaration(attribute_specification)
2078 | TokenKind::Interface
2080 | TokenKind::Class => {
2081 self.continue_from(parser1);
2082 self.parse_classish_declaration(attribute_specification)
2085 // ERROR RECOVERY: we encountered an unexpected token, raise an error and continue
2086 // TODO: This is wrong; we have lost the attribute specification
2088 self.continue_from(parser2);
2089 self.with_error(Errors::error1057(self.token_text(&token)));
2090 let token = S!(make_token, self, token);
2091 S!(make_error, self, token)
2096 fn parse_classish_element(&mut self) -> S::R {
2097 // We need to identify an element of a class, trait, etc. Possibilities
2100 // // constant-declaration:
2102 // abstract const T $x ;
2103 // public const T $x = v ; // PHP7 only
2105 // // type-constant-declaration
2106 // const type T = X;
2107 // abstract const type T;
2109 // // property-declaration:
2110 // public/private/protected/static T $x;
2111 // TODO: We may wish to parse "T $x" and give an error indicating
2112 // TODO: that we were expecting either const or public.
2113 // Note that a visibility modifier is required; static is optional;
2114 // any order is allowed.
2116 // // method-declaration
2117 // <<attr>> public/private/protected/abstract/final/static async function
2118 // Note that a modifier is required, the attr and async are optional.
2119 // TODO: Hack requires a visibility modifier, unless "static" is supplied,
2120 // TODO: in which case the method is considered to be public. Is this
2121 // TODO: desired? Resolve this disagreement with the spec.
2123 // // constructor-declaration
2124 // <<attr>> public/private/protected/abstract/final function __construct
2125 // Note that we allow static constructors in this parser; we produce an
2126 // error in the post-parse error detection pass.
2129 // require extends qualified-name
2130 // require implements qualified-name
2132 // // XHP class attribute declaration
2135 // // XHP category declaration
2138 // // XHP children declaration
2141 // // Pocket Universe Enumeration
2142 // final? enum id { ... (pocket-field ;) * }
2143 match self.peek_token_kind() {
2144 TokenKind::Children => self.parse_xhp_children_declaration(),
2145 TokenKind::Category => self.parse_xhp_category_declaration(),
2146 TokenKind::Use => self.parse_trait_use(),
2148 | TokenKind::Abstract
2150 | TokenKind::Protected
2151 | TokenKind::Private
2152 | TokenKind::Static => self.parse_methodish_or_property_or_const_or_type_const(),
2153 TokenKind::Enum => self.parse_class_enum(false),
2154 TokenKind::Final => {
2155 match self.peek_token_kind_with_lookahead(1) {
2156 TokenKind::Enum => self.parse_class_enum(/* final:*/ true),
2158 // Parse class methods, constructors, properties
2159 // or type constants.
2160 let attr = self.parse_attribute_specification_opt();
2161 self.parse_methodish_or_property_or_type_constant(attr)
2165 TokenKind::Async | TokenKind::LessThanLessThan => {
2166 // Parse methods, constructors, properties, or type constants.
2167 let attr = self.parse_attribute_specification_opt();
2168 self.parse_methodish_or_property_or_type_constant(attr)
2170 TokenKind::At if self.env.allow_new_attribute_syntax => {
2171 let attr = self.parse_attribute_specification_opt();
2172 self.parse_methodish_or_property_or_type_constant(attr)
2174 TokenKind::Require => {
2175 // We give an error if these are found where they should not be,
2177 self.parse_require_clause()
2179 TokenKind::Attribute => self.parse_xhp_class_attribute_declaration(),
2180 TokenKind::Function => {
2182 // Hack requires that a function inside a class be marked
2183 // with a visibility modifier, but PHP does not have this requirement.
2184 // We accept the lack of a modifier here, and produce an error in
2186 let missing1 = S!(make_missing, self, self.pos());
2187 let missing2 = S!(make_missing, self, self.pos());
2188 self.parse_methodish(missing1, missing2)
2190 kind if self.expects(kind) => S!(make_missing, self, self.pos()),
2192 // If this is a property declaration which is missing its visibility
2193 // modifier, accept it here, but emit an error in a later pass.
2194 let mut parser1 = self.clone();
2195 let missing1 = S!(make_missing, parser1, self.pos());
2196 let missing2 = S!(make_missing, parser1, self.pos());
2197 let property = parser1.parse_property_declaration(missing1, missing2);
2198 if self.errors.len() == parser1.errors.len() {
2199 self.continue_from(parser1);
2202 // TODO ERROR RECOVERY could be improved here.
2203 let token = self.fetch_token();
2204 self.with_error(Errors::error1033);
2205 S!(make_error, self, token)
2206 // Parser does not detect the error where non-static instance variables
2207 // or methods are within abstract final classes in its first pass, but
2208 // instead detects it in its second pass.
2214 fn parse_generic_type_parameter_list_opt(&mut self) -> S::R {
2215 match self.peek_token_kind_with_possible_attributized_type_list() {
2216 TokenKind::LessThan => self.with_type_parser(|p: &mut TypeParser<'a, S, T>| {
2217 p.parse_generic_type_parameter_list()
2219 _ => S!(make_missing, self, self.pos()),
2223 fn parse_type_constraint_opt(&mut self) -> S::R {
2224 self.with_type_parser(|p: &mut TypeParser<'a, S, T>| p.parse_type_constraint_opt())
2227 fn parse_alias_declaration(&mut self, attr: S::R) -> S::R {
2229 // alias-declaration:
2230 // attribute-spec-opt type name
2231 // generic-type-parameter-list-opt = type-specifier ;
2232 // attribute-spec-opt newtype name
2233 // generic-type-parameter-list-opt type-constraint-opt
2234 // = type-specifier ;
2235 let token = self.fetch_token();
2236 // Not `require_name` but `require_name_allow_non_reserved`, because the parser
2237 // must allow keywords in the place of identifiers; at least to parse .hhi
2239 let name = self.require_name_allow_non_reserved();
2240 let generic = self.parse_generic_type_parameter_list_opt();
2241 let constr = self.parse_type_constraint_opt();
2242 let equal = self.require_equal();
2243 let ty = self.parse_type_specifier(false /* allow_var */, true /* allow_attr */);
2244 let semi = self.require_semicolon();
2246 make_alias_declaration,
2259 fn parse_enumerator(&mut self) -> S::R {
2262 // enumerator-constant = constant-expression ;
2263 // enumerator-constant:
2266 // TODO: Add an error to a later pass that determines the value is
2269 // TODO: We must allow TRUE to be a legal enum member name; here we allow
2270 // any keyword. Consider making this more strict.
2271 let name = self.require_name_allow_all_keywords();
2272 let equal = self.require_equal();
2273 let value = self.parse_expression();
2274 let semicolon = self.require_semicolon();
2275 S!(make_enumerator, self, name, equal, value, semicolon)
2278 fn parse_inclusion_directive(&mut self) -> S::R {
2280 // inclusion-directive:
2281 // require-multiple-directive
2282 // require-once-directive
2284 // require-multiple-directive:
2285 // require include-filename ;
2287 // include-filename:
2290 // require-once-directive:
2291 // require_once include-filename ;
2293 // In non-strict mode we allow an inclusion directive (without semi) to be
2294 // used as an expression. It is therefore easier to actually parse this as:
2296 // inclusion-directive:
2297 // inclusion-expression ;
2299 // inclusion-expression:
2300 // require include-filename
2301 // require_once include-filename
2302 let expr = self.parse_expression();
2303 let semi = self.require_semicolon();
2304 S!(make_inclusion_directive, self, expr, semi)
2307 fn parse_declaration(&mut self) -> S::R {
2308 self.expect_in_new_scope(ExpectedTokens::Classish);
2309 let mut parser1 = self.clone();
2310 let token = parser1.next_token();
2312 match token.kind() {
2314 | TokenKind::Include_once
2315 | TokenKind::Require
2316 | TokenKind::Require_once => self.parse_inclusion_directive(),
2317 TokenKind::Type | TokenKind::Newtype
2319 let kind = parser1.peek_token_kind();
2320 kind == TokenKind::Name || kind == TokenKind::Classname
2323 let missing = S!(make_missing, self, self.pos());
2324 self.parse_alias_declaration(missing)
2326 TokenKind::Enum => {
2327 let missing = S!(make_missing, self, self.pos());
2328 self.parse_enum_declaration(missing)
2330 TokenKind::RecordDec => {
2331 let missing = S!(make_missing, self, self.pos());
2332 self.parse_record_declaration(missing)
2334 // The keyword namespace before a name should be parsed as
2335 // "the current namespace we are in", essentially a no op.
2337 // namespace\f1(); should be parsed as a call to the function f1 in
2338 // the current namespace.
2339 TokenKind::Namespace if parser1.peek_token_kind() == TokenKind::Backslash => self
2340 .with_statement_parser(|p: &mut StatementParser<'a, S, T>| p.parse_statement()),
2341 TokenKind::Namespace => self.parse_namespace_declaration(),
2342 TokenKind::Use => self.parse_namespace_use_declaration(),
2343 TokenKind::Trait | TokenKind::Interface | TokenKind::Class => {
2344 let missing = S!(make_missing, self, self.pos());
2345 self.parse_classish_declaration(missing)
2347 TokenKind::Abstract | TokenKind::Final => {
2348 let missing = S!(make_missing, self, self.pos());
2349 match parser1.peek_token_kind() {
2350 TokenKind::RecordDec => self.parse_record_declaration(missing),
2351 _ => self.parse_classish_declaration(missing),
2354 TokenKind::Async | TokenKind::Coroutine | TokenKind::Function => self
2355 .with_statement_parser(|p: &mut StatementParser<'a, S, T>| {
2356 p.parse_possible_php_function(true)
2358 TokenKind::At if self.env.allow_new_attribute_syntax => {
2359 self.parse_enum_or_classish_or_function_declaration()
2361 TokenKind::LessThanLessThan => match parser1.peek_token_kind() {
2363 if parser1.peek_token_kind_with_lookahead(1) == TokenKind::Colon =>
2365 self.parse_file_attribute_specification_opt()
2367 _ => self.parse_enum_or_classish_or_function_declaration(),
2369 // TODO figure out what global const differs from class const
2370 TokenKind::Const => {
2371 let missing1 = S!(make_missing, parser1, self.pos());
2372 self.continue_from(parser1);
2373 let token = S!(make_token, self, token);
2374 self.parse_const_declaration(missing1, token)
2376 // TODO: What if it's not a legal statement? Do we still make progress here?
2378 .with_statement_parser(|p: &mut StatementParser<'a, S, T>| p.parse_statement()),
2381 self.pop_scope(ExpectedTokens::Classish);
2385 fn parse_pocket_mapping(&mut self) -> S::R {
2387 // pocket-mapping ::=
2388 // | 'type' identifier '=' type-expression
2389 // | identifier '=' expression
2390 match self.peek_token_kind() {
2391 TokenKind::Type => {
2392 let typ = self.require_token(TokenKind::Type, Errors::type_keyword);
2393 let tyname = self.require_name();
2394 let equal = self.require_equal();
2395 let ty = self.parse_type_specifier(false, true);
2397 make_pocket_mapping_type_declaration,
2405 TokenKind::Name => {
2406 let id = self.require_name();
2407 let equal = self.require_equal();
2408 let simple_init = self.parse_expression();
2409 let sc_init = S!(make_simple_initializer, self, equal, simple_init);
2410 S!(make_pocket_mapping_id_declaration, self, id, sc_init)
2413 self.with_error(Errors::pocket_universe_invalid_field);
2414 S!(make_missing, self, self.pos())
2419 fn parse_pocket_field(&mut self) -> S::R {
2423 // | enum-member '(' (pocket-mapping ',')')' ;
2424 // | 'case' type-expression identifier ;
2425 // | 'case' 'type' identifier ;
2427 // enum-member ::= ':@' name
2428 match self.peek_token_kind() {
2429 TokenKind::ColonAt => {
2430 let glyph = self.assert_token(TokenKind::ColonAt);
2431 let enum_name = self.require_name();
2432 match self.peek_token_kind() {
2433 TokenKind::LeftParen => {
2434 let (left_paren, mappings, right_paren) =
2435 self.parse_parenthesized_comma_list(|x| x.parse_pocket_mapping());
2436 let semi = self.require_semicolon();
2438 make_pocket_atom_mapping_declaration,
2449 let missing_left = S!(make_missing, self, self.pos());
2450 let missing_mappings = S!(make_missing, self, self.pos());
2451 let missing_right = S!(make_missing, self, self.pos());
2452 let semi = self.require_semicolon();
2454 make_pocket_atom_mapping_declaration,
2466 TokenKind::Case => {
2467 let case_tok = self.assert_token(TokenKind::Case);
2468 match self.peek_token_kind() {
2469 TokenKind::Type => {
2470 let type_tok = self.assert_token(TokenKind::Type);
2471 let name = self.require_name();
2472 let semi = self.require_semicolon();
2474 make_pocket_field_type_declaration,
2483 let ty = self.parse_type_specifier(false, true);
2484 let name = self.require_name();
2485 let semi = self.require_semicolon();
2487 make_pocket_field_type_expr_declaration,
2498 self.with_error(Errors::pocket_universe_invalid_field);
2499 S!(make_missing, self, self.pos())
2504 fn parse_pocket_fields_opt(&mut self) -> S::R {
2506 // pocket-field-list:
2508 // pocket-field-list pocket-field
2509 self.parse_terminated_list(|x| x.parse_pocket_field(), TokenKind::RightBrace)
2512 fn parse_class_enum(&mut self, final_: bool /* = false */) -> S::R {
2514 // 'final'? 'enum' identifier '{' pocket-field-list '}'
2516 // from parse_classish_declaration.. probably could do better
2518 let final_tok = if final_ {
2519 self.require_token(TokenKind::Final, Errors::pocket_universe_final_expected)
2521 S!(make_missing, self, self.pos())
2524 let enum_tok = self.require_token(TokenKind::Enum, Errors::pocket_universe_enum_expected);
2525 let name = self.require_name();
2526 let (left_brace, pocket_fields, right_brace) =
2527 self.parse_braced_list(|x| x.parse_pocket_fields_opt());
2529 make_pocket_enum_declaration,
2540 pub fn parse_script(&mut self) -> S::R {
2541 // TODO(kasper): no_markup for ".hack" files
2542 let header = self.parse_leading_markup_section();
2543 let mut declarations = vec![];
2544 if let Some(x) = header {
2545 declarations.push(x)
2548 let token_kind = self.peek_token_kind();
2550 TokenKind::EndOfFile => {
2551 let token = self.next_token();
2552 let token = S!(make_token, self, token);
2553 let end_of_file = S!(make_end_of_file, self, token);
2554 declarations.push(end_of_file);
2557 _ => declarations.push(self.parse_declaration()),
2560 let declarations = S!(make_list, self, declarations, self.pos());
2561 let result = S!(make_script, self, declarations);
2562 assert_eq!(self.peek_token_kind(), TokenKind::EndOfFile);