@malloydata/malloy 0.0.55 → 0.0.56-dev230707230009

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.
@@ -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: ContainsID): ast.FieldName;
46
- protected getModelEntryName(cx: ContainsID): ast.ModelEntryReference;
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 string_parser_1 = require("./string-parser");
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,36 @@ 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
+ return safeParts.join('');
189
+ }
190
+ // string: shortString | sqlString; So this will never happen
191
+ return '';
192
+ }
229
193
  makeSqlString(pcx, sqlStr) {
230
- var _a;
231
- for (const part of pcx.sqlInterpolation()) {
232
- const upToOpen = part.OPEN_CODE().text;
233
- if (upToOpen.length > 2) {
234
- sqlStr.push(upToOpen.slice(0, upToOpen.length - 2));
194
+ for (const part of (0, parse_utils_1.getStringParts)(pcx)) {
195
+ if (part instanceof antlr4ts_1.ParserRuleContext) {
196
+ sqlStr.push(this.visit(part));
197
+ }
198
+ else {
199
+ sqlStr.push(part);
235
200
  }
236
- sqlStr.push(this.visit(part.query()));
237
201
  }
238
- const lastChars = (_a = pcx.SQL_END()) === null || _a === void 0 ? void 0 : _a.text.slice(0, -3);
239
- sqlStr.push(lastChars || '');
240
202
  sqlStr.complete();
241
203
  this.astAt(sqlStr, pcx);
242
204
  }
@@ -260,14 +222,14 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
260
222
  visitDefineSourceStatement(pcx) {
261
223
  const defsCx = pcx.sourcePropertyList().sourceDefinition();
262
224
  const defs = defsCx.map(dcx => this.visitSourceDefinition(dcx));
263
- const blockNotes = getNotes(pcx.tags());
225
+ const blockNotes = (0, parse_utils_1.getNotes)(pcx.tags());
264
226
  const defList = new ast.DefineSourceList(defs);
265
227
  defList.extendNote({ blockNotes });
266
228
  return defList;
267
229
  }
268
230
  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()));
231
+ const exploreDef = new ast.DefineSource((0, parse_utils_1.getId)(pcx.sourceNameDef()), this.visitExplore(pcx.explore()), true, []);
232
+ const notes = (0, parse_utils_1.getNotes)(pcx.tags()).concat((0, parse_utils_1.getIsNotes)(pcx.isDefine()));
271
233
  exploreDef.extendNote({ notes });
272
234
  return this.astAt(exploreDef, pcx);
273
235
  }
@@ -289,7 +251,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
289
251
  return propList;
290
252
  }
291
253
  visitTableFunction(pcx) {
292
- const tableURI = getShortString(pcx.tableURI());
254
+ const tableURI = this.getPlainString(pcx.tableURI());
293
255
  const el = this.astAt(new ast.TableFunctionSource(tableURI), pcx);
294
256
  if (ENABLE_M4_WARNINGS) {
295
257
  this.astError(el, "`table('connection_name:table_path')` is deprecated; use `connection_name.table('table_path')`", 'warn');
@@ -299,7 +261,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
299
261
  visitTableMethod(pcx) {
300
262
  const connId = pcx.connectionId();
301
263
  const connectionName = this.astAt(this.getModelEntryName(connId), connId);
302
- const tablePath = getShortString(pcx.tablePath());
264
+ const tablePath = this.getPlainString(pcx.tablePath());
303
265
  return this.astAt(new ast.TableMethodSource(connectionName, tablePath), pcx);
304
266
  }
305
267
  visitTableSource(pcx) {
@@ -321,9 +283,9 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
321
283
  if (selCx) {
322
284
  this.makeSqlString(selCx, sqlStr);
323
285
  }
324
- const shortSelect = getOptionalString(pcx);
325
- if (shortSelect) {
326
- sqlStr.push(shortSelect);
286
+ const shortCX = pcx.shortString();
287
+ if (shortCX) {
288
+ sqlStr.push((0, parse_utils_1.getShortString)(shortCX));
327
289
  }
328
290
  const expr = new ast.SQLSource(connectionName, sqlStr);
329
291
  return this.astAt(expr, pcx);
@@ -353,7 +315,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
353
315
  }
354
316
  }
355
317
  const joinMany = new ast.Joins(joins);
356
- joinMany.extendNote({ blockNotes: getNotes(pcx.tags()) });
318
+ joinMany.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
357
319
  return joinMany;
358
320
  }
359
321
  visitDefJoinOne(pcx) {
@@ -368,7 +330,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
368
330
  }
369
331
  }
