@malloydata/malloy-tag 0.0.339 → 0.0.341
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/dist/index.d.ts +1 -3
- package/dist/index.js +4 -5
- package/dist/index.js.map +1 -1
- package/dist/{peggy/index.d.ts → parser.d.ts} +13 -4
- package/dist/parser.js +181 -0
- package/dist/parser.js.map +1 -0
- package/package.json +12 -5
- package/src/index.ts +1 -3
- package/src/parser.ts +203 -0
- package/CONTEXT.md +0 -173
- package/README.md +0 -0
- package/dist/peggy/dist/peg-tag-parser.d.ts +0 -11
- package/dist/peggy/dist/peg-tag-parser.js +0 -3130
- package/dist/peggy/dist/peg-tag-parser.js.map +0 -1
- package/dist/peggy/index.js +0 -117
- package/dist/peggy/index.js.map +0 -1
- package/dist/peggy/interpreter.d.ts +0 -32
- package/dist/peggy/interpreter.js +0 -208
- package/dist/peggy/interpreter.js.map +0 -1
- package/dist/peggy/statements.d.ts +0 -51
- package/dist/peggy/statements.js +0 -7
- package/dist/peggy/statements.js.map +0 -1
- package/dist/schema.d.ts +0 -41
- package/dist/schema.js +0 -573
- package/dist/schema.js.map +0 -1
- package/dist/schema.spec.d.ts +0 -1
- package/dist/schema.spec.js +0 -980
- package/dist/schema.spec.js.map +0 -1
- package/dist/tags.spec.d.ts +0 -8
- package/dist/tags.spec.js +0 -884
- package/dist/tags.spec.js.map +0 -1
- package/dist/util.spec.d.ts +0 -1
- package/dist/util.spec.js +0 -43
- package/dist/util.spec.js.map +0 -1
- package/src/motly-schema.motly +0 -52
- package/src/peggy/dist/peg-tag-parser.js +0 -2790
- package/src/peggy/index.ts +0 -89
- package/src/peggy/interpreter.ts +0 -265
- package/src/peggy/malloy-tag.peggy +0 -224
- package/src/peggy/statements.ts +0 -49
- package/src/schema.spec.ts +0 -1280
- package/src/schema.ts +0 -852
- package/src/tags.spec.ts +0 -967
- package/src/util.spec.ts +0 -43
- package/tsconfig.json +0 -12
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -36,7 +36,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
36
36
|
};
|
|
37
37
|
})();
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.
|
|
39
|
+
exports.ParseUtil = exports.TagParser = exports.parseTag = void 0;
|
|
40
40
|
/*
|
|
41
41
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
42
42
|
*
|
|
@@ -44,9 +44,8 @@ exports.validateTag = exports.ParseUtil = exports.parseTag = void 0;
|
|
|
44
44
|
* LICENSE file in the root directory of this source tree.
|
|
45
45
|
*/
|
|
46
46
|
__exportStar(require("./tags"), exports);
|
|
47
|
-
var
|
|
48
|
-
Object.defineProperty(exports, "parseTag", { enumerable: true, get: function () { return
|
|
47
|
+
var parser_1 = require("./parser");
|
|
48
|
+
Object.defineProperty(exports, "parseTag", { enumerable: true, get: function () { return parser_1.parseTag; } });
|
|
49
|
+
Object.defineProperty(exports, "TagParser", { enumerable: true, get: function () { return parser_1.TagParser; } });
|
|
49
50
|
exports.ParseUtil = __importStar(require("./util"));
|
|
50
|
-
var schema_1 = require("./schema");
|
|
51
|
-
Object.defineProperty(exports, "validateTag", { enumerable: true, get: function () { return schema_1.validateTag; } });
|
|
52
51
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;GAKG;AACH,yCAAuB;AACvB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;GAKG;AACH,yCAAuB;AACvB,mCAA6C;AAArC,kGAAA,QAAQ,OAAA;AAAE,mGAAA,SAAS,OAAA;AAC3B,oDAAoC"}
|
|
@@ -1,13 +1,22 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { Tag } from './tags';
|
|
2
|
+
import type { TagParse } from './tags';
|
|
3
|
+
/**
|
|
4
|
+
* Session-based parser for Malloy tag language. Create an instance,
|
|
5
|
+
* call parse() for each line, then finish() to get the final Tag.
|
|
6
|
+
*/
|
|
7
|
+
export declare class TagParser {
|
|
8
|
+
private session;
|
|
9
|
+
constructor();
|
|
10
|
+
parse(source: string): TagParse;
|
|
11
|
+
finish(): Tag;
|
|
12
|
+
}
|
|
3
13
|
/**
|
|
4
14
|
* Parse Malloy tag language into a Tag which can be queried.
|
|
5
15
|
*
|
|
6
16
|
* @param source - A single string or array of strings to parse. If a string
|
|
7
17
|
* starts with #, all characters up to the first space are skipped.
|
|
8
18
|
* When an array is provided, strings are parsed sequentially and merged.
|
|
9
|
-
* @param extending - A tag which this parse will extend
|
|
10
19
|
* @returns TagParse with the resulting tag and any errors. For arrays,
|
|
11
20
|
* error line numbers indicate the index in the array where the error occurred.
|
|
12
21
|
*/
|
|
13
|
-
export declare function parseTag(source: string | string[]
|
|
22
|
+
export declare function parseTag(source: string | string[]): TagParse;
|
package/dist/parser.js
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright Contributors to the Malloy project
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.TagParser = void 0;
|
|
8
|
+
exports.parseTag = parseTag;
|
|
9
|
+
const motly_ts_parser_1 = require("@malloydata/motly-ts-parser");
|
|
10
|
+
const tags_1 = require("./tags");
|
|
11
|
+
/**
|
|
12
|
+
* Strip the Malloy tag prefix (e.g., "# " or "#(docs) ") from source.
|
|
13
|
+
*/
|
|
14
|
+
function stripPrefix(source) {
|
|
15
|
+
if (source[0] === '#') {
|
|
16
|
+
const skipTo = source.indexOf(' ');
|
|
17
|
+
if (skipTo > 0) {
|
|
18
|
+
return source.slice(skipTo);
|
|
19
|
+
}
|
|
20
|
+
return '';
|
|
21
|
+
}
|
|
22
|
+
return source;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Map a MOTLYError (from motly-ts parser) to a TagError.
|
|
26
|
+
*/
|
|
27
|
+
function mapMOTLYError(error) {
|
|
28
|
+
return {
|
|
29
|
+
code: error.code,
|
|
30
|
+
message: error.message,
|
|
31
|
+
line: error.begin.line,
|
|
32
|
+
offset: error.begin.column,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Parse a reference string like "$^^path.to[0].thing" back into
|
|
37
|
+
* structured form {ups, refPath}.
|
|
38
|
+
*/
|
|
39
|
+
function parseRefString(linkTo) {
|
|
40
|
+
let i = 1;
|
|
41
|
+
let ups = 0;
|
|
42
|
+
while (i < linkTo.length && linkTo[i] === '^') {
|
|
43
|
+
ups++;
|
|
44
|
+
i++;
|
|
45
|
+
}
|
|
46
|
+
const refPath = [];
|
|
47
|
+
const rest = linkTo.slice(i);
|
|
48
|
+
if (rest.length === 0) {
|
|
49
|
+
return { ups, refPath };
|
|
50
|
+
}
|
|
51
|
+
let pos = 0;
|
|
52
|
+
let needDot = false;
|
|
53
|
+
while (pos < rest.length) {
|
|
54
|
+
if (rest[pos] === '.') {
|
|
55
|
+
pos++;
|
|
56
|
+
needDot = false;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (rest[pos] === '[') {
|
|
60
|
+
const close = rest.indexOf(']', pos);
|
|
61
|
+
refPath.push(Number(rest.slice(pos + 1, close)));
|
|
62
|
+
pos = close + 1;
|
|
63
|
+
needDot = true;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (needDot) {
|
|
67
|
+
// Expected a dot separator but didn't get one
|
|
68
|
+
}
|
|
69
|
+
if (rest[pos] === '`') {
|
|
70
|
+
pos++;
|
|
71
|
+
let seg = '';
|
|
72
|
+
while (pos < rest.length && rest[pos] !== '`') {
|
|
73
|
+
if (rest[pos] === '\\') {
|
|
74
|
+
pos++;
|
|
75
|
+
seg += rest[pos];
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
seg += rest[pos];
|
|
79
|
+
}
|
|
80
|
+
pos++;
|
|
81
|
+
}
|
|
82
|
+
pos++;
|
|
83
|
+
refPath.push(seg);
|
|
84
|
+
needDot = true;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
let seg = '';
|
|
88
|
+
while (pos < rest.length &&
|
|
89
|
+
rest[pos] !== '.' &&
|
|
90
|
+
rest[pos] !== '[' &&
|
|
91
|
+
rest[pos] !== '`') {
|
|
92
|
+
seg += rest[pos];
|
|
93
|
+
pos++;
|
|
94
|
+
}
|
|
95
|
+
if (seg.length > 0) {
|
|
96
|
+
refPath.push(seg);
|
|
97
|
+
needDot = true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return { ups, refPath };
|
|
101
|
+
}
|
|
102
|
+
function isRef(node) {
|
|
103
|
+
return 'linkTo' in node;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Convert a MOTLYNode tree into a Tag tree with parent links.
|
|
107
|
+
*/
|
|
108
|
+
function hydrate(node, parent) {
|
|
109
|
+
if (isRef(node)) {
|
|
110
|
+
const { ups, refPath } = parseRefString(node.linkTo);
|
|
111
|
+
return new tags_1.RefTag(ups, refPath, parent);
|
|
112
|
+
}
|
|
113
|
+
const tag = new tags_1.Tag({}, parent);
|
|
114
|
+
if (node.eq !== undefined) {
|
|
115
|
+
if (Array.isArray(node.eq)) {
|
|
116
|
+
tag.eq = node.eq.map(el => hydrate(el, tag));
|
|
117
|
+
}
|
|
118
|
+
else if (node.eq instanceof Date) {
|
|
119
|
+
tag.eq = new Date(node.eq);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
tag.eq = node.eq;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (node.properties !== undefined) {
|
|
126
|
+
tag.properties = {};
|
|
127
|
+
for (const [key, val] of Object.entries(node.properties)) {
|
|
128
|
+
tag.properties[key] = hydrate(val, tag);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (node.deleted) {
|
|
132
|
+
tag.deleted = true;
|
|
133
|
+
}
|
|
134
|
+
return tag;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Session-based parser for Malloy tag language. Create an instance,
|
|
138
|
+
* call parse() for each line, then finish() to get the final Tag.
|
|
139
|
+
*/
|
|
140
|
+
class TagParser {
|
|
141
|
+
constructor() {
|
|
142
|
+
this.session = new motly_ts_parser_1.MOTLYSession();
|
|
143
|
+
}
|
|
144
|
+
parse(source) {
|
|
145
|
+
const stripped = stripPrefix(source);
|
|
146
|
+
const errors = this.session.parse(stripped);
|
|
147
|
+
const tagErrors = errors.map(mapMOTLYError);
|
|
148
|
+
const value = this.session.getValue();
|
|
149
|
+
return { tag: hydrate(value), log: tagErrors };
|
|
150
|
+
}
|
|
151
|
+
finish() {
|
|
152
|
+
const value = this.session.getValue();
|
|
153
|
+
this.session.dispose();
|
|
154
|
+
return hydrate(value);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
exports.TagParser = TagParser;
|
|
158
|
+
/**
|
|
159
|
+
* Parse Malloy tag language into a Tag which can be queried.
|
|
160
|
+
*
|
|
161
|
+
* @param source - A single string or array of strings to parse. If a string
|
|
162
|
+
* starts with #, all characters up to the first space are skipped.
|
|
163
|
+
* When an array is provided, strings are parsed sequentially and merged.
|
|
164
|
+
* @returns TagParse with the resulting tag and any errors. For arrays,
|
|
165
|
+
* error line numbers indicate the index in the array where the error occurred.
|
|
166
|
+
*/
|
|
167
|
+
function parseTag(source) {
|
|
168
|
+
const session = new TagParser();
|
|
169
|
+
if (typeof source === 'string') {
|
|
170
|
+
return session.parse(source);
|
|
171
|
+
}
|
|
172
|
+
const allErrs = [];
|
|
173
|
+
for (let i = 0; i < source.length; i++) {
|
|
174
|
+
const result = session.parse(source[i]);
|
|
175
|
+
for (const err of result.log) {
|
|
176
|
+
allErrs.push({ ...err, line: i + err.line });
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return { tag: session.finish(), log: allErrs };
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@malloydata/malloy-tag",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.341",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist/**/*.js",
|
|
9
|
+
"dist/**/*.js.map",
|
|
10
|
+
"dist/**/*.d.ts",
|
|
11
|
+
"!dist/**/*.spec.*",
|
|
12
|
+
"src",
|
|
13
|
+
"!src/**/*.spec.*"
|
|
14
|
+
],
|
|
7
15
|
"homepage": "https://github.com/malloydata/malloy#readme",
|
|
8
16
|
"engines": {
|
|
9
17
|
"node": ">=20"
|
|
@@ -14,17 +22,16 @@
|
|
|
14
22
|
},
|
|
15
23
|
"scripts": {
|
|
16
24
|
"test": "jest --config=../../jest.config.js",
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"build": "npm run build-peggy && tsc --build && npm run generate-flow",
|
|
25
|
+
"clean": "rm -rf dist && tsc --build --clean && rm -f tsconfig.tsbuildinfo && rimraf @flowtyped",
|
|
26
|
+
"build": "tsc --build && npm run generate-flow",
|
|
20
27
|
"prepublishOnly": "npm run clean && npm run build",
|
|
21
28
|
"generate-flow": "ts-node ../../scripts/gen-flow.ts"
|
|
22
29
|
},
|
|
23
30
|
"dependencies": {
|
|
31
|
+
"@malloydata/motly-ts-parser": "^0.0.2",
|
|
24
32
|
"assert": "^2.0.0"
|
|
25
33
|
},
|
|
26
34
|
"devDependencies": {
|
|
27
|
-
"peggy": "^4.2.0",
|
|
28
35
|
"rimraf": "^6.0.1",
|
|
29
36
|
"ts-node": "^10.9.2"
|
|
30
37
|
}
|
package/src/index.ts
CHANGED
|
@@ -5,7 +5,5 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
export * from './tags';
|
|
8
|
-
export {parseTag} from './
|
|
8
|
+
export {parseTag, TagParser} from './parser';
|
|
9
9
|
export * as ParseUtil from './util';
|
|
10
|
-
export {validateTag} from './schema';
|
|
11
|
-
export type {SchemaError} from './schema';
|
package/src/parser.ts
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Contributors to the Malloy project
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {MOTLYError, MOTLYNode} from '@malloydata/motly-ts-parser';
|
|
7
|
+
import {MOTLYSession} from '@malloydata/motly-ts-parser';
|
|
8
|
+
import {Tag, RefTag} from './tags';
|
|
9
|
+
import type {TagParse, TagError, Path} from './tags';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Strip the Malloy tag prefix (e.g., "# " or "#(docs) ") from source.
|
|
13
|
+
*/
|
|
14
|
+
function stripPrefix(source: string): string {
|
|
15
|
+
if (source[0] === '#') {
|
|
16
|
+
const skipTo = source.indexOf(' ');
|
|
17
|
+
if (skipTo > 0) {
|
|
18
|
+
return source.slice(skipTo);
|
|
19
|
+
}
|
|
20
|
+
return '';
|
|
21
|
+
}
|
|
22
|
+
return source;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Map a MOTLYError (from motly-ts parser) to a TagError.
|
|
27
|
+
*/
|
|
28
|
+
function mapMOTLYError(error: MOTLYError): TagError {
|
|
29
|
+
return {
|
|
30
|
+
code: error.code,
|
|
31
|
+
message: error.message,
|
|
32
|
+
line: error.begin.line,
|
|
33
|
+
offset: error.begin.column,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Parse a reference string like "$^^path.to[0].thing" back into
|
|
39
|
+
* structured form {ups, refPath}.
|
|
40
|
+
*/
|
|
41
|
+
function parseRefString(linkTo: string): {ups: number; refPath: Path} {
|
|
42
|
+
let i = 1;
|
|
43
|
+
let ups = 0;
|
|
44
|
+
while (i < linkTo.length && linkTo[i] === '^') {
|
|
45
|
+
ups++;
|
|
46
|
+
i++;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const refPath: Path = [];
|
|
50
|
+
const rest = linkTo.slice(i);
|
|
51
|
+
|
|
52
|
+
if (rest.length === 0) {
|
|
53
|
+
return {ups, refPath};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let pos = 0;
|
|
57
|
+
let needDot = false;
|
|
58
|
+
|
|
59
|
+
while (pos < rest.length) {
|
|
60
|
+
if (rest[pos] === '.') {
|
|
61
|
+
pos++;
|
|
62
|
+
needDot = false;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (rest[pos] === '[') {
|
|
67
|
+
const close = rest.indexOf(']', pos);
|
|
68
|
+
refPath.push(Number(rest.slice(pos + 1, close)));
|
|
69
|
+
pos = close + 1;
|
|
70
|
+
needDot = true;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (needDot) {
|
|
75
|
+
// Expected a dot separator but didn't get one
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (rest[pos] === '`') {
|
|
79
|
+
pos++;
|
|
80
|
+
let seg = '';
|
|
81
|
+
while (pos < rest.length && rest[pos] !== '`') {
|
|
82
|
+
if (rest[pos] === '\\') {
|
|
83
|
+
pos++;
|
|
84
|
+
seg += rest[pos];
|
|
85
|
+
} else {
|
|
86
|
+
seg += rest[pos];
|
|
87
|
+
}
|
|
88
|
+
pos++;
|
|
89
|
+
}
|
|
90
|
+
pos++;
|
|
91
|
+
refPath.push(seg);
|
|
92
|
+
needDot = true;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let seg = '';
|
|
97
|
+
while (
|
|
98
|
+
pos < rest.length &&
|
|
99
|
+
rest[pos] !== '.' &&
|
|
100
|
+
rest[pos] !== '[' &&
|
|
101
|
+
rest[pos] !== '`'
|
|
102
|
+
) {
|
|
103
|
+
seg += rest[pos];
|
|
104
|
+
pos++;
|
|
105
|
+
}
|
|
106
|
+
if (seg.length > 0) {
|
|
107
|
+
refPath.push(seg);
|
|
108
|
+
needDot = true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return {ups, refPath};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function isRef(node: MOTLYNode): node is {linkTo: string} {
|
|
116
|
+
return 'linkTo' in node;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Convert a MOTLYNode tree into a Tag tree with parent links.
|
|
121
|
+
*/
|
|
122
|
+
function hydrate(node: MOTLYNode, parent?: Tag): Tag {
|
|
123
|
+
if (isRef(node)) {
|
|
124
|
+
const {ups, refPath} = parseRefString(node.linkTo);
|
|
125
|
+
return new RefTag(ups, refPath, parent);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const tag = new Tag({}, parent);
|
|
129
|
+
|
|
130
|
+
if (node.eq !== undefined) {
|
|
131
|
+
if (Array.isArray(node.eq)) {
|
|
132
|
+
tag.eq = node.eq.map(el => hydrate(el, tag));
|
|
133
|
+
} else if (node.eq instanceof Date) {
|
|
134
|
+
tag.eq = new Date(node.eq);
|
|
135
|
+
} else {
|
|
136
|
+
tag.eq = node.eq;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (node.properties !== undefined) {
|
|
141
|
+
tag.properties = {};
|
|
142
|
+
for (const [key, val] of Object.entries(node.properties)) {
|
|
143
|
+
tag.properties[key] = hydrate(val, tag);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (node.deleted) {
|
|
148
|
+
tag.deleted = true;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return tag;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Session-based parser for Malloy tag language. Create an instance,
|
|
156
|
+
* call parse() for each line, then finish() to get the final Tag.
|
|
157
|
+
*/
|
|
158
|
+
export class TagParser {
|
|
159
|
+
private session: MOTLYSession;
|
|
160
|
+
|
|
161
|
+
constructor() {
|
|
162
|
+
this.session = new MOTLYSession();
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
parse(source: string): TagParse {
|
|
166
|
+
const stripped = stripPrefix(source);
|
|
167
|
+
const errors = this.session.parse(stripped);
|
|
168
|
+
const tagErrors = errors.map(mapMOTLYError);
|
|
169
|
+
const value = this.session.getValue();
|
|
170
|
+
return {tag: hydrate(value), log: tagErrors};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
finish(): Tag {
|
|
174
|
+
const value = this.session.getValue();
|
|
175
|
+
this.session.dispose();
|
|
176
|
+
return hydrate(value);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Parse Malloy tag language into a Tag which can be queried.
|
|
182
|
+
*
|
|
183
|
+
* @param source - A single string or array of strings to parse. If a string
|
|
184
|
+
* starts with #, all characters up to the first space are skipped.
|
|
185
|
+
* When an array is provided, strings are parsed sequentially and merged.
|
|
186
|
+
* @returns TagParse with the resulting tag and any errors. For arrays,
|
|
187
|
+
* error line numbers indicate the index in the array where the error occurred.
|
|
188
|
+
*/
|
|
189
|
+
export function parseTag(source: string | string[]): TagParse {
|
|
190
|
+
const session = new TagParser();
|
|
191
|
+
if (typeof source === 'string') {
|
|
192
|
+
return session.parse(source);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const allErrs: TagError[] = [];
|
|
196
|
+
for (let i = 0; i < source.length; i++) {
|
|
197
|
+
const result = session.parse(source[i]);
|
|
198
|
+
for (const err of result.log) {
|
|
199
|
+
allErrs.push({...err, line: i + err.line});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return {tag: session.finish(), log: allErrs};
|
|
203
|
+
}
|
package/CONTEXT.md
DELETED
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
# Malloy Tag Language (MOTLY)
|
|
2
|
-
|
|
3
|
-
The Malloy Tag Language (also called MOTLY - Malloy Object Tagging Language) is a concise, readable syntax for adding structured metadata to Malloy objects through annotations. It's designed to work seamlessly with Malloy's annotation system and can also be used as a standalone configuration language.
|
|
4
|
-
|
|
5
|
-
## Purpose
|
|
6
|
-
|
|
7
|
-
While Malloy annotations can contain arbitrary text, the Tag Language provides a standardized way to express structured metadata that is:
|
|
8
|
-
- Human-readable and writable
|
|
9
|
-
- Easy to parse programmatically
|
|
10
|
-
- Flexible enough for various use cases
|
|
11
|
-
- Concise and unobtrusive in code
|
|
12
|
-
|
|
13
|
-
## Syntax Overview
|
|
14
|
-
|
|
15
|
-
The Tag Language supports several data types:
|
|
16
|
-
|
|
17
|
-
### Boolean Tags
|
|
18
|
-
```malloy
|
|
19
|
-
# hidden
|
|
20
|
-
```
|
|
21
|
-
A tag name without a value is a boolean (implicitly `true`).
|
|
22
|
-
|
|
23
|
-
### Typed Values
|
|
24
|
-
Values prefixed with `@` are typed:
|
|
25
|
-
```malloy
|
|
26
|
-
# enabled=@true
|
|
27
|
-
# debug=@false
|
|
28
|
-
# created=@2024-01-15
|
|
29
|
-
# updated=@2024-01-15T10:30:00Z
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### String Values
|
|
33
|
-
```malloy
|
|
34
|
-
# color=blue
|
|
35
|
-
# name="User Name"
|
|
36
|
-
# description="""
|
|
37
|
-
Multi-line string
|
|
38
|
-
with preserved newlines.
|
|
39
|
-
"""
|
|
40
|
-
```
|
|
41
|
-
Unquoted strings for simple values (alphanumeric and underscore), quoted strings for values with spaces or special characters, triple-quoted for multi-line.
|
|
42
|
-
|
|
43
|
-
### Numeric Values
|
|
44
|
-
```malloy
|
|
45
|
-
# size=10
|
|
46
|
-
# width=100.5
|
|
47
|
-
# rate=-0.05
|
|
48
|
-
```
|
|
49
|
-
Numbers are automatically parsed as numeric types.
|
|
50
|
-
|
|
51
|
-
### Arrays
|
|
52
|
-
```malloy
|
|
53
|
-
# colors=[red, green, blue]
|
|
54
|
-
# ports=[80, 443, 8080]
|
|
55
|
-
# users=[{ name=alice role=admin }, { name=bob role=user }]
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### Nested Properties
|
|
59
|
-
```malloy
|
|
60
|
-
# box: { width=100 height=200 }
|
|
61
|
-
```
|
|
62
|
-
Colon and curly braces create nested property groups.
|
|
63
|
-
|
|
64
|
-
### Deep Path Notation
|
|
65
|
-
```malloy
|
|
66
|
-
# database.connection.pool.max=100
|
|
67
|
-
```
|
|
68
|
-
Dot notation for setting nested values directly.
|
|
69
|
-
|
|
70
|
-
### Delete Property
|
|
71
|
-
```malloy
|
|
72
|
-
# -deprecated_field
|
|
73
|
-
```
|
|
74
|
-
Minus prefix removes a property.
|
|
75
|
-
|
|
76
|
-
### Combined Example
|
|
77
|
-
```malloy
|
|
78
|
-
#(myApp) hidden color=blue size=10 box: { width=100 height=200 } name="Blue Thing"
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
## Colon vs Space Syntax
|
|
82
|
-
|
|
83
|
-
Two ways to add properties to objects with different semantics:
|
|
84
|
-
|
|
85
|
-
**Colon syntax (`: { }`) replaces all properties:**
|
|
86
|
-
```malloy
|
|
87
|
-
# server: { host=localhost port=8080 }
|
|
88
|
-
# server: { url="http://example.com" } # Replaces - only url remains
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
**Space syntax (`{ }`) merges with existing properties:**
|
|
92
|
-
```malloy
|
|
93
|
-
# server: { host=localhost }
|
|
94
|
-
# server { port=8080 } # Merges - both host and port exist
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## Annotation Prefixes
|
|
98
|
-
|
|
99
|
-
Different prefixes are used to avoid collision between different uses of annotations:
|
|
100
|
-
|
|
101
|
-
- **`# `** (hash-space) - Reserved for Malloy renderer
|
|
102
|
-
- **`#!`** - Compiler directives
|
|
103
|
-
- **`#(docs)`** - Malloy documentation
|
|
104
|
-
- **`#(appName) `** - Encouraged pattern for application-specific tags
|
|
105
|
-
|
|
106
|
-
Example with application prefix:
|
|
107
|
-
```malloy
|
|
108
|
-
#(myApp) visible theme=dark priority=high
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
## Multi-line Annotations
|
|
112
|
-
|
|
113
|
-
The tag language works with single-line annotations. For multi-line text that is NOT in the tag language:
|
|
114
|
-
|
|
115
|
-
```malloy
|
|
116
|
-
#" This is a multi-line string annotation
|
|
117
|
-
#" which is NOT in the tag language
|
|
118
|
-
#" but could be displayed as help text
|
|
119
|
-
source: name is VALUE
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
## Usage Pattern
|
|
123
|
-
|
|
124
|
-
The expected workflow for using tag annotations:
|
|
125
|
-
|
|
126
|
-
1. **Write annotations** in Malloy code using tag syntax
|
|
127
|
-
2. **Query annotations** from compiled model using pattern matching (filter by prefix)
|
|
128
|
-
3. **Parse tags** using the malloy-tag package
|
|
129
|
-
4. **Extract values** and use in your application
|
|
130
|
-
|
|
131
|
-
## Implementation
|
|
132
|
-
|
|
133
|
-
The `malloy-tag` package provides:
|
|
134
|
-
- **Peggy-based parser** for tag language syntax
|
|
135
|
-
- **Tag class** with methods for type-safe value access
|
|
136
|
-
- **Type definitions** for parsed tag structures
|
|
137
|
-
|
|
138
|
-
### Key API Methods
|
|
139
|
-
|
|
140
|
-
```typescript
|
|
141
|
-
import {Tag} from '@malloydata/malloy-tag';
|
|
142
|
-
|
|
143
|
-
const {tag, log} = Tag.parse('enabled=@true port=8080 name="My App"');
|
|
144
|
-
|
|
145
|
-
// Convert to plain JavaScript object
|
|
146
|
-
const obj = tag.toObject(); // { enabled: true, port: 8080, name: "My App" }
|
|
147
|
-
|
|
148
|
-
// Type-safe accessors
|
|
149
|
-
tag.text('name'); // "My App"
|
|
150
|
-
tag.numeric('port'); // 8080
|
|
151
|
-
tag.boolean('enabled'); // true
|
|
152
|
-
tag.isTrue('enabled'); // true
|
|
153
|
-
tag.date('created'); // Date object
|
|
154
|
-
tag.textArray('features'); // string[]
|
|
155
|
-
tag.has('name'); // true
|
|
156
|
-
|
|
157
|
-
// Nested access
|
|
158
|
-
tag.text('server', 'host');
|
|
159
|
-
tag.tag('server'); // Get nested Tag object
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
## Documentation
|
|
163
|
-
|
|
164
|
-
For complete tag language syntax and examples, see:
|
|
165
|
-
- `docs/motly.md` in this package (comprehensive reference)
|
|
166
|
-
- https://docs.malloydata.dev/documentation/language/tags
|
|
167
|
-
|
|
168
|
-
## Important Notes
|
|
169
|
-
|
|
170
|
-
- Not all annotations use the tag language - raw text is also valid
|
|
171
|
-
- The tag language is optional - annotations can be simple strings
|
|
172
|
-
- Each application defines its own conventions for tag usage
|
|
173
|
-
- Tags are metadata only - they don't affect query execution
|
package/README.md
DELETED
|
File without changes
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
declare function peg$SyntaxError(message: any, expected: any, found: any, location: any): Error;
|
|
2
|
-
declare class peg$SyntaxError {
|
|
3
|
-
constructor(message: any, expected: any, found: any, location: any);
|
|
4
|
-
format(sources: any): string;
|
|
5
|
-
}
|
|
6
|
-
declare namespace peg$SyntaxError {
|
|
7
|
-
function buildMessage(expected: any, found: any): string;
|
|
8
|
-
}
|
|
9
|
-
declare function peg$parse(input: any, options: any): any;
|
|
10
|
-
export declare let StartRules: string[];
|
|
11
|
-
export { peg$SyntaxError as SyntaxError, peg$parse as parse };
|