@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.
@@ -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,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
- 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));
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
- const lastChars = (_a = pcx.SQL_END()) === null || _a === void 0 ? void 0 : _a.text.slice(0, -3);
239
- sqlStr.push(lastChars || '');
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 = getShortString(pcx.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 = getShortString(pcx.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 shortSelect = getOptionalString(pcx);
325
- if (shortSelect) {
326
- sqlStr.push(shortSelect);
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 timezoneStatement = this.astAt(new ast.TimezoneStatement(getShortString(cx)), cx.shortString());
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
- return new ast.ExprString(getShortString(pcx));
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 = getShortString(pcx.importURL());
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 = getShortString(nmCx);
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 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,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 {};