@@ -139,7 +139,6 @@ private static boolean invalidPredicateChar(char c) {
139139 return !(Character .isLetterOrDigit (c ) || c == '_' || c == '-' || c == '.' || c == '?' || c == '!' );
140140 }
141141
142- @ SuppressWarnings ("DuplicatedCode" )
143142 private void handlePredicates (String source , MemorySegment query , @ Unsigned int patternCount )
144143 throws QueryError .Predicate {
145144 try (var alloc = Arena .ofConfined ()) {
@@ -149,6 +148,8 @@ private void handlePredicates(String source, MemorySegment query, @Unsigned int
149148 if ((steps = count .get (C_INT , 0 )) == 0 ) continue ;
150149 int offset = ts_query_start_byte_for_pattern (query , i );
151150 long row = source .chars ().limit (offset ).filter (c -> c == '\n' ).count ();
151+ var predicates = this .predicates .get (i );
152+
152153 for (long j = 0 ; j < steps ; ++j ) {
153154 long nargs = 0 ;
154155 for (; ; ++nargs ) {
@@ -160,99 +161,20 @@ private void handlePredicates(String source, MemorySegment query, @Unsigned int
160161 var name = captureNames .get (TSQueryPredicateStep .value_id (t0 ));
161162 throw new QueryError .Predicate (row , "@%s" .formatted (name ));
162163 }
164+
163165 var predicate = stringValues .get (TSQueryPredicateStep .value_id (t0 ));
164166 if (QueryPredicate .Eq .NAMES .contains (predicate )) {
165- if (nargs != 3 ) {
166- var error = "#%s expects 2 arguments, got %d" ;
167- throw new QueryError .Predicate (row , error , predicate , nargs - 1 );
168- }
169- var t1 = TSQueryPredicateStep .asSlice (tokens , 1 );
170- if (TSQueryPredicateStep .type (t1 ) != TSQueryPredicateStepTypeCapture ()) {
171- var value = stringValues .get (TSQueryPredicateStep .value_id (t1 ));
172- var error = "first argument to #%s must be a capture name, got \" %s\" " ;
173- throw new QueryError .Predicate (row , error , predicate , value );
174- }
175- var capture = captureNames .get (TSQueryPredicateStep .value_id (t1 ));
176- var t2 = TSQueryPredicateStep .asSlice (tokens , 2 );
177- var id = TSQueryPredicateStep .value_id (t2 );
178- var isCapture = TSQueryPredicateStep .type (t2 ) == TSQueryPredicateStepTypeCapture ();
179- var value = isCapture ? captureNames .get (id ) : stringValues .get (id );
180- predicates .get (i ).add (new QueryPredicate .Eq (predicate , capture , value , isCapture ));
167+ predicates .add (handlePredicateEq (predicate , tokens , nargs , row ));
181168 } else if (QueryPredicate .Match .NAMES .contains (predicate )) {
182- if (nargs != 3 ) {
183- var error = "#%s expects 2 arguments, got %d" ;
184- throw new QueryError .Predicate (row , error , predicate , nargs - 1 );
185- }
186- var t1 = TSQueryPredicateStep .asSlice (tokens , 1 );
187- if (TSQueryPredicateStep .type (t1 ) != TSQueryPredicateStepTypeCapture ()) {
188- var value = stringValues .get (TSQueryPredicateStep .value_id (t1 ));
189- var error = "first argument to #%s must be a capture name, got \" %s\" " ;
190- throw new QueryError .Predicate (row , error , predicate , value );
191- }
192- var t2 = TSQueryPredicateStep .asSlice (tokens , 2 );
193- if (TSQueryPredicateStep .type (t2 ) != TSQueryPredicateStepTypeString ()) {
194- var value = captureNames .get (TSQueryPredicateStep .value_id (t2 ));
195- var error = "second argument to #%s must be a string literal, got @%s" ;
196- throw new QueryError .Predicate (row , error , predicate , value );
197- }
198- try {
199- var capture = captureNames .get (TSQueryPredicateStep .value_id (t1 ));
200- var pattern = Pattern .compile (stringValues .get (TSQueryPredicateStep .value_id (t2 )));
201- predicates .get (i ).add (new QueryPredicate .Match (predicate , capture , pattern ));
202- } catch (PatternSyntaxException e ) {
203- throw new QueryError .Predicate (row , "pattern error" , e );
204- }
169+ predicates .add (handlePredicateMatch (predicate , tokens , nargs , row ));
205170 } else if (QueryPredicate .AnyOf .NAMES .contains (predicate )) {
206- if (nargs < 3 ) {
207- var error = "#%s expects at least 2 arguments, got %d" ;
208- throw new QueryError .Predicate (row , error , predicate , nargs - 1 );
209- }
210- var t1 = TSQueryPredicateStep .asSlice (tokens , 1 );
211- if (TSQueryPredicateStep .type (t1 ) != TSQueryPredicateStepTypeCapture ()) {
212- var value = stringValues .get (TSQueryPredicateStep .value_id (t1 ));
213- var error = "first argument to #%s must be a capture name, got \" %s\" " ;
214- throw new QueryError .Predicate (row , error , predicate , value );
215- }
216- List <String > values = new ArrayList <>((int ) nargs - 2 );
217- for (long k = 2 ; k < nargs ; ++k ) {
218- var t = TSQueryPredicateStep .asSlice (tokens , k );
219- if (TSQueryPredicateStep .type (t ) != TSQueryPredicateStepTypeString ()) {
220- var value = captureNames .get (TSQueryPredicateStep .value_id (t ));
221- var error = "arguments to #%s must be string literals, got @%s" ;
222- throw new QueryError .Predicate (row , error , predicate , value );
223- }
224- values .add (stringValues .get (TSQueryPredicateStep .value_id (t )));
225- }
226- var capture = captureNames .get (TSQueryPredicateStep .value_id (t1 ));
227- predicates .get (i ).add (new QueryPredicate .AnyOf (predicate , capture , values ));
228- } else if (predicate .equals ("is?" ) || predicate .equals ("is-not?" ) || predicate .equals ("set!" )) {
229- if (nargs == 1 || nargs > 3 ) {
230- var error = "#%s expects 1-2 arguments, got %d" ;
231- throw new QueryError .Predicate (row , error , predicate , nargs - 1 );
232- }
233- var t1 = TSQueryPredicateStep .asSlice (tokens , 1 );
234- if (TSQueryPredicateStep .type (t1 ) != TSQueryPredicateStepTypeString ()) {
235- var value = captureNames .get (TSQueryPredicateStep .value_id (t1 ));
236- var error = "first argument to #%s must be a string literal, got @%s" ;
237- throw new QueryError .Predicate (row , error , predicate , value );
238- }
239- String key = stringValues .get (TSQueryPredicateStep .value_id (t1 )), value = null ;
240- if (nargs == 3 ) {
241- var t2 = TSQueryPredicateStep .asSlice (tokens , 2 );
242- if (TSQueryPredicateStep .type (t2 ) != TSQueryPredicateStepTypeString ()) {
243- var capture = captureNames .get (TSQueryPredicateStep .value_id (t2 ));
244- var error = "second argument to #%s must be a string literal, got @%s" ;
245- throw new QueryError .Predicate (row , error , predicate , capture );
246- }
247- value = stringValues .get (TSQueryPredicateStep .value_id (t2 ));
248- }
249- if (predicate .equals ("is?" )) {
250- positiveAssertions .get (i ).put (key , Optional .ofNullable (value ));
251- } else if (predicate .equals ("is-not?" )) {
252- negativeAssertions .get (i ).put (key , Optional .ofNullable (value ));
253- } else {
254- settings .get (i ).put (key , Optional .ofNullable (value ));
255- }
171+ predicates .add (handlePredicateAnyOf (predicate , tokens , nargs , row ));
172+ } else if (predicate .equals ("is?" ) || predicate .equals ("is-not?" )) {
173+ var assertions = (predicate .equals ("is?" ) ? positiveAssertions : negativeAssertions ).get (i );
174+ handlePredicateAssertion (predicate , tokens , nargs , row , assertions );
175+ } else if (predicate .equals ("set!" )) {
176+ var settings = this .settings .get (i );
177+ handleDirectiveSet (predicate , tokens , nargs , row , settings );
256178 } else {
257179 List <QueryPredicateArg > values = new ArrayList <>((int ) nargs - 1 );
258180 for (long k = 1 ; k < nargs ; ++k ) {
@@ -265,7 +187,7 @@ private void handlePredicates(String source, MemorySegment query, @Unsigned int
265187 values .add (new QueryPredicateArg .Capture (capture ));
266188 }
267189 }
268- predicates .get ( i ). add (new QueryPredicate (predicate , values ));
190+ predicates .add (new QueryPredicate (predicate , values ));
269191 }
270192 j += nargs ;
271193 tokens = TSQueryPredicateStep .asSlice (tokens , nargs + 1 );
@@ -274,6 +196,131 @@ private void handlePredicates(String source, MemorySegment query, @Unsigned int
274196 }
275197 }
276198
199+ /** {@code #eq?} predicate */
200+ private QueryPredicate handlePredicateEq (String name , MemorySegment tokens , long nargs , long row ) {
201+ if (nargs != 3 ) {
202+ var error = "#%s expects 2 arguments, got %d" ;
203+ throw new QueryError .Predicate (row , error , name , nargs - 1 );
204+ }
205+ var t1 = TSQueryPredicateStep .asSlice (tokens , 1 );
206+ if (TSQueryPredicateStep .type (t1 ) != TSQueryPredicateStepTypeCapture ()) {
207+ var value = stringValues .get (TSQueryPredicateStep .value_id (t1 ));
208+ var error = "first argument to #%s must be a capture name, got \" %s\" " ;
209+ throw new QueryError .Predicate (row , error , name , value );
210+ }
211+ var capture = captureNames .get (TSQueryPredicateStep .value_id (t1 ));
212+ var t2 = TSQueryPredicateStep .asSlice (tokens , 2 );
213+ var id = TSQueryPredicateStep .value_id (t2 );
214+ var isCapture = TSQueryPredicateStep .type (t2 ) == TSQueryPredicateStepTypeCapture ();
215+ var value = isCapture ? captureNames .get (id ) : stringValues .get (id );
216+ return new QueryPredicate .Eq (name , capture , value , isCapture );
217+ }
218+
219+ /** {@code #match?} predicate */
220+ private QueryPredicate handlePredicateMatch (String name , MemorySegment tokens , long nargs , long row ) {
221+ if (nargs != 3 ) {
222+ var error = "#%s expects 2 arguments, got %d" ;
223+ throw new QueryError .Predicate (row , error , name , nargs - 1 );
224+ }
225+ var t1 = TSQueryPredicateStep .asSlice (tokens , 1 );
226+ if (TSQueryPredicateStep .type (t1 ) != TSQueryPredicateStepTypeCapture ()) {
227+ var value = stringValues .get (TSQueryPredicateStep .value_id (t1 ));
228+ var error = "first argument to #%s must be a capture name, got \" %s\" " ;
229+ throw new QueryError .Predicate (row , error , name , value );
230+ }
231+ var t2 = TSQueryPredicateStep .asSlice (tokens , 2 );
232+ if (TSQueryPredicateStep .type (t2 ) != TSQueryPredicateStepTypeString ()) {
233+ var value = captureNames .get (TSQueryPredicateStep .value_id (t2 ));
234+ var error = "second argument to #%s must be a string literal, got @%s" ;
235+ throw new QueryError .Predicate (row , error , name , value );
236+ }
237+ try {
238+ var capture = captureNames .get (TSQueryPredicateStep .value_id (t1 ));
239+ var pattern = Pattern .compile (stringValues .get (TSQueryPredicateStep .value_id (t2 )));
240+ return new QueryPredicate .Match (name , capture , pattern );
241+ } catch (PatternSyntaxException e ) {
242+ throw new QueryError .Predicate (row , "pattern error" , e );
243+ }
244+ }
245+
246+ /** {@code #any-of?} predicate */
247+ private QueryPredicate handlePredicateAnyOf (String name , MemorySegment tokens , long nargs , long row ) {
248+ if (nargs < 3 ) {
249+ var error = "#%s expects at least 2 arguments, got %d" ;
250+ throw new QueryError .Predicate (row , error , name , nargs - 1 );
251+ }
252+ var t1 = TSQueryPredicateStep .asSlice (tokens , 1 );
253+ if (TSQueryPredicateStep .type (t1 ) != TSQueryPredicateStepTypeCapture ()) {
254+ var value = stringValues .get (TSQueryPredicateStep .value_id (t1 ));
255+ var error = "first argument to #%s must be a capture name, got \" %s\" " ;
256+ throw new QueryError .Predicate (row , error , name , value );
257+ }
258+ List <String > values = new ArrayList <>((int ) nargs - 2 );
259+ for (long k = 2 ; k < nargs ; ++k ) {
260+ var t = TSQueryPredicateStep .asSlice (tokens , k );
261+ if (TSQueryPredicateStep .type (t ) != TSQueryPredicateStepTypeString ()) {
262+ var value = captureNames .get (TSQueryPredicateStep .value_id (t ));
263+ var error = "arguments to #%s must be string literals, got @%s" ;
264+ throw new QueryError .Predicate (row , error , name , value );
265+ }
266+ values .add (stringValues .get (TSQueryPredicateStep .value_id (t )));
267+ }
268+ var capture = captureNames .get (TSQueryPredicateStep .value_id (t1 ));
269+ return new QueryPredicate .AnyOf (name , capture , values );
270+ }
271+
272+ /** {@code #is?} predicate */
273+ private void handlePredicateAssertion (
274+ String name , MemorySegment tokens , long nargs , long row , Map <String , Optional <String >> assertions ) {
275+ if (nargs == 1 || nargs > 3 ) {
276+ var error = "#%s expects 1-2 arguments, got %d" ;
277+ throw new QueryError .Predicate (row , error , name , nargs - 1 );
278+ }
279+ var t1 = TSQueryPredicateStep .asSlice (tokens , 1 );
280+ if (TSQueryPredicateStep .type (t1 ) != TSQueryPredicateStepTypeString ()) {
281+ var value = captureNames .get (TSQueryPredicateStep .value_id (t1 ));
282+ var error = "first argument to #%s must be a string literal, got @%s" ;
283+ throw new QueryError .Predicate (row , error , name , value );
284+ }
285+ String key = stringValues .get (TSQueryPredicateStep .value_id (t1 )), value = null ;
286+ if (nargs == 3 ) {
287+ var t2 = TSQueryPredicateStep .asSlice (tokens , 2 );
288+ if (TSQueryPredicateStep .type (t2 ) != TSQueryPredicateStepTypeString ()) {
289+ var capture = captureNames .get (TSQueryPredicateStep .value_id (t2 ));
290+ var error = "second argument to #%s must be a string literal, got @%s" ;
291+ throw new QueryError .Predicate (row , error , name , capture );
292+ }
293+ value = stringValues .get (TSQueryPredicateStep .value_id (t2 ));
294+ }
295+ assertions .put (key , Optional .ofNullable (value ));
296+ }
297+
298+ /** {@code #set!} directive */
299+ private void handleDirectiveSet (
300+ String name , MemorySegment tokens , long nargs , long row , Map <String , Optional <String >> settings ) {
301+ if (nargs == 1 || nargs > 3 ) {
302+ var error = "#%s expects 1-2 arguments, got %d" ;
303+ throw new QueryError .Predicate (row , error , name , nargs - 1 );
304+ }
305+ var t1 = TSQueryPredicateStep .asSlice (tokens , 1 );
306+ if (TSQueryPredicateStep .type (t1 ) != TSQueryPredicateStepTypeString ()) {
307+ var value = captureNames .get (TSQueryPredicateStep .value_id (t1 ));
308+ var error = "first argument to #%s must be a string literal, got @%s" ;
309+ throw new QueryError .Predicate (row , error , name , value );
310+ }
311+ String key = stringValues .get (TSQueryPredicateStep .value_id (t1 )), value = null ;
312+ if (nargs == 3 ) {
313+ var t2 = TSQueryPredicateStep .asSlice (tokens , 2 );
314+ if (TSQueryPredicateStep .type (t2 ) != TSQueryPredicateStepTypeString ()) {
315+ var capture = captureNames .get (TSQueryPredicateStep .value_id (t2 ));
316+ var error = "second argument to #%s must be a string literal, got @%s" ;
317+ throw new QueryError .Predicate (row , error , name , capture );
318+ }
319+ value = stringValues .get (TSQueryPredicateStep .value_id (t2 ));
320+ }
321+ settings .put (key , Optional .ofNullable (value ));
322+ }
323+
277324 MemorySegment segment () {
278325 return self ;
279326 }
0 commit comments