@malloydata/malloy 0.0.237-dev250225015031 → 0.0.237-dev250225213433
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/annotation.d.ts +15 -0
- package/dist/annotation.js +86 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +5 -3
- package/dist/lang/ast/types/annotation-elements.d.ts +1 -1
- package/dist/lang/ast/types/annotation-elements.js +2 -2
- package/dist/lang/ast/types/malloy-element.d.ts +1 -1
- package/dist/lang/ast/types/malloy-element.js +2 -2
- package/dist/lang/malloy-to-ast.d.ts +1 -1
- package/dist/lang/malloy-to-ast.js +2 -2
- package/dist/lang/parse-malloy.d.ts +1 -1
- package/dist/lang/parse-malloy.js +4 -3
- package/dist/lang/parse-utils.d.ts +0 -11
- package/dist/lang/parse-utils.js +4 -82
- package/dist/lang/syntax-errors/custom-error-messages.d.ts +4 -2
- package/dist/lang/syntax-errors/custom-error-messages.js +75 -16
- package/dist/lang/syntax-errors/malloy-error-strategy.d.ts +4 -6
- package/dist/lang/syntax-errors/malloy-error-strategy.js +3 -22
- package/dist/lang/syntax-errors/malloy-parser-error-listener.d.ts +1 -1
- package/dist/lang/syntax-errors/malloy-parser-error-listener.js +107 -10
- package/dist/lang/test/literals.spec.js +0 -34
- package/dist/lang/test/syntax-errors.spec.js +113 -59
- package/dist/malloy.d.ts +13 -8
- package/dist/malloy.js +23 -23
- package/dist/model/malloy_query.d.ts +3 -1
- package/dist/model/malloy_query.js +18 -3
- package/dist/model/materialization/utils.js +2 -2
- package/dist/to_stable.d.ts +3 -0
- package/dist/to_stable.js +170 -0
- package/package.json +3 -1
- package/dist/lang/lib/Malloy/MalloyTagLexer.d.ts +0 -42
- package/dist/lang/lib/Malloy/MalloyTagLexer.js +0 -385
- package/dist/lang/lib/Malloy/MalloyTagParser.d.ts +0 -180
- package/dist/lang/lib/Malloy/MalloyTagParser.js +0 -1051
- package/dist/lang/lib/Malloy/MalloyTagVisitor.d.ts +0 -120
- package/dist/lang/lib/Malloy/MalloyTagVisitor.js +0 -4
- package/dist/tags.d.ts +0 -72
- package/dist/tags.js +0 -512
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Tag } from '@malloydata/malloy-tag';
|
|
2
|
+
import { Annotation } from './model';
|
|
3
|
+
import { LogMessage } from './lang';
|
|
4
|
+
export interface TagParseSpec {
|
|
5
|
+
prefix?: RegExp;
|
|
6
|
+
extending?: Tag;
|
|
7
|
+
scopes?: Tag[];
|
|
8
|
+
}
|
|
9
|
+
export declare function addModelScope(spec: TagParseSpec | undefined, modelScope: Tag): TagParseSpec;
|
|
10
|
+
export declare function annotationToTaglines(annote: Annotation | undefined, prefix?: RegExp): string[];
|
|
11
|
+
export interface MalloyTagParse {
|
|
12
|
+
tag: Tag;
|
|
13
|
+
log: LogMessage[];
|
|
14
|
+
}
|
|
15
|
+
export declare function annotationToTag(annote: Annotation | undefined, spec?: TagParseSpec): MalloyTagParse;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.annotationToTag = exports.annotationToTaglines = exports.addModelScope = void 0;
|
|
4
|
+
const malloy_tag_1 = require("@malloydata/malloy-tag");
|
|
5
|
+
function addModelScope(spec, modelScope) {
|
|
6
|
+
const useSpec = spec ? { ...spec } : {};
|
|
7
|
+
if (useSpec.scopes) {
|
|
8
|
+
useSpec.scopes = useSpec.scopes.concat(modelScope);
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
useSpec.scopes = [modelScope];
|
|
12
|
+
}
|
|
13
|
+
return useSpec;
|
|
14
|
+
}
|
|
15
|
+
exports.addModelScope = addModelScope;
|
|
16
|
+
function annotationToTaglines(annote, prefix) {
|
|
17
|
+
annote || (annote = {});
|
|
18
|
+
const tagLines = annote.inherits
|
|
19
|
+
? annotationToTaglines(annote.inherits, prefix)
|
|
20
|
+
: [];
|
|
21
|
+
function prefixed(na) {
|
|
22
|
+
const ret = [];
|
|
23
|
+
for (const n of na || []) {
|
|
24
|
+
if (prefix === undefined || n.text.match(prefix)) {
|
|
25
|
+
ret.push(n.text);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return ret;
|
|
29
|
+
}
|
|
30
|
+
return tagLines.concat(prefixed(annote.blockNotes), prefixed(annote.notes));
|
|
31
|
+
}
|
|
32
|
+
exports.annotationToTaglines = annotationToTaglines;
|
|
33
|
+
function annotationToTag(annote, spec = {}) {
|
|
34
|
+
var _a;
|
|
35
|
+
let extending = spec.extending || new malloy_tag_1.Tag();
|
|
36
|
+
const prefix = spec.prefix || /^##? /;
|
|
37
|
+
annote || (annote = {});
|
|
38
|
+
const allErrs = [];
|
|
39
|
+
if (annote.inherits) {
|
|
40
|
+
const inherits = annotationToTag(annote.inherits, spec);
|
|
41
|
+
allErrs.push(...inherits.log);
|
|
42
|
+
extending = inherits.tag;
|
|
43
|
+
}
|
|
44
|
+
const allNotes = [];
|
|
45
|
+
if (annote.blockNotes) {
|
|
46
|
+
allNotes.push(...annote.blockNotes);
|
|
47
|
+
}
|
|
48
|
+
if (annote.notes) {
|
|
49
|
+
allNotes.push(...annote.notes);
|
|
50
|
+
}
|
|
51
|
+
const matchingNotes = [];
|
|
52
|
+
for (const note of allNotes) {
|
|
53
|
+
if (note.text.match(prefix)) {
|
|
54
|
+
matchingNotes.push(note);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
for (let i = 0; i < matchingNotes.length; i++) {
|
|
58
|
+
const note = matchingNotes[i];
|
|
59
|
+
if (note.text.match(prefix)) {
|
|
60
|
+
const noteParse = malloy_tag_1.Tag.fromTagLine(note.text, i, extending, ...((_a = spec.scopes) !== null && _a !== void 0 ? _a : []));
|
|
61
|
+
extending = noteParse.tag;
|
|
62
|
+
allErrs.push(...noteParse.log.map((e) => mapMalloyError(e, note)));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return { tag: extending, log: allErrs };
|
|
66
|
+
}
|
|
67
|
+
exports.annotationToTag = annotationToTag;
|
|
68
|
+
function mapMalloyError(e, note) {
|
|
69
|
+
const loc = {
|
|
70
|
+
line: note.at.range.start.line,
|
|
71
|
+
character: note.at.range.start.character + e.offset,
|
|
72
|
+
};
|
|
73
|
+
return {
|
|
74
|
+
code: 'tag-parse-error',
|
|
75
|
+
severity: 'error',
|
|
76
|
+
message: e.message,
|
|
77
|
+
at: {
|
|
78
|
+
url: note.at.url,
|
|
79
|
+
range: {
|
|
80
|
+
start: loc,
|
|
81
|
+
end: loc,
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=annotation.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -10,4 +10,5 @@ export type { QueryOptionsReader, RunSQLOptions } from './run_sql_options';
|
|
|
10
10
|
export type { EventStream, ModelString, ModelURL, QueryString, QueryURL, URLReader, InvalidationKey, } from './runtime_types';
|
|
11
11
|
export type { Connection, ConnectionConfig, ConnectionFactory, ConnectionParameter, ConnectionParameterValue, ConnectionConfigSchema, FetchSchemaOptions, InfoConnection, LookupConnection, PersistSQLResults, PooledConnection, TestableConnection, StreamingConnection, } from './connection/types';
|
|
12
12
|
export { toAsyncGenerator } from './connection_utils';
|
|
13
|
-
export {
|
|
13
|
+
export { modelDefToModelInfo } from './to_stable';
|
|
14
|
+
export { annotationToTag } from './annotation';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.InMemoryURLReader = exports.EmptyURLReader = exports.SingleConnectionRuntime = exports.ConnectionRuntime = exports.AtomicFieldType = exports.Runtime = exports.Malloy = exports.Model = exports.MalloyTranslator = exports.composeSQLExpr = exports.indent = exports.expressionIsUngroupedAggregate = exports.expressionIsScalar = exports.expressionIsCalculation = exports.expressionIsAnalytic = exports.expressionIsAggregate = exports.mkFieldDef = exports.mkArrayDef = exports.isScalarArray = exports.isRepeatedRecord = exports.isSamplingRows = exports.isSamplingPercent = exports.isSamplingEnable = exports.isJoinedSource = exports.isJoined = exports.isLeafAtomic = exports.Segment = exports.isSourceDef = exports.TinyParser = exports.Dialect = exports.spread = exports.literal = exports.variadicParam = exports.param = exports.makeParam = exports.sql = exports.maxScalar = exports.minAggregate = exports.anyExprType = exports.minScalar = exports.overload = exports.qtz = exports.arg = exports.registerDialect = exports.MySQLDialect = exports.SnowflakeDialect = exports.PostgresDialect = exports.TrinoDialect = exports.StandardSQLDialect = exports.DuckDBDialect = void 0;
|
|
4
|
-
exports.
|
|
4
|
+
exports.annotationToTag = exports.modelDefToModelInfo = exports.toAsyncGenerator = exports.CacheManager = exports.InMemoryModelCache = exports.Explore = exports.DataWriter = exports.Parse = exports.JSONWriter = exports.CSVWriter = exports.QueryMaterializer = exports.Result = exports.PreparedResult = exports.TimestampTimeframe = exports.DateTimeframe = exports.SourceRelationship = exports.JoinRelationship = exports.MalloyError = exports.FixedConnectionMap = void 0;
|
|
5
5
|
/*
|
|
6
6
|
* Copyright 2023 Google LLC
|
|
7
7
|
*
|
|
@@ -98,6 +98,8 @@ Object.defineProperty(exports, "InMemoryModelCache", { enumerable: true, get: fu
|
|
|
98
98
|
Object.defineProperty(exports, "CacheManager", { enumerable: true, get: function () { return malloy_1.CacheManager; } });
|
|
99
99
|
var connection_utils_1 = require("./connection_utils");
|
|
100
100
|
Object.defineProperty(exports, "toAsyncGenerator", { enumerable: true, get: function () { return connection_utils_1.toAsyncGenerator; } });
|
|
101
|
-
var
|
|
102
|
-
Object.defineProperty(exports, "
|
|
101
|
+
var to_stable_1 = require("./to_stable");
|
|
102
|
+
Object.defineProperty(exports, "modelDefToModelInfo", { enumerable: true, get: function () { return to_stable_1.modelDefToModelInfo; } });
|
|
103
|
+
var annotation_1 = require("./annotation");
|
|
104
|
+
Object.defineProperty(exports, "annotationToTag", { enumerable: true, get: function () { return annotation_1.annotationToTag; } });
|
|
103
105
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Note } from '../../../model/malloy_types';
|
|
2
|
-
import { Tag } from '
|
|
2
|
+
import { Tag } from '@malloydata/malloy-tag';
|
|
3
3
|
import { MessageLogger } from '../../parse-log';
|
|
4
4
|
import { Document, DocStatement, MalloyElement } from './malloy-element';
|
|
5
5
|
import { QueryPropertyInterface } from './query-property-interface';
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
*/
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
25
|
exports.ModelAnnotation = exports.ObjectAnnotation = void 0;
|
|
26
|
-
const tags_1 = require("../../../tags");
|
|
27
26
|
const malloy_element_1 = require("./malloy-element");
|
|
27
|
+
const annotation_1 = require("../../../annotation");
|
|
28
28
|
class ObjectAnnotation extends malloy_element_1.MalloyElement {
|
|
29
29
|
constructor(notes) {
|
|
30
30
|
super();
|
|
@@ -42,7 +42,7 @@ class ModelAnnotation extends ObjectAnnotation {
|
|
|
42
42
|
this.elementType = 'modelAnnotation';
|
|
43
43
|
}
|
|
44
44
|
getCompilerFlags(existing, logTo) {
|
|
45
|
-
const tagParse =
|
|
45
|
+
const tagParse = (0, annotation_1.annotationToTag)({ notes: this.notes }, {
|
|
46
46
|
prefix: /^##! /,
|
|
47
47
|
extending: existing,
|
|
48
48
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Annotation, DocumentLocation, DocumentReference, ModelDef, ModelAnnotation, NamedModelObject, Query, StructDef } from '../../../model/malloy_types';
|
|
2
|
-
import { Tag } from '
|
|
2
|
+
import { Tag } from '@malloydata/malloy-tag';
|
|
3
3
|
import { LogMessageOptions, MessageLogger, MessageParameterType, MessageCode } from '../../parse-log';
|
|
4
4
|
import { MalloyTranslation } from '../../parse-malloy';
|
|
5
5
|
import { ModelDataRequest } from '../../translate-response';
|
|
@@ -25,7 +25,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
25
25
|
exports.Document = exports.DocStatementList = exports.ListOf = exports.isDocStatementOrDocStatementList = exports.isDocStatement = exports.ExperimentalExperiment = exports.ModelEntryReference = exports.Unimplemented = exports.MalloyElement = void 0;
|
|
26
26
|
const dialect_1 = require("../../../dialect");
|
|
27
27
|
const malloy_types_1 = require("../../../model/malloy_types");
|
|
28
|
-
const
|
|
28
|
+
const malloy_tag_1 = require("@malloydata/malloy-tag");
|
|
29
29
|
const parse_log_1 = require("../../parse-log");
|
|
30
30
|
const ast_utils_1 = require("../ast-utils");
|
|
31
31
|
const dialect_name_space_1 = require("./dialect-name-space");
|
|
@@ -432,7 +432,7 @@ class Document extends MalloyElement {
|
|
|
432
432
|
this.queryList = [];
|
|
433
433
|
this.didInitModel = false;
|
|
434
434
|
this.annotation = {};
|
|
435
|
-
this.experiments = new
|
|
435
|
+
this.experiments = new malloy_tag_1.Tag({});
|
|
436
436
|
this.modelAnnotationTodoList = [];
|
|
437
437
|
this.dialectNameSpaces = new Map();
|
|
438
438
|
this.statements = new DocStatementList(statements);
|
|
@@ -10,7 +10,7 @@ import { FieldDeclarationConstructor } from './ast';
|
|
|
10
10
|
import { HasString, HasID } from './parse-utils';
|
|
11
11
|
import { CastType } from '../model';
|
|
12
12
|
import { AccessModifierLabel, DocumentLocation, DocumentRange, Note } from '../model/malloy_types';
|
|
13
|
-
import { Tag } from '
|
|
13
|
+
import { Tag } from '@malloydata/malloy-tag';
|
|
14
14
|
declare class ErrorNode extends ast.SourceQueryElement {
|
|
15
15
|
elementType: string;
|
|
16
16
|
}
|
|
@@ -55,7 +55,7 @@ const Interval_1 = require("antlr4ts/misc/Interval");
|
|
|
55
55
|
const ast_1 = require("./ast");
|
|
56
56
|
const parse_utils_1 = require("./parse-utils");
|
|
57
57
|
const malloy_types_1 = require("../model/malloy_types");
|
|
58
|
-
const
|
|
58
|
+
const malloy_tag_1 = require("@malloydata/malloy-tag");
|
|
59
59
|
const constant_expression_1 = require("./ast/expressions/constant-expression");
|
|
60
60
|
const utils_1 = require("./utils");
|
|
61
61
|
class ErrorNode extends ast.SourceQueryElement {
|
|
@@ -83,7 +83,7 @@ class MalloyToAST extends AbstractParseTreeVisitor_1.AbstractParseTreeVisitor {
|
|
|
83
83
|
this.msgLog = msgLog;
|
|
84
84
|
this.compilerFlags = compilerFlags;
|
|
85
85
|
for (const flag of DEFAULT_COMPILER_FLAGS) {
|
|
86
|
-
const withNewTag =
|
|
86
|
+
const withNewTag = malloy_tag_1.Tag.fromTagLine(flag, 0, this.compilerFlags);
|
|
87
87
|
this.compilerFlags = withNewTag.tag;
|
|
88
88
|
}
|
|
89
89
|
}
|
|
@@ -4,7 +4,7 @@ import { BaseMessageLogger, LogMessage, LogMessageOptions, MessageCode, MessageP
|
|
|
4
4
|
import { Zone, ZoneData } from './zone';
|
|
5
5
|
import { ReferenceList } from './reference-list';
|
|
6
6
|
import { ASTResponse, CompletionsResponse, DataRequestResponse, ProblemResponse, FatalResponse, FinalResponse, HelpContextResponse, MetadataResponse, ModelDataRequest, NeedURLData, TranslateResponse, ModelAnnotationResponse, TablePathResponse } from './translate-response';
|
|
7
|
-
import { Tag } from '
|
|
7
|
+
import { Tag } from '@malloydata/malloy-tag';
|
|
8
8
|
import { MalloyParseInfo } from './malloy-parse-info';
|
|
9
9
|
import { EventStream } from '../runtime_types';
|
|
10
10
|
export type StepResponses = DataRequestResponse | ASTResponse | TranslateResponse | ParseResponse | MetadataResponse | PretranslatedResponse;
|
|
@@ -61,9 +61,10 @@ const document_help_context_walker_1 = require("./parse-tree-walkers/document-he
|
|
|
61
61
|
const reference_list_1 = require("./reference-list");
|
|
62
62
|
const translate_response_1 = require("./translate-response");
|
|
63
63
|
const utils_1 = require("./utils");
|
|
64
|
-
const
|
|
64
|
+
const malloy_tag_1 = require("@malloydata/malloy-tag");
|
|
65
65
|
const model_annotation_walker_1 = require("./parse-tree-walkers/model-annotation-walker");
|
|
66
66
|
const find_table_path_walker_1 = require("./parse-tree-walkers/find-table-path-walker");
|
|
67
|
+
const annotation_1 = require("../annotation");
|
|
67
68
|
const malloy_error_strategy_1 = require("./syntax-errors/malloy-error-strategy");
|
|
68
69
|
const malloy_parser_error_listener_1 = require("./syntax-errors/malloy-parser-error-listener");
|
|
69
70
|
/**
|
|
@@ -470,7 +471,7 @@ class TranslateStep {
|
|
|
470
471
|
}
|
|
471
472
|
// begin with the compiler flags of the model we are extending
|
|
472
473
|
if (extendingModel && !this.importedAnnotations) {
|
|
473
|
-
const tagParse =
|
|
474
|
+
const tagParse = (0, annotation_1.annotationToTag)(extendingModel.annotation, {
|
|
474
475
|
prefix: /^##! /,
|
|
475
476
|
});
|
|
476
477
|
that.compilerFlags = tagParse.tag;
|
|
@@ -530,7 +531,7 @@ class MalloyTranslation {
|
|
|
530
531
|
this.grammarRule = grammarRule;
|
|
531
532
|
this.sqlSources = [];
|
|
532
533
|
this.imports = [];
|
|
533
|
-
this.compilerFlags = new
|
|
534
|
+
this.compilerFlags = new malloy_tag_1.Tag();
|
|
534
535
|
this._urlIsFullPath = undefined;
|
|
535
536
|
/*
|
|
536
537
|
Experimental dialect support, not confident this is how this should work.
|
|
@@ -14,17 +14,6 @@ export type HasString = {
|
|
|
14
14
|
};
|
|
15
15
|
type StringPart = ParserRuleContext | string;
|
|
16
16
|
export declare function getStringParts(cx: SqlStringContext): Generator<StringPart>;
|
|
17
|
-
/**
|
|
18
|
-
* Parses the interior of a string, doing all \ substitutions. In most cases
|
|
19
|
-
* a lexical analyzer has already recognized this as a string. As a convenience,
|
|
20
|
-
* strip off the quoting outer chartacters if asked, then parse the interior of
|
|
21
|
-
* the string. The intention is to be compatible with JSON strings, in terms
|
|
22
|
-
* of which \X substitutions are processed.
|
|
23
|
-
* @param str is the string to parse
|
|
24
|
-
* @param surround is the quoting character, default means quotes already stripped
|
|
25
|
-
* @returns a string with the \ processing completed
|
|
26
|
-
*/
|
|
27
|
-
export declare function parseString(str: string, surround?: string): string;
|
|
28
17
|
export type HasID = ParserRuleContext & {
|
|
29
18
|
id: () => IdContext;
|
|
30
19
|
};
|
package/dist/lang/parse-utils.js
CHANGED
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.getPlainString = exports.unIndent = exports.getOptionalId = exports.idToStr = exports.getId = exports.
|
|
25
|
+
exports.getPlainString = exports.unIndent = exports.getOptionalId = exports.idToStr = exports.getId = exports.getStringParts = exports.getStringIfShort = exports.getShortString = void 0;
|
|
26
|
+
const malloy_tag_1 = require("@malloydata/malloy-tag");
|
|
26
27
|
/**
|
|
27
28
|
* Take the text of a matched string, including the matching quote
|
|
28
29
|
* characters, and return the actual contents of the string after
|
|
@@ -34,7 +35,7 @@ function getShortString(scx) {
|
|
|
34
35
|
var _a, _b;
|
|
35
36
|
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);
|
|
36
37
|
if (str) {
|
|
37
|
-
return parseString(str, str[0]);
|
|
38
|
+
return malloy_tag_1.ParseUtil.parseString(str, str[0]);
|
|
38
39
|
}
|
|
39
40
|
// shortString: DQ_STRING | SQ_STRING; So this will never happen
|
|
40
41
|
return '';
|
|
@@ -66,85 +67,6 @@ function* getStringParts(cx) {
|
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
exports.getStringParts = getStringParts;
|
|
69
|
-
var ParseState;
|
|
70
|
-
(function (ParseState) {
|
|
71
|
-
ParseState[ParseState["Normal"] = 0] = "Normal";
|
|
72
|
-
ParseState[ParseState["ReverseVirgule"] = 1] = "ReverseVirgule";
|
|
73
|
-
ParseState[ParseState["Unicode"] = 2] = "Unicode";
|
|
74
|
-
})(ParseState || (ParseState = {}));
|
|
75
|
-
/**
|
|
76
|
-
* Parses the interior of a string, doing all \ substitutions. In most cases
|
|
77
|
-
* a lexical analyzer has already recognized this as a string. As a convenience,
|
|
78
|
-
* strip off the quoting outer chartacters if asked, then parse the interior of
|
|
79
|
-
* the string. The intention is to be compatible with JSON strings, in terms
|
|
80
|
-
* of which \X substitutions are processed.
|
|
81
|
-
* @param str is the string to parse
|
|
82
|
-
* @param surround is the quoting character, default means quotes already stripped
|
|
83
|
-
* @returns a string with the \ processing completed
|
|
84
|
-
*/
|
|
85
|
-
function parseString(str, surround = '') {
|
|
86
|
-
let inner = str.slice(surround.length);
|
|
87
|
-
let state = ParseState.Normal;
|
|
88
|
-
if (surround.length) {
|
|
89
|
-
inner = inner.slice(0, -surround.length);
|
|
90
|
-
}
|
|
91
|
-
let out = '';
|
|
92
|
-
let unicode = '';
|
|
93
|
-
for (const c of inner) {
|
|
94
|
-
switch (state) {
|
|
95
|
-
case ParseState.Normal: {
|
|
96
|
-
if (c === '\\') {
|
|
97
|
-
state = ParseState.ReverseVirgule;
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
out += c;
|
|
101
|
-
}
|
|
102
|
-
break;
|
|
103
|
-
}
|
|
104
|
-
case ParseState.ReverseVirgule: {
|
|
105
|
-
let outc = c;
|
|
106
|
-
if (c === 'u') {
|
|
107
|
-
state = ParseState.Unicode;
|
|
108
|
-
unicode = '';
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
if (c === 'b') {
|
|
112
|
-
outc = '\b';
|
|
113
|
-
}
|
|
114
|
-
else if (c === 'f') {
|
|
115
|
-
outc = '\f';
|
|
116
|
-
}
|
|
117
|
-
else if (c === 'n') {
|
|
118
|
-
outc = '\n';
|
|
119
|
-
}
|
|
120
|
-
else if (c === 'r') {
|
|
121
|
-
outc = '\r';
|
|
122
|
-
}
|
|
123
|
-
else if (c === 't') {
|
|
124
|
-
outc = '\t';
|
|
125
|
-
}
|
|
126
|
-
out += outc;
|
|
127
|
-
state = ParseState.Normal;
|
|
128
|
-
break;
|
|
129
|
-
}
|
|
130
|
-
case ParseState.Unicode: {
|
|
131
|
-
if ('ABCDEFabcdef0123456789'.includes(c)) {
|
|
132
|
-
unicode += c;
|
|
133
|
-
if (unicode.length === 4) {
|
|
134
|
-
out += String.fromCharCode(parseInt(unicode, 16));
|
|
135
|
-
state = ParseState.Normal;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
// Don't think we ever get here ...
|
|
140
|
-
state = ParseState.Normal;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
return out;
|
|
146
|
-
}
|
|
147
|
-
exports.parseString = parseString;
|
|
148
70
|
/**
|
|
149
71
|
* An identifier is either a sequence of id characters or a `quoted`
|
|
150
72
|
* This parses either to simply the resulting text.
|
|
@@ -158,7 +80,7 @@ exports.getId = getId;
|
|
|
158
80
|
function idToStr(cx) {
|
|
159
81
|
const quoted = cx.BQ_STRING();
|
|
160
82
|
if (quoted) {
|
|
161
|
-
return parseString(quoted.text, '`');
|
|
83
|
+
return malloy_tag_1.ParseUtil.parseString(quoted.text, '`');
|
|
162
84
|
}
|
|
163
85
|
return cx.text;
|
|
164
86
|
}
|
|
@@ -2,10 +2,12 @@ import { Parser, Token } from 'antlr4ts';
|
|
|
2
2
|
export interface ErrorCase {
|
|
3
3
|
ruleContextOptions?: string[];
|
|
4
4
|
offendingSymbol?: number;
|
|
5
|
+
offendingSymbolTextOptions?: string[];
|
|
5
6
|
currentToken?: number;
|
|
6
7
|
precedingTokenOptions?: number[][];
|
|
7
|
-
lookAheadOptions?: number[][];
|
|
8
|
+
lookAheadOptions?: (number | string)[][];
|
|
8
9
|
errorMessage: string;
|
|
9
|
-
|
|
10
|
+
lookbackSiblingRuleOptions?: number[];
|
|
11
|
+
predecessorHasAncestorRule?: number;
|
|
10
12
|
}
|
|
11
13
|
export declare const checkCustomErrorMessage: (parser: Parser, offendingSymbol: Token | undefined, errorCases: ErrorCase[]) => string;
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.checkCustomErrorMessage = void 0;
|
|
10
10
|
const checkCustomErrorMessage = (parser, offendingSymbol, errorCases) => {
|
|
11
|
+
var _a, _b;
|
|
11
12
|
const currentRuleName = parser.getRuleInvocationStack()[0];
|
|
12
13
|
const currentToken = parser.currentToken;
|
|
13
14
|
for (const errorCase of errorCases) {
|
|
@@ -17,52 +18,110 @@ const checkCustomErrorMessage = (parser, offendingSymbol, errorCases) => {
|
|
|
17
18
|
(offendingSymbol === null || offendingSymbol === void 0 ? void 0 : offendingSymbol.type) === errorCase.offendingSymbol;
|
|
18
19
|
const isRuleContextMatch = !errorCase.ruleContextOptions ||
|
|
19
20
|
errorCase.ruleContextOptions.includes(currentRuleName);
|
|
20
|
-
|
|
21
|
+
const isOffendingSymbolTextMatch = !errorCase.offendingSymbolTextOptions ||
|
|
22
|
+
errorCase.offendingSymbolTextOptions.includes(((_a = offendingSymbol === null || offendingSymbol === void 0 ? void 0 : offendingSymbol.text) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '');
|
|
23
|
+
if (isCurrentTokenMatch &&
|
|
24
|
+
isOffendingSymbolMatch &&
|
|
25
|
+
isRuleContextMatch &&
|
|
26
|
+
isOffendingSymbolTextMatch) {
|
|
27
|
+
if (errorCase.lookbackSiblingRuleOptions) {
|
|
28
|
+
const siblings = parser.ruleContext.children;
|
|
29
|
+
if (!siblings) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
// We use 'any' here because the sibling isn't guaranteed to be a RuleContext,
|
|
33
|
+
// but we only care if it has a ruleIndex. If it doesn't then .includes() won't
|
|
34
|
+
// match anyways.
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
36
|
+
const precedingRule = siblings[siblings.length - 1];
|
|
37
|
+
if (!errorCase.lookbackSiblingRuleOptions.includes(precedingRule.ruleIndex)) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
21
41
|
// If so, try to check the preceding tokens.
|
|
22
42
|
if (errorCase.precedingTokenOptions) {
|
|
23
|
-
const hasPrecedingTokenMatch = errorCase.precedingTokenOptions.some(sequence => checkTokenSequenceMatch(parser, sequence, 'lookback',
|
|
24
|
-
? offendingSymbol === null || offendingSymbol === void 0 ? void 0 : offendingSymbol.tokenIndex
|
|
25
|
-
: undefined));
|
|
43
|
+
const hasPrecedingTokenMatch = errorCase.precedingTokenOptions.some(sequence => checkTokenSequenceMatch(parser, sequence, 'lookback', offendingSymbol === null || offendingSymbol === void 0 ? void 0 : offendingSymbol.tokenIndex));
|
|
26
44
|
if (!hasPrecedingTokenMatch) {
|
|
27
45
|
continue; // Continue to check a different error case
|
|
28
46
|
}
|
|
29
47
|
}
|
|
30
48
|
if (errorCase.lookAheadOptions) {
|
|
31
|
-
const hasLookaheadTokenMatch = errorCase.lookAheadOptions.some(sequence => checkTokenSequenceMatch(parser, sequence, 'lookahead',
|
|
32
|
-
? offendingSymbol === null || offendingSymbol === void 0 ? void 0 : offendingSymbol.tokenIndex
|
|
33
|
-
: undefined));
|
|
49
|
+
const hasLookaheadTokenMatch = errorCase.lookAheadOptions.some(sequence => checkTokenSequenceMatch(parser, sequence, 'lookahead', offendingSymbol === null || offendingSymbol === void 0 ? void 0 : offendingSymbol.tokenIndex));
|
|
34
50
|
if (!hasLookaheadTokenMatch) {
|
|
35
51
|
continue; // Continue to check a different error case
|
|
36
52
|
}
|
|
37
53
|
}
|
|
54
|
+
if (errorCase.predecessorHasAncestorRule) {
|
|
55
|
+
const precedingSibling = (_b = parser.ruleContext.children) === null || _b === void 0 ? void 0 : _b[0];
|
|
56
|
+
if (!precedingSibling ||
|
|
57
|
+
!doesRightmostBranchContainRule(precedingSibling, errorCase.predecessorHasAncestorRule)) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
38
61
|
// If all cases match, return the custom error message
|
|
39
|
-
|
|
62
|
+
let message = errorCase.errorMessage
|
|
63
|
+
.replace('${currentToken}', currentToken.text || '')
|
|
64
|
+
.replace('${offendingSymbol}', (offendingSymbol === null || offendingSymbol === void 0 ? void 0 : offendingSymbol.text) || '');
|
|
65
|
+
try {
|
|
66
|
+
const previousToken = parser.inputStream.LT(-1);
|
|
67
|
+
message = message.replace('${previousToken}', previousToken.text || '');
|
|
68
|
+
}
|
|
69
|
+
catch (ex) {
|
|
70
|
+
// This shouldn't ever occur, but if it does, just leave the untokenized message.
|
|
71
|
+
}
|
|
40
72
|
return message;
|
|
41
73
|
}
|
|
42
74
|
}
|
|
43
75
|
return '';
|
|
44
76
|
};
|
|
45
77
|
exports.checkCustomErrorMessage = checkCustomErrorMessage;
|
|
78
|
+
// Recursively walk the rightmost branch (the path to the most recent token)
|
|
79
|
+
// to see whether any of those parse tree nodes match the provided rule number.
|
|
80
|
+
const doesRightmostBranchContainRule = (root, ruleNumber, depthLimit = 20) => {
|
|
81
|
+
var _a;
|
|
82
|
+
if (root.ruleIndex === ruleNumber) {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
if (depthLimit <= 0) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
const childCount = ((_a = root.children) === null || _a === void 0 ? void 0 : _a.length) || 0;
|
|
89
|
+
if (root.children && childCount > 0) {
|
|
90
|
+
const rightmostChild = root.children[root.children.length - 1];
|
|
91
|
+
return doesRightmostBranchContainRule(rightmostChild, ruleNumber, depthLimit - 1);
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
};
|
|
46
95
|
const checkTokenSequenceMatch = (parser, sequence, direction, anchorTokenPosition) => {
|
|
96
|
+
var _a;
|
|
47
97
|
try {
|
|
48
98
|
for (let i = 0; i < sequence.length; i++) {
|
|
49
99
|
let streamToken = undefined;
|
|
50
100
|
if (typeof anchorTokenPosition === 'number') {
|
|
51
101
|
const tokenOffset = direction === 'lookahead' ? i + 1 : -1 * (i + 1);
|
|
52
|
-
streamToken = parser.inputStream.get(anchorTokenPosition + tokenOffset)
|
|
102
|
+
streamToken = parser.inputStream.get(anchorTokenPosition + tokenOffset);
|
|
53
103
|
}
|
|
54
104
|
else {
|
|
55
105
|
// Note: positive lookahead starts at '2' because '1' is the current token.
|
|
56
106
|
const tokenOffset = direction === 'lookahead' ? i + 2 : -1 * (i + 1);
|
|
57
|
-
streamToken = parser.inputStream.
|
|
107
|
+
streamToken = parser.inputStream.LT(tokenOffset);
|
|
58
108
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
109
|
+
if (typeof sequence[i] === 'number') {
|
|
110
|
+
const tokenIndex = sequence[i];
|
|
111
|
+
// Note: negative checking is < -1 becuase Token.EOF is -1, but below
|
|
112
|
+
// that we use negatives to indicate "does-not-match" rules.
|
|
113
|
+
if (tokenIndex >= -1 && streamToken.type !== tokenIndex) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
if (tokenIndex < -1 && streamToken.type === -1 * tokenIndex) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
63
119
|
}
|
|
64
|
-
if (sequence[i]
|
|
65
|
-
|
|
120
|
+
else if (typeof sequence[i] === 'string') {
|
|
121
|
+
const tokenText = sequence[i];
|
|
122
|
+
if (tokenText !== ((_a = streamToken.text) === null || _a === void 0 ? void 0 : _a.toLowerCase())) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
66
125
|
}
|
|
67
126
|
}
|
|
68
127
|
return true;
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import { DefaultErrorStrategy
|
|
1
|
+
import { DefaultErrorStrategy } from 'antlr4ts';
|
|
2
2
|
/**
|
|
3
|
-
* Custom error strategy for the Malloy Parser.
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* custom error strategy will fall back to the default error strategy.
|
|
3
|
+
* Custom error strategy for the Malloy Parser.
|
|
4
|
+
*
|
|
5
|
+
* This class does not currently override default ANTLR error handling.
|
|
7
6
|
*
|
|
8
7
|
* For more details, read the documentation in DefaultErrorStrategy.d.ts
|
|
9
8
|
* or reference the superclass at:
|
|
10
9
|
* https://github.com/tunnelvisionlabs/antlr4ts/blob/master/src/DefaultErrorStrategy.ts
|
|
11
10
|
*/
|
|
12
11
|
export declare class MalloyErrorStrategy extends DefaultErrorStrategy {
|
|
13
|
-
sync(parser: Parser): void;
|
|
14
12
|
}
|
|
@@ -8,35 +8,16 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.MalloyErrorStrategy = void 0;
|
|
10
10
|
const antlr4ts_1 = require("antlr4ts");
|
|
11
|
-
const MalloyParser_1 = require("../lib/Malloy/MalloyParser");
|
|
12
|
-
const custom_error_messages_1 = require("./custom-error-messages");
|
|
13
|
-
const customErrorCases = [
|
|
14
|
-
{
|
|
15
|
-
errorMessage: "Missing '{' after 'extend'",
|
|
16
|
-
currentToken: MalloyParser_1.MalloyParser.EXTEND,
|
|
17
|
-
ruleContextOptions: ['sqExpr'],
|
|
18
|
-
lookAheadOptions: [[-MalloyParser_1.MalloyParser.OCURLY]],
|
|
19
|
-
},
|
|
20
|
-
];
|
|
21
11
|
/**
|
|
22
|
-
* Custom error strategy for the Malloy Parser.
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* custom error strategy will fall back to the default error strategy.
|
|
12
|
+
* Custom error strategy for the Malloy Parser.
|
|
13
|
+
*
|
|
14
|
+
* This class does not currently override default ANTLR error handling.
|
|
26
15
|
*
|
|
27
16
|
* For more details, read the documentation in DefaultErrorStrategy.d.ts
|
|
28
17
|
* or reference the superclass at:
|
|
29
18
|
* https://github.com/tunnelvisionlabs/antlr4ts/blob/master/src/DefaultErrorStrategy.ts
|
|
30
19
|
*/
|
|
31
20
|
class MalloyErrorStrategy extends antlr4ts_1.DefaultErrorStrategy {
|
|
32
|
-
sync(parser) {
|
|
33
|
-
const interceptedErrorMessage = (0, custom_error_messages_1.checkCustomErrorMessage)(parser, undefined, customErrorCases);
|
|
34
|
-
if (interceptedErrorMessage) {
|
|
35
|
-
parser.notifyErrorListeners(interceptedErrorMessage, parser.currentToken, undefined);
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
super.sync(parser);
|
|
39
|
-
}
|
|
40
21
|
}
|
|
41
22
|
exports.MalloyErrorStrategy = MalloyErrorStrategy;
|
|
42
23
|
//# sourceMappingURL=malloy-error-strategy.js.map
|
|
@@ -2,7 +2,7 @@ import { ANTLRErrorListener, Token } from 'antlr4ts';
|
|
|
2
2
|
import { ErrorCase } from './custom-error-messages';
|
|
3
3
|
import { MessageLogger, MessageCode, MessageParameterType, LogMessageOptions } from '../parse-log';
|
|
4
4
|
import { MalloyTranslation } from '../parse-malloy';
|
|
5
|
-
export declare const
|
|
5
|
+
export declare const malloyCustomErrorCases: ErrorCase[];
|
|
6
6
|
export declare class MalloyParserErrorListener implements ANTLRErrorListener<Token> {
|
|
7
7
|
readonly translator: MalloyTranslation;
|
|
8
8
|
readonly messages: MessageLogger;
|