php8.1: added enum (#12)
This commit is contained in:
		
							parent
							
								
									44bbff6073
								
							
						
					
					
						commit
						af394e9eb0
					
				| @ -1152,6 +1152,105 @@ func (b *Builder) NewInterface( | |||||||
| 	return iface | 	return iface | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (b *Builder) NewEnumType( | ||||||
|  | 	ColonTkn *token.Token, | ||||||
|  | 	Type ast.Vertex, | ||||||
|  | ) *ReturnType { | ||||||
|  | 	return &ReturnType{ | ||||||
|  | 		ColonTkn: ColonTkn, | ||||||
|  | 		Type:     Type, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (b *Builder) NewEnumExpr( | ||||||
|  | 	AssignTkn *token.Token, | ||||||
|  | 	Expr ast.Vertex, | ||||||
|  | ) *EnumCaseExpr { | ||||||
|  | 	return &EnumCaseExpr{ | ||||||
|  | 		AssignTkn: AssignTkn, | ||||||
|  | 		Expr:      Expr, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (b *Builder) NewEnum( | ||||||
|  | 	AttrGroups []ast.Vertex, | ||||||
|  | 	EnumTkn *token.Token, | ||||||
|  | 	Name *token.Token, | ||||||
|  | 
 | ||||||
|  | 	EnumScalarType ast.Vertex, | ||||||
|  | 
 | ||||||
|  | 	ImplementsList ast.Vertex, | ||||||
|  | 
 | ||||||
|  | 	OpenCurlyBracketTkn *token.Token, | ||||||
|  | 	Stmts []ast.Vertex, | ||||||
|  | 	CloseCurlyBracketTkn *token.Token, | ||||||
|  | ) *ast.StmtEnum { | ||||||
|  | 	var pos *position2.Position | ||||||
|  | 	if AttrGroups != nil { | ||||||
|  | 		pos = b.Pos.NewNodeListTokenPosition(AttrGroups, CloseCurlyBracketTkn) | ||||||
|  | 	} else { | ||||||
|  | 		pos = b.Pos.NewTokensPosition(EnumTkn, CloseCurlyBracketTkn) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	enum := &ast.StmtEnum{ | ||||||
|  | 		Position:             pos, | ||||||
|  | 		AttrGroups:           AttrGroups, | ||||||
|  | 		EnumTkn:              EnumTkn, | ||||||
|  | 		Name:                 b.NewIdentifier(Name), | ||||||
|  | 		OpenCurlyBracketTkn:  OpenCurlyBracketTkn, | ||||||
|  | 		Stmts:                Stmts, | ||||||
|  | 		CloseCurlyBracketTkn: CloseCurlyBracketTkn, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if EnumScalarType != nil { | ||||||
|  | 		enumType := EnumScalarType.(*ReturnType) | ||||||
|  | 		enum.ColonTkn = enumType.ColonTkn | ||||||
|  | 		enum.Type = enumType.Type | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if ImplementsList != nil { | ||||||
|  | 		enum.ImplementsTkn = ImplementsList.(*ast.StmtClass).ImplementsTkn | ||||||
|  | 		enum.Implements = ImplementsList.(*ast.StmtClass).Implements | ||||||
|  | 		enum.ImplementsSeparatorTkns = ImplementsList.(*ast.StmtClass).ImplementsSeparatorTkns | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return enum | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (b *Builder) NewEnumCase( | ||||||
|  | 	AttrGroups []ast.Vertex, | ||||||
|  | 	CaseTkn *token.Token, | ||||||
|  | 	Name *token.Token, | ||||||
|  | 	Expr ast.Vertex, | ||||||
|  | 	SemiColonTkn *token.Token, | ||||||
|  | ) *ast.EnumCase { | ||||||
|  | 	var equalTkn *token.Token | ||||||
|  | 	var expr ast.Vertex | ||||||
|  | 	if Expr != nil { | ||||||
|  | 		caseExpr := Expr.(*EnumCaseExpr) | ||||||
|  | 		equalTkn = caseExpr.AssignTkn | ||||||
|  | 		expr = caseExpr.Expr | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var pos *position2.Position | ||||||
|  | 
 | ||||||
|  | 	if AttrGroups != nil { | ||||||
|  | 		pos = b.Pos.NewNodeListTokenPosition(AttrGroups, SemiColonTkn) | ||||||
|  | 	} else { | ||||||
|  | 		pos = b.Pos.NewTokensPosition(CaseTkn, SemiColonTkn) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return &ast.EnumCase{ | ||||||
|  | 		Position:     pos, | ||||||
|  | 		CaseTkn:      CaseTkn, | ||||||
|  | 		AttrGroups:   AttrGroups, | ||||||
|  | 		Name:         b.NewIdentifier(Name), | ||||||
|  | 		EqualTkn:     equalTkn, | ||||||
|  | 		Expr:         expr, | ||||||
|  | 		SemiColonTkn: SemiColonTkn, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (b *Builder) NewFunction( | func (b *Builder) NewFunction( | ||||||
| 	AttrGroups []ast.Vertex, | 	AttrGroups []ast.Vertex, | ||||||
| 	FunctionTkn *token.Token, | 	FunctionTkn *token.Token, | ||||||
|  | |||||||
| @ -68,6 +68,20 @@ func (n *ArgumentList) GetPosition() *position.Position { | |||||||
| 	return n.Position | 	return n.Position | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type EnumCaseExpr struct { | ||||||
|  | 	Position  *position.Position | ||||||
|  | 	AssignTkn *token.Token | ||||||
|  | 	Expr      ast.Vertex | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (n *EnumCaseExpr) Accept(v ast.Visitor) { | ||||||
|  | 	// do nothing | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (n *EnumCaseExpr) GetPosition() *position.Position { | ||||||
|  | 	return n.Position | ||||||
|  | } | ||||||
|  | 
 | ||||||
| type ReturnType struct { | type ReturnType struct { | ||||||
| 	Position *position.Position | 	Position *position.Position | ||||||
| 	ColonTkn *token.Token | 	ColonTkn *token.Token | ||||||
|  | |||||||
| @ -254,3 +254,71 @@ function f(): never {} | |||||||
| 
 | 
 | ||||||
| 	suite.Run() | 	suite.Run() | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func TestEnum(t *testing.T) { | ||||||
|  | 	suite := tester.NewParserDumpTestSuite(t) | ||||||
|  | 	suite.UsePHP8() | ||||||
|  | 	suite.Code = `<?php | ||||||
|  | enum A {} | ||||||
|  | enum B implements Bar, Baz { | ||||||
|  | } | ||||||
|  | enum C: int implements Bar {} | ||||||
|  | ` | ||||||
|  | 
 | ||||||
|  | 	suite.Expected = `&ast.Root{ | ||||||
|  | 	Stmts: []ast.Vertex{ | ||||||
|  | 		&ast.StmtEnum{ | ||||||
|  | 			Name: &ast.Identifier{ | ||||||
|  | 				Val: []byte("A"), | ||||||
|  | 			}, | ||||||
|  | 			Stmts: []ast.Vertex{}, | ||||||
|  | 		}, | ||||||
|  | 		&ast.StmtEnum{ | ||||||
|  | 			Name: &ast.Identifier{ | ||||||
|  | 				Val: []byte("B"), | ||||||
|  | 			}, | ||||||
|  | 			Implements: []ast.Vertex{ | ||||||
|  | 				&ast.Name{ | ||||||
|  | 					Parts: []ast.Vertex{ | ||||||
|  | 						&ast.NamePart{ | ||||||
|  | 							Val: []byte("Bar"), | ||||||
|  | 						}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 				&ast.Name{ | ||||||
|  | 					Parts: []ast.Vertex{ | ||||||
|  | 						&ast.NamePart{ | ||||||
|  | 							Val: []byte("Baz"), | ||||||
|  | 						}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			Stmts: []ast.Vertex{}, | ||||||
|  | 		}, | ||||||
|  | 		&ast.StmtEnum{ | ||||||
|  | 			Name: &ast.Identifier{ | ||||||
|  | 				Val: []byte("C"), | ||||||
|  | 			}, | ||||||
|  | 			Type: &ast.Name{ | ||||||
|  | 				Parts: []ast.Vertex{ | ||||||
|  | 					&ast.NamePart{ | ||||||
|  | 						Val: []byte("int"), | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			Implements: []ast.Vertex{ | ||||||
|  | 				&ast.Name{ | ||||||
|  | 					Parts: []ast.Vertex{ | ||||||
|  | 						&ast.NamePart{ | ||||||
|  | 							Val: []byte("Bar"), | ||||||
|  | 						}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			Stmts: []ast.Vertex{}, | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  | },` | ||||||
|  | 
 | ||||||
|  | 	suite.Run() | ||||||
|  | } | ||||||
|  | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -161,6 +161,7 @@ import ( | |||||||
| %token <token> T_NAME_QUALIFIED | %token <token> T_NAME_QUALIFIED | ||||||
| %token <token> T_NAME_FULLY_QUALIFIED | %token <token> T_NAME_FULLY_QUALIFIED | ||||||
| %token <token> T_READONLY | %token <token> T_READONLY | ||||||
|  | %token <token> T_ENUM | ||||||
| %token <token> '"' | %token <token> '"' | ||||||
| %token <token> '`' | %token <token> '`' | ||||||
| %token <token> '{' | %token <token> '{' | ||||||
| @ -284,6 +285,7 @@ import ( | |||||||
| %type <node> catch_list catch | %type <node> catch_list catch | ||||||
| %type <node> property_modifier | %type <node> property_modifier | ||||||
| %type <node> attribute_decl attribute_group attribute | %type <node> attribute_decl attribute_group attribute | ||||||
|  | %type <node> enum_declaration_statement enum_case_expr enum_scalar_type | ||||||
| 
 | 
 | ||||||
| %type <node> member_modifier | %type <node> member_modifier | ||||||
| %type <node> foreach_variable | %type <node> foreach_variable | ||||||
| @ -322,7 +324,7 @@ reserved_non_modifiers: | |||||||
|     | T_THROW {$$=$1} | T_USE {$$=$1} | T_INSTEADOF {$$=$1} | T_GLOBAL {$$=$1} | T_VAR {$$=$1} | T_UNSET {$$=$1} | T_ISSET {$$=$1} | T_EMPTY {$$=$1} | T_CONTINUE {$$=$1} | T_GOTO {$$=$1} |     | T_THROW {$$=$1} | T_USE {$$=$1} | T_INSTEADOF {$$=$1} | T_GLOBAL {$$=$1} | T_VAR {$$=$1} | T_UNSET {$$=$1} | T_ISSET {$$=$1} | T_EMPTY {$$=$1} | T_CONTINUE {$$=$1} | T_GOTO {$$=$1} | ||||||
|     | T_FUNCTION {$$=$1} | T_CONST {$$=$1} | T_RETURN {$$=$1} | T_PRINT {$$=$1} | T_YIELD {$$=$1} | T_LIST {$$=$1} | T_SWITCH {$$=$1} | T_ENDSWITCH {$$=$1} | T_CASE {$$=$1} | T_DEFAULT {$$=$1} | T_BREAK {$$=$1} |     | T_FUNCTION {$$=$1} | T_CONST {$$=$1} | T_RETURN {$$=$1} | T_PRINT {$$=$1} | T_YIELD {$$=$1} | T_LIST {$$=$1} | T_SWITCH {$$=$1} | T_ENDSWITCH {$$=$1} | T_CASE {$$=$1} | T_DEFAULT {$$=$1} | T_BREAK {$$=$1} | ||||||
|     | T_ARRAY {$$=$1} | T_CALLABLE {$$=$1} | T_EXTENDS {$$=$1} | T_IMPLEMENTS {$$=$1} | T_NAMESPACE {$$=$1} | T_TRAIT {$$=$1} | T_INTERFACE {$$=$1} | T_CLASS {$$=$1} |     | T_ARRAY {$$=$1} | T_CALLABLE {$$=$1} | T_EXTENDS {$$=$1} | T_IMPLEMENTS {$$=$1} | T_NAMESPACE {$$=$1} | T_TRAIT {$$=$1} | T_INTERFACE {$$=$1} | T_CLASS {$$=$1} | ||||||
|     | T_CLASS_C {$$=$1} | T_TRAIT_C {$$=$1} | T_FUNC_C {$$=$1} | T_METHOD_C {$$=$1} | T_LINE {$$=$1} | T_FILE {$$=$1} | T_DIR {$$=$1} | T_NS_C {$$=$1} | T_FN {$$=$1} | T_MATCH {$$=$1} |     | T_CLASS_C {$$=$1} | T_TRAIT_C {$$=$1} | T_FUNC_C {$$=$1} | T_METHOD_C {$$=$1} | T_LINE {$$=$1} | T_FILE {$$=$1} | T_DIR {$$=$1} | T_NS_C {$$=$1} | T_FN {$$=$1} | T_MATCH {$$=$1} | T_ENUM {$$=$1} | ||||||
| ; | ; | ||||||
| 
 | 
 | ||||||
| semi_reserved: | semi_reserved: | ||||||
| @ -422,6 +424,7 @@ top_statement: | |||||||
|     |   class_declaration_statement     { $$ = $1 } |     |   class_declaration_statement     { $$ = $1 } | ||||||
|     |   trait_declaration_statement     { $$ = $1 } |     |   trait_declaration_statement     { $$ = $1 } | ||||||
|     |   interface_declaration_statement { $$ = $1 } |     |   interface_declaration_statement { $$ = $1 } | ||||||
|  |     |   enum_declaration_statement      { $$ = $1 } | ||||||
|     |   T_HALT_COMPILER '(' ')' ';' |     |   T_HALT_COMPILER '(' ')' ';' | ||||||
|             { |             { | ||||||
|                 $$ = &ast.StmtHaltCompiler{ |                 $$ = &ast.StmtHaltCompiler{ | ||||||
| @ -540,6 +543,7 @@ inner_statement: | |||||||
|     |   class_declaration_statement          { $$ = $1 } |     |   class_declaration_statement          { $$ = $1 } | ||||||
|     |   trait_declaration_statement          { $$ = $1 } |     |   trait_declaration_statement          { $$ = $1 } | ||||||
|     |   interface_declaration_statement      { $$ = $1 } |     |   interface_declaration_statement      { $$ = $1 } | ||||||
|  |     |   enum_declaration_statement           { $$ = $1 } | ||||||
|     |   T_HALT_COMPILER '(' ')' ';' |     |   T_HALT_COMPILER '(' ')' ';' | ||||||
|             { |             { | ||||||
|                 $$ = &ast.StmtHaltCompiler{ |                 $$ = &ast.StmtHaltCompiler{ | ||||||
| @ -886,6 +890,20 @@ interface_declaration_statement: | |||||||
|             { $$ = yylex.(*Parser).builder.NewInterface($1, $2, $3, $4, $5, $6, $7) } |             { $$ = yylex.(*Parser).builder.NewInterface($1, $2, $3, $4, $5, $6, $7) } | ||||||
| ; | ; | ||||||
| 
 | 
 | ||||||
|  | enum_declaration_statement: | ||||||
|  |         optional_attributes | ||||||
|  |         T_ENUM T_STRING enum_scalar_type implements_list '{' class_statement_list '}' | ||||||
|  |             { $$ = yylex.(*Parser).builder.NewEnum($1, $2, $3, $4, $5, $6, $7, $8) } | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | enum_scalar_type: | ||||||
|  |         /* empty */   { $$ = nil } | ||||||
|  |     |   ':' type      { $$ = yylex.(*Parser).builder.NewEnumType($1, $2) } | ||||||
|  | 
 | ||||||
|  | enum_case_expr: | ||||||
|  |         /* empty */   { $$ = nil } | ||||||
|  |     |   '=' expr      { $$ = yylex.(*Parser).builder.NewEnumExpr($1, $2) } | ||||||
|  | 
 | ||||||
| extends_from: | extends_from: | ||||||
|         /* empty */ |         /* empty */ | ||||||
|             { |             { | ||||||
| @ -1468,6 +1486,8 @@ class_statement: | |||||||
| 
 | 
 | ||||||
|                 $$ = traitUse |                 $$ = traitUse | ||||||
|             } |             } | ||||||
|  |     |   optional_attributes T_CASE T_STRING enum_case_expr ';' | ||||||
|  |             { $$ = yylex.(*Parser).builder.NewEnumCase($1, $2, $3, $4, $5) } | ||||||
| ; | ; | ||||||
| 
 | 
 | ||||||
| name_list: | name_list: | ||||||
|  | |||||||
							
								
								
									
										11255
									
								
								internal/php8/scanner.go
									
									
									
									
									
								
							
							
						
						
									
										11255
									
								
								internal/php8/scanner.go
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -239,6 +239,7 @@ func (lex *Lexer) Lex() *token.Token { | |||||||
|             'endif'i                          => {lex.setTokenPosition(tkn); tok = token.T_ENDIF; fbreak;}; |             'endif'i                          => {lex.setTokenPosition(tkn); tok = token.T_ENDIF; fbreak;}; | ||||||
|             'endswitch'i                      => {lex.setTokenPosition(tkn); tok = token.T_ENDSWITCH; fbreak;}; |             'endswitch'i                      => {lex.setTokenPosition(tkn); tok = token.T_ENDSWITCH; fbreak;}; | ||||||
|             'endwhile'i                       => {lex.setTokenPosition(tkn); tok = token.T_ENDWHILE; fbreak;}; |             'endwhile'i                       => {lex.setTokenPosition(tkn); tok = token.T_ENDWHILE; fbreak;}; | ||||||
|  |             'enum'i                           => {lex.setTokenPosition(tkn); tok = token.T_ENUM; fbreak;}; | ||||||
|             'eval'i                           => {lex.setTokenPosition(tkn); tok = token.T_EVAL; fbreak;}; |             'eval'i                           => {lex.setTokenPosition(tkn); tok = token.T_EVAL; fbreak;}; | ||||||
|             'exit'i | 'die'i                  => {lex.setTokenPosition(tkn); tok = token.T_EXIT; fbreak;}; |             'exit'i | 'die'i                  => {lex.setTokenPosition(tkn); tok = token.T_EXIT; fbreak;}; | ||||||
|             'extends'i                        => {lex.setTokenPosition(tkn); tok = token.T_EXTENDS; fbreak;}; |             'extends'i                        => {lex.setTokenPosition(tkn); tok = token.T_EXTENDS; fbreak;}; | ||||||
|  | |||||||
| @ -155,3 +155,28 @@ func TestNumberStringTokens(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| 	suite.Run() | 	suite.Run() | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func TestEnumTokens(t *testing.T) { | ||||||
|  | 	suite := tester.NewLexerTokenStructTestSuite(t) | ||||||
|  | 	suite.UsePHP8() | ||||||
|  | 	suite.Code = "<?php enum A {}" | ||||||
|  | 	suite.Expected = []*token.Token{ | ||||||
|  | 		{ | ||||||
|  | 			ID:    token.T_ENUM, | ||||||
|  | 			Value: []byte("enum"), | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			ID:    token.T_STRING, | ||||||
|  | 			Value: []byte("A"), | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			ID:    '{', | ||||||
|  | 			Value: []byte("{"), | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			ID:    '}', | ||||||
|  | 			Value: []byte("}"), | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	suite.Run() | ||||||
|  | } | ||||||
|  | |||||||
| @ -21,6 +21,8 @@ type Visitor interface { | |||||||
| 	StmtBreak(n *StmtBreak) | 	StmtBreak(n *StmtBreak) | ||||||
| 	StmtCase(n *StmtCase) | 	StmtCase(n *StmtCase) | ||||||
| 	StmtCatch(n *StmtCatch) | 	StmtCatch(n *StmtCatch) | ||||||
|  | 	StmtEnum(n *StmtEnum) | ||||||
|  | 	EnumCase(n *EnumCase) | ||||||
| 	StmtClass(n *StmtClass) | 	StmtClass(n *StmtClass) | ||||||
| 	StmtClassConstList(n *StmtClassConstList) | 	StmtClassConstList(n *StmtClassConstList) | ||||||
| 	StmtClassMethod(n *StmtClassMethod) | 	StmtClassMethod(n *StmtClassMethod) | ||||||
|  | |||||||
| @ -337,6 +337,49 @@ func (n *StmtCatch) GetPosition() *position.Position { | |||||||
| 	return n.Position | 	return n.Position | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // StmtEnum node | ||||||
|  | type StmtEnum struct { | ||||||
|  | 	Position                *position.Position | ||||||
|  | 	AttrGroups              []Vertex | ||||||
|  | 	EnumTkn                 *token.Token | ||||||
|  | 	Name                    Vertex | ||||||
|  | 	ColonTkn                *token.Token | ||||||
|  | 	Type                    Vertex | ||||||
|  | 	ImplementsTkn           *token.Token | ||||||
|  | 	Implements              []Vertex | ||||||
|  | 	ImplementsSeparatorTkns []*token.Token | ||||||
|  | 	OpenCurlyBracketTkn     *token.Token | ||||||
|  | 	Stmts                   []Vertex | ||||||
|  | 	CloseCurlyBracketTkn    *token.Token | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (n *StmtEnum) Accept(v Visitor) { | ||||||
|  | 	v.StmtEnum(n) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (n *StmtEnum) GetPosition() *position.Position { | ||||||
|  | 	return n.Position | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // EnumCase node | ||||||
|  | type EnumCase struct { | ||||||
|  | 	Position     *position.Position | ||||||
|  | 	AttrGroups   []Vertex | ||||||
|  | 	CaseTkn      *token.Token | ||||||
|  | 	Name         Vertex | ||||||
|  | 	EqualTkn     *token.Token | ||||||
|  | 	Expr         Vertex | ||||||
|  | 	SemiColonTkn *token.Token | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (n *EnumCase) Accept(v Visitor) { | ||||||
|  | 	v.EnumCase(n) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (n *EnumCase) GetPosition() *position.Position { | ||||||
|  | 	return n.Position | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // StmtClass node | // StmtClass node | ||||||
| type StmtClass struct { | type StmtClass struct { | ||||||
| 	Position                *position.Position | 	Position                *position.Position | ||||||
|  | |||||||
| @ -151,6 +151,7 @@ const ( | |||||||
| 	T_NAME_QUALIFIED | 	T_NAME_QUALIFIED | ||||||
| 	T_NAME_FULLY_QUALIFIED | 	T_NAME_FULLY_QUALIFIED | ||||||
| 	T_READONLY | 	T_READONLY | ||||||
|  | 	T_ENUM | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type Token struct { | type Token struct { | ||||||
|  | |||||||
| @ -153,11 +153,12 @@ func _() { | |||||||
| 	_ = x[T_NAME_QUALIFIED-57488] | 	_ = x[T_NAME_QUALIFIED-57488] | ||||||
| 	_ = x[T_NAME_FULLY_QUALIFIED-57489] | 	_ = x[T_NAME_FULLY_QUALIFIED-57489] | ||||||
| 	_ = x[T_READONLY-57490] | 	_ = x[T_READONLY-57490] | ||||||
|  | 	_ = x[T_ENUM-57491] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const _ID_name = "T_INCLUDET_INCLUDE_ONCET_EXITT_IFT_LNUMBERT_DNUMBERT_STRINGT_STRING_VARNAMET_VARIABLET_NUM_STRINGT_INLINE_HTMLT_CHARACTERT_BAD_CHARACTERT_ENCAPSED_AND_WHITESPACET_CONSTANT_ENCAPSED_STRINGT_ECHOT_DOT_WHILET_ENDWHILET_FORT_ENDFORT_FOREACHT_ENDFOREACHT_DECLARET_ENDDECLARET_AST_SWITCHT_ENDSWITCHT_CASET_DEFAULTT_BREAKT_CONTINUET_GOTOT_FUNCTIONT_FNT_CONSTT_RETURNT_TRYT_CATCHT_FINALLYT_THROWT_USET_INSTEADOFT_GLOBALT_VART_UNSETT_ISSETT_EMPTYT_HALT_COMPILERT_CLASST_TRAITT_INTERFACET_EXTENDST_IMPLEMENTST_OBJECT_OPERATORT_DOUBLE_ARROWT_LISTT_ARRAYT_CALLABLET_CLASS_CT_TRAIT_CT_METHOD_CT_FUNC_CT_LINET_FILET_COMMENTT_DOC_COMMENTT_OPEN_TAGT_OPEN_TAG_WITH_ECHOT_CLOSE_TAGT_WHITESPACET_START_HEREDOCT_END_HEREDOCT_DOLLAR_OPEN_CURLY_BRACEST_CURLY_OPENT_PAAMAYIM_NEKUDOTAYIMT_NAMESPACET_NS_CT_DIRT_NS_SEPARATORT_ELLIPSIST_EVALT_REQUIRET_REQUIRE_ONCET_LOGICAL_ORT_LOGICAL_XORT_LOGICAL_ANDT_INSTANCEOFT_NEWT_CLONET_ELSEIFT_ELSET_ENDIFT_PRINTT_YIELDT_STATICT_ABSTRACTT_FINALT_PRIVATET_PROTECTEDT_PUBLICT_INCT_DECT_YIELD_FROMT_INT_CASTT_DOUBLE_CASTT_STRING_CASTT_ARRAY_CASTT_OBJECT_CASTT_BOOL_CASTT_UNSET_CASTT_COALESCET_SPACESHIPT_NOELSET_PLUS_EQUALT_MINUS_EQUALT_MUL_EQUALT_POW_EQUALT_DIV_EQUALT_CONCAT_EQUALT_MOD_EQUALT_AND_EQUALT_OR_EQUALT_XOR_EQUALT_SL_EQUALT_SR_EQUALT_COALESCE_EQUALT_BOOLEAN_ORT_BOOLEAN_ANDT_POWT_SLT_SRT_IS_IDENTICALT_IS_NOT_IDENTICALT_IS_EQUALT_IS_NOT_EQUALT_IS_SMALLER_OR_EQUALT_IS_GREATER_OR_EQUALT_NULLSAFE_OBJECT_OPERATORT_MATCHT_ATTRIBUTET_NAME_RELATIVET_NAME_QUALIFIEDT_NAME_FULLY_QUALIFIEDT_READONLY" | const _ID_name = "T_INCLUDET_INCLUDE_ONCET_EXITT_IFT_LNUMBERT_DNUMBERT_STRINGT_STRING_VARNAMET_VARIABLET_NUM_STRINGT_INLINE_HTMLT_CHARACTERT_BAD_CHARACTERT_ENCAPSED_AND_WHITESPACET_CONSTANT_ENCAPSED_STRINGT_ECHOT_DOT_WHILET_ENDWHILET_FORT_ENDFORT_FOREACHT_ENDFOREACHT_DECLARET_ENDDECLARET_AST_SWITCHT_ENDSWITCHT_CASET_DEFAULTT_BREAKT_CONTINUET_GOTOT_FUNCTIONT_FNT_CONSTT_RETURNT_TRYT_CATCHT_FINALLYT_THROWT_USET_INSTEADOFT_GLOBALT_VART_UNSETT_ISSETT_EMPTYT_HALT_COMPILERT_CLASST_TRAITT_INTERFACET_EXTENDST_IMPLEMENTST_OBJECT_OPERATORT_DOUBLE_ARROWT_LISTT_ARRAYT_CALLABLET_CLASS_CT_TRAIT_CT_METHOD_CT_FUNC_CT_LINET_FILET_COMMENTT_DOC_COMMENTT_OPEN_TAGT_OPEN_TAG_WITH_ECHOT_CLOSE_TAGT_WHITESPACET_START_HEREDOCT_END_HEREDOCT_DOLLAR_OPEN_CURLY_BRACEST_CURLY_OPENT_PAAMAYIM_NEKUDOTAYIMT_NAMESPACET_NS_CT_DIRT_NS_SEPARATORT_ELLIPSIST_EVALT_REQUIRET_REQUIRE_ONCET_LOGICAL_ORT_LOGICAL_XORT_LOGICAL_ANDT_INSTANCEOFT_NEWT_CLONET_ELSEIFT_ELSET_ENDIFT_PRINTT_YIELDT_STATICT_ABSTRACTT_FINALT_PRIVATET_PROTECTEDT_PUBLICT_INCT_DECT_YIELD_FROMT_INT_CASTT_DOUBLE_CASTT_STRING_CASTT_ARRAY_CASTT_OBJECT_CASTT_BOOL_CASTT_UNSET_CASTT_COALESCET_SPACESHIPT_NOELSET_PLUS_EQUALT_MINUS_EQUALT_MUL_EQUALT_POW_EQUALT_DIV_EQUALT_CONCAT_EQUALT_MOD_EQUALT_AND_EQUALT_OR_EQUALT_XOR_EQUALT_SL_EQUALT_SR_EQUALT_COALESCE_EQUALT_BOOLEAN_ORT_BOOLEAN_ANDT_POWT_SLT_SRT_IS_IDENTICALT_IS_NOT_IDENTICALT_IS_EQUALT_IS_NOT_EQUALT_IS_SMALLER_OR_EQUALT_IS_GREATER_OR_EQUALT_NULLSAFE_OBJECT_OPERATORT_MATCHT_ATTRIBUTET_NAME_RELATIVET_NAME_QUALIFIEDT_NAME_FULLY_QUALIFIEDT_READONLYT_ENUM" | ||||||
| 
 | 
 | ||||||
| var _ID_index = [...]uint16{0, 9, 23, 29, 33, 42, 51, 59, 75, 85, 97, 110, 121, 136, 161, 187, 193, 197, 204, 214, 219, 227, 236, 248, 257, 269, 273, 281, 292, 298, 307, 314, 324, 330, 340, 344, 351, 359, 364, 371, 380, 387, 392, 403, 411, 416, 423, 430, 437, 452, 459, 466, 477, 486, 498, 515, 529, 535, 542, 552, 561, 570, 580, 588, 594, 600, 609, 622, 632, 652, 663, 675, 690, 703, 729, 741, 763, 774, 780, 785, 799, 809, 815, 824, 838, 850, 863, 876, 888, 893, 900, 908, 914, 921, 928, 935, 943, 953, 960, 969, 980, 988, 993, 998, 1010, 1020, 1033, 1046, 1058, 1071, 1082, 1094, 1104, 1115, 1123, 1135, 1148, 1159, 1170, 1181, 1195, 1206, 1217, 1227, 1238, 1248, 1258, 1274, 1286, 1299, 1304, 1308, 1312, 1326, 1344, 1354, 1368, 1389, 1410, 1436, 1443, 1454, 1469, 1485, 1507, 1517} | var _ID_index = [...]uint16{0, 9, 23, 29, 33, 42, 51, 59, 75, 85, 97, 110, 121, 136, 161, 187, 193, 197, 204, 214, 219, 227, 236, 248, 257, 269, 273, 281, 292, 298, 307, 314, 324, 330, 340, 344, 351, 359, 364, 371, 380, 387, 392, 403, 411, 416, 423, 430, 437, 452, 459, 466, 477, 486, 498, 515, 529, 535, 542, 552, 561, 570, 580, 588, 594, 600, 609, 622, 632, 652, 663, 675, 690, 703, 729, 741, 763, 774, 780, 785, 799, 809, 815, 824, 838, 850, 863, 876, 888, 893, 900, 908, 914, 921, 928, 935, 943, 953, 960, 969, 980, 988, 993, 998, 1010, 1020, 1033, 1046, 1058, 1071, 1082, 1094, 1104, 1115, 1123, 1135, 1148, 1159, 1170, 1181, 1195, 1206, 1217, 1227, 1238, 1248, 1258, 1274, 1286, 1299, 1304, 1308, 1312, 1326, 1344, 1354, 1368, 1389, 1410, 1436, 1443, 1454, 1469, 1485, 1507, 1517, 1523} | ||||||
| 
 | 
 | ||||||
| func (i ID) String() string { | func (i ID) String() string { | ||||||
| 	i -= 57346 | 	i -= 57346 | ||||||
|  | |||||||
| @ -336,6 +336,43 @@ func (v *Dumper) StmtCatch(n *ast.StmtCatch) { | |||||||
| 	v.print(v.indent, "},\n") | 	v.print(v.indent, "},\n") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (v *Dumper) StmtEnum(n *ast.StmtEnum) { | ||||||
|  | 	v.print(0, "&ast.StmtEnum{\n") | ||||||
|  | 	v.indent++ | ||||||
|  | 
 | ||||||
|  | 	v.dumpPosition(n.Position) | ||||||
|  | 	v.dumpVertexList("AttrGroups", n.AttrGroups) | ||||||
|  | 	v.dumpToken("EnumTkn", n.EnumTkn) | ||||||
|  | 	v.dumpVertex("Name", n.Name) | ||||||
|  | 	v.dumpToken("ColonTkn", n.ColonTkn) | ||||||
|  | 	v.dumpVertex("Type", n.Type) | ||||||
|  | 	v.dumpToken("ImplementsTkn", n.ImplementsTkn) | ||||||
|  | 	v.dumpVertexList("Implements", n.Implements) | ||||||
|  | 	v.dumpTokenList("ImplementsSeparatorTkns", n.ImplementsSeparatorTkns) | ||||||
|  | 	v.dumpToken("OpenCurlyBracketTkn", n.OpenCurlyBracketTkn) | ||||||
|  | 	v.dumpVertexList("Stmts", n.Stmts) | ||||||
|  | 	v.dumpToken("CloseCurlyBracketTkn", n.CloseCurlyBracketTkn) | ||||||
|  | 
 | ||||||
|  | 	v.indent-- | ||||||
|  | 	v.print(v.indent, "},\n") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (v *Dumper) EnumCase(n *ast.EnumCase) { | ||||||
|  | 	v.print(0, "&ast.EnumCase{\n") | ||||||
|  | 	v.indent++ | ||||||
|  | 
 | ||||||
|  | 	v.dumpPosition(n.Position) | ||||||
|  | 	v.dumpVertexList("AttrGroups", n.AttrGroups) | ||||||
|  | 	v.dumpToken("CaseTkn", n.CaseTkn) | ||||||
|  | 	v.dumpVertex("Name", n.Name) | ||||||
|  | 	v.dumpToken("EqualTkn", n.EqualTkn) | ||||||
|  | 	v.dumpVertex("Expr", n.Expr) | ||||||
|  | 	v.dumpToken("SemiColonTkn", n.SemiColonTkn) | ||||||
|  | 
 | ||||||
|  | 	v.indent-- | ||||||
|  | 	v.print(v.indent, "},\n") | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (v *Dumper) StmtClass(n *ast.StmtClass) { | func (v *Dumper) StmtClass(n *ast.StmtClass) { | ||||||
| 	v.print(0, "&ast.StmtClass{\n") | 	v.print(0, "&ast.StmtClass{\n") | ||||||
| 	v.indent++ | 	v.indent++ | ||||||
|  | |||||||
| @ -318,7 +318,65 @@ func (f *formatter) StmtCatch(n *ast.StmtCatch) { | |||||||
| 	n.CloseCurlyBracketTkn = f.newToken('}', []byte("}")) | 	n.CloseCurlyBracketTkn = f.newToken('}', []byte("}")) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (f *formatter) StmtEnum(n *ast.StmtEnum) { | ||||||
|  | 	for _, m := range n.AttrGroups { | ||||||
|  | 		m.Accept(f) | ||||||
|  | 		f.addFreeFloating(token.T_WHITESPACE, []byte(" ")) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	n.EnumTkn = f.newToken(token.T_CLASS, []byte("enum")) | ||||||
|  | 
 | ||||||
|  | 	f.addFreeFloating(token.T_WHITESPACE, []byte(" ")) | ||||||
|  | 	n.Name.Accept(f) | ||||||
|  | 
 | ||||||
|  | 	n.ColonTkn = f.newToken(':', []byte(":")) | ||||||
|  | 	n.Type.Accept(f) | ||||||
|  | 
 | ||||||
|  | 	f.addFreeFloating(token.T_WHITESPACE, []byte(" ")) | ||||||
|  | 
 | ||||||
|  | 	if n.Implements != nil { | ||||||
|  | 		n.ImplementsTkn = f.newToken(token.T_IMPLEMENTS, []byte("implements")) | ||||||
|  | 		n.ImplementsSeparatorTkns = f.formatList(n.Implements, ',') | ||||||
|  | 		f.addFreeFloating(token.T_WHITESPACE, []byte(" ")) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	n.OpenCurlyBracketTkn = f.newToken('{', []byte("{")) | ||||||
|  | 
 | ||||||
|  | 	if len(n.Stmts) > 0 { | ||||||
|  | 		f.indent++ | ||||||
|  | 		f.formatStmts(&n.Stmts) | ||||||
|  | 		f.indent-- | ||||||
|  | 
 | ||||||
|  | 		f.addFreeFloating(token.T_WHITESPACE, []byte("\n")) | ||||||
|  | 		f.addIndent() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	n.CloseCurlyBracketTkn = f.newToken('}', []byte("}")) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (f *formatter) EnumCase(n *ast.EnumCase) { | ||||||
|  | 	for _, m := range n.AttrGroups { | ||||||
|  | 		m.Accept(f) | ||||||
|  | 		f.addFreeFloating(token.T_WHITESPACE, []byte(" ")) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	n.CaseTkn = f.newToken(token.T_CASE, []byte("case")) | ||||||
|  | 
 | ||||||
|  | 	f.addFreeFloating(token.T_WHITESPACE, []byte(" ")) | ||||||
|  | 	n.Name.Accept(f) | ||||||
|  | 
 | ||||||
|  | 	n.EqualTkn = f.newToken('=', []byte("=")) | ||||||
|  | 	n.Expr.Accept(f) | ||||||
|  | 
 | ||||||
|  | 	n.SemiColonTkn = f.newToken(';', []byte(";")) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (f *formatter) StmtClass(n *ast.StmtClass) { | func (f *formatter) StmtClass(n *ast.StmtClass) { | ||||||
|  | 	for _, m := range n.AttrGroups { | ||||||
|  | 		m.Accept(f) | ||||||
|  | 		f.addFreeFloating(token.T_WHITESPACE, []byte(" ")) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	for _, m := range n.Modifiers { | 	for _, m := range n.Modifiers { | ||||||
| 		m.Accept(f) | 		m.Accept(f) | ||||||
| 		f.addFreeFloating(token.T_WHITESPACE, []byte(" ")) | 		f.addFreeFloating(token.T_WHITESPACE, []byte(" ")) | ||||||
|  | |||||||
| @ -70,6 +70,14 @@ func (v *Null) StmtCatch(_ *ast.StmtCatch) { | |||||||
| 	// do nothing | 	// do nothing | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (v *Null) StmtEnum(_ *ast.StmtEnum) { | ||||||
|  | 	// do nothing | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (v *Null) EnumCase(_ *ast.EnumCase) { | ||||||
|  | 	// do nothing | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (v *Null) StmtClass(_ *ast.StmtClass) { | func (v *Null) StmtClass(_ *ast.StmtClass) { | ||||||
| 	// do nothing | 	// do nothing | ||||||
| } | } | ||||||
|  | |||||||
| @ -234,6 +234,28 @@ func (p *printer) StmtClass(n *ast.StmtClass) { | |||||||
| 	p.printToken(n.CloseCurlyBracketTkn, []byte("}")) | 	p.printToken(n.CloseCurlyBracketTkn, []byte("}")) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (p *printer) StmtEnum(n *ast.StmtEnum) { | ||||||
|  | 	p.printList(n.AttrGroups) | ||||||
|  | 	p.printToken(n.EnumTkn, []byte("enum")) | ||||||
|  | 	p.printNode(n.Name) | ||||||
|  | 	p.printToken(n.ColonTkn, nil) | ||||||
|  | 	p.printNode(n.Type) | ||||||
|  | 	p.printToken(n.ImplementsTkn, p.ifNodeList(n.Implements, []byte("implements"))) | ||||||
|  | 	p.printSeparatedList(n.Implements, n.ImplementsSeparatorTkns, []byte(",")) | ||||||
|  | 	p.printToken(n.OpenCurlyBracketTkn, []byte("{")) | ||||||
|  | 	p.printList(n.Stmts) | ||||||
|  | 	p.printToken(n.CloseCurlyBracketTkn, []byte("}")) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (p *printer) EnumCase(n *ast.EnumCase) { | ||||||
|  | 	p.printList(n.AttrGroups) | ||||||
|  | 	p.printToken(n.CaseTkn, []byte("case")) | ||||||
|  | 	p.printNode(n.Name) | ||||||
|  | 	p.printToken(n.EqualTkn, nil) | ||||||
|  | 	p.printNode(n.Expr) | ||||||
|  | 	p.printToken(n.SemiColonTkn, []byte(";")) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (p *printer) StmtClassConstList(n *ast.StmtClassConstList) { | func (p *printer) StmtClassConstList(n *ast.StmtClassConstList) { | ||||||
| 	p.printList(n.AttrGroups) | 	p.printList(n.AttrGroups) | ||||||
| 	p.printList(n.Modifiers) | 	p.printList(n.Modifiers) | ||||||
|  | |||||||
| @ -40,3 +40,37 @@ echo 0o10; | |||||||
| echo 0O10; | echo 0O10; | ||||||
| `) | `) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func TestEnumPHP81(t *testing.T) { | ||||||
|  | 	tester.NewParserPrintTestSuite(t).UsePHP8().Run(`<?php | ||||||
|  | enum A { | ||||||
|  |   case B; | ||||||
|  |   case B = 100; | ||||||
|  |   case C = "aa"; | ||||||
|  |   case  | ||||||
|  | 	D; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | enum A: int { | ||||||
|  |   case B; | ||||||
|  |   case B = 100; | ||||||
|  | 
 | ||||||
|  |   #[Attribute] | ||||||
|  |   case C = 100; | ||||||
|  | 
 | ||||||
|  |   #[Attribute1] | ||||||
|  |   #[Attribute2] | ||||||
|  |   case D; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | enum A implements B { | ||||||
|  |   case C; | ||||||
|  |   public function f(): string {} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | enum A implements B, C, D { | ||||||
|  |   case E; | ||||||
|  |   public function f(): string {} | ||||||
|  | } | ||||||
|  | `) | ||||||
|  | } | ||||||
|  | |||||||
| @ -122,6 +122,33 @@ func (t *Traverser) StmtCatch(n *ast.StmtCatch) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (t *Traverser) StmtEnum(n *ast.StmtEnum) { | ||||||
|  | 	n.Accept(t.v) | ||||||
|  | 
 | ||||||
|  | 	for _, nn := range n.AttrGroups { | ||||||
|  | 		nn.Accept(t) | ||||||
|  | 	} | ||||||
|  | 	t.Traverse(n.Name) | ||||||
|  | 	t.Traverse(n.Type) | ||||||
|  | 
 | ||||||
|  | 	for _, nn := range n.Implements { | ||||||
|  | 		nn.Accept(t) | ||||||
|  | 	} | ||||||
|  | 	for _, nn := range n.Stmts { | ||||||
|  | 		nn.Accept(t) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (t *Traverser) EnumCase(n *ast.EnumCase) { | ||||||
|  | 	n.Accept(t.v) | ||||||
|  | 
 | ||||||
|  | 	for _, nn := range n.AttrGroups { | ||||||
|  | 		nn.Accept(t) | ||||||
|  | 	} | ||||||
|  | 	t.Traverse(n.Name) | ||||||
|  | 	t.Traverse(n.Expr) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (t *Traverser) StmtClass(n *ast.StmtClass) { | func (t *Traverser) StmtClass(n *ast.StmtClass) { | ||||||
| 	n.Accept(t.v) | 	n.Accept(t.v) | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user