11package io .cucumber .cucumberexpressions ;
22
3- import java .util .List ;
3+ import org .jspecify .annotations .Nullable ;
4+
45import java .util .Objects ;
56import java .util .StringJoiner ;
67
7- import static java .util .Arrays .asList ;
88import static java .util .Objects .requireNonNull ;
9- import static java .util .stream .Collectors .joining ;
109
1110final class Ast {
1211
13- private static final char escapeCharacter = '\\' ;
14- private static final char alternationCharacter = '/' ;
15- private static final char beginParameterCharacter = '{' ;
16- private static final char endParameterCharacter = '}' ;
17- private static final char beginOptionalCharacter = '(' ;
18- private static final char endOptionalCharacter = ')' ;
19-
2012 interface Located {
2113 int start ();
2214
2315 int end ();
2416
2517 }
2618
27- static final class Node implements Located {
28-
29- private final Type type ;
30- private final List <Node > nodes ;
31- private final String token ;
32- private final int start ;
33- private final int end ;
34-
35- Node (Type type , int start , int end , String token ) {
36- this (type , start , end , null , token );
37- }
38-
39- Node (Type type , int start , int end , List <Node > nodes ) {
40- this (type , start , end , nodes , null );
41- }
42-
43- private Node (Type type , int start , int end , List <Node > nodes , String token ) {
44- this .type = requireNonNull (type );
45- this .nodes = nodes ;
46- this .token = token ;
47- this .start = start ;
48- this .end = end ;
49- }
50-
51- enum Type {
52- TEXT_NODE ,
53- OPTIONAL_NODE ,
54- ALTERNATION_NODE ,
55- ALTERNATIVE_NODE ,
56- PARAMETER_NODE ,
57- EXPRESSION_NODE
58- }
59-
60- public int start () {
61- return start ;
62- }
63-
64- public int end () {
65- return end ;
66- }
67-
68- List <Node > nodes () {
69- return nodes ;
70- }
71-
72- Type type () {
73- return type ;
74- }
75-
76- String text () {
77- if (nodes == null )
78- return token ;
79-
80- return nodes ().stream ()
81- .map (Node ::text )
82- .collect (joining ());
83- }
84-
85- @ Override
86- public String toString () {
87- return toString (0 ).toString ();
88- }
89-
90- private StringBuilder toString (int depth ) {
91- StringBuilder sb = new StringBuilder ();
92- for (int i = 0 ; i < depth ; i ++) {
93- sb .append (" " );
94- }
95- sb .append ("{" )
96- .append ("\" type\" : \" " ).append (type )
97- .append ("\" , \" start\" : " )
98- .append (start )
99- .append (", \" end\" : " )
100- .append (end );
101-
102- if (token != null ) {
103- sb .append (", \" token\" : \" " ).append (token .replaceAll ("\\ \\ " , "\\ \\ \\ \\ " )).append ("\" " );
104- }
105-
106- if (nodes != null ) {
107- sb .append (", \" nodes\" : " );
108- if (!nodes .isEmpty ()) {
109- StringBuilder padding = new StringBuilder ();
110- for (int i = 0 ; i < depth ; i ++) {
111- padding .append (" " );
112- }
113- sb .append (nodes .stream ()
114- .map (node -> node .toString (depth + 1 ))
115- .collect (joining (",\n " , "[\n " , "\n " +padding + "]" )));
116-
117- } else {
118- sb .append ("[]" );
119- }
120- }
121- sb .append ("}" );
122- return sb ;
123- }
124-
125- @ Override
126- public boolean equals (Object o ) {
127- if (this == o )
128- return true ;
129- if (o == null || getClass () != o .getClass ())
130- return false ;
131- Node node = (Node ) o ;
132- return start == node .start &&
133- end == node .end &&
134- type == node .type &&
135- Objects .equals (nodes , node .nodes ) &&
136- Objects .equals (token , node .token );
137- }
138-
139- @ Override
140- public int hashCode () {
141- return Objects .hash (type , nodes , token , start , end );
142- }
143-
144- }
145-
14619 static final class Token implements Located {
14720
21+ private static final char escapeCharacter = '\\' ;
22+ private static final char alternationCharacter = '/' ;
23+ private static final char beginParameterCharacter = '{' ;
24+ private static final char endParameterCharacter = '}' ;
25+ private static final char beginOptionalCharacter = '(' ;
26+ private static final char endOptionalCharacter = ')' ;
27+
14828 final String text ;
149- final Token . Type type ;
29+ final Type type ;
15030 final int start ;
15131 final int end ;
15232
153- Token (String text , Token . Type type , int start , int end ) {
33+ Token (String text , Type type , int start , int end ) {
15434 this .text = requireNonNull (text );
15535 this .type = requireNonNull (type );
15636 this .start = start ;
@@ -161,45 +41,41 @@ static boolean canEscape(Integer token) {
16141 if (Character .isWhitespace (token )) {
16242 return true ;
16343 }
164- switch (token ) {
165- case (int ) escapeCharacter :
166- case (int ) alternationCharacter :
167- case (int ) beginParameterCharacter :
168- case (int ) endParameterCharacter :
169- case (int ) beginOptionalCharacter :
170- case (int ) endOptionalCharacter :
171- return true ;
172- }
173- return false ;
44+ return switch (token ) {
45+ case (int ) escapeCharacter ,
46+ (int ) alternationCharacter ,
47+ (int ) beginParameterCharacter ,
48+ (int ) endParameterCharacter ,
49+ (int ) beginOptionalCharacter ,
50+ (int ) endOptionalCharacter -> true ;
51+ default -> false ;
52+ };
17453 }
17554
17655 static Type typeOf (Integer token ) {
17756 if (Character .isWhitespace (token )) {
17857 return Type .WHITE_SPACE ;
17958 }
180- switch (token ) {
181- case (int ) alternationCharacter :
182- return Type .ALTERNATION ;
183- case (int ) beginParameterCharacter :
184- return Type .BEGIN_PARAMETER ;
185- case (int ) endParameterCharacter :
186- return Type .END_PARAMETER ;
187- case (int ) beginOptionalCharacter :
188- return Type .BEGIN_OPTIONAL ;
189- case (int ) endOptionalCharacter :
190- return Type .END_OPTIONAL ;
191- }
192- return Type .TEXT ;
59+ return switch (token ) {
60+ case (int ) alternationCharacter -> Type .ALTERNATION ;
61+ case (int ) beginParameterCharacter -> Type .BEGIN_PARAMETER ;
62+ case (int ) endParameterCharacter -> Type .END_PARAMETER ;
63+ case (int ) beginOptionalCharacter -> Type .BEGIN_OPTIONAL ;
64+ case (int ) endOptionalCharacter -> Type .END_OPTIONAL ;
65+ default -> Type .TEXT ;
66+ };
19367 }
19468
19569 static boolean isEscapeCharacter (int token ) {
19670 return token == escapeCharacter ;
19771 }
19872
73+ @ Override
19974 public int start () {
20075 return start ;
20176 }
20277
78+ @ Override
20379 public int end () {
20480 return end ;
20581 }
@@ -224,10 +100,10 @@ public int hashCode() {
224100
225101 @ Override
226102 public String toString () {
227- return new StringJoiner (", " , "" + " {" , "}" )
103+ return new StringJoiner (", " , "{" , "}" )
228104 .add ("\" type\" : \" " + type + "\" " )
229- .add ("\" start\" : " + start + "" )
230- .add ("\" end\" : " + end + "" )
105+ .add ("\" start\" : " + start )
106+ .add ("\" end\" : " + end )
231107 .add ("\" text\" : \" " + text + "\" " )
232108 .toString ();
233109 }
@@ -243,14 +119,14 @@ enum Type {
243119 ALTERNATION ("" + alternationCharacter , "alternation" ),
244120 TEXT ;
245121
246- private final String symbol ;
247- private final String purpose ;
122+ private final @ Nullable String symbol ;
123+ private final @ Nullable String purpose ;
248124
249125 Type () {
250126 this (null , null );
251127 }
252128
253- Type (String symbol , String purpose ) {
129+ Type (@ Nullable String symbol , @ Nullable String purpose ) {
254130 this .symbol = symbol ;
255131 this .purpose = purpose ;
256132 }
0 commit comments