UNPKG

wael-lib

Version:

Well-Known Text Arithmetic Expression Language

1,389 lines (1,342 loc) 59 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 turf3 = _interopRequireWildcard(_turf); var turf2 = _interopRequireWildcard(_turf); var turf = _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 INDENT = " "; 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 point3 = turf.point(coords).geometry; return coordsMapFn(point3).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"); var objectToString = /* @__PURE__ */ __name((obj, includeHistory = true) => { const bindings = Object.keys(obj != null ? obj : {}).filter((identifier) => { var _a; return identifier !== "toString" && (includeHistory || !(identifier == null ? void 0 : identifier.startsWith("$"))) && ((_a = obj[identifier]) != null ? _a : null) !== null; }).map((identifier) => { const value = obj[identifier]; let strValue; if (value == null ? void 0 : value.toStringShort) { strValue = value.toStringShort(); } else if (typeof value === "object") { if (isAnyGeometryType(value)) { strValue = value == null ? void 0 : value.type; } else { strValue = `Module(...)`; } } else if (typeof value === "string") { strValue = `"${value}"`; } else if (typeof value === "function") { strValue = `<Native Function>`; } else { strValue = value; } return `${INDENT}${identifier} = ${strValue}`; }); return `Module( ${bindings.join("\n")} )`; }, "objectToString"); var generateGeometries = /* @__PURE__ */ __name((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, num); while (condition) { const result = mapFn(i); if (result !== void 0) { if (!isAnyGeometryType(result)) { throw new Error(`Expected geometry type return value but got: ${toString(result)}`); } items.push(result); } condition = num(++i); } } else { for (let i = 0; i < num; i++) { const result = mapFn(i, num); if (result !== void 0) { if (!isAnyGeometryType(result)) { throw new Error(`Expected geometry type return value but got: ${toString(result)}`); } items.push(result); } } } return turf.geometryCollection(items).geometry; }, "generateGeometries"); // package.json var package_default = { name: "wael-lib", version: "0.0.25", description: "Well-Known Text Arithmetic Expression Language", bin: { wael: "./dist/wael/wael.cjs" }, repository: { type: "git", url: "git+https://github.com/anthonydgj/wael.git" }, files: [ "dist", "examples" ], browser: { fs: false, path: false, os: false }, type: "commonjs", main: "dist/cjs/index.cjs", module: "dist/esm/index.mjs", types: "dist/cjs/index.d.ts", exports: { "./package.json": "./package.json", ".": { import: { types: "./dist/esm/index.d.mts", default: "./dist/esm/index.mjs" }, require: { types: "./dist/cjs/index.d.ts", default: "./dist/cjs/index.cjs" } } }, scripts: { build: "tsup --config ./tsup.config.ts", "build-all": "npm run build-binary && npm run build-release-binaries", "build-binary": 'npm run build && pkg ./dist/wael/wael.cjs -t=latest --no-bytecode --public-packages "*" --public --out-path dist/bin/', "build-release-binaries": 'pkg ./dist/wael/wael.cjs -t=latest,latest-macos-arm64,latest-linuxstatic-x64,latest-win-x64 --no-bytecode --public-packages "*" --public --out-path dist/bin/release/', test: "jest", "publish-lib": "npm run build && npm test && npm publish" }, author: "AnthonyDGJ", license: "MIT", devDependencies: { "@types/geojson": "^7946.0.16", "@types/jest": "^29.5.14", "@types/sync-fetch": "^0.4.3", "@types/wellknown": "^0.5.8", jest: "^29.7.0", pkg: "^5.8.1", "ts-jest": "^29.3.2", "ts-node": "^10.9.2", tsup: "^8.4.0", typescript: "^5.8.3" }, dependencies: { "@turf/turf": "^7.2.0", chalk: "^4.1.2", fs: "^0.0.1-security", "ohm-js": "^17.1.0", "sync-fetch": "^0.6.0-2", tslib: "^2.8.1", wellknown: "^0.5.0", yargs: "^17.7.2" }, keywords: [ "wkt", "well-known text", "ohm", "dsl", "domain-specific language", "geospatial" ] }; // src/interpreter/scope.ts var _Scope = class _Scope { constructor(parent, level = 0, defaultBindings = {}) { this.parent = parent; this.level = level; this.IDENTIFIER_SCOPE = "$SCOPE"; this.IDENTIFIER_VERSION = "$VERSION"; this.bindings = {}; this.availableBindings = {}; this.metadata = {}; this.closures = []; 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; } for (const closure of this.closures) { if (closure.bindings.hasOwnProperty(identifier)) { return closure; } } if (this.parent) { return this.parent.resolveScope(identifier); } return void 0; } resolve(identifier) { var _a, _b; const scope = (_a = this.resolveScope(identifier)) != null ? _a : this; const binding = scope.bindings[identifier]; if (!binding) { if (identifier === this.IDENTIFIER_SCOPE) { const currentBindings = __spreadValues({}, scope.bindings); currentBindings.toString = function() { return objectToString(currentBindings, false); }; return currentBindings; } if (identifier === this.IDENTIFIER_VERSION) { return ((_b = package_default) == null ? void 0 : _b.version) || "UNKNOWN"; } } return binding; } 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({}, scopeBindings); } useImports(selectedIdentifiers) { let selectedBindings = {}; if (selectedIdentifiers) { selectedIdentifiers.forEach((selectedIdentifier) => { selectedBindings[selectedIdentifier] = this.availableBindings[selectedIdentifier]; delete 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.store(selectedIdentifier, this.availableBindings[selectedIdentifier]); delete this.availableBindings[selectedIdentifier]; }); } return selectedBindings; } capture(capturedScope) { this.closures.push(capturedScope); } release() { this.closures.pop(); } }; __name(_Scope, "Scope"); var Scope = _Scope; // 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<ComputedValue<FunctionCallExp>> importKeyword = caseInsensitive<"use"> usingKeyword = caseInsensitive<"with"> // 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 | AccessibleExp<GeometryExp> | NumberExp | 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 Pipeable = FunctionCallExp | Callable GenerateExp = GenerateSymbolExp GenerateSymbolExp = GenerateCountExpr ">>" ComputedGenerateValue GenerateCountExpr = ComputedValue<NumberExp> | FunctionTextExp ConcatExp = MappableValue concatOperator MappableValue ComputedGenerateValue = FunctionExp | ComputedValue<GenerateValue> GenerateValue = GeometryExp | FunctionTextExp 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 | spreadOperator anyPipeOperator = doublePipeOperator | coordinatesPipeOperator | filterOperator | reduceOperator | pipeOperator pipeOperator = "|" coordinatesPipeOperator = "|*" doublePipeOperator = "||" filterOperator = "|~" reduceOperator = "|>" concatOperator = "++" plusOperator = "+" minusOperator = "-" timesOperator = "*" divideOperator = "/" powerOperator = "^" modOperator = "%" accessorOperator = ":" spreadOperator = "..." // Function expressions FunctionTextExp = functionKeyword LeftParen FunctionExp RightParen --keyword | OptionallyParen<FunctionExp> FunctionExp = FunctionParameters "=>" OptionallyParen<FunctionBody> FunctionParameters = | LeftParen spreadOperator Identifier RightParen --spread | 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 | LogicalExp | booleanValue | Paren<BooleanResultExp> EqualityExp = ComparePrimitive equalityOperatorPrimitive ComparePrimitive NotExp = notOperator ComparePrimitive CompareExp = ComparePrimitive compareOperatorPrimitive ComparePrimitive LogicalExp = LogicalPrimitive logicalOperator LogicalPrimitive ComparePrimitive = BooleanResultExp | ComputedValue<NumberExp> | AccessibleExp<GeometryExp> | geometryKeyword LogicalPrimitive = ComputedValue<BooleanResultExp> conditionalOperator = compareOperatorPrimitive | equalityOperatorPrimitive compareOperatorPrimitive = "<=" | ">=" | "<" | ">" equalityOperatorPrimitive = | "==" | "!=" 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> | GeometryCollectionLiteral GeometryCollectionText = emptySet --empty | LeftParen ListOf<GeometryExp, Comma> RightParen --present geometryCollectionKeyword = caseInsensitive<"GEOMETRYCOLLECTION"> GeometryCollectionLiteral = Paren<GeometryCollectionParameters> GeometryCollectionParameters = ListOf<GeometryExp, Comma> 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 | MultiPoint MultiPoint = Paren<PointList> multiPointKeyword = caseInsensitive<"MULTIPOINT"> // Base point type helpers PointList = PointListLiteral | PointListSpread PointListLiteral = NonemptyListOf<PointListArgument, Comma> PointListSpread = spreadOperator Identifier 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 | 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 _path = require('path'); var _path2 = _interopRequireDefault(_path); var _fs = require('fs'); var _syncfetch = require('sync-fetch'); var _syncfetch2 = _interopRequireDefault(_syncfetch); var grammarString = GRAMMAR; var Interpreter; ((Interpreter2) => { Interpreter2.IMPORT_USING_ALL = "*"; Interpreter2.DEFAULT_EXPORT_BINDING = "export"; Interpreter2.STANDARD_LIBRARY = {}; const math = {}; Object.getOwnPropertyNames(Math).forEach((prop) => { math[prop] = Math[prop]; }); Interpreter2.STANDARD_LIBRARY["Math"] = math; Interpreter2.createGlobalScope = /* @__PURE__ */ __name(() => new Scope(void 0, void 0, Interpreter2.STANDARD_LIBRARY), "createGlobalScope"); function evaluateInput(input, initialScope, workingDirectory = ".") { 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(); const importObj = currentScope.useImports(); if (importObj && Object.keys(importObj).length > 0) { if ((ret != null ? ret : null) !== null) { importObj[Interpreter2.DEFAULT_EXPORT_BINDING] = ret; } importObj.toString = function() { return objectToString(importObj); }; return importObj; } return ret; }, 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, _path2.default.join(workingDirectory, uri), "utf8"); } currentScope = currentScope.push(); let ret = void 0; try { ret = convertToGeometry(JSON.parse(data)); } catch (e) { try { const libRet = evaluateInput(data, currentScope, workingDirectory); if (libRet) { ret = libRet; } } catch (e2) { throw new Error(`Unable to import file: ${uri}`); } } currentScope = currentScope.pop() || GLOBAL_SCOPE; return ret; }, ImportFunctionExp(_keyword, importFn) { return 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; } throw new Error(`Operator not supported: ${operator}`); }, LogicalExp(v1, op, v2) { const value1 = v1.eval(); const operator = op.sourceString; const value2 = v2.eval(); switch (operator.trim().toLocaleLowerCase()) { 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 turf2.lineString(combined).geometry; } if (type1 === "MultiPoint" /* MultiPoint */) { return turf2.multiPoint(combined).geometry; } if (type1 === "GeometryCollection" /* GeometryCollection */) { return turf2.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 turf2.lineString(combined).geometry; } if (type1 === "MultiPoint" /* MultiPoint */) { return turf2.multiPoint(combined).geometry; } if (type1 === "GeometryCollection" /* GeometryCollection */) { return turf2.geometryCollection(combined).geometry; } } } if (type1 === "GeometryCollection" /* GeometryCollection */) { return turf2.geometryCollection(geom1.geometries.concat([geom2])).geometry; } if (type2 === "GeometryCollection" /* GeometryCollection */) { return turf2.geometryCollection([geom1].concat(...geom2.geometries)).geometry; } return turf2.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 turf2.geometryCollection(mappedList).geometry; } if (isGeometryType("LineString" /* LineString */, val)) { let mappedList = listFn.call( list.map((coords) => turf2.point(coords).geometry), fn ); if (isAnyGeometryType(mappedList)) { return mappedList; } mappedList = mappedList.map((v) => v.coordinates); return turf2.lineString(mappedList).geometry; } if (isGeometryType("MultiPoint" /* MultiPoint */, val)) { let mappedList = listFn.call( list.map((coords) => turf2.point(coords).geometry), fn ); if (isAnyGeometryType(mappedList)) { return mappedList; } mappedList = mappedList.map((v) => v.coordinates); return turf2.multiPoint(mappedList).geometry; } throw Error(`Error mapping values to geometries`); }, TopLevel(scopedExpressions, _end) { let lastValue = scopedExpressions.eval(); return lastValue; }, GenerateSymbolExp(numExp, _symbol, valueExp) { return generateGeometries(numExp, valueExp); }, FunctionCallExp(callable, p) { var _a; let fn = callable.eval(); const params = p.eval(); if ((fn != null ? fn : null) === null) { throw new Error(`${callable.sourceString} is: ${fn}`); } if (typeof fn === "object" && ((_a = fn[Interpreter2.DEFAULT_EXPORT_BINDING]) != null ? _a : null) !== null) { fn = fn[Interpreter2.DEFAULT_EXPORT_BINDING]; } if (typeof fn !== "function") { return fn; } fn.context = { currentScope }; return fn(...params); }, 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(); let isSpread = false; if (!Array.isArray(params)) { isSpread = params == null ? void 0 : params.isSpread; } params = Array.isArray(params) ? params : [params]; let fnScope = currentScope; const fn = /* @__PURE__ */ __name((...values) => { var _a; const contextScope = ((_a = fn == null ? void 0 : fn.context) == null ? void 0 : _a.currentScope) || currentScope; currentScope = contextScope.push(); currentScope.capture(fnScope); if (isSpread) { const geometries = turf2.geometryCollection(values).geometry; currentScope.store(params[0].identifier, geometries, void 0, false); } else { params.forEach((paramName, index) => { currentScope.store(paramName, values[index], void 0, false); }); } const ret = body.eval(); currentScope = currentScope.pop() || GLOBAL_SCOPE; return ret; }, "fn"); fn.toString = function() { return `Function(${p.sourceString} => ${body.sourceString})`; }; fn.toStringShort = function() { return `Function(${p.sourceString} => (...))`; }; return fn; }, FunctionParameters_spread(_leftParen, _operator, identifier, _rightParen) { return { identifier: identifier.sourceString, isSpread: true }; }, 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 turf2.geometryCollection(geometries).geometry; }, GeometryCollectionParameters(list) { const geometries = (list || []).asIteration().children.map((c) => c.eval()); return turf2.geometryCollection(geometries).geometry; }, MultiPolygonText_present(_leftParen, list, _rightParen) { const polygons = list.asIteration().children.map((c) => c.eval()); return turf2.multiPolygon(polygons.map((p) => p.coordinates)).geometry; }, MultiLineStringText_present(_leftParen, list, _rightParen) { const lineStrings = list.asIteration().children.map((c) => c.eval()); return turf2.multiLineString(lineStrings.map((p) => p.coordinates)).geometry; }, MultiPointText(multiPoint3) { return multiPoint3.eval(); }, MultiPoint(list) { const points = list.eval(); return turf2.multiPoint(points.map((p) => p.coordinates)).geometry; }, PolygonText_present(_leftParen, list, _rightParen) { const points = list.asIteration().children.map((c) => c.eval()); return turf2.polygon(points.map((p) => p.coordinates)).geometry; }, LineStringText_present(_leftParen, list, _rightParen) { const points = list.eval(); return turf2.lineString(points.map((p) => p.coordinates)).geometry; }, PointListLiteral(list) { return list.asIteration().children.map((c) => c.eval()); }, PointListSpread(_op, collection) { return getArrayLikeItems(collection.eval()); }, PointTaggedText(_, point3) { return point3.eval(); }, PointText_present(_leftParen, point3, _rightParen) { return point3.eval(); }, Point(x, y) { return turf2.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())}