diff --git a/pygeofilter/parsers/cql2_text/grammar.lark b/pygeofilter/parsers/cql2_text/grammar.lark index 703cb43..5b0d52e 100644 --- a/pygeofilter/parsers/cql2_text/grammar.lark +++ b/pygeofilter/parsers/cql2_text/grammar.lark @@ -82,8 +82,6 @@ ?spatial_predicate: _binary_spatial_predicate_func "(" expression "," expression ")" -> binary_spatial_predicate - | "RELATE" "(" expression "," expression "," SINGLE_QUOTED ")" -> relate_spatial_predicate - | _binary_spatial_predicate_func "(" expression "," bbox ")" -> binary_spatial_predicate !_binary_spatial_predicate_func: "S_INTERSECTS"i | "S_DISJOINT"i @@ -120,17 +118,14 @@ func.2: attribute "(" expression ("," expression)* ")" -> function | BOOLEAN | SINGLE_QUOTED | ewkt_geometry -> geometry - | envelope - | bbox + | bbox_literal ?full_number: number | "-" number -> neg ?number: FLOAT | INT -envelope: "ENVELOPE"i "(" number number number number ")" - -bbox: "BBOX"i "(" full_number "," full_number "," full_number "," full_number ")" +bbox_literal: "BBOX"i "(" full_number "," full_number "," full_number "," full_number ")" BOOLEAN.2: ( "TRUE"i | "FALSE"i) diff --git a/pygeofilter/parsers/cql2_text/parser.py b/pygeofilter/parsers/cql2_text/parser.py index cced284..d01c119 100644 --- a/pygeofilter/parsers/cql2_text/parser.py +++ b/pygeofilter/parsers/cql2_text/parser.py @@ -132,9 +132,6 @@ def binary_temporal_predicate(self, lhs, op, rhs): op = op.lower() return TEMPORAL_PREDICATES_MAP[op](lhs, rhs) - def relate_spatial_predicate(self, lhs, rhs, pattern): - return ast.Relate(lhs, rhs, pattern) - def distance_spatial_predicate(self, op, lhs, rhs, distance, units): cls = ast.DistanceWithin if op == "DWITHIN" else ast.DistanceBeyond return cls(lhs, rhs, distance, units) @@ -142,9 +139,6 @@ def distance_spatial_predicate(self, op, lhs, rhs, distance, units): def distance_units(self, value): return value - def bbox_spatial_predicate(self, lhs, minx, miny, maxx, maxy, crs=None): - return ast.BBox(lhs, minx, miny, maxx, maxy, crs) - def function(self, func_name, *expressions): name = func_name.name.lower() if name == "casei": @@ -190,8 +184,8 @@ def SINGLE_QUOTED(self, token): def geometry(self, value): return values.Geometry(value) - def bbox(self, x1, y1, x2, y2): - return values.Envelope(x1, x2, y1, y2) + def bbox_literal(self, west, south, east, north): + return values.Envelope(west, east, south, north) def interval(self, start, end): return values.Interval(start, end) diff --git a/tests/parsers/cql2_text/test_parser.py b/tests/parsers/cql2_text/test_parser.py index 7d4c38e..c8c91be 100644 --- a/tests/parsers/cql2_text/test_parser.py +++ b/tests/parsers/cql2_text/test_parser.py @@ -259,6 +259,17 @@ def test_intersects_geometry(): assert isinstance(result.rhs, values.Geometry) +def test_intersects_bbox_literal(): + result = parse("S_INTERSECTS(attr, BBOX(-118, 33, -117, 34))") + assert isinstance(result, ast.GeometryIntersects) + assert result.lhs == ast.Attribute("attr") + assert isinstance(result.rhs, values.Envelope) + assert result.rhs.x1 == -118 + assert result.rhs.y1 == 33 + assert result.rhs.x2 == -117 + assert result.rhs.y2 == 34 + + def test_attribute_boolean_literal_true(): result = parse("attr = TRUE") assert result == ast.Equal(