@malloydata/malloy 0.0.56-dev230707210748 → 0.0.56-dev230710162623
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/lang/lib/Malloy/MalloyParser.d.ts +43 -32
- package/dist/lang/lib/Malloy/MalloyParser.js +1363 -1276
- package/dist/lang/lib/Malloy/MalloyParserListener.d.ts +11 -0
- package/dist/lang/lib/Malloy/MalloyParserVisitor.d.ts +7 -0
- package/dist/lang/malloy-to-ast.d.ts +4 -5
- package/dist/lang/malloy-to-ast.js +82 -114
- package/dist/lang/parse-tree-walkers/find-external-references.js +26 -11
- package/dist/lang/parse-utils.d.ts +51 -0
- package/dist/lang/parse-utils.js +238 -0
- package/dist/lang/test/strings.spec.js +108 -13
- package/package.json +1 -1
- package/dist/lang/string-parser.d.ts +0 -11
- package/dist/lang/string-parser.js +0 -105
|
@@ -165,6 +165,7 @@ import { SampleSpecContext } from "./MalloyParser";
|
|
|
165
165
|
import { AggregateContext } from "./MalloyParser";
|
|
166
166
|
import { MalloyTypeContext } from "./MalloyParser";
|
|
167
167
|
import { CompareOpContext } from "./MalloyParser";
|
|
168
|
+
import { StringContext } from "./MalloyParser";
|
|
168
169
|
import { ShortStringContext } from "./MalloyParser";
|
|
169
170
|
import { NumericLiteralContext } from "./MalloyParser";
|
|
170
171
|
import { LiteralContext } from "./MalloyParser";
|
|
@@ -2006,6 +2007,16 @@ export interface MalloyParserListener extends ParseTreeListener {
|
|
|
2006
2007
|
* @param ctx the parse tree
|
|
2007
2008
|
*/
|
|
2008
2009
|
exitCompareOp?: (ctx: CompareOpContext) => void;
|
|
2010
|
+
/**
|
|
2011
|
+
* Enter a parse tree produced by `MalloyParser.string`.
|
|
2012
|
+
* @param ctx the parse tree
|
|
2013
|
+
*/
|
|
2014
|
+
enterString?: (ctx: StringContext) => void;
|
|
2015
|
+
/**
|
|
2016
|
+
* Exit a parse tree produced by `MalloyParser.string`.
|
|
2017
|
+
* @param ctx the parse tree
|
|
2018
|
+
*/
|
|
2019
|
+
exitString?: (ctx: StringContext) => void;
|
|
2009
2020
|
/**
|
|
2010
2021
|
* Enter a parse tree produced by `MalloyParser.shortString`.
|
|
2011
2022
|
* @param ctx the parse tree
|
|
@@ -165,6 +165,7 @@ import { SampleSpecContext } from "./MalloyParser";
|
|
|
165
165
|
import { AggregateContext } from "./MalloyParser";
|
|
166
166
|
import { MalloyTypeContext } from "./MalloyParser";
|
|
167
167
|
import { CompareOpContext } from "./MalloyParser";
|
|
168
|
+
import { StringContext } from "./MalloyParser";
|
|
168
169
|
import { ShortStringContext } from "./MalloyParser";
|
|
169
170
|
import { NumericLiteralContext } from "./MalloyParser";
|
|
170
171
|
import { LiteralContext } from "./MalloyParser";
|
|
@@ -1270,6 +1271,12 @@ export interface MalloyParserVisitor<Result> extends ParseTreeVisitor<Result> {
|
|
|
1270
1271
|
* @return the visitor result
|
|
1271
1272
|
*/
|
|
1272
1273
|
visitCompareOp?: (ctx: CompareOpContext) => Result;
|
|
1274
|
+
/**
|
|
1275
|
+
* Visit a parse tree produced by `MalloyParser.string`.
|
|
1276
|
+
* @param ctx the parse tree
|
|
1277
|
+
* @return the visitor result
|
|
1278
|
+
*/
|
|
1279
|
+
visitString?: (ctx: StringContext) => Result;
|
|
1273
1280
|
/**
|
|
1274
1281
|
* Visit a parse tree produced by `MalloyParser.shortString`.
|
|
1275
1282
|
* @param ctx the parse tree
|
|
@@ -7,14 +7,12 @@ import * as ast from './ast';
|
|
|
7
7
|
import { LogSeverity, MessageLogger } from './parse-log';
|
|
8
8
|
import { MalloyParseRoot } from './parse-malloy';
|
|
9
9
|
import { FieldDeclarationConstructor } from './ast';
|
|
10
|
+
import { HasString, HasID } from './parse-utils';
|
|
10
11
|
declare class IgnoredElement extends ast.MalloyElement {
|
|
11
12
|
elementType: string;
|
|
12
13
|
malloySrc: string;
|
|
13
14
|
constructor(src: string);
|
|
14
15
|
}
|
|
15
|
-
declare type ContainsID = ParserRuleContext & {
|
|
16
|
-
id: () => parse.IdContext;
|
|
17
|
-
};
|
|
18
16
|
/**
|
|
19
17
|
* ANTLR visitor pattern parse tree traversal. Generates a Malloy
|
|
20
18
|
* AST from an ANTLR parse tree.
|
|
@@ -42,8 +40,8 @@ export declare class MalloyToAST extends AbstractParseTreeVisitor<ast.MalloyElem
|
|
|
42
40
|
protected contextError(cx: ParserRuleContext, msg: string, sev?: LogSeverity): void;
|
|
43
41
|
protected only<T extends ast.MalloyElement>(els: ast.MalloyElement[], isGood: (el: ast.MalloyElement) => T | false, desc: string): T[];
|
|
44
42
|
protected getNumber(term: ParseTree): number;
|
|
45
|
-
protected getFieldName(cx:
|
|
46
|
-
protected getModelEntryName(cx:
|
|
43
|
+
protected getFieldName(cx: HasID): ast.FieldName;
|
|
44
|
+
protected getModelEntryName(cx: HasID): ast.ModelEntryReference;
|
|
47
45
|
defaultResult(): ast.MalloyElement;
|
|
48
46
|
protected astAt<MT extends ast.MalloyElement>(el: MT, cx: ParserRuleContext): MT;
|
|
49
47
|
protected getSourceCode(cx: ParserRuleContext): string;
|
|
@@ -53,6 +51,7 @@ export declare class MalloyToAST extends AbstractParseTreeVisitor<ast.MalloyElem
|
|
|
53
51
|
protected getSegments(segments: parse.PipeElementContext[]): ast.QOPDesc[];
|
|
54
52
|
protected getFilterShortcut(cx: parse.FilterShortcutContext): ast.Filter;
|
|
55
53
|
protected getExploreSource(pcx: parse.ExploreSourceContext): ast.Source;
|
|
54
|
+
protected getPlainString(cx: HasString): string;
|
|
56
55
|
protected makeSqlString(pcx: parse.SqlStringContext, sqlStr: ast.SQLString): void;
|
|
57
56
|
/**
|
|
58
57
|
* Parse a time string into an AST TimeLiteral, if the string fails
|
|
@@ -46,11 +46,12 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
46
46
|
};
|
|
47
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
48
|
exports.MalloyToAST = void 0;
|
|
49
|
+
const antlr4ts_1 = require("antlr4ts");
|
|
49
50
|
const AbstractParseTreeVisitor_1 = require("antlr4ts/tree/AbstractParseTreeVisitor");
|
|
50
51
|
const ast = __importStar(require("./ast"));
|
|
51
52
|
const Interval_1 = require("antlr4ts/misc/Interval");
|
|
52
53
|
const ast_1 = require("./ast");
|
|
53
|
-
const
|
|
54
|
+
const parse_utils_1 = require("./parse-utils");
|
|
54
55
|
const ENABLE_M4_WARNINGS = false;
|
|
55
56
|
class IgnoredElement extends ast.MalloyElement {
|
|
56
57
|
constructor(src) {
|
|
@@ -59,64 +60,6 @@ class IgnoredElement extends ast.MalloyElement {
|
|
|
59
60
|
this.malloySrc = src;
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
|
-
/**
|
|
63
|
-
* Get all the possibly missing annotations from this parse rule
|
|
64
|
-
* @param cx Any parse context which has an ANNOTATION* rules
|
|
65
|
-
* @returns Array of texts for the annotations
|
|
66
|
-
*/
|
|
67
|
-
function getNotes(cx) {
|
|
68
|
-
return cx.ANNOTATION().map(a => a.text);
|
|
69
|
-
}
|
|
70
|
-
function getIsNotes(cx) {
|
|
71
|
-
const before = getNotes(cx._beforeIs);
|
|
72
|
-
return before.concat(getNotes(cx._afterIs));
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Take the text of a matched string, including the matching quote
|
|
76
|
-
* characters, and return the actual contents of the string after
|
|
77
|
-
* \ processing.
|
|
78
|
-
* @param cx Any parse context which contains a string
|
|
79
|
-
* @returns Decocded string
|
|
80
|
-
*/
|
|
81
|
-
function getShortString(cx) {
|
|
82
|
-
var _a, _b;
|
|
83
|
-
const scx = cx.shortString();
|
|
84
|
-
const str = ((_a = scx.DQ_STRING()) === null || _a === void 0 ? void 0 : _a.text) || ((_b = scx.SQ_STRING()) === null || _b === void 0 ? void 0 : _b.text);
|
|
85
|
-
if (str) {
|
|
86
|
-
return (0, string_parser_1.parseString)(str, str[0]);
|
|
87
|
-
}
|
|
88
|
-
// shortString: DQ_STRING | SQ_STRING; So this will never happen
|
|
89
|
-
return '';
|
|
90
|
-
}
|
|
91
|
-
function getOptionalString(cx) {
|
|
92
|
-
function containsString(cx) {
|
|
93
|
-
return 'shortString' in cx;
|
|
94
|
-
}
|
|
95
|
-
if (containsString(cx) && cx.shortString()) {
|
|
96
|
-
return getShortString(cx);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* An identifier is either a sequence of id characters or a `quoted`
|
|
101
|
-
* This parses either to simply the resulting text.
|
|
102
|
-
* @param cx A context which has an identifier
|
|
103
|
-
* @returns The indenftifier text
|
|
104
|
-
*/
|
|
105
|
-
function getId(cx) {
|
|
106
|
-
const quoted = cx.id().BQ_STRING();
|
|
107
|
-
if (quoted) {
|
|
108
|
-
return (0, string_parser_1.parseString)(quoted.text, '`');
|
|
109
|
-
}
|
|
110
|
-
return cx.id().text;
|
|
111
|
-
}
|
|
112
|
-
function getOptionalId(cx) {
|
|
113
|
-
function containsID(cx) {
|
|
114
|
-
return 'id' in cx;
|
|
115
|
-
}
|
|
116
|
-
if (containsID(cx) && cx.id()) {
|
|
117
|
-
return getId(cx);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
63
|
/**
|
|
121
64
|
* ANTLR visitor pattern parse tree traversal. Generates a Malloy
|
|
122
65
|
* AST from an ANTLR parse tree.
|
|
@@ -176,10 +119,10 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
176
119
|
return Number.parseInt(term.text);
|
|
177
120
|
}
|
|
178
121
|
getFieldName(cx) {
|
|
179
|
-
return this.astAt(new ast.FieldName(getId(cx)), cx);
|
|
122
|
+
return this.astAt(new ast.FieldName((0, parse_utils_1.getId)(cx)), cx);
|
|
180
123
|
}
|
|
181
124
|
getModelEntryName(cx) {
|
|
182
|
-
return this.astAt(new ast.ModelEntryReference(getId(cx)), cx);
|
|
125
|
+
return this.astAt(new ast.ModelEntryReference((0, parse_utils_1.getId)(cx)), cx);
|
|
183
126
|
}
|
|
184
127
|
defaultResult() {
|
|
185
128
|
return new ast.Unimplemented();
|
|
@@ -226,17 +169,40 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
226
169
|
}
|
|
227
170
|
throw this.internalError(pcx, `'${element.elementType}': illegal source`);
|
|
228
171
|
}
|
|
172
|
+
getPlainString(cx) {
|
|
173
|
+
const shortStr = (0, parse_utils_1.getStringIfShort)(cx);
|
|
174
|
+
if (shortStr) {
|
|
175
|
+
return shortStr;
|
|
176
|
+
}
|
|
177
|
+
const safeParts = [];
|
|
178
|
+
const multiLineStr = cx.string().sqlString();
|
|
179
|
+
if (multiLineStr) {
|
|
180
|
+
for (const part of (0, parse_utils_1.getStringParts)(multiLineStr)) {
|
|
181
|
+
if (part instanceof antlr4ts_1.ParserRuleContext) {
|
|
182
|
+
this.contextError(part, '%{ query }% illegal in this string');
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
safeParts.push(part);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
(0, parse_utils_1.unIndent)(safeParts);
|
|
189
|
+
return safeParts.join('');
|
|
190
|
+
}
|
|
191
|
+
// string: shortString | sqlString; So this will never happen
|
|
192
|
+
return '';
|
|
193
|
+
}
|
|
229
194
|
makeSqlString(pcx, sqlStr) {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
195
|
+
for (const part of (0, parse_utils_1.getStringParts)(pcx)) {
|
|
196
|
+
if (part instanceof antlr4ts_1.ParserRuleContext) {
|
|
197
|
+
sqlStr.push(this.visit(part));
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
sqlStr.push(part);
|
|
235
201
|
}
|
|
236
|
-
sqlStr.push(this.visit(part.query()));
|
|
237
202
|
}
|
|
238
|
-
|
|
239
|
-
|
|
203
|
+
// Until SQL writer properly indents turducken, it actually looks better
|
|
204
|
+
// in the output to NOT de-indent the SQL sources
|
|
205
|
+
// unIndent(sqlStr.elements);
|
|
240
206
|
sqlStr.complete();
|
|
241
207
|
this.astAt(sqlStr, pcx);
|
|
242
208
|
}
|
|
@@ -260,14 +226,14 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
260
226
|
visitDefineSourceStatement(pcx) {
|
|
261
227
|
const defsCx = pcx.sourcePropertyList().sourceDefinition();
|
|
262
228
|
const defs = defsCx.map(dcx => this.visitSourceDefinition(dcx));
|
|
263
|
-
const blockNotes = getNotes(pcx.tags());
|
|
229
|
+
const blockNotes = (0, parse_utils_1.getNotes)(pcx.tags());
|
|
264
230
|
const defList = new ast.DefineSourceList(defs);
|
|
265
231
|
defList.extendNote({ blockNotes });
|
|
266
232
|
return defList;
|
|
267
233
|
}
|
|
268
234
|
visitSourceDefinition(pcx) {
|
|
269
|
-
const exploreDef = new ast.DefineSource(getId(pcx.sourceNameDef()), this.visitExplore(pcx.explore()), true, []);
|
|
270
|
-
const notes = getNotes(pcx.tags()).concat(getIsNotes(pcx.isDefine()));
|
|
235
|
+
const exploreDef = new ast.DefineSource((0, parse_utils_1.getId)(pcx.sourceNameDef()), this.visitExplore(pcx.explore()), true, []);
|
|
236
|
+
const notes = (0, parse_utils_1.getNotes)(pcx.tags()).concat((0, parse_utils_1.getIsNotes)(pcx.isDefine()));
|
|
271
237
|
exploreDef.extendNote({ notes });
|
|
272
238
|
return this.astAt(exploreDef, pcx);
|
|
273
239
|
}
|
|
@@ -289,7 +255,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
289
255
|
return propList;
|
|
290
256
|
}
|
|
291
257
|
visitTableFunction(pcx) {
|
|
292
|
-
const tableURI =
|
|
258
|
+
const tableURI = this.getPlainString(pcx.tableURI());
|
|
293
259
|
const el = this.astAt(new ast.TableFunctionSource(tableURI), pcx);
|
|
294
260
|
if (ENABLE_M4_WARNINGS) {
|
|
295
261
|
this.astError(el, "`table('connection_name:table_path')` is deprecated; use `connection_name.table('table_path')`", 'warn');
|
|
@@ -299,7 +265,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
299
265
|
visitTableMethod(pcx) {
|
|
300
266
|
const connId = pcx.connectionId();
|
|
301
267
|
const connectionName = this.astAt(this.getModelEntryName(connId), connId);
|
|
302
|
-
const tablePath =
|
|
268
|
+
const tablePath = this.getPlainString(pcx.tablePath());
|
|
303
269
|
return this.astAt(new ast.TableMethodSource(connectionName, tablePath), pcx);
|
|
304
270
|
}
|
|
305
271
|
visitTableSource(pcx) {
|
|
@@ -321,9 +287,9 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
321
287
|
if (selCx) {
|
|
322
288
|
this.makeSqlString(selCx, sqlStr);
|
|
323
289
|
}
|
|
324
|
-
const
|
|
325
|
-
if (
|
|
326
|
-
sqlStr.push(
|
|
290
|
+
const shortCX = pcx.shortString();
|
|
291
|
+
if (shortCX) {
|
|
292
|
+
sqlStr.push((0, parse_utils_1.getShortString)(shortCX));
|
|
327
293
|
}
|
|
328
294
|
const expr = new ast.SQLSource(connectionName, sqlStr);
|
|
329
295
|
return this.astAt(expr, pcx);
|
|
@@ -353,7 +319,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
353
319
|
}
|
|
354
320
|
}
|
|
355
321
|
const joinMany = new ast.Joins(joins);
|
|
356
|
-
joinMany.extendNote({ blockNotes: getNotes(pcx.tags()) });
|
|
322
|
+
joinMany.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
|
|
357
323
|
return joinMany;
|
|
358
324
|
}
|
|
359
325
|
visitDefJoinOne(pcx) {
|
|
@@ -368,7 +334,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
368
334
|
}
|
|
369
335
|
}
|
|
370
336
|
const joinOne = new ast.Joins(joins);
|
|
371
|
-
joinOne.extendNote({ blockNotes: getNotes(pcx.tags()) });
|
|
337
|
+
joinOne.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
|
|
372
338
|
return joinOne;
|
|
373
339
|
}
|
|
374
340
|
visitDefJoinCross(pcx) {
|
|
@@ -386,7 +352,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
386
352
|
}
|
|
387
353
|
}
|
|
388
354
|
const joinCross = new ast.Joins(joins);
|
|
389
|
-
joinCross.extendNote({ blockNotes: getNotes(pcx.tags()) });
|
|
355
|
+
joinCross.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
|
|
390
356
|
return joinCross;
|
|
391
357
|
}
|
|
392
358
|
getJoinList(pcx) {
|
|
@@ -395,7 +361,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
395
361
|
getJoinSource(name, ecx) {
|
|
396
362
|
if (ecx) {
|
|
397
363
|
const joinSrc = this.visitExplore(ecx.explore());
|
|
398
|
-
const notes = getNotes(ecx._before_is).concat(getNotes(ecx._after_is));
|
|
364
|
+
const notes = (0, parse_utils_1.getNotes)(ecx._before_is).concat((0, parse_utils_1.getNotes)(ecx._after_is));
|
|
399
365
|
return { joinFrom: joinSrc, notes };
|
|
400
366
|
}
|
|
401
367
|
return { joinFrom: new ast.NamedSource(name), notes: [] };
|
|
@@ -415,7 +381,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
415
381
|
if (onCx) {
|
|
416
382
|
join.joinOn = this.getFieldExpr(onCx);
|
|
417
383
|
}
|
|
418
|
-
join.extendNote({ notes: getNotes(pcx).concat(notes) });
|
|
384
|
+
join.extendNote({ notes: (0, parse_utils_1.getNotes)(pcx).concat(notes) });
|
|
419
385
|
return this.astAt(join, pcx);
|
|
420
386
|
}
|
|
421
387
|
visitJoinWith(pcx) {
|
|
@@ -423,28 +389,28 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
423
389
|
const { joinFrom, notes } = this.getJoinSource(joinAs, pcx.isExplore());
|
|
424
390
|
const joinOn = this.getFieldExpr(pcx.fieldExpr());
|
|
425
391
|
const join = new ast.KeyJoin(joinAs, joinFrom, joinOn);
|
|
426
|
-
join.extendNote({ notes: getNotes(pcx).concat(notes) });
|
|
392
|
+
join.extendNote({ notes: (0, parse_utils_1.getNotes)(pcx).concat(notes) });
|
|
427
393
|
return this.astAt(join, pcx);
|
|
428
394
|
}
|
|
429
395
|
getFieldDef(pcx, makeFieldDef) {
|
|
430
396
|
const defCx = pcx.fieldExpr();
|
|
431
|
-
const fieldName = getId(pcx.fieldNameDef());
|
|
397
|
+
const fieldName = (0, parse_utils_1.getId)(pcx.fieldNameDef());
|
|
432
398
|
const valExpr = this.getFieldExpr(defCx);
|
|
433
399
|
const def = new makeFieldDef(valExpr, fieldName, this.getSourceCode(defCx));
|
|
434
|
-
const notes = getNotes(pcx.tags()).concat(getIsNotes(pcx.isDefine()));
|
|
400
|
+
const notes = (0, parse_utils_1.getNotes)(pcx.tags()).concat((0, parse_utils_1.getIsNotes)(pcx.isDefine()));
|
|
435
401
|
def.extendNote({ notes });
|
|
436
402
|
return this.astAt(def, pcx);
|
|
437
403
|
}
|
|
438
404
|
visitDefDimensions(pcx) {
|
|
439
405
|
const defs = this.getFieldDefs(pcx.defList().fieldDef(), ast.DimensionFieldDeclaration);
|
|
440
406
|
const stmt = new ast.Dimensions(defs);
|
|
441
|
-
stmt.extendNote({ blockNotes: getNotes(pcx.tags()) });
|
|
407
|
+
stmt.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
|
|
442
408
|
return this.astAt(stmt, pcx);
|
|
443
409
|
}
|
|
444
410
|
visitDefMeasures(pcx) {
|
|
445
411
|
const defs = this.getFieldDefs(pcx.defList().fieldDef(), ast.MeasureFieldDeclaration);
|
|
446
412
|
const stmt = new ast.Measures(defs);
|
|
447
|
-
stmt.extendNote({ blockNotes: getNotes(pcx.tags()) });
|
|
413
|
+
stmt.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
|
|
448
414
|
return this.astAt(stmt, pcx);
|
|
449
415
|
}
|
|
450
416
|
visitQueryExtend(pcx) {
|
|
@@ -476,7 +442,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
476
442
|
visitExploreRenameDef(pcx) {
|
|
477
443
|
const newName = pcx.fieldName(0);
|
|
478
444
|
const oldName = pcx.fieldName(1);
|
|
479
|
-
const rename = new ast.RenameField(getId(newName), this.getFieldName(oldName));
|
|
445
|
+
const rename = new ast.RenameField((0, parse_utils_1.getId)(newName), this.getFieldName(oldName));
|
|
480
446
|
return this.astAt(rename, pcx);
|
|
481
447
|
}
|
|
482
448
|
visitDefExploreRename(pcx) {
|
|
@@ -510,7 +476,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
510
476
|
}
|
|
511
477
|
visitDefExploreQuery(pcx) {
|
|
512
478
|
const queryDefs = this.visitSubQueryDefList(pcx.subQueryDefList());
|
|
513
|
-
const blockNotes = getNotes(pcx.tags());
|
|
479
|
+
const blockNotes = (0, parse_utils_1.getNotes)(pcx.tags());
|
|
514
480
|
queryDefs.extendNote({ blockNotes });
|
|
515
481
|
return queryDefs;
|
|
516
482
|
}
|
|
@@ -532,7 +498,8 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
532
498
|
return this.visitTimezoneStatement(cx.timezoneStatement());
|
|
533
499
|
}
|
|
534
500
|
visitTimezoneStatement(cx) {
|
|
535
|
-
const
|
|
501
|
+
const timezone = this.getPlainString(cx);
|
|
502
|
+
const timezoneStatement = this.astAt(new ast.TimezoneStatement(timezone), cx.string());
|
|
536
503
|
if (!timezoneStatement.isValid) {
|
|
537
504
|
this.astError(timezoneStatement, `Invalid timezone: ${timezoneStatement.tz}`);
|
|
538
505
|
}
|
|
@@ -574,22 +541,22 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
574
541
|
}
|
|
575
542
|
visitAggregateStatement(pcx) {
|
|
576
543
|
const agStmt = new ast.Aggregate(this.getQueryItems(pcx.queryFieldList(), ast.AggregateFieldDeclaration, ast.AggregateFieldReference));
|
|
577
|
-
agStmt.extendNote({ blockNotes: getNotes(pcx.tags()) });
|
|
544
|
+
agStmt.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
|
|
578
545
|
return agStmt;
|
|
579
546
|
}
|
|
580
547
|
visitGroupByStatement(pcx) {
|
|
581
548
|
const groupBy = new ast.GroupBy(this.getQueryItems(pcx.queryFieldList(), ast.GroupByFieldDeclaration, ast.GroupByFieldReference));
|
|
582
|
-
groupBy.extendNote({ blockNotes: getNotes(pcx.tags()) });
|
|
549
|
+
groupBy.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
|
|
583
550
|
return groupBy;
|
|
584
551
|
}
|
|
585
552
|
visitCalculateStatement(pcx) {
|
|
586
553
|
const stmt = new ast.Calculate(this.getQueryItems(pcx.queryFieldList(), ast.CalculateFieldDeclaration, ast.CalculateFieldReference));
|
|
587
|
-
stmt.extendNote({ blockNotes: getNotes(pcx.tags()) });
|
|
554
|
+
stmt.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
|
|
588
555
|
return stmt;
|
|
589
556
|
}
|
|
590
557
|
getTaggedRef(pcx, makeFieldRef) {
|
|
591
558
|
const ref = this.getFieldPath(pcx.fieldPath(), makeFieldRef);
|
|
592
|
-
ref.extendNote({ notes: getNotes(pcx.tags()) });
|
|
559
|
+
ref.extendNote({ notes: (0, parse_utils_1.getNotes)(pcx.tags()) });
|
|
593
560
|
return ref;
|
|
594
561
|
}
|
|
595
562
|
getFieldCollectionMember(pcx, makeFieldDef, makeFieldRef) {
|
|
@@ -616,7 +583,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
616
583
|
}
|
|
617
584
|
visitProjectStatement(pcx) {
|
|
618
585
|
const stmt = this.visitFieldCollection(pcx.fieldCollection());
|
|
619
|
-
stmt.extendNote({ blockNotes: getNotes(pcx.tags()) });
|
|
586
|
+
stmt.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
|
|
620
587
|
return stmt;
|
|
621
588
|
}
|
|
622
589
|
visitCollectionWildCard(pcx) {
|
|
@@ -691,7 +658,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
691
658
|
return this.astAt(top, pcx);
|
|
692
659
|
}
|
|
693
660
|
visitSourceID(pcx) {
|
|
694
|
-
return this.astAt(new ast.NamedSource(getId(pcx)), pcx);
|
|
661
|
+
return this.astAt(new ast.NamedSource((0, parse_utils_1.getId)(pcx)), pcx);
|
|
695
662
|
}
|
|
696
663
|
buildPipelineFromName(pipe, pipeCx) {
|
|
697
664
|
const firstCx = pipeCx.firstSegment();
|
|
@@ -732,16 +699,16 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
732
699
|
const stmts = pcx
|
|
733
700
|
.topLevelQueryDef()
|
|
734
701
|
.map(cx => this.visitTopLevelQueryDef(cx));
|
|
735
|
-
const blockNotes = getNotes(pcx.tags());
|
|
702
|
+
const blockNotes = (0, parse_utils_1.getNotes)(pcx.tags());
|
|
736
703
|
const queryDefs = new ast.DefineQueryList(stmts);
|
|
737
704
|
queryDefs.extendNote({ blockNotes });
|
|
738
705
|
return queryDefs;
|
|
739
706
|
}
|
|
740
707
|
visitTopLevelQueryDef(pcx) {
|
|
741
|
-
const queryName = getId(pcx.queryName());
|
|
708
|
+
const queryName = (0, parse_utils_1.getId)(pcx.queryName());
|
|
742
709
|
const queryExpr = this.visit(pcx.query());
|
|
743
710
|
if (ast.isQueryElement(queryExpr)) {
|
|
744
|
-
const notes = getNotes(pcx.tags()).concat(getIsNotes(pcx.isDefine()));
|
|
711
|
+
const notes = (0, parse_utils_1.getNotes)(pcx.tags()).concat((0, parse_utils_1.getIsNotes)(pcx.isDefine()));
|
|
745
712
|
const queryDef = new ast.DefineQuery(queryName, queryExpr);
|
|
746
713
|
queryDef.extendNote({ notes });
|
|
747
714
|
return this.astAt(queryDef, pcx);
|
|
@@ -753,8 +720,8 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
753
720
|
const query = this.visit(defCx.query());
|
|
754
721
|
if (ast.isQueryElement(query)) {
|
|
755
722
|
const theQuery = new ast.AnonymousQuery(query);
|
|
756
|
-
const notes = getNotes(pcx.topLevelAnonQueryDef().tags());
|
|
757
|
-
const blockNotes = getNotes(pcx.tags());
|
|
723
|
+
const notes = (0, parse_utils_1.getNotes)(pcx.topLevelAnonQueryDef().tags());
|
|
724
|
+
const blockNotes = (0, parse_utils_1.getNotes)(pcx.tags());
|
|
758
725
|
theQuery.extendNote({ notes, blockNotes });
|
|
759
726
|
if (ENABLE_M4_WARNINGS) {
|
|
760
727
|
this.astError(theQuery, 'Anonymous `query:` statements are deprecated, use `run:` instead', 'warn');
|
|
@@ -767,8 +734,8 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
767
734
|
const query = this.visit(pcx.topLevelAnonQueryDef().query());
|
|
768
735
|
if (ast.isQueryElement(query)) {
|
|
769
736
|
const el = new ast.RunQueryDef(query);
|
|
770
|
-
el.extendNote({ blockNotes: getNotes(pcx._blockTags) });
|
|
771
|
-
el.extendNote({ notes: getNotes(pcx._noteTags) });
|
|
737
|
+
el.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx._blockTags) });
|
|
738
|
+
el.extendNote({ notes: (0, parse_utils_1.getNotes)(pcx._noteTags) });
|
|
772
739
|
return this.astAt(el, pcx);
|
|
773
740
|
}
|
|
774
741
|
throw this.internalError(pcx, `Run query matched, but ${query.elementType} found`);
|
|
@@ -780,7 +747,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
780
747
|
}
|
|
781
748
|
visitNestStatement(pcx) {
|
|
782
749
|
const nests = this.visitNestedQueryList(pcx.nestedQueryList());
|
|
783
|
-
nests.extendNote({ blockNotes: getNotes(pcx.tags()) });
|
|
750
|
+
nests.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
|
|
784
751
|
return nests;
|
|
785
752
|
}
|
|
786
753
|
visitNestedQueryList(pcx) {
|
|
@@ -789,7 +756,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
789
756
|
visitNestExisting(pcx) {
|
|
790
757
|
const name = this.getFieldName(pcx.queryName());
|
|
791
758
|
const propsCx = pcx.queryProperties();
|
|
792
|
-
const notes = getNotes(pcx.tags());
|
|
759
|
+
const notes = (0, parse_utils_1.getNotes)(pcx.tags());
|
|
793
760
|
if (propsCx) {
|
|
794
761
|
const nestRefine = new ast.NestRefinement(name);
|
|
795
762
|
const queryDesc = this.visitQueryProperties(propsCx);
|
|
@@ -802,18 +769,18 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
802
769
|
return nestRef;
|
|
803
770
|
}
|
|
804
771
|
visitNestDef(pcx) {
|
|
805
|
-
const name = getId(pcx.queryName());
|
|
772
|
+
const name = (0, parse_utils_1.getId)(pcx.queryName());
|
|
806
773
|
const nestDef = new ast.NestDefinition(name);
|
|
807
774
|
this.buildPipelineFromName(nestDef, pcx.pipelineFromName());
|
|
808
775
|
nestDef.extendNote({
|
|
809
|
-
notes: getNotes(pcx.tags()).concat(getIsNotes(pcx.isDefine())),
|
|
776
|
+
notes: (0, parse_utils_1.getNotes)(pcx.tags()).concat((0, parse_utils_1.getIsNotes)(pcx.isDefine())),
|
|
810
777
|
});
|
|
811
778
|
return this.astAt(nestDef, pcx);
|
|
812
779
|
}
|
|
813
780
|
visitExploreQueryDef(pcx) {
|
|
814
|
-
const name = getId(pcx.exploreQueryNameDef());
|
|
781
|
+
const name = (0, parse_utils_1.getId)(pcx.exploreQueryNameDef());
|
|
815
782
|
const queryDef = new ast.TurtleDecl(name);
|
|
816
|
-
const notes = getNotes(pcx).concat(getIsNotes(pcx.isDefine()));
|
|
783
|
+
const notes = (0, parse_utils_1.getNotes)(pcx).concat((0, parse_utils_1.getIsNotes)(pcx.isDefine()));
|
|
817
784
|
queryDef.extendNote({ notes });
|
|
818
785
|
this.buildPipelineFromName(queryDef, pcx.pipelineFromName());
|
|
819
786
|
return this.astAt(queryDef, pcx);
|
|
@@ -865,7 +832,8 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
865
832
|
return fieldExpr;
|
|
866
833
|
}
|
|
867
834
|
visitExprString(pcx) {
|
|
868
|
-
|
|
835
|
+
const str = this.getPlainString(pcx);
|
|
836
|
+
return new ast.ExprString(str);
|
|
869
837
|
}
|
|
870
838
|
visitExprRegex(pcx) {
|
|
871
839
|
const malloyRegex = pcx.HACKY_REGEX().text;
|
|
@@ -1002,7 +970,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
1002
970
|
visitExprAggFunc(pcx) {
|
|
1003
971
|
const argsCx = pcx.argumentList();
|
|
1004
972
|
const args = argsCx ? this.allFieldExpressions(argsCx.fieldExpr()) : [];
|
|
1005
|
-
const fn = getId(pcx);
|
|
973
|
+
const fn = (0, parse_utils_1.getId)(pcx);
|
|
1006
974
|
const pathCx = pcx.fieldPath();
|
|
1007
975
|
const path = pathCx
|
|
1008
976
|
? this.getFieldPath(pathCx, ast.ExpressionFieldReference)
|
|
@@ -1029,7 +997,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
1029
997
|
rawType = undefined;
|
|
1030
998
|
}
|
|
1031
999
|
}
|
|
1032
|
-
let fn = getOptionalId(pcx) || ((_b = pcx.timeframe()) === null || _b === void 0 ? void 0 : _b.text);
|
|
1000
|
+
let fn = (0, parse_utils_1.getOptionalId)(pcx) || ((_b = pcx.timeframe()) === null || _b === void 0 ? void 0 : _b.text);
|
|
1033
1001
|
if (fn === undefined) {
|
|
1034
1002
|
this.contextError(pcx, 'Function name error');
|
|
1035
1003
|
fn = 'FUNCTION_NAME_ERROR';
|
|
@@ -1096,7 +1064,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
1096
1064
|
return this.parseTime(pcx, ast.LiteralYear.parse);
|
|
1097
1065
|
}
|
|
1098
1066
|
visitImportStatement(pcx) {
|
|
1099
|
-
const url =
|
|
1067
|
+
const url = this.getPlainString(pcx.importURL());
|
|
1100
1068
|
return this.astAt(new ast.ImportStatement(url, this.parse.subTranslator.sourceURL), pcx);
|
|
1101
1069
|
}
|
|
1102
1070
|
visitJustExpr(pcx) {
|
|
@@ -1115,7 +1083,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
1115
1083
|
this.contextError(nmCx, 'Cannot redefine connection');
|
|
1116
1084
|
}
|
|
1117
1085
|
else {
|
|
1118
|
-
connectionName =
|
|
1086
|
+
connectionName = this.getPlainString(nmCx);
|
|
1119
1087
|
}
|
|
1120
1088
|
}
|
|
1121
1089
|
const selCx = blockEnt.sqlString();
|
|
@@ -24,6 +24,27 @@
|
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
25
|
exports.findReferences = exports.deprecatedParseTableURI = exports.constructTableKey = void 0;
|
|
26
26
|
const ParseTreeWalker_1 = require("antlr4ts/tree/ParseTreeWalker");
|
|
27
|
+
const parse_utils_1 = require("../parse-utils");
|
|
28
|
+
// Copy of the version in the parser which also errors on each non-string in a
|
|
29
|
+
// multi-line string collection. No need to error here, which is well, because
|
|
30
|
+
// we don't have access to the error log.
|
|
31
|
+
function getPlainString(cx) {
|
|
32
|
+
const shortStr = (0, parse_utils_1.getStringIfShort)(cx);
|
|
33
|
+
if (shortStr) {
|
|
34
|
+
return shortStr;
|
|
35
|
+
}
|
|
36
|
+
const safeParts = [];
|
|
37
|
+
const multiLineStr = cx.string().sqlString();
|
|
38
|
+
if (multiLineStr) {
|
|
39
|
+
for (const part of (0, parse_utils_1.getStringParts)(multiLineStr)) {
|
|
40
|
+
if (typeof part === 'string') {
|
|
41
|
+
safeParts.push(part);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return safeParts.join('');
|
|
45
|
+
}
|
|
46
|
+
return '';
|
|
47
|
+
}
|
|
27
48
|
class FindExternalReferences {
|
|
28
49
|
constructor(trans, tokens) {
|
|
29
50
|
this.trans = trans;
|
|
@@ -42,13 +63,13 @@ class FindExternalReferences {
|
|
|
42
63
|
}
|
|
43
64
|
}
|
|
44
65
|
enterTableMethod(pcx) {
|
|
45
|
-
const
|
|
46
|
-
const tablePath =
|
|
66
|
+
const connId = (0, parse_utils_1.getId)(pcx.connectionId());
|
|
67
|
+
const tablePath = getPlainString(pcx.tablePath());
|
|
47
68
|
const reference = this.trans.rangeFromContext(pcx);
|
|
48
|
-
this.registerTableReference(
|
|
69
|
+
this.registerTableReference(connId, tablePath, reference);
|
|
49
70
|
}
|
|
50
71
|
enterTableFunction(pcx) {
|
|
51
|
-
const tableURI =
|
|
72
|
+
const tableURI = getPlainString(pcx.tableURI());
|
|
52
73
|
// This use of `deprecatedParseTableURI` is ok because it is for handling the
|
|
53
74
|
// old, soon-to-be-deprecated table syntax.
|
|
54
75
|
const { connectionName, tablePath } = deprecatedParseTableURI(tableURI);
|
|
@@ -56,17 +77,11 @@ class FindExternalReferences {
|
|
|
56
77
|
this.registerTableReference(connectionName, tablePath, reference);
|
|
57
78
|
}
|
|
58
79
|
enterImportURL(pcx) {
|
|
59
|
-
const url =
|
|
80
|
+
const url = getPlainString(pcx);
|
|
60
81
|
if (!this.needImports[url]) {
|
|
61
82
|
this.needImports[url] = this.trans.rangeFromContext(pcx);
|
|
62
83
|
}
|
|
63
84
|
}
|
|
64
|
-
stripIdQuotes(id) {
|
|
65
|
-
if (id[0] === '`' && id[id.length - 1] === '`') {
|
|
66
|
-
return id.slice(1, -1);
|
|
67
|
-
}
|
|
68
|
-
return id;
|
|
69
|
-
}
|
|
70
85
|
}
|
|
71
86
|
function constructTableKey(connectionName, tablePath) {
|
|
72
87
|
return connectionName === undefined
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { ParserRuleContext } from 'antlr4ts';
|
|
2
|
+
import { StringContext, ShortStringContext, SqlStringContext, IsDefineContext, IdContext } from './lib/Malloy/MalloyParser';
|
|
3
|
+
import { TerminalNode } from 'antlr4ts/tree/TerminalNode';
|
|
4
|
+
/**
|
|
5
|
+
* Take the text of a matched string, including the matching quote
|
|
6
|
+
* characters, and return the actual contents of the string after
|
|
7
|
+
* \ processing.
|
|
8
|
+
* @param cx Any parse context which contains a string
|
|
9
|
+
* @returns Decocded string
|
|
10
|
+
*/
|
|
11
|
+
export declare function getShortString(scx: ShortStringContext): string;
|
|
12
|
+
export declare function getStringIfShort(cx: HasString): string | undefined;
|
|
13
|
+
export declare type HasString = ParserRuleContext & {
|
|
14
|
+
string: () => StringContext;
|
|
15
|
+
};
|
|
16
|
+
declare type StringPart = ParserRuleContext | string;
|
|
17
|
+
export declare function getStringParts(cx: SqlStringContext): Generator<StringPart>;
|
|
18
|
+
/**
|
|
19
|
+
* Parses the interior of a string, doing all \ substitutions. In most cases
|
|
20
|
+
* a lexical analyzer has already recognized this as a string. As a convenience,
|
|
21
|
+
* strip off the quoting outer chartacters if asked, then parse the interior of
|
|
22
|
+
* the string. The intention is to be compatible with JSON strings, in terms
|
|
23
|
+
* of which \X substitutions are processed.
|
|
24
|
+
* @param str is the string to parse
|
|
25
|
+
* @param surround is the quoting character, default means quotes already stripped
|
|
26
|
+
* @returns a string with the \ processing completed
|
|
27
|
+
*/
|
|
28
|
+
export declare function parseString(str: string, surround?: string): string;
|
|
29
|
+
declare type HasAnnotations = ParserRuleContext & {
|
|
30
|
+
ANNOTATION: () => TerminalNode[];
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Get all the possibly missing annotations from this parse rule
|
|
34
|
+
* @param cx Any parse context which has an ANNOTATION* rules
|
|
35
|
+
* @returns Array of texts for the annotations
|
|
36
|
+
*/
|
|
37
|
+
export declare function getNotes(cx: HasAnnotations): string[];
|
|
38
|
+
export declare function getIsNotes(cx: IsDefineContext): string[];
|
|
39
|
+
export declare type HasID = ParserRuleContext & {
|
|
40
|
+
id: () => IdContext;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* An identifier is either a sequence of id characters or a `quoted`
|
|
44
|
+
* This parses either to simply the resulting text.
|
|
45
|
+
* @param cx A context which has an identifier
|
|
46
|
+
* @returns The indenftifier text
|
|
47
|
+
*/
|
|
48
|
+
export declare function getId(cx: HasID): string;
|
|
49
|
+
export declare function getOptionalId(cx: ParserRuleContext): string | undefined;
|
|
50
|
+
export declare function unIndent(parts: (string | unknown)[]): void;
|
|
51
|
+
export {};
|