@@ -79,6 +79,15 @@ def referenced_fields(self):
79
79
return frozenset ([self .field_name ])
80
80
81
81
82
+ class IndexedIdentifier (Identifier ):
83
+ def __init__ (self , mapper , tokens ):
84
+ super ().__init__ (mapper , tokens [0 ])
85
+ # Only literal integers are supported as indexes in bcftools
86
+ # assert isinstance(self.index, str)
87
+ self .index = tokens [0 ][1 ]
88
+ raise UnsupportedArraySubscriptError ()
89
+
90
+
82
91
class RegexOperator (EvaluationNode ):
83
92
def __init__ (self , tokens ):
84
93
raise UnsupportedRegexError ()
@@ -186,26 +195,31 @@ def make_bcftools_filter_parser(all_fields=None, map_vcf_identifiers=True):
186
195
vcf_prefixes = pp .Literal ("INFO/" ) | pp .Literal ("FORMAT/" ) | pp .Literal ("FMT/" )
187
196
vcf_identifier = pp .Combine (vcf_prefixes + identifier ) | identifier
188
197
189
- # indexed_identifier = pp.Forward()
190
- # indexed_identifier <<= identifier + (
191
- # pp.Literal("[") + pp.common.integer + pp.Literal("]"))
192
- # fn_call = (ident + lpar - Group(expr_list) + rpar).setParseAction(
193
- # insert_fn_argcount_tuple
194
- # )
195
-
196
- # lbrack, rbrack = map(pp.Suppress, "[]")
197
- # indexed_identifier = identifier + lbrack - pp.Group(pp.common.integer) + rbrack
198
- # print(indexed_identifier)
198
+ lbracket , rbracket = map (pp .Suppress , "[]" )
199
+ # TODO we need to define the indexing grammar more carefully, but
200
+ # this at least let's us match correct strings and raise an informative
201
+ # error
202
+ index_expr = pp .OneOrMore (
203
+ pp .common .number
204
+ | pp .Literal ("*" )
205
+ | pp .Literal (":" )
206
+ | pp .Literal ("-" )
207
+ | pp .Literal ("," )
208
+ )
209
+ indexed_identifier = pp .Group (vcf_identifier + (lbracket + index_expr + rbracket ))
199
210
200
211
name_mapper = _identity
201
212
if map_vcf_identifiers :
202
213
name_mapper = functools .partial (vcf_name_to_vcz_name , all_fields )
203
214
identifier = vcf_identifier .set_parse_action (
204
215
functools .partial (Identifier , name_mapper )
205
216
)
217
+ indexed_identifier = indexed_identifier .set_parse_action (
218
+ functools .partial (IndexedIdentifier , name_mapper )
219
+ )
206
220
comp_op = pp .oneOf ("< = == > >= <= !=" )
207
221
filter_expression = pp .infix_notation (
208
- constant | identifier ,
222
+ constant | indexed_identifier | identifier ,
209
223
[
210
224
("-" , 1 , pp .OpAssoc .RIGHT , UnaryMinus ),
211
225
(pp .one_of ("* /" ), 2 , pp .OpAssoc .LEFT , BinaryOperator ),
0 commit comments