@@ -557,10 +557,8 @@ private function parseStatementFn() {
557557 // class-declaration
558558 case TokenKind::FinalKeyword:
559559 case TokenKind::AbstractKeyword:
560- if (!$ this ->lookahead (TokenKind::ClassKeyword)) {
561- $ this ->advanceToken ();
562- return new SkippedToken ($ token );
563- }
560+ case TokenKind::ReadonlyKeyword:
561+ // fallthrough
564562 case TokenKind::ClassKeyword:
565563 return $ this ->parseClassDeclaration ($ parentNode );
566564
@@ -657,10 +655,20 @@ private function parseClassElementFn() {
657655 };
658656 }
659657
658+ /** @return Token[] */
659+ private function parseClassModifiers (): array {
660+ $ modifiers = [];
661+ while ($ token = $ this ->eatOptional (TokenKind::AbstractKeyword, TokenKind::FinalKeyword, TokenKind::ReadonlyKeyword)) {
662+ $ modifiers [] = $ token ;
663+ }
664+ return $ modifiers ;
665+ }
666+
660667 private function parseClassDeclaration ($ parentNode ) : Node {
661668 $ classNode = new ClassDeclaration (); // TODO verify not nested
662669 $ classNode ->parent = $ parentNode ;
663- $ classNode ->abstractOrFinalModifier = $ this ->eatOptional (TokenKind::AbstractKeyword, TokenKind::FinalKeyword);
670+ $ classNode ->abstractOrFinalModifier = $ this ->eatOptional (TokenKind::AbstractKeyword, TokenKind::FinalKeyword, TokenKind::ReadonlyKeyword);
671+ $ classNode ->modifiers = $ this ->parseClassModifiers ();
664672 $ classNode ->classKeyword = $ this ->eat1 (TokenKind::ClassKeyword);
665673 $ classNode ->name = $ this ->eat ($ this ->nameOrReservedWordTokens ); // TODO should be any
666674 $ classNode ->name ->kind = TokenKind::Name;
@@ -1036,6 +1044,7 @@ private function isStatementStart(Token $token) {
10361044 case TokenKind::ClassKeyword:
10371045 case TokenKind::AbstractKeyword:
10381046 case TokenKind::FinalKeyword:
1047+ case TokenKind::ReadonlyKeyword:
10391048
10401049 // interface-declaration
10411050 case TokenKind::InterfaceKeyword:
@@ -3533,6 +3542,7 @@ private function isTraitMemberDeclarationStart($token) {
35333542 case TokenKind::AbstractKeyword:
35343543 case TokenKind::FinalKeyword:
35353544 case TokenKind::ReadonlyKeyword:
3545+ case TokenKind::ConstKeyword:
35363546
35373547 // method-declaration
35383548 case TokenKind::FunctionKeyword:
@@ -3553,6 +3563,9 @@ private function parseTraitElementFn() {
35533563
35543564 $ token = $ this ->getCurrentToken ();
35553565 switch ($ token ->kind ) {
3566+ case TokenKind::ConstKeyword:
3567+ return $ this ->parseClassConstDeclaration ($ parentNode , $ modifiers );
3568+
35563569 case TokenKind::FunctionKeyword:
35573570 return $ this ->parseMethodDeclaration ($ parentNode , $ modifiers );
35583571
0 commit comments