@lbdudc/gp-gis-dsl 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +7 -0
- package/grammar/.antlr/GISGrammar.interp +182 -0
- package/grammar/.antlr/GISGrammar.tokens +73 -0
- package/grammar/.antlr/GISGrammarBaseListener.java +579 -0
- package/grammar/.antlr/GISGrammarLexer.interp +241 -0
- package/grammar/.antlr/GISGrammarLexer.java +686 -0
- package/grammar/.antlr/GISGrammarLexer.tokens +73 -0
- package/grammar/.antlr/GISGrammarListener.java +459 -0
- package/grammar/.antlr/GISGrammarParser.java +2948 -0
- package/grammar/GISGrammar.g4 +313 -313
- package/package.json +1 -1
- package/parse-file.js +73 -0
- package/src/GISVisitorHelper.js +93 -93
- package/src/cli.js +34 -34
- package/src/error/ErrorListener.js +26 -26
- package/src/error/SyntaxGenericError.js +18 -18
- package/src/index.js +4 -1
- package/src/lib/GISGrammar.interp +181 -181
- package/src/lib/GISGrammarLexer.interp +241 -241
- package/src/lib/GISGrammarLexer.js +202 -202
- package/src/lib/GISGrammarListener.js +1 -1
- package/src/lib/GISGrammarParser.js +1 -1
- package/src/lib/GISGrammarVisitor.js +1 -1
- package/src/spl/GIS.js +234 -234
- package/src/spl/GeoJSONLayer.js +21 -21
- package/src/spl/GeoJSONLayerStyle.js +14 -14
- package/src/spl/TileLayer.js +16 -16
- package/src/spl/WMSLayer.js +30 -30
- package/src/spl/WMSStyle.js +13 -13
- package/src/spl/WMSStyleCustom.js +22 -22
- package/src/store.js +74 -74
- package/test-examples.js +120 -0
- package/test-output/agriculture.json +429 -0
- package/test-output/basic.json +315 -0
- package/test-output/complete.json +1259 -0
- package/test-output/emergency.json +755 -0
- package/test-output/environmental.json +591 -0
- package/test-output/gis.json +254 -0
- package/test-output/tourism.json +704 -0
- package/test-output/transportation.json +488 -0
- package/test-output/utilities.json +620 -0
- package/test-output/wms.json +110 -0
package/parse-file.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Simple utility to read a GIS DSL file and parse it
|
|
5
|
+
* Usage: node parse-file.js <path-to-file.txt> [--debug]
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
import parse from './src/index.js';
|
|
12
|
+
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = path.dirname(__filename);
|
|
15
|
+
|
|
16
|
+
// Parse command line arguments
|
|
17
|
+
const args = process.argv.slice(2);
|
|
18
|
+
const debugMode = args.includes('--debug');
|
|
19
|
+
const filePath = args.find(arg => !arg.startsWith('--'));
|
|
20
|
+
|
|
21
|
+
if (!filePath) {
|
|
22
|
+
console.error('Error: No file path provided');
|
|
23
|
+
console.log('\nUsage: node parse-file.js <path-to-file.txt> [--debug]');
|
|
24
|
+
console.log('Example: node parse-file.js examples/basic.txt');
|
|
25
|
+
console.log('Example: node parse-file.js examples/basic.txt --debug');
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Resolve the file path
|
|
30
|
+
const resolvedPath = path.isAbsolute(filePath)
|
|
31
|
+
? filePath
|
|
32
|
+
: path.join(__dirname, filePath);
|
|
33
|
+
|
|
34
|
+
// Check if file exists
|
|
35
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
36
|
+
console.error(`Error: File not found: ${resolvedPath}`);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
console.log(`Reading file: ${resolvedPath}\n`);
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
// Read the file content
|
|
44
|
+
const content = fs.readFileSync(resolvedPath, 'utf8');
|
|
45
|
+
console.log(`File size: ${content.length} characters\n`);
|
|
46
|
+
|
|
47
|
+
if (debugMode) {
|
|
48
|
+
console.log('=== FILE CONTENT ===');
|
|
49
|
+
console.log(content);
|
|
50
|
+
console.log('\n=== PARSING ===\n');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Parse the content
|
|
54
|
+
const result = parse(content, debugMode);
|
|
55
|
+
|
|
56
|
+
if (result) {
|
|
57
|
+
console.log('✓ Parsing successful!\n');
|
|
58
|
+
console.log('=== GENERATED PRODUCT ===');
|
|
59
|
+
console.log(JSON.stringify(result, null, 2));
|
|
60
|
+
} else {
|
|
61
|
+
console.log('⚠ Parsing completed but no product was generated');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
process.exit(0);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error('✗ Parsing failed!');
|
|
67
|
+
console.error(`Error: ${error.message}`);
|
|
68
|
+
if (debugMode && error.stack) {
|
|
69
|
+
console.error('\nStack trace:');
|
|
70
|
+
console.error(error.stack);
|
|
71
|
+
}
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
package/src/GISVisitorHelper.js
CHANGED
|
@@ -1,93 +1,93 @@
|
|
|
1
|
-
import features from "./features.js";
|
|
2
|
-
|
|
3
|
-
function transformation(spec) {
|
|
4
|
-
_relationships(spec);
|
|
5
|
-
const newSpec = {
|
|
6
|
-
features: features,
|
|
7
|
-
basicData: {
|
|
8
|
-
name: spec.name,
|
|
9
|
-
},
|
|
10
|
-
data: {
|
|
11
|
-
dataModel: {
|
|
12
|
-
entities: spec.entities,
|
|
13
|
-
enums: [],
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
mapViewer: {
|
|
17
|
-
maps: spec.maps,
|
|
18
|
-
layers: spec.layers,
|
|
19
|
-
styles: spec.styles,
|
|
20
|
-
},
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
if (spec.extra) {
|
|
24
|
-
newSpec.basicData.extra = spec.extra;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return newSpec;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function _relationships(spec) {
|
|
31
|
-
let source, target;
|
|
32
|
-
|
|
33
|
-
spec.relationships.forEach((r) => {
|
|
34
|
-
source = spec.getEntity(r.source);
|
|
35
|
-
target = spec.getEntity(r.target);
|
|
36
|
-
let sourceOwner = false;
|
|
37
|
-
let targetOwner = false;
|
|
38
|
-
let sourceMultiple = _multiple(r.sourceOpts.multiplicity);
|
|
39
|
-
let targetMultiple = _multiple(r.targetOpts.multiplicity);
|
|
40
|
-
if (sourceMultiple && !targetMultiple) {
|
|
41
|
-
targetOwner = true;
|
|
42
|
-
} else {
|
|
43
|
-
sourceOwner = true;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
source.properties.push({
|
|
47
|
-
name: r.sourceOpts.label,
|
|
48
|
-
class: target.name,
|
|
49
|
-
owner: sourceOwner,
|
|
50
|
-
bidirectional: r.targetOpts.label,
|
|
51
|
-
multiple: sourceMultiple,
|
|
52
|
-
required: _required(r.sourceOpts.multiplicity),
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
target.properties.push({
|
|
56
|
-
name: r.targetOpts.label,
|
|
57
|
-
class: source.name,
|
|
58
|
-
owner: targetOwner,
|
|
59
|
-
bidirectional: r.sourceOpts.label,
|
|
60
|
-
multiple: targetMultiple,
|
|
61
|
-
required: _required(r.targetOpts.multiplicity),
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function _multiple(multiplicity) {
|
|
67
|
-
return ["1..1", "0..1"].find((a) => a == multiplicity) == null;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function _required(multiplicity) {
|
|
71
|
-
return ["1..1", "1..*"].find((a) => a == multiplicity) != null;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function getPropertyParams(symbols) {
|
|
75
|
-
if (!symbols.length) return null;
|
|
76
|
-
|
|
77
|
-
const ret = {};
|
|
78
|
-
if (symbols.includes("identifier")) {
|
|
79
|
-
ret.pk = true;
|
|
80
|
-
}
|
|
81
|
-
if (symbols.includes("required")) {
|
|
82
|
-
ret.required = true;
|
|
83
|
-
}
|
|
84
|
-
if (symbols.includes("unique")) {
|
|
85
|
-
ret.unique = true;
|
|
86
|
-
}
|
|
87
|
-
if (symbols.includes("display_string")) {
|
|
88
|
-
ret.displayString = true;
|
|
89
|
-
}
|
|
90
|
-
return ret;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export { transformation, getPropertyParams };
|
|
1
|
+
import features from "./features.js";
|
|
2
|
+
|
|
3
|
+
function transformation(spec) {
|
|
4
|
+
_relationships(spec);
|
|
5
|
+
const newSpec = {
|
|
6
|
+
features: features,
|
|
7
|
+
basicData: {
|
|
8
|
+
name: spec.name,
|
|
9
|
+
},
|
|
10
|
+
data: {
|
|
11
|
+
dataModel: {
|
|
12
|
+
entities: spec.entities,
|
|
13
|
+
enums: [],
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
mapViewer: {
|
|
17
|
+
maps: spec.maps,
|
|
18
|
+
layers: spec.layers,
|
|
19
|
+
styles: spec.styles,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
if (spec.extra) {
|
|
24
|
+
newSpec.basicData.extra = spec.extra;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return newSpec;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function _relationships(spec) {
|
|
31
|
+
let source, target;
|
|
32
|
+
|
|
33
|
+
spec.relationships.forEach((r) => {
|
|
34
|
+
source = spec.getEntity(r.source);
|
|
35
|
+
target = spec.getEntity(r.target);
|
|
36
|
+
let sourceOwner = false;
|
|
37
|
+
let targetOwner = false;
|
|
38
|
+
let sourceMultiple = _multiple(r.sourceOpts.multiplicity);
|
|
39
|
+
let targetMultiple = _multiple(r.targetOpts.multiplicity);
|
|
40
|
+
if (sourceMultiple && !targetMultiple) {
|
|
41
|
+
targetOwner = true;
|
|
42
|
+
} else {
|
|
43
|
+
sourceOwner = true;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
source.properties.push({
|
|
47
|
+
name: r.sourceOpts.label,
|
|
48
|
+
class: target.name,
|
|
49
|
+
owner: sourceOwner,
|
|
50
|
+
bidirectional: r.targetOpts.label,
|
|
51
|
+
multiple: sourceMultiple,
|
|
52
|
+
required: _required(r.sourceOpts.multiplicity),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
target.properties.push({
|
|
56
|
+
name: r.targetOpts.label,
|
|
57
|
+
class: source.name,
|
|
58
|
+
owner: targetOwner,
|
|
59
|
+
bidirectional: r.sourceOpts.label,
|
|
60
|
+
multiple: targetMultiple,
|
|
61
|
+
required: _required(r.targetOpts.multiplicity),
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function _multiple(multiplicity) {
|
|
67
|
+
return ["1..1", "0..1"].find((a) => a == multiplicity) == null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function _required(multiplicity) {
|
|
71
|
+
return ["1..1", "1..*"].find((a) => a == multiplicity) != null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function getPropertyParams(symbols) {
|
|
75
|
+
if (!symbols.length) return null;
|
|
76
|
+
|
|
77
|
+
const ret = {};
|
|
78
|
+
if (symbols.includes("identifier")) {
|
|
79
|
+
ret.pk = true;
|
|
80
|
+
}
|
|
81
|
+
if (symbols.includes("required")) {
|
|
82
|
+
ret.required = true;
|
|
83
|
+
}
|
|
84
|
+
if (symbols.includes("unique")) {
|
|
85
|
+
ret.unique = true;
|
|
86
|
+
}
|
|
87
|
+
if (symbols.includes("display_string")) {
|
|
88
|
+
ret.displayString = true;
|
|
89
|
+
}
|
|
90
|
+
return ret;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export { transformation, getPropertyParams };
|
package/src/cli.js
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import meow from "meow";
|
|
4
|
-
import fs from "fs";
|
|
5
|
-
import gisdslParser from "./index.js";
|
|
6
|
-
import path from "path";
|
|
7
|
-
|
|
8
|
-
const usage = "Usage: gisdsl input output";
|
|
9
|
-
|
|
10
|
-
const cli = meow(usage, {
|
|
11
|
-
importMeta: import.meta,
|
|
12
|
-
flags: {
|
|
13
|
-
debug: {
|
|
14
|
-
type: "boolean",
|
|
15
|
-
default: false,
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
if (cli.input.length < 2) {
|
|
21
|
-
cli.showHelp();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const inputPath = path.resolve(process.cwd(), cli.input.at(0));
|
|
25
|
-
const input = fs.readFileSync(inputPath, {
|
|
26
|
-
encoding: "utf-8",
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
const spec = gisdslParser(input, cli.flags.debug);
|
|
30
|
-
|
|
31
|
-
const outputPath = path.resolve(process.cwd(), cli.input.at(1));
|
|
32
|
-
fs.writeFileSync(outputPath, JSON.stringify(spec, null, 2), "utf8");
|
|
33
|
-
|
|
34
|
-
console.log(`File ${cli.input.at(1)} generated`);
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import meow from "meow";
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import gisdslParser from "./index.js";
|
|
6
|
+
import path from "path";
|
|
7
|
+
|
|
8
|
+
const usage = "Usage: gisdsl input output";
|
|
9
|
+
|
|
10
|
+
const cli = meow(usage, {
|
|
11
|
+
importMeta: import.meta,
|
|
12
|
+
flags: {
|
|
13
|
+
debug: {
|
|
14
|
+
type: "boolean",
|
|
15
|
+
default: false,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
if (cli.input.length < 2) {
|
|
21
|
+
cli.showHelp();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const inputPath = path.resolve(process.cwd(), cli.input.at(0));
|
|
25
|
+
const input = fs.readFileSync(inputPath, {
|
|
26
|
+
encoding: "utf-8",
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const spec = gisdslParser(input, cli.flags.debug);
|
|
30
|
+
|
|
31
|
+
const outputPath = path.resolve(process.cwd(), cli.input.at(1));
|
|
32
|
+
fs.writeFileSync(outputPath, JSON.stringify(spec, null, 2), "utf8");
|
|
33
|
+
|
|
34
|
+
console.log(`File ${cli.input.at(1)} generated`);
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import antlr4 from "antlr4";
|
|
2
|
-
|
|
3
|
-
import SyntaxGenericError from "./SyntaxGenericError.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Custom Error Listener
|
|
7
|
-
*
|
|
8
|
-
* @returns {object}
|
|
9
|
-
*/
|
|
10
|
-
class ErrorListener extends antlr4.error.ErrorListener {
|
|
11
|
-
/**
|
|
12
|
-
* Checks syntax error
|
|
13
|
-
*
|
|
14
|
-
* @param {object} recognizer The parsing support code essentially. Most of it is error recovery stuff
|
|
15
|
-
* @param {object} symbol Offending symbol
|
|
16
|
-
* @param {int} line Line of offending symbol
|
|
17
|
-
* @param {int} column Position in line of offending symbol
|
|
18
|
-
* @param {string} message Error message
|
|
19
|
-
* @param {string} payload Stack trace
|
|
20
|
-
*/
|
|
21
|
-
syntaxError(recognizer, symbol, line, column, message) {
|
|
22
|
-
throw new SyntaxGenericError({ line, column, message });
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export default ErrorListener;
|
|
1
|
+
import antlr4 from "antlr4";
|
|
2
|
+
|
|
3
|
+
import SyntaxGenericError from "./SyntaxGenericError.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Custom Error Listener
|
|
7
|
+
*
|
|
8
|
+
* @returns {object}
|
|
9
|
+
*/
|
|
10
|
+
class ErrorListener extends antlr4.error.ErrorListener {
|
|
11
|
+
/**
|
|
12
|
+
* Checks syntax error
|
|
13
|
+
*
|
|
14
|
+
* @param {object} recognizer The parsing support code essentially. Most of it is error recovery stuff
|
|
15
|
+
* @param {object} symbol Offending symbol
|
|
16
|
+
* @param {int} line Line of offending symbol
|
|
17
|
+
* @param {int} column Position in line of offending symbol
|
|
18
|
+
* @param {string} message Error message
|
|
19
|
+
* @param {string} payload Stack trace
|
|
20
|
+
*/
|
|
21
|
+
syntaxError(recognizer, symbol, line, column, message) {
|
|
22
|
+
throw new SyntaxGenericError({ line, column, message });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default ErrorListener;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
export default class SyntaxGenericError extends Error {
|
|
2
|
-
constructor(payload) {
|
|
3
|
-
super(payload);
|
|
4
|
-
|
|
5
|
-
this.code = "E_SYNTAX_GENERIC";
|
|
6
|
-
this.message = "Something went wrong";
|
|
7
|
-
|
|
8
|
-
if (typeof payload !== "undefined") {
|
|
9
|
-
this.message = payload.message || this.message;
|
|
10
|
-
this.payload = payload;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
console.error(
|
|
14
|
-
`line ${this.payload.line}, col ${this.payload.column}: ${this.payload.message}`,
|
|
15
|
-
);
|
|
16
|
-
Error.captureStackTrace(this, SyntaxGenericError);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
1
|
+
export default class SyntaxGenericError extends Error {
|
|
2
|
+
constructor(payload) {
|
|
3
|
+
super(payload);
|
|
4
|
+
|
|
5
|
+
this.code = "E_SYNTAX_GENERIC";
|
|
6
|
+
this.message = "Something went wrong";
|
|
7
|
+
|
|
8
|
+
if (typeof payload !== "undefined") {
|
|
9
|
+
this.message = payload.message || this.message;
|
|
10
|
+
this.payload = payload;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
console.error(
|
|
14
|
+
`line ${this.payload.line}, col ${this.payload.column}: ${this.payload.message}`,
|
|
15
|
+
);
|
|
16
|
+
Error.captureStackTrace(this, SyntaxGenericError);
|
|
17
|
+
}
|
|
18
|
+
}
|
package/src/index.js
CHANGED