370
332
  const joinOne = new ast.Joins(joins);
371
- joinOne.extendNote({ blockNotes: getNotes(pcx.tags()) });
333
+ joinOne.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
372
334
  return joinOne;
373
335
  }
374
336
  visitDefJoinCross(pcx) {
@@ -386,7 +348,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
386
348
  }
387
349
  }
388
350
  const joinCross = new ast.Joins(joins);
389
- joinCross.extendNote({ blockNotes: getNotes(pcx.tags()) });
351
+ joinCross.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
390
352
  return joinCross;
391
353
  }
392
354
  getJoinList(pcx) {
@@ -395,7 +357,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
395
357
  getJoinSource(name, ecx) {
396
358
  if (ecx) {
397
359
  const joinSrc = this.visitExplore(ecx.explore());
398
- const notes = getNotes(ecx._before_is).concat(getNotes(ecx._after_is));
360
+ const notes = (0, parse_utils_1.getNotes)(ecx._before_is).concat((0, parse_utils_1.getNotes)(ecx._after_is));
399
361
  return { joinFrom: joinSrc, notes };
400
362
  }
401
363
  return { joinFrom: new ast.NamedSource(name), notes: [] };
@@ -415,7 +377,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
415
377
  if (onCx) {
416
378
  join.joinOn = this.getFieldExpr(onCx);
417
379
  }
418
- join.extendNote({ notes: getNotes(pcx).concat(notes) });
380
+ join.extendNote({ notes: (0, parse_utils_1.getNotes)(pcx).concat(notes) });
419
381
  return this.astAt(join, pcx);
420
382
  }
421
383
  visitJoinWith(pcx) {
@@ -423,28 +385,28 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
423
385
  const { joinFrom, notes } = this.getJoinSource(joinAs, pcx.isExplore());
424
386
  const joinOn = this.getFieldExpr(pcx.fieldExpr());
425
387
  const join = new ast.KeyJoin(joinAs, joinFrom, joinOn);
426
- join.extendNote({ notes: getNotes(pcx).concat(notes) });
388
+ join.extendNote({ notes: (0, parse_utils_1.getNotes)(pcx).concat(notes) });
427
389
  return this.astAt(join, pcx);
428
390
  }
429
391
  getFieldDef(pcx, makeFieldDef) {
430
392
  const defCx = pcx.fieldExpr();
431
- const fieldName = getId(pcx.fieldNameDef());
393
+ const fieldName = (0, parse_utils_1.getId)(pcx.fieldNameDef());
432
394
  const valExpr = this.getFieldExpr(defCx);
433
395
  const def = new makeFieldDef(valExpr, fieldName, this.getSourceCode(defCx));
434
- const notes = getNotes(pcx.tags()).concat(getIsNotes(pcx.isDefine()));
396
+ const notes = (0, parse_utils_1.getNotes)(pcx.tags()).concat((0, parse_utils_1.getIsNotes)(pcx.isDefine()));
435
397
  def.extendNote({ notes });
436
398
  return this.astAt(def, pcx);
437
399
  }
438
400
  visitDefDimensions(pcx) {
439
401
  const defs = this.getFieldDefs(pcx.defList().fieldDef(), ast.DimensionFieldDeclaration);
440
402
  const stmt = new ast.Dimensions(defs);
441
- stmt.extendNote({ blockNotes: getNotes(pcx.tags()) });
403
+ stmt.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
442
404
  return this.astAt(stmt, pcx);
443
405
  }
444
406
  visitDefMeasures(pcx) {
445
407
  const defs = this.getFieldDefs(pcx.defList().fieldDef(), ast.MeasureFieldDeclaration);
446
408
  const stmt = new ast.Measures(defs);
447
- stmt.extendNote({ blockNotes: getNotes(pcx.tags()) });
409
+ stmt.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
448
410
  return this.astAt(stmt, pcx);
449
411
  }
450
412
  visitQueryExtend(pcx) {
@@ -476,7 +438,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
476
438
  visitExploreRenameDef(pcx) {
477
439
  const newName = pcx.fieldName(0);
478
440
  const oldName = pcx.fieldName(1);
479
- const rename = new ast.RenameField(getId(newName), this.getFieldName(oldName));
441
+ const rename = new ast.RenameField((0, parse_utils_1.getId)(newName), this.getFieldName(oldName));
480
442
  return this.astAt(rename, pcx);
481
443
  }
482
444
  visitDefExploreRename(pcx) {
@@ -510,7 +472,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
510
472
  }
511
473
  visitDefExploreQuery(pcx) {
512
474
  const queryDefs = this.visitSubQueryDefList(pcx.subQueryDefList());
513
- const blockNotes = getNotes(pcx.tags());
475
+ const blockNotes = (0, parse_utils_1.getNotes)(pcx.tags());
514
476
  queryDefs.extendNote({ blockNotes });
515
477
  return queryDefs;
516
478
  }
@@ -532,7 +494,8 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
532
494
  return this.visitTimezoneStatement(cx.timezoneStatement());
533
495
  }
534
496
  visitTimezoneStatement(cx) {
535
- const timezoneStatement = this.astAt(new ast.TimezoneStatement(getShortString(cx)), cx.shortString());
497
+ const timezone = this.getPlainString(cx);
498
+ const timezoneStatement = this.astAt(new ast.TimezoneStatement(timezone), cx.string());
536
499
  if (!timezoneStatement.isValid) {
537
500
  this.astError(timezoneStatement, `Invalid timezone: ${timezoneStatement.tz}`);
538
501
  }
@@ -574,22 +537,22 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
574
537
  }
575
538
  visitAggregateStatement(pcx) {
576
539
  const agStmt = new ast.Aggregate(this.getQueryItems(pcx.queryFieldList(), ast.AggregateFieldDeclaration, ast.AggregateFieldReference));
577
- agStmt.extendNote({ blockNotes: getNotes(pcx.tags()) });
540
+ agStmt.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
578
541
  return agStmt;
579
542
  }
580
543
  visitGroupByStatement(pcx) {
581
544
  const groupBy = new ast.GroupBy(this.getQueryItems(pcx.queryFieldList(), ast.GroupByFieldDeclaration, ast.GroupByFieldReference));
582
- groupBy.extendNote({ blockNotes: getNotes(pcx.tags()) });
545
+ groupBy.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
583
546
  return groupBy;
584
547
  }
585
548
  visitCalculateStatement(pcx) {
586
549
  const stmt = new ast.Calculate(this.getQueryItems(pcx.queryFieldList(), ast.CalculateFieldDeclaration, ast.CalculateFieldReference));
587
- stmt.extendNote({ blockNotes: getNotes(pcx.tags()) });
550
+ stmt.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
588
551
  return stmt;
589
552
  }
590
553
  getTaggedRef(pcx, makeFieldRef) {
591
554
  const ref = this.getFieldPath(pcx.fieldPath(), makeFieldRef);
592
- ref.extendNote({ notes: getNotes(pcx.tags()) });
555
+ ref.extendNote({ notes: (0, parse_utils_1.getNotes)(pcx.tags()) });
593
556
  return ref;
594
557
  }
595
558
  getFieldCollectionMember(pcx, makeFieldDef, makeFieldRef) {
@@ -616,7 +579,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
616
579
  }
617
580
  visitProjectStatement(pcx) {
618
581
  const stmt = this.visitFieldCollection(pcx.fieldCollection());
619
- stmt.extendNote({ blockNotes: getNotes(pcx.tags()) });
582
+ stmt.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
620
583
  return stmt;
621
584
  }
622
585
  visitCollectionWildCard(pcx) {
@@ -691,7 +654,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
691
654
  return this.astAt(top, pcx);
692
655
  }
693
656
  visitSourceID(pcx) {
694
- return this.astAt(new ast.NamedSource(getId(pcx)), pcx);
657
+ return this.astAt(new ast.NamedSource((0, parse_utils_1.getId)(pcx)), pcx);
695
658
  }
696
659
  buildPipelineFromName(pipe, pipeCx) {
697
660
  const firstCx = pipeCx.firstSegment();
@@ -732,16 +695,16 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
732
695
  const stmts = pcx
733
696
  .topLevelQueryDef()
734
697
  .map(cx => this.visitTopLevelQueryDef(cx));
735
- const blockNotes = getNotes(pcx.tags());
698
+ const blockNotes = (0, parse_utils_1.getNotes)(pcx.tags());
736
699
  const queryDefs = new ast.DefineQueryList(stmts);
737
700
  queryDefs.extendNote({ blockNotes });
738
701
  return queryDefs;
739
702
  }
740
703
  visitTopLevelQueryDef(pcx) {
741
- const queryName = getId(pcx.queryName());
704
+ const queryName = (0, parse_utils_1.getId)(pcx.queryName());
742
705
  const queryExpr = this.visit(pcx.query());
743
706
  if (ast.isQueryElement(queryExpr)) {
744
- const notes = getNotes(pcx.tags()).concat(getIsNotes(pcx.isDefine()));
707
+ const notes = (0, parse_utils_1.getNotes)(pcx.tags()).concat((0, parse_utils_1.getIsNotes)(pcx.isDefine()));
745
708
  const queryDef = new ast.DefineQuery(queryName, queryExpr);
746
709
  queryDef.extendNote({ notes });
747
710
  return this.astAt(queryDef, pcx);
@@ -753,8 +716,8 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
753
716
  const query = this.visit(defCx.query());
754
717
  if (ast.isQueryElement(query)) {
755
718
  const theQuery = new ast.AnonymousQuery(query);
756
- const notes = getNotes(pcx.topLevelAnonQueryDef().tags());
757
- const blockNotes = getNotes(pcx.tags());
719
+ const notes = (0, parse_utils_1.getNotes)(pcx.topLevelAnonQueryDef().tags());
720
+ const blockNotes = (0, parse_utils_1.getNotes)(pcx.tags());
758
721
  theQuery.extendNote({ notes, blockNotes });
759
722
  if (ENABLE_M4_WARNINGS) {
760
723
  this.astError(theQuery, 'Anonymous `query:` statements are deprecated, use `run:` instead', 'warn');
@@ -767,8 +730,8 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
767
730
  const query = this.visit(pcx.topLevelAnonQueryDef().query());
768
731
  if (ast.isQueryElement(query)) {
769
732
  const el = new ast.RunQueryDef(query);
770
- el.extendNote({ blockNotes: getNotes(pcx._blockTags) });
771
- el.extendNote({ notes: getNotes(pcx._noteTags) });
733
+ el.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx._blockTags) });
734
+ el.extendNote({ notes: (0, parse_utils_1.getNotes)(pcx._noteTags) });
772
735
  return this.astAt(el, pcx);
773
736
  }
774
737
  throw this.internalError(pcx, `Run query matched, but ${query.elementType} found`);
@@ -780,7 +743,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
780
743
  }
781
744
  visitNestStatement(pcx) {
782
745
  const nests = this.visitNestedQueryList(pcx.nestedQueryList());
783
- nests.extendNote({ blockNotes: getNotes(pcx.tags()) });
746
+ nests.extendNote({ blockNotes: (0, parse_utils_1.getNotes)(pcx.tags()) });
784
747
  return nests;
785
748
  }
786
749
  visitNestedQueryList(pcx) {
@@ -789,7 +752,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
789
752
  visitNestExisting(pcx) {
790
753
  const name = this.getFieldName(pcx.queryName());
791
754
  const propsCx = pcx.queryProperties();
792
- const notes = getNotes(pcx.tags());
755
+ const notes = (0, parse_utils_1.getNotes)(pcx.tags());
793
756
  if (propsCx) {
794
757
  const nestRefine = new ast.NestRefinement(name);
795
758
  const queryDesc = this.visitQueryProperties(propsCx);
@@ -802,18 +765,18 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
802
765
  return nestRef;
803
766
  }
804
767
  visitNestDef(pcx) {
805
- const name = getId(pcx.queryName());
768
+ const name = (0, parse_utils_1.getId)(pcx.queryName());
806
769
  const nestDef = new ast.NestDefinition(name);
807
770
  this.buildPipelineFromName(nestDef, pcx.pipelineFromName());
808
771
  nestDef.extendNote({
809
- notes: getNotes(pcx.tags()).concat(getIsNotes(pcx.isDefine())),
772
+ notes: (0, parse_utils_1.getNotes)(pcx.tags()).concat((0, parse_utils_1.getIsNotes)(pcx.isDefine())),
810
773
  });
811
774
  return this.astAt(nestDef, pcx);
812
775
  }
813
776
  visitExploreQueryDef(pcx) {
814
- const name = getId(pcx.exploreQueryNameDef());
777
+ const name = (0, parse_utils_1.getId)(pcx.exploreQueryNameDef());
815
778
  const queryDef = new ast.TurtleDecl(name);
816
- const notes = getNotes(pcx).concat(getIsNotes(pcx.isDefine()));
779
+ const notes = (0, parse_utils_1.getNotes)(pcx).concat((0, parse_utils_1.getIsNotes)(pcx.isDefine()));
817
780
  queryDef.extendNote({ notes });
818
781
  this.buildPipelineFromName(queryDef, pcx.pipelineFromName());
819
782
  return this.astAt(queryDef, pcx);
@@ -865,7 +828,8 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
865
828
  return fieldExpr;
866
829
  }
867
830
  visitExprString(pcx) {
868
- return new ast.ExprString(getShortString(pcx));
831
+ const str = this.getPlainString(pcx);
832
+ return new ast.ExprString(str);
869
833
  }
870
834
  visitExprRegex(pcx) {
871
835
  const malloyRegex = pcx.HACKY_REGEX().text;
@@ -1002,7 +966,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
1002
966
  visitExprAggFunc(pcx) {
1003
967
  const argsCx = pcx.argumentList();
1004
968
  const args = argsCx ? this.allFieldExpressions(argsCx.fieldExpr()) : [];
1005
- const fn = getId(pcx);
969
+ const fn = (0, parse_utils_1.getId)(pcx);
1006
970
  const pathCx = pcx.fieldPath();
1007
971
  const path = pathCx
1008
972
  ? this.getFieldPath(pathCx, ast.ExpressionFieldReference)
@@ -1029,7 +993,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
1029
993
  rawType = undefined;
1030
994
  }
1031
995
  }
1032
- let fn = getOptionalId(pcx) || ((_b = pcx.timeframe()) === null || _b === void 0 ? void 0 : _b.text);
996
+ let fn = (0, parse_utils_1.getOptionalId)(pcx) || ((_b = pcx.timeframe()) === null || _b === void 0 ? void 0 : _b.text);
1033
997
  if (fn === undefined) {
1034
998
  this.contextError(pcx, 'Function name error');
1035
999
  fn = 'FUNCTION_NAME_ERROR';
@@ -1096,7 +1060,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
1096
1060
  return this.parseTime(pcx, ast.LiteralYear.parse);
1097
1061
  }
1098
1062
  visitImportStatement(pcx) {
1099
- const url = getShortString(pcx.importURL());
1063
+ const url = this.getPlainString(pcx.importURL());
1100
1064
  return this.astAt(new ast.ImportStatement(url, this.parse.subTranslator.sourceURL), pcx);
1101
1065
  }
1102
1066
  visitJustExpr(pcx) {
@@ -1115,7 +1079,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
1115
1079
  this.contextError(nmCx, 'Cannot redefine connection');
1116
1080
  }
1117
1081
  else {
1118
- connectionName = getShortString(nmCx);
1082
+ connectionName = this.getPlainString(nmCx);
1119
1083
  }
1120
1084
  }
1121
1085
  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 connectionName = this.stripIdQuotes(pcx.connectionId().text);
46
- const tablePath = this.tokens.getText(pcx.tablePath()).slice(1, -1);
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(connectionName, tablePath, reference);
69
+ this.registerTableReference(connId, tablePath, reference);
49
70
  }
50
71
  enterTableFunction(pcx) {
51
- const tableURI = this.tokens.getText(pcx.tableURI()).slice(1, -1);
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 = JSON.parse(pcx.shortString().text);
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,50 @@
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): 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 {};