UNPKG

wael-lib

Version:

Well-Known Text Arithmetic Expression Language

1,325 lines (1,277 loc) 53.9 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); // src/main.ts var _turf = require('@turf/turf'); var turf4 = _interopRequireWildcard(_turf); var turf3 = _interopRequireWildcard(_turf); var turf = _interopRequireWildcard(_turf); var turf2 = _interopRequireWildcard(_turf); var _wellknown = require('wellknown'); var wellknown = _interopRequireWildcard(_wellknown); // src/interpreter/interpreter.ts var _ohmjs = require('ohm-js'); var ohm = _interopRequireWildcard(_ohmjs); // src/interpreter/types.ts var GeometryType = /* @__PURE__ */ ((GeometryType2) => { GeometryType2["Point"] = "Point"; GeometryType2["LineString"] = "LineString"; GeometryType2["Polygon"] = "Polygon"; GeometryType2["MultiPoint"] = "MultiPoint"; GeometryType2["MultiLineString"] = "MultiLineString"; GeometryType2["MultiPolygon"] = "MultiPolygon"; GeometryType2["GeometryCollection"] = "GeometryCollection"; return GeometryType2; })(GeometryType || {}); var UNIT = null; // src/interpreter/helpers.ts var isAnyGeometryType = /* @__PURE__ */ __name((value) => { const types = Object.values(GeometryType); for (const type of types) { if (isGeometryType(type, value)) { return true; } } return false; }, "isAnyGeometryType"); var isGeometryType = /* @__PURE__ */ __name((type, ...values) => { var _a; for (const value of values) { const isType2 = typeof value === "object" && (value == null ? void 0 : value.type) === type || ((_a = value == null ? void 0 : value.geometry) == null ? void 0 : _a.type) === type; if (!isType2) { return false; } } return true; }, "isGeometryType"); var getGeometryType = /* @__PURE__ */ __name((value, isForDisplay = false) => { var _a; if (typeof value === "object") { const type = ((_a = value == null ? void 0 : value.geometry) == null ? void 0 : _a.type) || (value == null ? void 0 : value.type); if (isForDisplay && type === "GeometryCollection" /* GeometryCollection */) { return "GeometryCollection" /* GeometryCollection */; } return type; } return void 0; }, "getGeometryType"); var getArrayLikeItems = /* @__PURE__ */ __name((value) => { if (isGeometryType("LineString" /* LineString */, value) || isGeometryType("MultiPoint" /* MultiPoint */, value)) { return value.coordinates; } else if (isGeometryType("GeometryCollection" /* GeometryCollection */, value)) { return value.geometries; } return void 0; }, "getArrayLikeItems"); var isNumber = /* @__PURE__ */ __name((...values) => { return isType("number", ...values); }, "isNumber"); var isType = /* @__PURE__ */ __name((type, ...values) => { for (const value of values) { const isType2 = typeof value === type; if (!isType2) { return false; } } return true; }, "isType"); var arithmeticOperationExp = /* @__PURE__ */ __name((a, b, op) => { return arithmeticOperation(a.eval(), b.eval(), op); }, "arithmeticOperationExp"); var arithmeticOperation = /* @__PURE__ */ __name((A, B, op) => { if (isNumber(A, B)) { return op(A, B); } if (isNumber(A) && isAnyGeometryType(B)) { return arithmeticOperation(turf.point([A, A]).geometry, B, op); } if (isNumber(B) && isAnyGeometryType(A)) { return arithmeticOperation(A, turf.point([B, B]).geometry, op); } if (isGeometryType("Point" /* Point */, A, B)) { return pointOperation(A, B, op); } if (isGeometryType("LineString" /* LineString */, A, B)) { return lineStringOperation(A, B, op); } if (isGeometryType("MultiPoint" /* MultiPoint */, A, B)) { return multiPointOperation(A, B, op); } if (isGeometryType("Point" /* Point */, A)) { return transform(B, (b) => pointOperation(A, b, op)); } if (isGeometryType("Point" /* Point */, B)) { return transform(A, (a) => pointOperation(a, B, op)); } return void 0; }, "arithmeticOperation"); var pointOperation = /* @__PURE__ */ __name((A, B, computeFn) => { return turf.point([ computeFn(A.coordinates[0], B.coordinates[0]), computeFn(A.coordinates[1], B.coordinates[1]) ]).geometry; }, "pointOperation"); var lineStringOperation = /* @__PURE__ */ __name((A, B, computeFn) => { return turf.lineString(A.coordinates.map((p, index) => { return [ computeFn(p[0], B.coordinates[index][0]), computeFn(p[1], B.coordinates[index][1]) ]; })).geometry; }, "lineStringOperation"); var multiPointOperation = /* @__PURE__ */ __name((A, B, computeFn) => { return turf.multiPoint(A.coordinates.map((p, index) => { return [ computeFn(p[0], B.coordinates[index][0]), computeFn(p[1], B.coordinates[index][1]) ]; })).geometry; }, "multiPointOperation"); var _OperationNotSupported = class _OperationNotSupported extends Error { constructor(message) { super(`Operation not supported: ${message}`); } }; __name(_OperationNotSupported, "OperationNotSupported"); var OperationNotSupported = _OperationNotSupported; function toString(value) { try { return `${JSON.stringify(value)}`; } catch (err) { return `${value}`; } } __name(toString, "toString"); function transformPoints(coords, coordsMapFn) { if (!!coords) { if (Array.isArray(coords)) { if (coords.length > 0) { const firstElement = coords[0]; if (Array.isArray(firstElement)) { return coords.map((c) => transformPoints(c, coordsMapFn)); } else { const point4 = turf.point(coords).geometry; return coordsMapFn(point4).coordinates; } } } } return coords; } __name(transformPoints, "transformPoints"); function transform(geoJson, coordsMapFn) { if (!!geoJson) { if (!!geoJson.features) { return __spreadProps(__spreadValues({}, geoJson), { features: geoJson.features.map((feature2) => transform(feature2, coordsMapFn)) }); } if (!!geoJson.geometries) { return __spreadProps(__spreadValues({}, geoJson), { geometries: geoJson.geometries.map((geometry2) => transform(geometry2, coordsMapFn)) }); } const geometry = geoJson.geometry; if (!!geometry) { if (geoJson.coordinates) { return __spreadProps(__spreadValues({}, geoJson), { geometry: __spreadProps(__spreadValues({}, geometry), { coordinates: transformPoints(geometry.coordinates, coordsMapFn) }) }); } } const coordinates = geoJson.coordinates; if (!!coordinates) { return __spreadProps(__spreadValues({}, geoJson), { coordinates: transformPoints(coordinates, coordsMapFn) }); } } return geoJson; } __name(transform, "transform"); function convertToGeometry(json) { if (json.type === "Feature") { return json.geometry; } else if (json.type === "FeatureCollection") { return { type: "GeometryCollection", geometries: json.features.map((f) => convertToGeometry(f)) }; } else if (Array.isArray(json)) { return { type: "GeometryCollection", geometries: json.map((f) => convertToGeometry(f)) }; } return json; } __name(convertToGeometry, "convertToGeometry"); function geometryAccessor(v, p, params) { const value = v.eval(); const property = p.sourceString; if (!isAnyGeometryType(value)) { throw new Error(`Expected a geometry type for value "${v.sourceString}" but got: ${toString(value)}`); } switch (property.toLocaleLowerCase()) { case "type": if ((params == null ? void 0 : params.length) > 1) { throw new Error(`Expected no parameters for "${property}" for ${v.sourceString}`); } return getGeometryType(value, true); } if (isGeometryType("Point" /* Point */, value)) { switch (property.toLocaleLowerCase()) { case "x": if ((params == null ? void 0 : params.length) > 0) { if (params.length === 1) { return turf.point([ params[0], value.coordinates[1] ]).geometry; } throw Error(`Expected one value in "${property}" setter for "${v.sourceString}" but got: ${toString(params)}`); } return value.coordinates[0]; case "y": if ((params == null ? void 0 : params.length) > 0) { if (params.length === 1) { return turf.point([ value.coordinates[0], params[0] ]).geometry; } throw Error(`Expected one value in "${property}" setter for "${v.sourceString}" but got: ${toString(params)}`); } return value.coordinates[1]; } } else if (isGeometryType("GeometryCollection" /* GeometryCollection */, value)) { switch (property.toLocaleLowerCase()) { case "geometryn": if (params.length === 1) { const index = parseInt(params[0]); return value.geometries[index]; } throw Error(`Expected one value in "${property}" setter for "${v.sourceString}" but got: ${toString(params)}`); case "numgeometries": return value.geometries.length; } } else if (isGeometryType("LineString" /* LineString */, value)) { switch (property.toLocaleLowerCase()) { case "pointn": if (params.length === 1) { const index = parseInt(params[0]); return turf.point(value.coordinates[index]).geometry; } throw Error(`Expected one value in "${property}" setter for "${v.sourceString}" but got: ${toString(params)}`); case "numpoints": return value.coordinates.length; } } throw new Error(`Property "${property}" not accessible on object: ${toString(value)}`); } __name(geometryAccessor, "geometryAccessor"); // src/interpreter/scope.ts var _Scope = class _Scope { constructor(parent, level = 0, defaultBindings = {}) { this.parent = parent; this.level = level; this.bindings = {}; this.availableBindings = {}; this.metadata = {}; for (const identifier in defaultBindings) { if (defaultBindings.hasOwnProperty(identifier)) { this.store(identifier, defaultBindings[identifier]); } } } store(identifier, value, metadata, searchParentChain = true) { let scope = this; if (searchParentChain) { const resolvedScope = this.resolveScope(identifier); if (resolvedScope) { scope = resolvedScope; } scope.store(identifier, value, metadata, false); return; } this.bindings[identifier] = value; if (metadata) { this.metadata[identifier] = metadata; } } resolveScope(identifier) { if (this.bindings.hasOwnProperty(identifier)) { return this; } if (this.parent) { return this.parent.resolveScope(identifier); } return void 0; } resolve(identifier) { var _a; const scope = (_a = this.resolveScope(identifier)) != null ? _a : this; return scope.bindings[identifier]; } push(extraBindings) { return new _Scope(this, this.level + 1, extraBindings); } pop(additionalBindings) { var _a; const exportedBindings = __spreadValues({}, additionalBindings); for (const identifier in this.metadata) { const metadata = this.metadata[identifier]; if (metadata && metadata.public) { exportedBindings[identifier] = this.bindings[identifier]; } } (_a = this.parent) == null ? void 0 : _a.import(exportedBindings); return this.parent; } import(scopeBindings) { this.availableBindings = __spreadValues(__spreadValues({}, this.availableBindings), scopeBindings); } useImports(selectedIdentifiers) { let selectedBindings = {}; if (selectedIdentifiers) { selectedIdentifiers.forEach((selectedIdentifier) => { selectedBindings[selectedIdentifier] = this.availableBindings[selectedIdentifier]; }); } else { selectedBindings = this.availableBindings; } this.availableBindings = {}; return selectedBindings; } useNamedImports(selectedIdentifiers) { let selectedBindings = {}; if (selectedIdentifiers) { selectedIdentifiers.forEach((selectedIdentifier) => { selectedBindings[selectedIdentifier] = this.availableBindings[selectedIdentifier]; }); } this.bindings = __spreadValues(__spreadValues({}, this.bindings), selectedBindings); return selectedBindings; } }; __name(_Scope, "Scope"); var Scope = _Scope; // src/interpreter/built-in-functions.ts var _booleanequal = require('@turf/boolean-equal'); var _booleanequal2 = _interopRequireDefault(_booleanequal); var BuiltInFunctions; ((BuiltInFunctions2) => { const FlattenHelper = /* @__PURE__ */ __name((value) => { const flattenedValues = []; if (!!value) { if ((value == null ? void 0 : value.type) === "GeometryCollection" /* GeometryCollection */) { for (const item of value.geometries) { flattenedValues.push(...FlattenHelper(item)); } } else { flattenedValues.push(value); } } return flattenedValues; }, "FlattenHelper"); BuiltInFunctions2.Flatten = /* @__PURE__ */ __name((value) => { if ((value == null ? void 0 : value.type) === "GeometryCollection" /* GeometryCollection */) { return turf2.geometryCollection(FlattenHelper(value)).geometry; } return value; }, "Flatten"); BuiltInFunctions2.PointCircle = /* @__PURE__ */ __name((radius, count) => { const circlePoints = []; const angleIncrement = 2 * Math.PI / count; for (let i = 0; i < count; i++) { const angle = i * angleIncrement; const x = radius * Math.cos(angle); const y = radius * Math.sin(angle); circlePoints.push(turf2.point([x, y]).geometry); } return turf2.geometryCollection(circlePoints).geometry; }, "PointCircle"); BuiltInFunctions2.PointGrid = /* @__PURE__ */ __name((x, y, spacing = 1) => { const points = []; for (let i = 0; i < x; i++) { for (let j = 0; j < y; j++) { const point4 = turf2.point([i * spacing, j * spacing]).geometry; points.push(point4); } } return turf2.geometryCollection(points).geometry; }, "PointGrid"); const getPointsList = /* @__PURE__ */ __name((value) => { let points; if (isGeometryType("GeometryCollection" /* GeometryCollection */, value)) { points = value == null ? void 0 : value.geometries.map((f) => f.coordinates); } else if (isGeometryType("LineString" /* LineString */, value) || isGeometryType("MultiPoint" /* MultiPoint */, value)) { points = value == null ? void 0 : value.coordinates; } if (points) { return points; } throw new Error("Expected geometry with points list"); }, "getPointsList"); BuiltInFunctions2.ToLineString = /* @__PURE__ */ __name((value) => { const pointsList = getPointsList(value); return turf2.lineString(pointsList).geometry; }, "ToLineString"); BuiltInFunctions2.ToMultiPoint = /* @__PURE__ */ __name((value) => { const pointsList = getPointsList(value); return turf2.multiPoint(pointsList).geometry; }, "ToMultiPoint"); BuiltInFunctions2.ToPolygon = /* @__PURE__ */ __name((value) => { const pointsList = getPointsList(value); if (pointsList.length > 0) { if (!_booleanequal2.default.call(void 0, turf2.point(pointsList[0]).geometry, turf2.point(pointsList[pointsList.length - 1]).geometry )) { pointsList.push(pointsList[0]); } } return turf2.polygon([pointsList]).geometry; }, "ToPolygon"); BuiltInFunctions2.ToGeometryCollection = /* @__PURE__ */ __name((value) => { const pointsList = getPointsList(value); return turf2.geometryCollection(pointsList.map((p) => turf2.point(p).geometry)).geometry; }, "ToGeometryCollection"); BuiltInFunctions2.Rotate = /* @__PURE__ */ __name((angleDegrees, origin = turf2.point([0, 0]).geometry, geometry) => { return transform(geometry, (p) => { const angleRadians = angleDegrees * Math.PI / -180; const originX = origin.coordinates[0]; const originY = origin.coordinates[1]; const x = p.coordinates[0]; const y = p.coordinates[1]; const dx = x - originX; const dy = y - originY; const newX = originX + dx * Math.cos(angleRadians) - dy * Math.sin(angleRadians); const newY = originY + dx * Math.sin(angleRadians) + dy * Math.cos(angleRadians); return turf2.point([newX, newY]).geometry; }); }, "Rotate"); BuiltInFunctions2.Round = /* @__PURE__ */ __name((precision = 0, val) => { if (typeof val === "number") { return +val.toFixed(precision); } if (isGeometryType("Point" /* Point */, val)) { const coords = val.coordinates; return turf2.point([ (0, BuiltInFunctions2.Round)(precision, coords[0]), (0, BuiltInFunctions2.Round)(precision, coords[1]) ]).geometry; } throw new OperationNotSupported(`Unable to round value: ${toString(val)}`); }, "Round"); })(BuiltInFunctions || (BuiltInFunctions = exports.BuiltInFunctions = {})); // src/interpreter/grammar.ts var GRAMMAR = String.raw` WAEL { /*************** * WAEL syntax * ***************/ // Top-level expressions TopLevel = ScopedExpressions TopLevelEnd TopLevelEnd = ExpressionDelimiter | end // Comments comment = "#" commentSpace* commentText* commentSpace* commentEnd commentText = ~commentEnd any commentEnd = "\n" | end commentSpace = " " // Expression structure ScopedExpressions = ListOf<GeneralExpression, ExpressionDelimiter> --list | GeneralExpression GeneralExpression = GeneralExpression comment --rightComment | comment GeneralExpression --leftComment | AssignmentExp | AssignableExpression | comment ExpressionDelimiter = expressionDelimiter expressionDelimiter = ";" // Imports ImportExpression = AccessibleExp<ImportExpressionType> ImportExpressionType = ImportUsingExpression | ImportAllExpression ImportUsingExpression = ImportEitherExpression usingKeyword ImportUsingParameters ImportUsingParameters = FunctionParameters | ImportUsingAllParams ImportUsingAllParams = Paren<"*"> ImportAllExpression = ImportEitherExpression ImportEitherExpression = ImportExternalExp | ImportFunctionExp ImportExternalExp = importKeyword Paren<ImportExternalParamExp> ImportExternalParamExp = stringLiteralExp | Identifier ImportFunctionExp = importKeyword Paren<FunctionCallExp> importKeyword = caseInsensitive<"import"> usingKeyword = caseInsensitive<"using"> // Exports exportKeyword = caseInsensitive<"export"> // Variables letKeyword = caseInsensitive<"let"> AssignmentExp = exportKeyword? letKeyword? Identifier assignmentOperator AssignableExpression AssignableExpression = | ImportExpression | NonArithmeticAssignableExpression | ArithmeticAssignableExpression NonArithmeticAssignableExpression = | OperationExp | stringLiteralExp ArithmeticAssignableExpression = Arithmetic<AssignableExpressionForArithmetic> AssignableExpressionForArithmetic = | BooleanResultExp | IfThenElseExp | ComputedExp | FunctionTextExp | NumberExp | AccessibleExp<GeometryExp> | BooleanValue | Paren<OperationExp> assignmentOperator = "=" ComputedValue<Type> = Type | ComputedExp ComputedExp = AccessibleExp<ComputedPrimitive> ComputedPrimitive = FunctionCallExp | Identifier AccessibleExp<Type> = | Type accessorOperator Identifier Invocation? --method | Type // Additional operation expressions OperationExp = PipeExp | GenerateExp | ConcatExp PipeExp = MappableValue anyPipeOperator Pipeable //Callable Pipeable = FunctionCallExp | Callable GenerateExp = generateKeyword GenerateCountExpr ComputedValue<GenerateValue> GenerateCountExpr = ComputedValue<NumberExp> | FunctionTextExp ConcatExp = MappableValue concatOperator MappableValue GenerateValue = GeometryExp | FunctionTextExp generateKeyword = caseInsensitive<"Generate"> MappableValue = AssignableExpression // Helpers Paren<type> = LeftParen type RightParen OptionallyParen<type> = LeftParen type RightParen --paren | type --noParen OptionallyBraced<type> = LeftBrace type RightBrace --brace | type // Arithmetic expressions Arithmetic<Type> = ArithmeticAdd<Type> ArithmeticAdd<Type> = | ArithmeticAdd<Type> plusOperator ArithmeticMul<Type> -- plus | ArithmeticAdd<Type> minusOperator ArithmeticMul<Type> -- minus | ArithmeticMul<Type> ArithmeticMul<Type> = | ArithmeticMul<Type> timesOperator ArithmeticExp<Type> -- times | ArithmeticMul<Type> divideOperator ArithmeticExp<Type> -- divide | ArithmeticMul<Type> modOperator ArithmeticExp<Type> -- mod | ArithmeticExp<Type> ArithmeticExp<Type> = | ArithmeticPri<Type> powerOperator ArithmeticExp<Type> -- power | ArithmeticPri<Type> ArithmeticPri<Type> = | Type | leftParen Arithmetic<Type> rightParen -- paren // Operators operator = | expressionDelimiter | anyPipeOperator | plusOperator | minusOperator | timesOperator | divideOperator | powerOperator | modOperator | accessorOperator | conditionalOperator | assignmentOperator | notOperator anyPipeOperator = doublePipeOperator | coordinatesPipeOperator | filterOperator | reduceOperator | pipeOperator pipeOperator = "|" coordinatesPipeOperator = "|*" doublePipeOperator = "||" filterOperator = "|~" reduceOperator = "|>" concatOperator = "++" plusOperator = "+" minusOperator = "-" timesOperator = "*" divideOperator = "/" powerOperator = "^" modOperator = "%" accessorOperator = ":" // Function expressions FunctionTextExp = functionKeyword LeftParen FunctionExp RightParen --keyword | OptionallyParen<FunctionExp> FunctionExp = FunctionParameters "=>" OptionallyParen<FunctionBody> FunctionParameters = LeftParen ListOf<Identifier, Comma> RightParen --multipleParams | Identifier --single FunctionBody = OptionallyParen<ScopedExpressions> | AssignableExpression FunctionCallExp = FunctionCallExp Invocation | Callable Invocation Invocation = LeftParen ListOf<GeneralExpression, Comma> RightParen functionKeyword = caseInsensitive<"Function"> Callable = | FunctionTextExp | FunctionCallExp | AccessibleExp<Callable> | Identifier // If-Then-Else expressions IfThenElseExp = ifKeyword Paren<BooleanResultExp> thenKeyword Paren<ScopedExpressions> elseKeyword Paren<ScopedExpressions> ifKeyword = caseInsensitive<"if"> thenKeyword = caseInsensitive<"then"> elseKeyword = caseInsensitive<"else"> // Conditional expressions BooleanResultExp = EqualityExp | CompareExp | NotExp | booleanValue EqualityExp = ComparePrimitive equalityOperatorPrimitive ComparePrimitive NotExp = notOperator ComparePrimitive ConditionalValue = CompareExp | EqualityExp | BooleanValue | NumberExp CompareExp = ComparePrimitive compareOperatorPrimitive ComparePrimitive ComparePrimitive = BooleanResultExp | ComputedValue<NumberExp> | AccessibleExp<GeometryExp> | geometryKeyword conditionalOperator = compareOperatorPrimitive | equalityOperatorPrimitive compareOperatorPrimitive = "<=" | ">=" | "<" | ">" equalityOperatorPrimitive = "==" | "!=" | logicalOperator logicalOperator = caseInsensitive<"And"> | caseInsensitive<"Or"> notOperator = "!" // Identifiers Identifier = basicIdentifier basicIdentifier = ~nonAllowedIdentifiers id id = firstIdCharacter idCharacter* firstIdCharacter = simpleLatinLetter | "$" | "_" idCharacter = simpleLatinLetter | digit | "_" | "?" | "'" nonAllowedIdentifiers = keyword identifierEnd identifierEnd = end | comma | leftParen | rightParen | operator | wktSpace /************************************* * OGC Well-Known Text (WKT) Grammar * *************************************/ // Based on WKT Syntax: https://www.ogc.org/standard/sfa/ GeometrySyntaxExp<GeometryTypeExp, geometryKeyword> = Arithmetic<GeometryArithmetic<GeometryTypeExp, geometryKeyword>> GeometryArithmetic<GeometryTypeExp, geometryKeyword> = GeometryPrimitive<GeometryTypeExp, geometryKeyword> GeometryPrimitive<GeometryTypeExp, geometryKeyword> = GeometryTaggedText<GeometryTypeExp, geometryKeyword> GeometryTaggedText<GeometryTypeExp, geometryKeyword> = geometryKeyword GeometryTypeExp GeometryCollectionExp = GeometrySyntaxExp<GeometryCollectionText, geometryCollectionKeyword> GeometryCollectionText = emptySet --empty | LeftParen ListOf<GeometryExp, Comma> RightParen --present geometryCollectionKeyword = caseInsensitive<"GEOMETRYCOLLECTION"> GeometryExp = | PointExp | MultiPointExp | LineStringExp | MultiLineStringExp | PolygonExp | MultiPolygonExp | GeometryCollectionExp // TODO -- support POLYHEDRALSURFACE geometry //PolyhedralSurfaceExp = GeometrySyntaxExp<PolyhedralSurfaceText, polyhedralSurfaceKeyword> //PolyhedralSurfaceText = emptySet --empty // | LeftParen NonemptyListOf<PolygonText, Comma> RightParen --present //polyhedralSurfaceKeyword = caseInsensitive<"PolyhedralSurface"> MultiPolygonExp = GeometrySyntaxExp<MultiPolygonText, multiPolygonKeyword> MultiPolygonText = emptySet --empty | LeftParen NonemptyListOf<PolygonText, Comma> RightParen --present multiPolygonKeyword = caseInsensitive<"MULTIPOLYGON"> PolygonExp = GeometrySyntaxExp<PolygonText, polygonKeyword> PolygonText = emptySet --empty | LeftParen NonemptyListOf<LineStringText, Comma> RightParen --present polygonKeyword = caseInsensitive<"POLYGON"> MultiLineStringExp = GeometrySyntaxExp<MultiLineStringText, multiLineStringKeyword> MultiLineStringText = emptySet --empty | LeftParen NonemptyListOf<LineStringText, Comma> RightParen --present multiLineStringKeyword = caseInsensitive<"MULTILINESTRING"> LineStringExp = GeometrySyntaxExp<LineStringText, lineStringKeyword> LineStringText = emptySet --empty | LeftParen PointList RightParen --present lineStringKeyword = caseInsensitive<"LINESTRING"> MultiPointExp = GeometrySyntaxExp<MultiPointText, multiPointKeyword> MultiPointText = emptySet --empty | LeftParen PointList RightParen --present multiPointKeyword = caseInsensitive<"MULTIPOINT"> // Base point type helpers PointList = NonemptyListOf<PointListArgument, Comma> PointListArgument = Point | ComputedValue<PointExp> PointExp = Arithmetic<PointArithmetic> PointArithmetic = PointPrimitive | ComputedExp PointPrimitive = PointTaggedText | PointText | Point PointTaggedText = pointKeyword PointText PointText = emptySet --empty | LeftParen Point RightParen --present Point = X Y pointKeyword = caseInsensitive<"POINT"> // Keywords keyword = geometryKeyword | functionKeyword | generateKeyword | booleanValue | ifKeyword | thenKeyword | elseKeyword | importKeyword | exportKeyword | letKeyword geometryKeyword = pointKeyword | multiPointKeyword | lineStringKeyword | multiLineStringKeyword | polygonKeyword | multiPolygonKeyword | geometryCollectionKeyword // Coordinate values X = PointNumberValue Y = PointNumberValue Z = PointNumberValue M = PointNumberValue // Numeric value PointNumberValue = signedNumericLiteral | OptionallyParen<ComputedValue<NumberExp>> | ComputedPrimitive NumberExp = Arithmetic<ComputedValue<signedNumericLiteral>> // Boolean value BooleanValue = ComputedValue<booleanValue> booleanValue = caseInsensitive<"true"> | caseInsensitive<"false"> // String literals stringLiteralExp = stringLiteral<"'"> | stringLiteral<"\""> stringLiteral<quoteChar> = quoteChar stringLiteralValue<quoteChar>* quoteChar stringLiteralValue<quoteChar> = ~quoteChar any // OGC specification primitives quotedName = doubleQuote name doubleQuote name = letters letters = wktLetter+ wktLetter = simpleLatinLetter | digit | special simpleLatinLetter = simpleLatinUpperCaseLetter | simpleLatinLowerCaseLetter signedNumericLiteral = sign unsignedNumericLiteral --signPresent | unsignedNumericLiteral --signMissing unsignedNumericLiteral = exactNumericLiteral | approximateNumericLiteral approximateNumericLiteral = mantissa "E" exponent // TODO -- handle this notation at higher level expressions mantissa = exactNumericLiteral exponent = signedInteger exactNumericLiteral = unsignedInteger decimalPoint unsignedInteger --decimalWithWholeNumber | decimalPoint unsignedInteger --decimalWithoutWholeNumber | unsignedInteger --wholeNumber signedInteger = sign unsignedInteger --signedInteger | unsignedInteger --unsignedInteger unsignedInteger = digit+ leftDelimiter = leftParen | leftBracket rightDelimiter = rightParen | rightBracket special = rightParen | leftParen | minusSign | underscore | period | quote | wktSpace sign = plusSign | minusSign decimalPoint = period // comma // TODO -- comma causes parsing issues emptySet = "EMPTY" minusSign = "-" LeftParen = leftParen leftParen = "(" RightParen = rightParen rightParen = ")" leftBracket = "[" rightBracket = "]" LeftBrace = leftBrace leftBrace = "{" RightBrace = rightBrace rightBrace = "}" period = "." plusSign = "+" doubleQuote = "\"" quote = "'" Comma = comma comma = "," underscore = "_" // digit = 0|1|2|3|4|5|6|7|8|9 // provided by default simpleLatinLowerCaseLetter = lower // a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z simpleLatinUpperCaseLetter = upper // A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z wktSpace = " " // unicode "U+0020" (space) // provided by default } `; // src/interpreter/interpreter.ts var _fs = require('fs'); var _syncfetch = require('sync-fetch'); var _syncfetch2 = _interopRequireDefault(_syncfetch); var grammarString = GRAMMAR; var Interpreter; ((Interpreter2) => { Interpreter2.IMPORT_DEFAULT_IDENTIFIER = "Default"; Interpreter2.IMPORT_USING_ALL = "*"; Interpreter2.STANDARD_LIBRARY = {}; const math = {}; Object.getOwnPropertyNames(Math).forEach((prop) => { math[prop] = Math[prop]; }); Interpreter2.STANDARD_LIBRARY["Math"] = math; Interpreter2.STANDARD_LIBRARY["Flatten"] = BuiltInFunctions.Flatten; Interpreter2.STANDARD_LIBRARY["PointCircle"] = BuiltInFunctions.PointCircle; Interpreter2.STANDARD_LIBRARY["PointGrid"] = BuiltInFunctions.PointGrid; Interpreter2.STANDARD_LIBRARY["ToLineString"] = BuiltInFunctions.ToLineString; Interpreter2.STANDARD_LIBRARY["ToMultiPoint"] = BuiltInFunctions.ToMultiPoint; Interpreter2.STANDARD_LIBRARY["ToPolygon"] = BuiltInFunctions.ToPolygon; Interpreter2.STANDARD_LIBRARY["ToGeometryCollection"] = BuiltInFunctions.ToGeometryCollection; Interpreter2.STANDARD_LIBRARY["_Rotate"] = BuiltInFunctions.Rotate; Interpreter2.STANDARD_LIBRARY["_Round"] = BuiltInFunctions.Round; Interpreter2.createGlobalScope = /* @__PURE__ */ __name(() => new Scope(void 0, void 0, Interpreter2.STANDARD_LIBRARY), "createGlobalScope"); function evaluateInput(input, initialScope) { const GLOBAL_SCOPE = (0, Interpreter2.createGlobalScope)(); let currentScope = initialScope || GLOBAL_SCOPE; const grammar2 = ohm.grammar(grammarString); const semantics = grammar2.createSemantics(); semantics.addOperation("eval", { stringLiteral(_leftQuote, str, _rightQuote) { return str.sourceString; }, ImportAllExpression(exp) { const ret = exp.eval(); if (ret) { return ret; } const importObj = currentScope.useImports(); return importObj; }, ImportUsingExpression(importAllExp, _keyword, identifierList) { importAllExp.eval(); const identifiers = identifierList.eval(); let importObj; if (identifiers === Interpreter2.IMPORT_USING_ALL) { importObj = currentScope.useNamedImports(Object.keys(currentScope.availableBindings)); } else { importObj = currentScope.useNamedImports(identifiers); } return importObj; }, ImportUsingAllParams(_) { return Interpreter2.IMPORT_USING_ALL; }, ImportExternalExp(_keyword, importUri) { const uri = importUri.eval(); let data; if (uri.startsWith("http://") || uri.startsWith("https://")) { data = _syncfetch2.default.call(void 0, uri).text(); } else { data = _fs.readFileSync.call(void 0, uri, "utf8"); } currentScope = currentScope.push(); let ret = void 0; let bindings = void 0; try { ret = convertToGeometry(JSON.parse(data)); } catch (e) { try { const libRet = evaluateInput(data, currentScope); bindings = {}; bindings[Interpreter2.IMPORT_DEFAULT_IDENTIFIER] = libRet; } catch (e2) { throw new Error(`Unable to import file: ${uri}`); } } currentScope = currentScope.pop(bindings) || GLOBAL_SCOPE; return ret; }, ImportFunctionExp(_keyword, importFn) { importFn.eval(); }, IfThenElseExp(_if, c, _then, exp1, _else, exp2) { const condition = c.eval(); if (condition) { return exp1.eval(); } return exp2.eval(); }, booleanValue(val) { const value = val.sourceString.toLocaleLowerCase(); if (value === "true") { return true; } if (value === "false") { return false; } throw new Error(`Invalid boolean value: ${val.sourceString}`); }, EqualityExp(v1, op, v2) { const value1 = v1.eval(); const operator = op.sourceString; const value2 = v2.eval(); switch (operator.trim().toLocaleLowerCase()) { case "==": return value1 === value2; case "!=": return value1 !== value2; case "and": return value1 && value2; case "or": return value1 || value2; } throw new Error(`Operator not supported: ${operator}`); }, NotExp(_, exp) { return !exp.eval(); }, geometryKeyword(keyword) { return keyword.sourceString; }, CompareExp(v1, op, v2) { const value1 = v1.eval(); if (!isNumber(value1)) { throw new Error(`Expected a number for ${v1.sourceString} but got: ${toString(value1)}`); } const operator = op.sourceString; const value2 = v2.eval(); if (!isNumber(value2)) { throw new Error(`Expected a number for ${v2.sourceString} but got: ${toString(value2)}`); } switch (operator.trim()) { case "<": return value1 < value2; case "<=": return value1 <= value2; case ">": return value1 > value2; case ">=": return value1 >= value2; } throw new Error(`Operator not supported: ${operator}`); }, ConcatExp(g1, _op, g2) { const geom1 = g1.eval(); const geom2 = g2.eval(); const type1 = getGeometryType(geom1); const type2 = getGeometryType(geom2); if (!type1 || !type2) { throw new Error(`Expected geometry types for concatenation but found geom1: ${toString(geom1)} and geom2: ${toString(geom2)}`); } if (type1 === type2) { const list1 = getArrayLikeItems(geom1); const list2 = getArrayLikeItems(geom2); if (type1 === "LineString" /* LineString */ || type1 === "MultiPoint" /* MultiPoint */ || type1 === "GeometryCollection" /* GeometryCollection */) { const combined = list1.concat(list2); if (type1 === "LineString" /* LineString */) { return turf3.lineString(combined).geometry; } if (type1 === "MultiPoint" /* MultiPoint */) { return turf3.multiPoint(combined).geometry; } if (type1 === "GeometryCollection" /* GeometryCollection */) { return turf3.geometryCollection(combined).geometry; } } } if (type1 === "LineString" /* LineString */ || type1 === "MultiPoint" /* MultiPoint */) { const list1 = getArrayLikeItems(geom1); let list2; if (type2 === "LineString" /* LineString */ || type2 === "MultiPoint" /* MultiPoint */) { list2 = getArrayLikeItems(geom2); } else { if (type2 === "Point" /* Point */) { list2 = [geom2.coordinates]; } } if (list2) { const combined = list1.concat(list2); if (type1 === "LineString" /* LineString */) { return turf3.lineString(combined).geometry; } if (type1 === "MultiPoint" /* MultiPoint */) { return turf3.multiPoint(combined).geometry; } if (type1 === "GeometryCollection" /* GeometryCollection */) { return turf3.geometryCollection(combined).geometry; } } } if (type1 === "GeometryCollection" /* GeometryCollection */) { return turf3.geometryCollection(geom1.geometries.concat([geom2])).geometry; } if (type2 === "GeometryCollection" /* GeometryCollection */) { return turf3.geometryCollection([geom1].concat(...geom2.geometries)).geometry; } return turf3.geometryCollection([geom1, geom2]).geometry; }, PipeExp(a, op, f) { const operator = op.sourceString; const val = a.eval(); const fn = f.eval(); if (operator === "|") { return fn(val); } if (operator === "|*") { return transform(val, fn); } const list = getArrayLikeItems(val); let listFn; switch (operator) { case "||": listFn = Array.prototype.map; break; case "|~": listFn = Array.prototype.filter; break; case "|>": listFn = Array.prototype.reduce; break; default: throw new Error(`Operator ${operator} not supported`); } if (isGeometryType("GeometryCollection" /* GeometryCollection */, val)) { const mappedList = listFn.call(list, fn); if (isAnyGeometryType(mappedList)) { return mappedList; } return turf3.geometryCollection(mappedList).geometry; } if (isGeometryType("LineString" /* LineString */, val)) { let mappedList = listFn.call( list.map((coords) => turf3.point(coords).geometry), fn ); if (isAnyGeometryType(mappedList)) { return mappedList; } mappedList = mappedList.map((v) => v.coordinates); return turf3.lineString(mappedList).geometry; } if (isGeometryType("MultiPoint" /* MultiPoint */, val)) { let mappedList = listFn.call( list.map((coords) => turf3.point(coords).geometry), fn ); if (isAnyGeometryType(mappedList)) { return mappedList; } mappedList = mappedList.map((v) => v.coordinates); return turf3.multiPoint(mappedList).geometry; } throw Error(`Error mapping values to geometries`); }, TopLevel(scopedExpressions, _end) { let lastValue = scopedExpressions.eval(); return lastValue; }, GenerateExp(_keyword, numExp, valueExp) { const num = numExp.eval(); if (!Number.isInteger(num) && typeof num !== "function") { throw new Error(`Expected integer but got: ${toString(num)}`); } let value = valueExp.eval(); let mapFn; if (typeof value === "function") { mapFn = value; } else if (isAnyGeometryType(value)) { mapFn = /* @__PURE__ */ __name(() => value, "mapFn"); } else { throw new Error(`Expected geometry type or function but got: ${toString(value)}`); } const items = []; if (typeof num === "function") { let i = 0; let condition = num(i); while (condition) { const result2 = mapFn(i); if (!isAnyGeometryType(result2)) { throw new Error(`Expected geometry type return value but got: ${toString(result2)}`); } items.push(result2); condition = num(++i); } } else { for (let i = 0; i < num; i++) { const result2 = mapFn(i); if (!isAnyGeometryType(result2)) { throw new Error(`Expected geometry type return value but got: ${toString(result2)}`); } items.push(result2); } } return turf3.geometryCollection(items).geometry; }, FunctionCallExp(callable, p) { const fn = callable.eval(); const params = p.eval(); if (!fn) { throw new Error(`${callable.sourceString} is: ${fn}`); } const value = fn(...params); return value; }, AccessibleExp_method(val, _accessOp, prop, optionalParams) { const value = val.eval(); const identifier = prop.sourceString; const isInvocation = optionalParams.children.length > 0; const parameters = isInvocation ? optionalParams.children.map((c) => c.eval())[0] : []; if (typeof value === "function") { if (identifier === "bind") { return value.bind(void 0, ...parameters); } throw new OperationNotSupported(`Method ${identifier} not supported on function type`); } if (isAnyGeometryType(value)) { return geometryAccessor(val, prop, parameters); } const resolvedValue = value[identifier]; if (typeof resolvedValue === "function" && isInvocation) { return resolvedValue(...parameters); } return resolvedValue; }, Invocation(_leftParen, list, _rightParen) { return list.asIteration().children.map((c) => c.eval()); }, FunctionExp(p, _, body) { let params = p.eval(); params = Array.isArray(params) ? params : [params]; let fnScope = currentScope; const fn = /* @__PURE__ */ __name(function(...values) { currentScope = currentScope.push(__spreadValues({}, fnScope.bindings)); params.forEach((paramName, index) => { currentScope.store(paramName, values[index], void 0, false); }); const ret = body.eval(); const defaultBindings = {}; defaultBindings[Interpreter2.IMPORT_DEFAULT_IDENTIFIER] = ret; currentScope = currentScope.pop(defaultBindings) || GLOBAL_SCOPE; return ret; }, "fn"); const boundFn = fn.bind(currentScope); boundFn.toString = function() { return `Function(${p.sourceString} => ${body.sourceString})`; }; return boundFn; }, FunctionParameters_multipleParams(_leftParen, identifierList, _rightParen) { const params = identifierList.asIteration().children.map((c) => c.sourceString); return params; }, FunctionParameters_single(identifier) { return [identifier.sourceString]; }, FunctionTextExp_keyword(_keyword, _leftParen, exp, _rightParen) { return exp.eval(); }, id(first, rest) { const key = first.sourceString + rest.sourceString; return currentScope.resolve(key); }, AssignmentExp(exportKeyword, letKeyword, identifier, _operator, value) { var _a, _b; const isPublic = !!((_a = exportKeyword == null ? void 0 : exportKeyword.children) == null ? void 0 : _a.length); const isLet = !!((_b = letKeyword == null ? void 0 : letKeyword.children) == null ? void 0 : _b.length); const variableName = identifier.sourceString; const variableValue = value.eval(); currentScope.store(variableName, variableValue, { public: isPublic }, !isLet); return variableValue; }, ScopedExpressions_list(list) { const expressions = list.asIteration().children.map((c) => c.eval()); return expressions[expressions.length - 1]; }, GeneralExpression_rightComment(exp, _) { return exp.eval(); }, GeneralExpression_leftComment(_, exp) { return exp.eval(); }, Paren(_leftParen, exp, _rightParen) { return exp.eval(); }, OptionallyParen_paren(_leftParen, exp, _rightParen) { return exp.eval(); }, OptionallyBraced_brace(_leftBrace, exp, _rightBrace) { return exp.eval(); }, GeometryTaggedText(_keyword, exp) { return exp.eval(); }, GeometryCollectionText_present(_leftParen, list, _rightParen) { const geometries = (list || []).asIteration().children.map((c) => c.eval()); return turf3.geometryCollection(geometries).geometry; }, MultiPolygonText_present(_leftParen, list, _rightParen) { const polygons = list.asIteration().children.map((c) => c.eval()); return turf3.multiPolygon(polygons.map((p) => p.coordinates)).geometry; }, MultiLineStringText_present(_leftParen, list, _rightParen) { const lineStrings = list.asIteration().children.map((c) => c.eval()); return turf3.multiLineString(lineStrings.map((p) => p.coordinates)).geometry; }, MultiPointText_present(_leftParen, list, _rightParen) { const points = list.eval(); return turf3.multiPoint(points.map((p) => p.coordinates)).geometry; }, PolygonText_present(_leftParen, list, _rightParen) { const points = list.asIteration().children.map((c) => c.eval()); return turf3.polygon(points.map((p) => p.coordinates)).geometry; }, LineStringText_present(_leftParen, list, _rightParen) { const points = list.eval(); return turf3.lineString(points.map((p) => p.coordinates)).geometry; }, PointList(list) { return list.asIteration().children.map((c) => c.eval()); }, PointTaggedText(_, point4) { return point4.eval(); }, PointText_present(_leftParen, point4, _rightParen) { return point4.eval(); }, Point(x, y) { return turf3.point([x.eval(), y.eval()]).geometry; }, ArithmeticAdd_plus(a, _, b) { const result2 = arithmeticOperationExp(a, b, (a2, b2) => a2 + b2); if (result2 !== void 0) { return result2; } throw new OperationNotSupported(`${toString(a.eval())} + ${toString(b.eval())}`); }, ArithmeticAdd_minus(a, _, b) { const result2 = arithmeticOperationExp(a, b, (a2, b2) => a2 - b2); if (result2 !== void 0) { return result2; } throw new OperationNotSupported(`${toString(a.eval())} - ${toString(b.eval())}`); }, ArithmeticMul_times(a, _, b) { const result2 = arithmeticOperationExp(a, b, (a2, b2) => a2 * b2); if (result2 !== void 0) { return result2; } throw new OperationNotSupported(`${toString(a.eval())} * ${toString(b.eval())}`); }, ArithmeticMul_divide(a, _, b) { const result2 = arithmeticOperationExp(a, b, (a2, b2) => a2 / b2); if (result2 !== void 0) { return result2; } throw new OperationNotSupported(`${toString(a.eval())} / ${toString(b.eval())}`); }, ArithmeticMul_mod(a, _, b) { const result2 = arithmeticOperationExp(a, b, (a2, b2) => a2 % b2); if (result2 !== void 0) { return result2; } throw new OperationNotSupported(`${toString(a.eval())} % ${toString(b.eval())}`); }, ArithmeticExp_power(a, _, b) { const result2 = arithmeticOperationExp(a, b, (a2, b2) => Math.pow(a2, b2)); if (result2 !== void 0) { return result2; } throw new OperationNotSupported(`${toString(a.eval())} ^ ${toString(b.eval())}`); }, ArithmeticPri_paren(_l, exp, _r) { return exp.eval(); }, exactNumericLiteral_decimalWithWholeNumber(whole, _, decimal) { return parseFloat(`${whole.sourceString}.${decimal.sourceString}`); }, exactNumericLiteral_decimalWithoutWholeNumber(_, decimal) { return parseFloat(`.${decimal.sourceString}`); }, exactNumericLiteral_wholeNumber(whole) { return parseInt(`${whole.sourceString}`); }, approximateNumericLiteral(mantissa, e, exponent) { return parseFloat(`${mantissa.eval()}${e}${exponent.eval()}`); }, signedNumericLiteral_signPresent(sign, numericLiteral) { return parseFloat(`${sign.sourceString}${numericLiteral.eva