@@ -115,9 +115,16 @@ operator
115115 // geo-intersects-operator
116116 / quotation_mark "$geoIntersects" quotation_mark name_separator geometry :geometry
117117 { return { pos: " geo-intersects-operator" , operator: " $geoIntersects" , geometry: geometry }; }
118- 118+ // near-operator
119+ / quotation_mark near_operator :("$nearSphere" / "$near" ) quotation_mark name_separator value :(geometry_point / legacy_coordinates )
120+ { return { pos: " near-operator" , operator: near_operator, value: value }; }
121+ // min-distance-operator
122+ / quotation_mark operator :distance_operator quotation_mark name_separator value :number_positive
123+ { return { pos: " distance-operator" , operator: operator, value: value }; }
119124
120125/* --- Geo Operators --- */
126+ distance_operator
127+ = "$minDistance" / "$maxDistance"
121128
122129shape
123130 = geometry
@@ -144,15 +151,41 @@ geometry
144151 end_object
145152 { return { " $geometry" : members }; }
146153
154+ geometry_point
155+ = begin_object
156+ quotation_mark "$geometry" quotation_mark name_separator
157+ begin_object
158+ geometry :(
159+ type :(
160+ quotation_mark "type" quotation_mark
161+ name_separator quotation_mark type :"Point" quotation_mark
162+ { return type; }
163+ )
164+ coordinates :(
165+ value_separator quotation_mark "coordinates" quotation_mark
166+ name_separator coordinates :legacy_coordinates
167+ { return coordinates; }
168+ )
169+ { return { " type" : type, " coordinates" : coordinates }; }
170+ )
171+ end_object
172+ distance :(
173+ value_separator quotation_mark operator :distance_operator quotation_mark
174+ name_separator value :number_positive
175+ { return { [operator]: value }; }
176+ )*
177+ end_object
178+ {
179+ return {
180+ " $geometry" : geometry,
181+ ... (distance ? distance : {})
182+ };
183+ }
184+ 147185geometry_type
148- = "Point"
149- / "LineString"
150- / "Polygon"
151- / "MultiPoint"
152- / "MultiLineString"
186+ = "Polygon"
153187 / "MultiPolygon"
154188
155- 156189geometry_coordinates
157190 = begin_array
158191 values :(
@@ -162,6 +195,12 @@ geometry_coordinates
162195 )?
163196 end_array
164197
198+ legacy_coordinates
199+ = begin_array
200+ number_longitude value_separator
201+ number_latitude
202+ end_array
203+ 165204legacy_shape
166205 = center_shape
167206 / polygon_shape
@@ -171,8 +210,8 @@ center_shape
171210 = begin_object
172211 quotation_mark center_operator :("$centerSphere" / "$center" ) quotation_mark name_separator
173212 parameters :$(begin_array
174- begin_array
175- number value_separator number
213+ begin_array
214+ number value_separator number
176215 end_array
177216 value_separator
178217 number
@@ -188,13 +227,13 @@ box_shape
188227 = begin_object
189228 quotation_mark "$box" quotation_mark name_separator
190229 parameters :$(begin_array
191- begin_array
192- number value_separator number
230+ begin_array
231+ number value_separator number
193232 end_array
194233 value_separator
195234 begin_array
196235 number value_separator number
197- end_array
236+ end_array
198237 end_array )
199238 end_object
200239 { return {" $box" : JSON .parse (parameters)}; }
@@ -204,19 +243,18 @@ polygon_shape
204243 = begin_object
205244 quotation_mark "$polygon" quotation_mark name_separator
206245 parameters :$(begin_array
207- head :(begin_array
208- number value_separator number
246+ head :(begin_array
247+ number value_separator number
209248 end_array )
210249 tail :(value_separator
211250 begin_array
212251 number value_separator number
213- end_array )*
252+ end_array )*
214253 end_array
215254 { return [head].concat (tail); })
216255 end_object
217256 { return {" $polygon" : JSON .parse (parameters)}; }
218257
219- 220258where_operator = "$where"
221259
222260text_operator = "$text"
@@ -369,9 +407,9 @@ ejson_undefined
369407
370408ejson_dbref
371409 = begin_object
372- members :(
410+ members :(
373411 ref :(
374- quotation_mark "$ref" quotation_mark
412+ quotation_mark "$ref" quotation_mark
375413 name_separator string :string
376414 { return string; }
377415 )
@@ -388,17 +426,17 @@ ejson_dbref
388426 {
389427 var result = {" $ref" : ref, " $id" : id};
390428 if (db !== null ) result[" $db" ] = db;
391- return result;
429+ return result;
392430 }
393431 )
394432 end_object
395433 { return members; }
396434
397435ejson_regex
398436 = begin_object
399- members :(
437+ members :(
400438 regex :(
401- quotation_mark "$regex" quotation_mark
439+ quotation_mark "$regex" quotation_mark
402440 name_separator string :string
403441 { return string; }
404442 )
@@ -414,9 +452,9 @@ ejson_regex
414452
415453ejson_binary
416454 = begin_object
417- members :(
455+ members :(
418456 binary :(
419- quotation_mark "$binary" quotation_mark
457+ quotation_mark "$binary" quotation_mark
420458 name_separator string :string
421459 { return string; }
422460 )
@@ -489,6 +527,33 @@ array_number
489527number "number"
490528 = minus ? int frac ? exp ? { return parseFloat (text ()); }
491529
530+ number_positive
531+ = int frac ? exp ? { return parseFloat (text ()); }
532+ 533+ // A numeric value that represents a longitude coordinate (to any precision between -180.0 and 180.0, inclusive)
534+ // Converted to PEG syntax from this regex: ^-?(180(\.0)?|(1[0-7]\d|[1-9]?\d)(\.(0|\d*[1-9]))?)$
535+ // Taking into account PEG's greedy behaviour and lack of backtracking.
536+ number_longitude
537+ = minus ? (
538+ "180" (decimal_point zero )?
539+ / (
540+ (("1" [0-7] DIGIT / digit1_9 DIGIT / DIGIT ) decimal_point int * )
541+ / (("1" [0-7] DIGIT / digit1_9 DIGIT / DIGIT ))
542+ )
543+ )
544+ 545+ // A numeric value that represents a latitude coordinate (to any precision between -90.0 and 90.0, inclusive)
546+ // Converted to PEG syntax from regex: ^-?(90(\.0)?|([1-8]?\d)(\.(0|\d*[1-9]))?)$
547+ // Taking into account PEG's greedy behaviour and lack of backtracking.
548+ number_latitude
549+ = minus ? (
550+ "90" (decimal_point zero )?
551+ / (
552+ ((digit1_9 DIGIT / DIGIT ) decimal_point int * )
553+ / ((digit1_9 DIGIT / DIGIT ))
554+ )
555+ )
556+ 492557decimal_point = "."
493558digit1_9 = [1-9]
494559e = [eE]
0 commit comments