Split lines with many copyright years
[gromacs.git] / src / gromacs / selection / parser.y
blob064f46e8a644e3dd954293692c6141071c5bc3cf
1 %code requires {
2 /*
3 * This file is part of the GROMACS molecular simulation package.
5 * Copyright (c) 2009,2010,2011,2012,2013 by the GROMACS development team.
6 * Copyright (c) 2014,2015,2016,2020, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
38 /*! \internal \file
39 * \brief Grammar description and parser for the selection language.
41 * \author Teemu Murtola <teemu.murtola@gmail.com>
42 * \ingroup module_selection
44 %code top {
45 /*! \internal \file parser.cpp
46 * \brief Generated (from parser.y by Bison) parser for the selection language.
48 * \ingroup module_selection
50 /*! \internal \file parser.h
51 * \brief Generated (from parser.y by Bison) parser include file.
53 * \ingroup module_selection
55 #include "gmxpre.h"
58 #include "gromacs/utility/unique_cptr.h"
60 #include "parser_internal.h"
62 using gmx::sfree_guard;
63 using gmx::SelectionParserValue;
64 using gmx::SelectionParserValueList;
65 using gmx::SelectionParserValueListPointer;
66 using gmx::SelectionParserParameter;
67 using gmx::SelectionParserParameterList;
68 using gmx::SelectionParserParameterListPointer;
69 using gmx::SelectionTreeElement;
70 using gmx::SelectionTreeElementPointer;
72 #ifdef _MSC_VER
73 #pragma warning(disable: 4065)
74 #endif
77 %code requires{
78 #include "parsetree.h"
79 #include "selelem.h"
81 #define YYLTYPE ::gmx::SelectionLocation
84 %union{
85 int i;
86 real r;
87 char *str;
88 struct gmx_ana_selmethod_t *meth;
90 gmx::SelectionStringMatchType smt;
92 gmx::SelectionTreeElementPointer *sel;
93 gmx::SelectionParserValue *val;
94 gmx::SelectionParserValueListPointer *vlist;
95 gmx::SelectionParserParameter *param;
96 gmx::SelectionParserParameterListPointer *plist;
99 /* Invalid token to report lexer errors */
100 %token INVALID
102 /* Simple input tokens */
103 %token <i> TOK_INT
104 %token <r> TOK_REAL
105 %token <str> STR
106 %token <str> IDENTIFIER
107 %token CMD_SEP
109 /* Simple keyword tokens */
110 %token GROUP
111 %token TO
113 /* Variable tokens */
114 %token <sel> VARIABLE_NUMERIC
115 %token <sel> VARIABLE_GROUP
116 %token <sel> VARIABLE_POS
118 /* Selection method tokens */
119 %token <meth> KEYWORD_NUMERIC
120 %token <meth> KEYWORD_STR
121 %token <str> KEYWORD_POS
122 %token <meth> KEYWORD_GROUP
123 %token <meth> METHOD_NUMERIC
124 %token <meth> METHOD_GROUP
125 %token <meth> METHOD_POS
126 %token <meth> MODIFIER
127 /* Empty token that should precede any non-position KEYWORD/METHOD token that
128 * is not preceded by KEYWORD_POS. This is used to work around reduce/reduce
129 * conflicts that appear when a lookahead token would require a reduction of
130 * a rule with empty RHS before shifting, and there is an alternative reduction
131 * available. Replacing the empty RHS with a dummy token makes these conflicts
132 * only shift/reduce conflicts. Another alternative would be to remove the
133 * pos_mod non-terminal completely and split each rule that uses it into two,
134 * but this would require duplicating six rules in the grammar. */
135 %token EMPTY_POSMOD
137 %token <str> PARAM
138 %token END_OF_METHOD
140 %token OF
141 /* Comparison operators have lower precedence than parameter reduction
142 * to make it possible to parse, e.g., "mindist from resnr 1 < 2" without
143 * parenthesis. */
144 %nonassoc <str> CMP_OP
145 /* A dummy token that determines the precedence of parameter reduction */
146 %nonassoc PARAM_REDUCT
147 /* Boolean operator tokens */
148 %left OR XOR
149 %left AND
150 %left NOT
151 /* Arithmetic operator tokens */
152 %left '+' '-'
153 %left '*' '/'
154 %right UNARY_NEG /* Dummy token for unary negation precedence */
155 %right '^'
156 %nonassoc NUM_REDUCT /* Dummy token for numerical keyword reduction precedence */
158 /* Simple non-terminals */
159 %type <i> integer_number
160 %type <r> real_number number
161 %type <str> string
162 %type <str> pos_mod
163 %type <smt> str_match_type
165 /* Expression non-terminals */
166 %type <sel> commands command cmd_plain
167 %type <sel> selection
168 %type <sel> sel_expr
169 %type <sel> num_expr
170 %type <sel> str_expr
171 %type <sel> pos_expr
173 /* Parameter/value non-terminals */
174 %type <plist> method_params method_param_list
175 %type <param> method_param
176 %type <vlist> value_list value_list_contents basic_value_list basic_value_list_contents
177 %type <val> value_item value_item_range basic_value_item
179 %destructor { free($$); } STR IDENTIFIER KEYWORD_POS CMP_OP string
180 %destructor { if($$) free($$); } PARAM pos_mod
181 %destructor { delete $$; } commands command cmd_plain selection
182 %destructor { delete $$; } sel_expr num_expr str_expr pos_expr
183 %destructor { delete $$; } method_params method_param_list method_param
184 %destructor { delete $$; } value_list value_list_contents basic_value_list basic_value_list_contents
185 %destructor { delete $$; } value_item value_item_range basic_value_item
187 %expect 35
188 %debug
189 %pure-parser
190 %define api.push-pull push
191 %locations
193 %name-prefix "_gmx_sel_yy"
194 %parse-param { void *scanner }
198 /* The start rule: allow one or more commands */
199 commands: /* empty */
201 BEGIN_ACTION;
202 set_empty($$);
203 END_ACTION_TOPLEVEL;
205 | commands command
207 BEGIN_ACTION;
208 set($$, _gmx_sel_append_selection(get($2), get($1), scanner));
209 if (_gmx_sel_parser_should_finish(scanner)) {
210 delete $$;
211 YYACCEPT;
213 END_ACTION_TOPLEVEL;
217 /* A command is formed from an actual command and a separator */
218 command: cmd_plain CMD_SEP { $$ = $1; }
219 | error CMD_SEP
221 BEGIN_ACTION;
222 _gmx_sel_lexer_clear_method_stack(scanner);
223 if (_gmx_selparser_handle_error(scanner))
225 yyerrok;
227 else
229 YYABORT;
231 _gmx_sel_lexer_clear_pselstr(scanner);
232 set_empty($$);
233 END_ACTION_TOPLEVEL;
237 /* Commands can be selections or variable assignments */
238 cmd_plain: /* empty */
240 BEGIN_ACTION;
241 set_empty($$);
242 END_ACTION;
244 | TOK_INT
246 BEGIN_ACTION;
247 SelectionTreeElementPointer s
248 = _gmx_sel_init_group_by_id($1, scanner);
249 SelectionTreeElementPointer p
250 = _gmx_sel_init_position(s, NULL, scanner);
251 if (!p) YYERROR;
252 set($$, _gmx_sel_init_selection(NULL, p, scanner));
253 END_ACTION;
255 | string
257 BEGIN_ACTION;
258 const sfree_guard nameGuard($1);
259 SelectionTreeElementPointer s
260 = _gmx_sel_init_group_by_name($1, scanner);
261 SelectionTreeElementPointer p
262 = _gmx_sel_init_position(s, NULL, scanner);
263 if (!p) YYERROR;
264 set($$, _gmx_sel_init_selection(NULL, p, scanner));
265 END_ACTION;
267 | selection
269 BEGIN_ACTION;
270 set($$, _gmx_sel_init_selection(NULL, get($1), scanner));
271 END_ACTION;
273 | STR selection
275 BEGIN_ACTION;
276 const sfree_guard nameGuard($1);
277 set($$, _gmx_sel_init_selection($1, get($2), scanner));
278 END_ACTION;
280 | IDENTIFIER '=' sel_expr
282 BEGIN_ACTION;
283 const sfree_guard nameGuard($1);
284 set($$, _gmx_sel_assign_variable($1, get($3), scanner));
285 END_ACTION;
287 | IDENTIFIER '=' num_expr
289 BEGIN_ACTION;
290 const sfree_guard nameGuard($1);
291 set($$, _gmx_sel_assign_variable($1, get($3), scanner));
292 END_ACTION;
294 | IDENTIFIER '=' pos_expr
296 BEGIN_ACTION;
297 const sfree_guard nameGuard($1);
298 set($$, _gmx_sel_assign_variable($1, get($3), scanner));
299 END_ACTION;
303 /* Selection is made of an expression and zero or more modifiers */
304 selection: pos_expr { $$ = $1; }
305 | sel_expr
307 BEGIN_ACTION;
308 set($$, _gmx_sel_init_position(get($1), NULL, scanner));
309 CHECK_SEL($$);
310 END_ACTION;
312 | '(' selection ')' { $$ = $2; }
313 | selection MODIFIER method_params
315 BEGIN_ACTION;
316 set($$, _gmx_sel_init_modifier($2, get($3), get($1), scanner));
317 CHECK_SEL($$);
318 END_ACTION;
322 /********************************************************************
323 * BASIC NON-TERMINAL SYMBOLS
324 ********************************************************************/
326 integer_number:
327 TOK_INT { $$ = $1; }
328 | '-' TOK_INT { $$ = -$2; }
331 real_number:
332 TOK_REAL { $$ = $1; }
333 | '-' TOK_REAL { $$ = -$2; }
336 number: integer_number { $$ = $1; }
337 | real_number { $$ = $1; }
340 string: STR { $$ = $1; }
341 | IDENTIFIER { $$ = $1; }
344 /********************************************************************
345 * ATOM SELECTION EXPRESSIONS
346 ********************************************************************/
348 /* Boolean expressions and grouping */
349 sel_expr: NOT sel_expr
351 BEGIN_ACTION;
352 SelectionTreeElementPointer arg(get($2));
353 SelectionTreeElementPointer sel(
354 new SelectionTreeElement(SEL_BOOLEAN, @$));
355 sel->u.boolt = BOOL_NOT;
356 sel->child = arg;
357 set($$, sel);
358 END_ACTION;
360 | sel_expr AND sel_expr
362 BEGIN_ACTION;
363 SelectionTreeElementPointer arg1(get($1)), arg2(get($3));
364 SelectionTreeElementPointer sel(
365 new SelectionTreeElement(SEL_BOOLEAN, @$));
366 sel->u.boolt = BOOL_AND;
367 sel->child = arg1; sel->child->next = arg2;
368 set($$, sel);
369 END_ACTION;
371 | sel_expr OR sel_expr
373 BEGIN_ACTION;
374 SelectionTreeElementPointer arg1(get($1)), arg2(get($3));
375 SelectionTreeElementPointer sel(
376 new SelectionTreeElement(SEL_BOOLEAN, @$));
377 sel->u.boolt = BOOL_OR;
378 sel->child = arg1; sel->child->next = arg2;
379 set($$, sel);
380 END_ACTION;
382 | '(' sel_expr ')' { $$ = $2; }
385 /* Numeric comparisons */
386 sel_expr: num_expr CMP_OP num_expr
388 BEGIN_ACTION;
389 const sfree_guard opGuard($2);
390 set($$, _gmx_sel_init_comparison(get($1), get($3), $2, scanner));
391 CHECK_SEL($$);
392 END_ACTION;
396 /* External groups */
397 sel_expr: GROUP string
399 BEGIN_ACTION;
400 const sfree_guard nameGuard($2);
401 set($$, _gmx_sel_init_group_by_name($2, scanner));
402 END_ACTION;
404 | GROUP TOK_INT
406 BEGIN_ACTION;
407 set($$, _gmx_sel_init_group_by_id($2, scanner));
408 END_ACTION;
412 /* Position modifiers for selection methods */
413 pos_mod: EMPTY_POSMOD { $$ = NULL; }
414 | KEYWORD_POS { $$ = $1; }
417 /* Matching mode forcing for keyword matching */
418 str_match_type:
419 '~' { $$ = gmx::eStringMatchType_RegularExpression; }
420 | '?' { $$ = gmx::eStringMatchType_Wildcard; }
421 | '=' { $$ = gmx::eStringMatchType_Exact; }
424 /* Keyword selections */
425 sel_expr: pos_mod KEYWORD_GROUP
427 BEGIN_ACTION;
428 const sfree_guard posmodGuard($1);
429 set($$, _gmx_sel_init_keyword($2, SelectionParserValueListPointer(), $1, scanner));
430 CHECK_SEL($$);
431 END_ACTION;
433 | pos_mod KEYWORD_STR basic_value_list
435 BEGIN_ACTION;
436 const sfree_guard posmodGuard($1);
437 set($$, _gmx_sel_init_keyword_strmatch($2, gmx::eStringMatchType_Auto, get($3), $1, scanner));
438 CHECK_SEL($$);
439 END_ACTION;
441 | pos_mod KEYWORD_STR str_match_type basic_value_list
443 BEGIN_ACTION;
444 const sfree_guard posmodGuard($1);
445 set($$, _gmx_sel_init_keyword_strmatch($2, $3, get($4), $1, scanner));
446 CHECK_SEL($$);
447 END_ACTION;
449 | pos_mod KEYWORD_NUMERIC basic_value_list
451 BEGIN_ACTION;
452 const sfree_guard posmodGuard($1);
453 set($$, _gmx_sel_init_keyword($2, get($3), $1, scanner));
454 CHECK_SEL($$);
455 END_ACTION;
459 /* Custom selection methods */
460 sel_expr: pos_mod METHOD_GROUP method_params
462 BEGIN_ACTION;
463 const sfree_guard posmodGuard($1);
464 set($$, _gmx_sel_init_method($2, get($3), $1, scanner));
465 CHECK_SEL($$);
466 END_ACTION;
470 /********************************************************************
471 * NUMERICAL EXPRESSIONS
472 ********************************************************************/
474 /* Basic numerical values */
475 num_expr: TOK_INT
477 BEGIN_ACTION;
478 SelectionTreeElementPointer sel(
479 new SelectionTreeElement(SEL_CONST, @$));
480 _gmx_selelem_set_vtype(sel, INT_VALUE);
481 _gmx_selvalue_reserve(&sel->v, 1);
482 sel->v.u.i[0] = $1;
483 set($$, sel);
484 END_ACTION;
486 | TOK_REAL
488 BEGIN_ACTION;
489 SelectionTreeElementPointer sel(
490 new SelectionTreeElement(SEL_CONST, @$));
491 _gmx_selelem_set_vtype(sel, REAL_VALUE);
492 _gmx_selvalue_reserve(&sel->v, 1);
493 sel->v.u.r[0] = $1;
494 set($$, sel);
495 END_ACTION;
499 /* Numeric selection methods */
500 num_expr: pos_mod KEYWORD_NUMERIC %prec NUM_REDUCT
502 BEGIN_ACTION;
503 const sfree_guard posmodGuard($1);
504 set($$, _gmx_sel_init_keyword($2, SelectionParserValueListPointer(), $1, scanner));
505 CHECK_SEL($$);
506 END_ACTION;
508 | pos_mod KEYWORD_NUMERIC OF pos_expr
510 BEGIN_ACTION;
511 const sfree_guard posmodGuard($1);
512 set($$, _gmx_sel_init_keyword_of($2, get($4), $1, scanner));
513 CHECK_SEL($$);
514 END_ACTION;
516 | pos_mod METHOD_NUMERIC method_params
518 BEGIN_ACTION;
519 const sfree_guard posmodGuard($1);
520 set($$, _gmx_sel_init_method($2, get($3), $1, scanner));
521 CHECK_SEL($$);
522 END_ACTION;
526 /* Arithmetic evaluation and grouping */
527 num_expr: num_expr '+' num_expr
529 BEGIN_ACTION;
530 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '+', scanner));
531 END_ACTION;
533 | num_expr '-' num_expr
535 BEGIN_ACTION;
536 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '-', scanner));
537 END_ACTION;
539 | num_expr '*' num_expr
541 BEGIN_ACTION;
542 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '*', scanner));
543 END_ACTION;
545 | num_expr '/' num_expr
547 BEGIN_ACTION;
548 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '/', scanner));
549 END_ACTION;
551 | '-' num_expr %prec UNARY_NEG
553 BEGIN_ACTION;
554 set($$, _gmx_sel_init_arithmetic(get($2), SelectionTreeElementPointer(), '-', scanner));
555 END_ACTION;
557 | num_expr '^' num_expr
559 BEGIN_ACTION;
560 set($$, _gmx_sel_init_arithmetic(get($1), get($3), '^', scanner));
561 END_ACTION;
563 | '(' num_expr ')' { $$ = $2; }
566 /********************************************************************
567 * STRING EXPRESSIONS
568 ********************************************************************/
570 str_expr: string
572 BEGIN_ACTION;
573 SelectionTreeElementPointer sel(
574 new SelectionTreeElement(SEL_CONST, @$));
575 _gmx_selelem_set_vtype(sel, STR_VALUE);
576 _gmx_selvalue_reserve(&sel->v, 1);
577 sel->v.u.s[0] = $1;
578 set($$, sel);
579 END_ACTION;
581 | pos_mod KEYWORD_STR
583 BEGIN_ACTION;
584 const sfree_guard posmodGuard($1);
585 set($$, _gmx_sel_init_keyword($2, SelectionParserValueListPointer(), $1, scanner));
586 CHECK_SEL($$);
587 END_ACTION;
591 /********************************************************************
592 * POSITION EXPRESSIONS
593 ********************************************************************/
595 /* Constant position expressions */
596 pos_expr: '[' number ',' number ',' number ']'
598 BEGIN_ACTION;
599 set($$, _gmx_sel_init_const_position($2, $4, $6, scanner));
600 END_ACTION;
604 /* Grouping of position expressions */
605 pos_expr: '(' pos_expr ')' { $$ = $2; }
608 /* Expressions with a position value */
609 pos_expr: METHOD_POS method_params
611 BEGIN_ACTION;
612 set($$, _gmx_sel_init_method($1, get($2), NULL, scanner));
613 CHECK_SEL($$);
614 END_ACTION;
618 /* Evaluation of positions using a keyword */
619 pos_expr: KEYWORD_POS OF sel_expr %prec PARAM_REDUCT
621 BEGIN_ACTION;
622 const sfree_guard keywordGuard($1);
623 set($$, _gmx_sel_init_position(get($3), $1, scanner));
624 CHECK_SEL($$);
625 END_ACTION;
629 /********************************************************************
630 * VARIABLES
631 ********************************************************************/
633 sel_expr: VARIABLE_GROUP
635 BEGIN_ACTION;
636 set($$, _gmx_sel_init_variable_ref(get($1), scanner));
637 END_ACTION;
641 num_expr: VARIABLE_NUMERIC
643 BEGIN_ACTION;
644 set($$, _gmx_sel_init_variable_ref(get($1), scanner));
645 END_ACTION;
649 pos_expr: VARIABLE_POS
651 BEGIN_ACTION;
652 set($$, _gmx_sel_init_variable_ref(get($1), scanner));
653 END_ACTION;
657 /********************************************************************
658 * METHOD PARAMETERS
659 ********************************************************************/
661 method_params:
662 method_param_list
663 { $$ = $1; }
664 | method_param_list END_OF_METHOD
665 { $$ = $1; }
668 method_param_list:
669 /* empty */
671 BEGIN_ACTION;
672 set($$, SelectionParserParameter::createList());
673 END_ACTION;
675 | method_param_list method_param
677 BEGIN_ACTION;
678 SelectionParserParameterListPointer list(get($1));
679 list->push_back(get($2));
680 set($$, std::move(list));
681 END_ACTION;
685 method_param:
686 PARAM value_list
688 BEGIN_ACTION;
689 const sfree_guard nameGuard($1);
690 set($$, SelectionParserParameter::create($1, get($2), @$));
691 END_ACTION;
695 value_list: value_list_contents { $$ = $1; }
696 | '{' value_list_contents '}' { $$ = $2; }
699 value_list_contents:
700 /* empty */
702 BEGIN_ACTION;
703 set($$, SelectionParserValue::createList());
704 END_ACTION;
706 | value_list_contents value_item
708 BEGIN_ACTION;
709 SelectionParserValueListPointer list(get($1));
710 list->push_back(get($2));
711 set($$, std::move(list));
712 END_ACTION;
714 | value_list_contents ',' value_item
716 BEGIN_ACTION;
717 SelectionParserValueListPointer list(get($1));
718 list->push_back(get($3));
719 set($$, std::move(list));
720 END_ACTION;
724 basic_value_list:
725 basic_value_list_contents { $$ = $1; }
726 | '{' basic_value_list_contents '}' { $$ = $2; }
729 basic_value_list_contents:
730 basic_value_item
732 BEGIN_ACTION;
733 set($$, SelectionParserValue::createList(get($1)));
734 END_ACTION;
736 | basic_value_list_contents basic_value_item
738 BEGIN_ACTION;
739 SelectionParserValueListPointer list(get($1));
740 list->push_back(get($2));
741 set($$, std::move(list));
742 END_ACTION;
744 | basic_value_list_contents ',' basic_value_item
746 BEGIN_ACTION;
747 SelectionParserValueListPointer list(get($1));
748 list->push_back(get($3));
749 set($$, std::move(list));
750 END_ACTION;
754 value_item: sel_expr %prec PARAM_REDUCT
756 BEGIN_ACTION;
757 set($$, SelectionParserValue::createExpr(get($1)));
758 END_ACTION;
760 | pos_expr %prec PARAM_REDUCT
762 BEGIN_ACTION;
763 set($$, SelectionParserValue::createExpr(get($1)));
764 END_ACTION;
766 | num_expr %prec PARAM_REDUCT
768 BEGIN_ACTION;
769 set($$, SelectionParserValue::createExpr(get($1)));
770 END_ACTION;
772 | str_expr %prec PARAM_REDUCT
774 BEGIN_ACTION;
775 set($$, SelectionParserValue::createExpr(get($1)));
776 END_ACTION;
778 | value_item_range { $$ = $1; }
781 basic_value_item:
782 integer_number %prec PARAM_REDUCT
784 BEGIN_ACTION;
785 set($$, SelectionParserValue::createInteger($1, @$));
786 END_ACTION;
788 | real_number %prec PARAM_REDUCT
790 BEGIN_ACTION;
791 set($$, SelectionParserValue::createReal($1, @$));
792 END_ACTION;
794 | string %prec PARAM_REDUCT
796 BEGIN_ACTION;
797 const sfree_guard stringGuard($1);
798 set($$, SelectionParserValue::createString($1, @$));
799 END_ACTION;
801 | value_item_range { $$ = $1; }
804 value_item_range:
805 integer_number TO integer_number
807 BEGIN_ACTION;
808 set($$, SelectionParserValue::createIntegerRange($1, $3, @$));
809 END_ACTION;
811 | integer_number TO real_number
813 BEGIN_ACTION;
814 set($$, SelectionParserValue::createRealRange($1, $3, @$));
815 END_ACTION;
817 | real_number TO number
819 BEGIN_ACTION;
820 set($$, SelectionParserValue::createRealRange($1, $3, @$));
821 END_ACTION;