@sap/cds-compiler 4.2.4 → 4.3.0
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/CHANGELOG.md +26 -0
- package/bin/cdsc.js +8 -0
- package/bin/cdshi.js +3 -3
- package/doc/CHANGELOG_BETA.md +7 -0
- package/lib/api/main.js +19 -0
- package/lib/base/location.js +16 -0
- package/lib/base/message-registry.js +47 -16
- package/lib/base/messages.js +49 -38
- package/lib/base/model.js +1 -1
- package/lib/checks/checkPathsInStoredCalcElement.js +83 -0
- package/lib/checks/existsExpressionsOnlyForeignKeys.js +71 -0
- package/lib/checks/existsMustEndInAssoc.js +27 -0
- package/lib/checks/onConditions.js +47 -1
- package/lib/checks/validator.js +10 -1
- package/lib/compiler/assert-consistency.js +23 -15
- package/lib/compiler/base.js +31 -14
- package/lib/compiler/builtins.js +21 -20
- package/lib/compiler/checks.js +36 -49
- package/lib/compiler/define.js +71 -91
- package/lib/compiler/extend.js +27 -25
- package/lib/compiler/finalize-parse-cdl.js +1 -1
- package/lib/compiler/generate.js +67 -87
- package/lib/compiler/kick-start.js +7 -5
- package/lib/compiler/populate.js +32 -30
- package/lib/compiler/propagator.js +2 -0
- package/lib/compiler/resolve.js +29 -25
- package/lib/compiler/shared.js +57 -31
- package/lib/compiler/tweak-assocs.js +203 -22
- package/lib/compiler/utils.js +0 -18
- package/lib/gen/Dictionary.json +10 -4
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/languageParser.js +3 -3
- package/lib/inspect/inspectPropagation.js +2 -1
- package/lib/json/from-csn.js +63 -28
- package/lib/json/to-csn.js +23 -13
- package/lib/language/antlrParser.js +1 -1
- package/lib/language/errorStrategy.js +5 -1
- package/lib/language/genericAntlrParser.js +67 -61
- package/lib/main.d.ts +26 -1
- package/lib/main.js +2 -1
- package/lib/model/csnRefs.js +1 -0
- package/lib/model/csnUtils.js +28 -0
- package/lib/model/revealInternalProperties.js +3 -9
- package/lib/optionProcessor.js +17 -1
- package/lib/render/toCdl.js +1 -1
- package/lib/transform/db/associations.js +3 -4
- package/lib/transform/db/backlinks.js +293 -0
- package/lib/transform/db/expansion.js +9 -7
- package/lib/transform/db/flattening.js +3 -2
- package/lib/transform/db/rewriteCalculatedElements.js +1 -67
- package/lib/transform/db/transformExists.js +3 -58
- package/lib/transform/db/views.js +8 -14
- package/lib/transform/effective/.eslintrc.json +4 -0
- package/lib/transform/effective/associations.js +101 -0
- package/lib/transform/effective/main.js +88 -0
- package/lib/transform/effective/misc.js +61 -0
- package/lib/transform/effective/queries.js +42 -0
- package/lib/transform/effective/types.js +121 -0
- package/lib/transform/forRelationalDB.js +12 -235
- package/lib/transform/localized.js +22 -3
- package/lib/transform/parseExpr.js +7 -3
- package/lib/transform/transformUtils.js +5 -22
- package/lib/transform/translateAssocsToJoins.js +42 -38
- package/lib/transform/universalCsn/universalCsnEnricher.js +17 -1
- package/package.json +1 -2
- package/lib/language/language.g4 +0 -3260
package/lib/language/language.g4
DELETED
|
@@ -1,3260 +0,0 @@
|
|
|
1
|
-
// ANTLR4 grammar to generate Parser and Lexer for CDS-Language
|
|
2
|
-
|
|
3
|
-
// To be built the parser by hand, install Java, download the ANTLR4 tool, then
|
|
4
|
-
// antlr4 -no-listener -o ../gen language.g4
|
|
5
|
-
// Alternatively, install Java, and use
|
|
6
|
-
// npm run download && npm run gen
|
|
7
|
-
//
|
|
8
|
-
// To test the parser in the REPL, see file './lib/language/antlrParser.js'.
|
|
9
|
-
|
|
10
|
-
// This grammar is built according to the following guidelines:
|
|
11
|
-
//
|
|
12
|
-
// * Do not express every syntactical restriction by grammar rules, and do
|
|
13
|
-
// not define a grammar which allows every nonsense. We might specify
|
|
14
|
-
// syntactical restrictions in a certain form inside actions or semantic
|
|
15
|
-
// predicates to have them directly available for IDE code completion.
|
|
16
|
-
//
|
|
17
|
-
// * Keep the number of token types small. Thus, do not define different
|
|
18
|
-
// token types for things which are not distinguished in the parser.
|
|
19
|
-
// Examples: one token type for numbers (have a check if you just want to
|
|
20
|
-
// allow integers at certain places), one token type for non-quoted and
|
|
21
|
-
// quoted identifiers.
|
|
22
|
-
//
|
|
23
|
-
// * Keep the number of keywords as small as possible. Thus, built-ins is a
|
|
24
|
-
// topic for the semantic analysis, not the grammar. Examples: no keywords
|
|
25
|
-
// for built-in types or built-in SQL functions. This also avoids noise in
|
|
26
|
-
// the grammar and a huge/slow generated parser.
|
|
27
|
-
// ┌─────────────────────────────────────────────────────────────────────────┐
|
|
28
|
-
// For our adapted ANTLR error strategy concerning (non-reserved) keywords,
|
|
29
|
-
// make sure to define non-reserved keywords between the lexer rule `Number`
|
|
30
|
-
// and `Identifier`. The latter must be the second last rule, the last is
|
|
31
|
-
// `IllegalToken`. Do not rename these three rules. Add each new
|
|
32
|
-
// non-reserved keyword to rule `ident`, but check for ambiguities!
|
|
33
|
-
// └─────────────────────────────────────────────────────────────────────────┘
|
|
34
|
-
//
|
|
35
|
-
// * Left-factor the parser grammar if the same initial part covers more than
|
|
36
|
-
// one or two tokens. ANTLRs adaptive predication allows to write "natural"
|
|
37
|
-
// rules, but slows down parsing, especially if a long lookahead is needed
|
|
38
|
-
// to solve an LLk ambiguity. Therefore, try to avoid it in rules which are
|
|
39
|
-
// called often. Unfortunately, we cannot use ANTLR3's grammar and subrule
|
|
40
|
-
// option 'k' (lookahead depth) anymore... Therefore...
|
|
41
|
-
// ┌─────────────────────────────────────────────────────────────────────────┐
|
|
42
|
-
// Before each alternative with LL1 ambiguities (looking at the next token
|
|
43
|
-
// is not enough for a decision), write a comment starting with `#ATN:`
|
|
44
|
-
// which describes the ambiguity. Additionally, put a comment `/* #ATN n
|
|
45
|
-
// */` INSIDE an (`@after`) action of a rule if the corresponding function
|
|
46
|
-
// in '../gen/languageParser.js' contains `n` occurrences of
|
|
47
|
-
// `adaptivePredict` calls. This is checked in 'test/testCompiler.js',
|
|
48
|
-
// which also counts the total number of `adaptivePredict` occurrences.
|
|
49
|
-
// └─────────────────────────────────────────────────────────────────────────┘
|
|
50
|
-
//
|
|
51
|
-
// * For fast parsing and lower memory consumption, we use ANTLR4 with SLL
|
|
52
|
-
// prediction-mode only. That means that ANTLR does not use the actual call
|
|
53
|
-
// stack when deciding which alternative to choose in a rule. You might
|
|
54
|
-
// need to copy a rule manually to get less ambiguities - this might be a
|
|
55
|
-
// good idea anyway to avoid calls to `adaptivePredict`, see the rules
|
|
56
|
-
// starting with `annotationAssignment_`.
|
|
57
|
-
//
|
|
58
|
-
// * Factoring out a sub rule into a named rule influences the error recovery:
|
|
59
|
-
// the parser tries to consume all tokens which are neither in the follow
|
|
60
|
-
// set of loops and named rules. So be careful.
|
|
61
|
-
//
|
|
62
|
-
// * Do not use actions in the lexer. Examples: de-quote string literals not
|
|
63
|
-
// in the lexer, but in the parser; do not throw errors, but produce error
|
|
64
|
-
// tokens if necessary.
|
|
65
|
-
//
|
|
66
|
-
// * Use actions in the parser to produce a Augmented CSN model. To have it
|
|
67
|
-
// also in the case of syntax errors, produce it by adding sub-nodes to a
|
|
68
|
-
// parent node, not by returning the nodes (the latter is fine for secondary
|
|
69
|
-
// attachments).
|
|
70
|
-
//
|
|
71
|
-
// * Action code should be a one-liner (<100 chars); usually, just one action
|
|
72
|
-
// is called per alternative (plus the @after action which sets the AST
|
|
73
|
-
// location). For more complicated code, define a method in file
|
|
74
|
-
// './genericAntlrParser.js'.
|
|
75
|
-
//
|
|
76
|
-
// * Do not write lexer rules for tokens like ';', use ';' directly in the
|
|
77
|
-
// parser rule. Advantage: better error messages; taste: more or less
|
|
78
|
-
// readable grammar; disadvantage: debugging in generated code.
|
|
79
|
-
//
|
|
80
|
-
// * Use all-upper token names for keywords (e.g. CONTEXT), capitalized ones
|
|
81
|
-
// (e.g. Number) for others - EOF is the exception (is ANTLR-builtin).
|
|
82
|
-
// Remember: parser rule names in ANTLR start with a lower-case letter.
|
|
83
|
-
//
|
|
84
|
-
// * No useless parentheses in the grammar. There are just two binary grammar
|
|
85
|
-
// operators: alternative (`|`) and sequence. It should not be too hard to
|
|
86
|
-
// remember that sequence binds stronger than alternative.
|
|
87
|
-
//
|
|
88
|
-
// * Use the following indentation rules:
|
|
89
|
-
// - rule header: indentation 0 + 2* parentheses/braces depth
|
|
90
|
-
// - rule colon (':' separating header & body): 2
|
|
91
|
-
// - rule body: 4 + 2* parentheses/braces depth, -2 for certain chars at
|
|
92
|
-
// beginning of line: '|', ')', ']' or '}'
|
|
93
|
-
// - inside action: as for the action language, e.g. function argument
|
|
94
|
-
// alignment
|
|
95
|
-
// - rule semicolon (';' ending body, before exceptions): 2
|
|
96
|
-
// - rule exceptions (not used): 2 + 2* parentheses/braces depth
|
|
97
|
-
|
|
98
|
-
// Some practical info:
|
|
99
|
-
//
|
|
100
|
-
// * The end location for the match of a rule is just available in the @after
|
|
101
|
-
// action. Use method `attachLocation` there on the produced AST.
|
|
102
|
-
//
|
|
103
|
-
// * Be careful with the rule names: the methods in antlr4.Parser, the methods
|
|
104
|
-
// in `./antlrParser' and the parser rule names share the same namespace.
|
|
105
|
-
// Any shadowing lead to an exception when running 'test/testCompiler.js'.
|
|
106
|
-
//
|
|
107
|
-
// * Be careful with names for rule arguments, returns, locals and rule
|
|
108
|
-
// reference labels: the names `parser`, `parent` and `invokingState` cannot
|
|
109
|
-
// be used (these are added by the generator).
|
|
110
|
-
//
|
|
111
|
-
// * The ANTLR error "missing attribute access on rule reference c in $c" can
|
|
112
|
-
// be solved with using $ctx.c instead of $c
|
|
113
|
-
//
|
|
114
|
-
// * If you want to set a property starting with '$' like $syntax, use
|
|
115
|
-
// obj['$'+'syntax'] as the ANTLR tool would replace $syntax by $ctx.syntax
|
|
116
|
-
//
|
|
117
|
-
// * If you want to use Unicode characters, move the corresponding code to
|
|
118
|
-
// ./genericAntlrParser.js; ANTLR or the TypeScript wrapper might destroy
|
|
119
|
-
// Unicode characters on certain operating systems.
|
|
120
|
-
|
|
121
|
-
grammar language;
|
|
122
|
-
options {
|
|
123
|
-
language = JavaScript;
|
|
124
|
-
superClass = genericAntlrParser;
|
|
125
|
-
}
|
|
126
|
-
tokens {
|
|
127
|
-
ELEMENT, // used with setLocalToken()
|
|
128
|
-
MASKED, // used with setLocalToken()
|
|
129
|
-
VIRTUAL, // used with setLocalToken()
|
|
130
|
-
OVER, // used with setLocalTokenIfBefore()
|
|
131
|
-
HelperToken1, // used with setLocalToken(), does not appear in messages
|
|
132
|
-
HelperToken2, // used with setLocalToken(), does not appear in messages
|
|
133
|
-
HideAlternatives, // hide alternative tokens (no token seq!)
|
|
134
|
-
GenericExpr, // via token rewriting according to specialFunctions
|
|
135
|
-
GenericSeparator, // via token rewriting according to specialFunctions
|
|
136
|
-
GenericIntro, // via token rewriting according to specialFunctions
|
|
137
|
-
DOTbeforeBRACE, // via token rewrite
|
|
138
|
-
COMPOSITIONofBRACE // via token rewrite in rule typeAssociationBase
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// Content:
|
|
142
|
-
// - top-level: USING, NAMESPACE, artifactDefOrExtend (start rule: start)
|
|
143
|
-
// - main definitions and annotation def
|
|
144
|
-
// - member definitions
|
|
145
|
-
// - EXTEND and ANNOTATE
|
|
146
|
-
// - type expressions
|
|
147
|
-
// - queries: the main query hierarchy (start rule: queryEOF)
|
|
148
|
-
// - queries: columns and other clauses
|
|
149
|
-
// - conditions and expressions (start rule: conditionEOF)
|
|
150
|
-
// - paths and functions
|
|
151
|
-
// - annotation assignments
|
|
152
|
-
// - literal values and identifiers
|
|
153
|
-
// - Lexer: spaces, literal values, reserved keywords, unreserved keywords, identifier
|
|
154
|
-
|
|
155
|
-
// Top-Level -----------------------------------------------------------------
|
|
156
|
-
|
|
157
|
-
start returns [ source ] locals [ _sync = 'recover' ]
|
|
158
|
-
@init{ $source = this.createSource(); }
|
|
159
|
-
:
|
|
160
|
-
usingDeclaration[$source]*
|
|
161
|
-
(
|
|
162
|
-
namespaceDeclaration[$source]
|
|
163
|
-
( usingDeclaration[$source] | artifactDefOrExtend[$source] )*
|
|
164
|
-
|
|
|
165
|
-
artifactDefOrExtend[$source]
|
|
166
|
-
( usingDeclaration[$source] | artifactDefOrExtend[$source] )*
|
|
167
|
-
)?
|
|
168
|
-
EOF
|
|
169
|
-
;
|
|
170
|
-
|
|
171
|
-
namespaceDeclaration[ source ] locals[ decl = {} ]
|
|
172
|
-
@after { $source.namespace = this.attachLocation($decl); }
|
|
173
|
-
:
|
|
174
|
-
NAMESPACE simplePath[ $decl, 'Namespace' ] ';'
|
|
175
|
-
;
|
|
176
|
-
|
|
177
|
-
usingDeclaration[ source ] locals[ decl = {} ]
|
|
178
|
-
@after { this.attachLocation($decl); }
|
|
179
|
-
:
|
|
180
|
-
{ $decl.location = this.startLocation(); }
|
|
181
|
-
USING
|
|
182
|
-
(
|
|
183
|
-
FROM str=String
|
|
184
|
-
{ $source.dependencies.push( this.quotedLiteral( $str, 'string' ) ); }
|
|
185
|
-
|
|
|
186
|
-
usingProxy[ $source, $decl ]
|
|
187
|
-
( FROM str=String
|
|
188
|
-
{ $source.dependencies.push( $decl.fileDep = this.quotedLiteral( $str, 'string' ) ); }
|
|
189
|
-
)?
|
|
190
|
-
|
|
|
191
|
-
{ this.addItem( $decl, $source, 'usings', 'using' ); }
|
|
192
|
-
// We could just create "independent" USING declaration, but if we want
|
|
193
|
-
// to have some check in the future whether the external artifacts are
|
|
194
|
-
// really in the FROM source...
|
|
195
|
-
'{' { $decl.usings = this.createArray(); }
|
|
196
|
-
usingProxy[ $decl, {} ]
|
|
197
|
-
( ',' { if (this.isStraightBefore("}")) break; } // allow ',' before '}'
|
|
198
|
-
usingProxy[ $decl, {} ] )*
|
|
199
|
-
'}' { this.finalizeDictOrArray( $decl.usings ); }
|
|
200
|
-
( FROM str=String
|
|
201
|
-
{ $source.dependencies.push( $decl.fileDep = this.quotedLiteral( $str, 'string' ) ); }
|
|
202
|
-
)?
|
|
203
|
-
)
|
|
204
|
-
';'
|
|
205
|
-
;
|
|
206
|
-
|
|
207
|
-
usingProxy[ outer, proxy ]
|
|
208
|
-
@after { this.attachLocation($proxy); }
|
|
209
|
-
:
|
|
210
|
-
{ if (!$proxy.location) $proxy.location = this.startLocation();
|
|
211
|
-
$proxy.extern = {}; }
|
|
212
|
-
simplePath[ $proxy.extern, 'global' ]
|
|
213
|
-
{ this.addItem( $proxy, $outer, 'usings', 'using' ); }
|
|
214
|
-
( AS name=ident['Using'] { $proxy.name = $name.id; }
|
|
215
|
-
| { this.classifyImplicitName( 'Using' ); }
|
|
216
|
-
)
|
|
217
|
-
;
|
|
218
|
-
|
|
219
|
-
artifactDefOrExtend[ outer, defOnly = false ] locals[ art = new parser.XsnArtifact() ] // cannot use `parent` as parameter name!
|
|
220
|
-
@after{ /* #ATN 1 */ }
|
|
221
|
-
:
|
|
222
|
-
{ $art.location = this.startLocation(); this.docComment( $art ); }
|
|
223
|
-
annotationAssignment_ll1[ $art ]*
|
|
224
|
-
(
|
|
225
|
-
DEFINE?
|
|
226
|
-
( serviceDef[ $art, $outer, $defOnly ]
|
|
227
|
-
| contextDef[ $art, $outer, $defOnly ]
|
|
228
|
-
| entityDef[ $art, $outer ]
|
|
229
|
-
| typeDef[ $art, $outer ]
|
|
230
|
-
| aspectDef[ $art, $outer ]
|
|
231
|
-
| annotationDef[ $art, $outer ]
|
|
232
|
-
| viewDef[ $art, $outer ]
|
|
233
|
-
| eventDef[ $art, $outer ]
|
|
234
|
-
| actionFunctionMainDef[ $art, $outer ]
|
|
235
|
-
)
|
|
236
|
-
|
|
|
237
|
-
extend=EXTEND
|
|
238
|
-
{ this.reportUnexpectedExtension( $defOnly, $extend );
|
|
239
|
-
if (!$outer.extensions) $outer.extensions = [];
|
|
240
|
-
}
|
|
241
|
-
// #ATN: EXTEND art, while CONTEXT, ENTITY etc are not reserved
|
|
242
|
-
( extendService[ $art, $outer ]
|
|
243
|
-
| extendContext[ $art, $outer ]
|
|
244
|
-
| extendEntityOrAspect[ $art, $outer ] // or aspect
|
|
245
|
-
| extendProjection[ $art, $outer ]
|
|
246
|
-
| extendType[ $art, $outer ]
|
|
247
|
-
// Streamlined Syntax; we won't add more kinds of the non-streamlined variants:
|
|
248
|
-
| extendArtifact[ $art, $outer ]
|
|
249
|
-
)
|
|
250
|
-
|
|
|
251
|
-
annotate=ANNOTATE
|
|
252
|
-
{ this.reportUnexpectedExtension( $defOnly, $annotate );
|
|
253
|
-
if (!$outer.extensions) $outer.extensions = [];
|
|
254
|
-
this.meltKeywordToIdentifier();
|
|
255
|
-
}
|
|
256
|
-
annotateArtifact[ $art, $outer ] // not kind-specific
|
|
257
|
-
)
|
|
258
|
-
;
|
|
259
|
-
|
|
260
|
-
optArtifactsBlock[ art, defOnly = false ]
|
|
261
|
-
@after { this.attachLocation( $art ); }
|
|
262
|
-
:
|
|
263
|
-
{ this.docComment( $art ); }
|
|
264
|
-
annotationAssignment_fix[ $art ]*
|
|
265
|
-
(
|
|
266
|
-
'{' { $art.artifacts = this.createDict(); $art.extensions = []; }
|
|
267
|
-
artifactDefOrExtend[ $art, defOnly ]*
|
|
268
|
-
'}' { this.finalizeDictOrArray( $art.artifacts ); }
|
|
269
|
-
optionalSemi
|
|
270
|
-
|
|
|
271
|
-
requiredSemi
|
|
272
|
-
)
|
|
273
|
-
;
|
|
274
|
-
|
|
275
|
-
requiredSemi
|
|
276
|
-
: ';'
|
|
277
|
-
| { return $ctx; } // do not actually parse the closing brace
|
|
278
|
-
'}'
|
|
279
|
-
;
|
|
280
|
-
|
|
281
|
-
optionalSemi
|
|
282
|
-
: { this.noAssignmentInSameLine(); } // issue warning for } @Anno \n? NextDef
|
|
283
|
-
';'?
|
|
284
|
-
;
|
|
285
|
-
|
|
286
|
-
// Annotation def and main definitions ------------------------------------------
|
|
287
|
-
|
|
288
|
-
annotationDef[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
289
|
-
@after { this.attachLocation( $art ); }
|
|
290
|
-
:
|
|
291
|
-
annotation=ANNOTATION simplePath[ $name, 'AnnoDef' ]
|
|
292
|
-
{ if ($outer.kind !== 'source') { // this is a syntax restriction to avoid confusion
|
|
293
|
-
this.error( 'syntax-unexpected-vocabulary', $annotation, { '#': $outer.kind } );
|
|
294
|
-
$art = new this.XsnArtifact(); }
|
|
295
|
-
else {
|
|
296
|
-
if (!$outer.vocabularies) $outer.vocabularies = Object.create(null);
|
|
297
|
-
this.addDef( $art, $outer, 'vocabularies', 'annotation', $name );
|
|
298
|
-
}
|
|
299
|
-
this.docComment( $art ); }
|
|
300
|
-
annotationAssignment_fix[ $art ]*
|
|
301
|
-
typeSpecSemi[ $art ] // also 'includes'...
|
|
302
|
-
;
|
|
303
|
-
|
|
304
|
-
serviceDef[ art, outer, defOnly = false ] locals[ name = new parser.XsnName(); ]
|
|
305
|
-
@after { this.attachLocation( $art ); }
|
|
306
|
-
:
|
|
307
|
-
SERVICE simplePath[ $name, 'Service' ]
|
|
308
|
-
{ this.addDef( $art, $outer, 'artifacts', 'service', $name ); }
|
|
309
|
-
optArtifactsBlock[ $art, defOnly ]
|
|
310
|
-
;
|
|
311
|
-
|
|
312
|
-
contextDef[ art, outer, defOnly = false ] locals[ name = new parser.XsnName(); ]
|
|
313
|
-
@after { this.attachLocation( $art ); }
|
|
314
|
-
:
|
|
315
|
-
CONTEXT simplePath[ $name, 'Context' ]
|
|
316
|
-
{ this.addDef( $art, $outer, 'artifacts', 'context', $name ); }
|
|
317
|
-
optArtifactsBlock[ $art, defOnly ]
|
|
318
|
-
;
|
|
319
|
-
|
|
320
|
-
eventDef[ art, outer ] locals[ name = new parser.XsnName(); ]
|
|
321
|
-
@after { /* #ATN 1 */ this.attachLocation( $art ); }
|
|
322
|
-
:
|
|
323
|
-
EVENT simplePath[ $name, 'Event' ]
|
|
324
|
-
{ this.addDef( $art, $outer, 'artifacts', 'event', $name );
|
|
325
|
-
this.docComment( $art ); }
|
|
326
|
-
annotationAssignment_fix[ $art ]*
|
|
327
|
-
(
|
|
328
|
-
typeStruct[ $art ] optionalSemi
|
|
329
|
-
|
|
|
330
|
-
':'
|
|
331
|
-
// #ATN: includeRef can be / start with PROJECTION
|
|
332
|
-
(
|
|
333
|
-
{ $art.type = {}; }
|
|
334
|
-
simplePath[ $art.type, 'artref' ]
|
|
335
|
-
(
|
|
336
|
-
{ $art.includes = [ $art.type ]; delete $art.type; }
|
|
337
|
-
( ',' { if (this.isStraightBefore('{')) break; } // allow ',' before '{' // }}
|
|
338
|
-
includeRef[ $art ]
|
|
339
|
-
)*
|
|
340
|
-
typeStruct[ $art ] optionalSemi
|
|
341
|
-
|
|
|
342
|
-
{ this.docComment( $art ); }
|
|
343
|
-
annotationAssignment_ll1[ $art ]*
|
|
344
|
-
requiredSemi
|
|
345
|
-
)
|
|
346
|
-
|
|
|
347
|
-
typeStruct[ $art ] optionalSemi
|
|
348
|
-
|
|
|
349
|
-
qp=projectionSpec
|
|
350
|
-
{ $art.query = $qp.query; $art['$'+'syntax'] = 'projection'; }
|
|
351
|
-
optionalSemi // TODO: not fully correct without columns or excluding
|
|
352
|
-
)
|
|
353
|
-
)
|
|
354
|
-
;
|
|
355
|
-
|
|
356
|
-
viewDef[ art, outer ] locals[ name = new parser.XsnName(); ]
|
|
357
|
-
@after { this.attachLocation( $art ); }
|
|
358
|
-
:
|
|
359
|
-
v=VIEW simplePath[ $name, 'Entity' ]
|
|
360
|
-
{ $art['$'+'syntax'] = 'view';
|
|
361
|
-
this.addDef( $art, $outer, 'artifacts', 'entity', $name );
|
|
362
|
-
this.docComment( $art ); }
|
|
363
|
-
annotationAssignment_fix[ $art ]*
|
|
364
|
-
(
|
|
365
|
-
parameterListDef[ $art ]
|
|
366
|
-
|
|
|
367
|
-
// TODO: warning deprecated?
|
|
368
|
-
( HideAlternatives | WITH ) { $art.params = this.createDict(); }
|
|
369
|
-
PARAMETERS
|
|
370
|
-
parameterDef[ $art ]
|
|
371
|
-
( ',' parameterDef[ $art ] )* // no optional final ',' here
|
|
372
|
-
{ this.finalizeDictOrArray( $art.params ); }
|
|
373
|
-
)?
|
|
374
|
-
AS qe=queryExpression { $art.query = $qe.query; }
|
|
375
|
-
// TODO check ANTLR: bad msg with 'view V as'<eof> but 'view V as FOO' is fine
|
|
376
|
-
requiredSemi
|
|
377
|
-
;
|
|
378
|
-
|
|
379
|
-
entityDef[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
380
|
-
@after { this.attachLocation( $art ); }
|
|
381
|
-
:
|
|
382
|
-
ENTITY simplePath[ $name, 'Entity' ]
|
|
383
|
-
{ this.addDef( $art, $outer, 'artifacts', 'entity', $name );
|
|
384
|
-
this.docComment( $art ); }
|
|
385
|
-
annotationAssignment_fix[ $art ]*
|
|
386
|
-
parameterListDef[ $art ]?
|
|
387
|
-
(
|
|
388
|
-
( ':'
|
|
389
|
-
includeRef[ $art ]
|
|
390
|
-
( ',' { if (this.isStraightBefore('{')) break; } // allow ',' before '{' // }}
|
|
391
|
-
includeRef[ $art ]
|
|
392
|
-
)*
|
|
393
|
-
)?
|
|
394
|
-
'{' { $art.elements = this.createDict(); }
|
|
395
|
-
elementDef[ $art ]*
|
|
396
|
-
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
397
|
-
(
|
|
398
|
-
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
399
|
-
actionFunctionDef[ $art ]*
|
|
400
|
-
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
401
|
-
)?
|
|
402
|
-
optionalSemi
|
|
403
|
-
|
|
|
404
|
-
AS
|
|
405
|
-
( qe=queryExpression
|
|
406
|
-
{ $art.query = $qe.query; $art['$'+'syntax'] = 'entity' }
|
|
407
|
-
(
|
|
408
|
-
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
409
|
-
actionFunctionDef[ $art ]*
|
|
410
|
-
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
411
|
-
optionalSemi
|
|
412
|
-
| requiredSemi
|
|
413
|
-
)
|
|
414
|
-
| qp=projectionSpec
|
|
415
|
-
{ $art.query = $qp.query; $art['$'+'syntax'] = 'projection'; }
|
|
416
|
-
projectionClauses[ $qp.query ]
|
|
417
|
-
(
|
|
418
|
-
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
419
|
-
actionFunctionDef[ $art ]*
|
|
420
|
-
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
421
|
-
)?
|
|
422
|
-
optionalSemi // TODO: not fully correct without columns or excluding
|
|
423
|
-
)
|
|
424
|
-
)
|
|
425
|
-
;
|
|
426
|
-
|
|
427
|
-
aspectDef[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
428
|
-
@after { this.attachLocation( $art ); }
|
|
429
|
-
:
|
|
430
|
-
( ASPECT | ( abs=ABSTRACT | HideAlternatives ) ent=ENTITY )
|
|
431
|
-
simplePath[ $name, 'Type' ]
|
|
432
|
-
{ this.addDef( $art, $outer, 'artifacts', 'aspect', $name );
|
|
433
|
-
if ($ent)
|
|
434
|
-
this.warning( 'syntax-deprecated-abstract', this.tokenLocation( $abs, $ent ) );
|
|
435
|
-
this.docComment( $art ); }
|
|
436
|
-
annotationAssignment_fix[ $art ]*
|
|
437
|
-
( ':'
|
|
438
|
-
(
|
|
439
|
-
includeRef[ $art ]
|
|
440
|
-
( ',' { if (this.isStraightBefore('{')) break; } // allow ',' before '{' // }}
|
|
441
|
-
includeRef[ $art ]
|
|
442
|
-
)*
|
|
443
|
-
)?
|
|
444
|
-
)?
|
|
445
|
-
( // `aspect MyAspect {};`
|
|
446
|
-
'{' { $art.elements = this.createDict(); }
|
|
447
|
-
( elementDef[ $art ]* )
|
|
448
|
-
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
449
|
-
(
|
|
450
|
-
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
451
|
-
actionFunctionDef[ $art ]*
|
|
452
|
-
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
453
|
-
)?
|
|
454
|
-
optionalSemi
|
|
455
|
-
| // `aspect MyAspect;`, e.g. for annotation aspects.
|
|
456
|
-
requiredSemi
|
|
457
|
-
)
|
|
458
|
-
;
|
|
459
|
-
|
|
460
|
-
typeDef[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
461
|
-
@after { this.attachLocation( $art ); }
|
|
462
|
-
:
|
|
463
|
-
TYPE simplePath[ $name, 'Type' ]
|
|
464
|
-
{ this.addDef( $art, $outer, 'artifacts', 'type', $name );
|
|
465
|
-
this.docComment( $art ); }
|
|
466
|
-
annotationAssignment_fix[ $art ]*
|
|
467
|
-
typeSpecSemi[ $art ]
|
|
468
|
-
;
|
|
469
|
-
|
|
470
|
-
actionFunctionMainDef[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
471
|
-
@after { this.attachLocation( $art ); }
|
|
472
|
-
:
|
|
473
|
-
ACTION simplePath[ $name, 'Action' ]
|
|
474
|
-
{ this.addDef( $art, $outer, 'artifacts', 'action', $name );
|
|
475
|
-
this.docComment( $art ); }
|
|
476
|
-
annotationAssignment_fix[ $art ]*
|
|
477
|
-
parameterListDef[ $art ]
|
|
478
|
-
( returnTypeSpec[ $art ] | requiredSemi )
|
|
479
|
-
|
|
|
480
|
-
FUNCTION simplePath[ $name, 'Action' ]
|
|
481
|
-
{ this.addDef( $art, $outer, 'artifacts', 'function', $name );
|
|
482
|
-
this.docComment( $art ); }
|
|
483
|
-
annotationAssignment_fix[ $art ]*
|
|
484
|
-
parameterListDef[ $art ]
|
|
485
|
-
returnTypeSpec[ $art ]
|
|
486
|
-
;
|
|
487
|
-
|
|
488
|
-
// Member definitions: actions, elements, enums, parameters: --------------------
|
|
489
|
-
|
|
490
|
-
actionFunctionDef[ outer ] locals[ art = new parser.XsnArtifact() ]
|
|
491
|
-
@after { this.attachLocation( $art ); }
|
|
492
|
-
:
|
|
493
|
-
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
494
|
-
annotationAssignment_ll1[ $art ]*
|
|
495
|
-
(
|
|
496
|
-
ACTION name=ident['BoundAction']
|
|
497
|
-
{ this.addDef( $art, $outer, 'actions', 'action', $name.id );
|
|
498
|
-
this.docComment( $art ); }
|
|
499
|
-
annotationAssignment_fix[ $art ]*
|
|
500
|
-
parameterListDef[ $art ]
|
|
501
|
-
( returnTypeSpec[ $art ] | requiredSemi )
|
|
502
|
-
|
|
|
503
|
-
FUNCTION name=ident['BoundAction']
|
|
504
|
-
{ this.addDef( $art, $outer, 'actions', 'function', $name.id );
|
|
505
|
-
this.docComment( $art ); }
|
|
506
|
-
annotationAssignment_fix[ $art ]*
|
|
507
|
-
parameterListDef[ $art ]
|
|
508
|
-
returnTypeSpec[ $art ]
|
|
509
|
-
)
|
|
510
|
-
;
|
|
511
|
-
|
|
512
|
-
parameterDef[ outer ] locals[ art = new parser.XsnArtifact() ]
|
|
513
|
-
@after { this.attachLocation( $art ); }
|
|
514
|
-
:
|
|
515
|
-
{ this.meltKeywordToIdentifier();; this.docComment( $art ); }
|
|
516
|
-
( annotationAssignment_ll1[ $art ]
|
|
517
|
-
{ this.meltKeywordToIdentifier(); }
|
|
518
|
-
)*
|
|
519
|
-
name=ident['Param']
|
|
520
|
-
{ this.addDef( $art, $outer, 'params', 'param', $name.id );
|
|
521
|
-
this.docComment( $art ); }
|
|
522
|
-
annotationAssignment_fix[ $art ]*
|
|
523
|
-
typeSpec[ $art ]
|
|
524
|
-
defaultValue[ $art ]?
|
|
525
|
-
{ this.docComment( $art ); }
|
|
526
|
-
annotationAssignment_ll1[ $art ]*
|
|
527
|
-
;
|
|
528
|
-
|
|
529
|
-
parameterListDef[ art ]
|
|
530
|
-
:
|
|
531
|
-
'(' { $art.params = this.createDict(); }
|
|
532
|
-
// also empty param list (we might do some hacking later to allow reserved words)
|
|
533
|
-
// see annotationAssignment_paren
|
|
534
|
-
{
|
|
535
|
-
if (this.isStraightBefore(')')) {
|
|
536
|
-
this.matchWildcard(); // we know it is the ')' - we do not reach the final match
|
|
537
|
-
this.finalizeDictOrArray( $art.params );
|
|
538
|
-
return $ctx;
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
parameterDef[ $art ]
|
|
542
|
-
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
543
|
-
parameterDef[ $art ]
|
|
544
|
-
)*
|
|
545
|
-
')' { this.finalizeDictOrArray( $art.params ); }
|
|
546
|
-
;
|
|
547
|
-
|
|
548
|
-
enumSymbolDef[ outer ] locals[ art = new parser.XsnArtifact() ]
|
|
549
|
-
@after { this.attachLocation( $art ); }
|
|
550
|
-
:
|
|
551
|
-
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
552
|
-
annotationAssignment_ll1[ $art ]*
|
|
553
|
-
name=ident['Enum']
|
|
554
|
-
{ this.addDef( $art, $outer, 'enum', 'enum', $name.id );
|
|
555
|
-
this.docComment( $art ); }
|
|
556
|
-
annotationAssignment_ll1[ $art ]*
|
|
557
|
-
( '='
|
|
558
|
-
{ this.excludeExpected( ['Boolean', 'QuotedLiteral', "'#'", 'NULL'] ); }
|
|
559
|
-
(
|
|
560
|
-
val=literalValue
|
|
561
|
-
{ $art.value = $val.val; }
|
|
562
|
-
|
|
|
563
|
-
( plus='+' | min='-' ) num=Number
|
|
564
|
-
{ $art.value = this.numberLiteral( $num, $plus||$min ); }
|
|
565
|
-
)
|
|
566
|
-
{ this.docComment( $art ); }
|
|
567
|
-
annotationAssignment_ll1[ $art ]*
|
|
568
|
-
)?
|
|
569
|
-
requiredSemi
|
|
570
|
-
;
|
|
571
|
-
|
|
572
|
-
elementDef[ outer ] locals[ $art = new parser.XsnArtifact() ]
|
|
573
|
-
:
|
|
574
|
-
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
575
|
-
annotationAssignment_ll1[ $art ]*
|
|
576
|
-
elementDefInner[ $art, $outer ]
|
|
577
|
-
;
|
|
578
|
-
|
|
579
|
-
elementDefInner[ art, outer, explicitElement = false ]
|
|
580
|
-
@after{ this.attachLocation( $art ); }
|
|
581
|
-
:
|
|
582
|
-
// VIRTUAL is keyword, except if before the following tokens texts:
|
|
583
|
-
{ this.setLocalToken( 'VIRTUAL', 'VIRTUAL', /^[;:{@=}]$/ ); }
|
|
584
|
-
( virtual=VIRTUAL { $art.virtual = this.valueWithTokenLocation( true, $virtual ); } )?
|
|
585
|
-
( key=KEY { $art.key = this.valueWithTokenLocation( true, $key ); } )?
|
|
586
|
-
{ this.setLocalToken( 'MASKED', 'MASKED', /^[;:{@=}]$/ ); }
|
|
587
|
-
( masked=MASKED
|
|
588
|
-
{
|
|
589
|
-
$art.masked = this.valueWithTokenLocation( true, $masked ) ;
|
|
590
|
-
this.message( 'syntax-unsupported-masked', $masked, { keyword: 'masked' } );
|
|
591
|
-
}
|
|
592
|
-
)?
|
|
593
|
-
{ this.setLocalToken( 'ELEMENT', 'ELEMENT', /^[;:{@=}]$/ ); }
|
|
594
|
-
( ELEMENT { $explicitElement = true; } )? // auto-recognizable at other places
|
|
595
|
-
name=ident['Element']
|
|
596
|
-
{ this.addDef( $art, $outer, 'elements', 'element', $name.id );
|
|
597
|
-
this.docComment( $art ); }
|
|
598
|
-
annotationAssignment_fix[ $art ]*
|
|
599
|
-
(
|
|
600
|
-
typeStruct[ $art ]
|
|
601
|
-
( nullability[ $art ]
|
|
602
|
-
requiredSemi
|
|
603
|
-
| optionalSemi // NOT and NULL are reserved...
|
|
604
|
-
)
|
|
605
|
-
|
|
|
606
|
-
':'
|
|
607
|
-
elementType[ $art ]
|
|
608
|
-
|
|
|
609
|
-
eq='=' e=expression // SQL has syntax variant using AS - we DO NOT
|
|
610
|
-
stored=STORED?
|
|
611
|
-
{ $art.value = $e.expr;
|
|
612
|
-
// this.setIntroLocation( eq ); -- future
|
|
613
|
-
if ($stored)
|
|
614
|
-
$art.value.stored = this.valueWithTokenLocation( true, $stored );
|
|
615
|
-
if ($explicitElement)
|
|
616
|
-
$art['$'+'syntax'] = 'element';
|
|
617
|
-
}
|
|
618
|
-
{ this.docComment( $art ); }
|
|
619
|
-
annotationAssignment_ll1[ $art ]* // for enum symbol def via EXTEND
|
|
620
|
-
requiredSemi
|
|
621
|
-
|
|
|
622
|
-
requiredSemi
|
|
623
|
-
)
|
|
624
|
-
;
|
|
625
|
-
|
|
626
|
-
elementType[ art ] // TODO: split this monster rule
|
|
627
|
-
@after{ /* #ATN 3 */ this.attachLocation( $art ); }
|
|
628
|
-
:
|
|
629
|
-
// #ATN: referenced type name can be ASSOCIATION or ARRAY or TYPE or LOCALIZED
|
|
630
|
-
typeStruct[ $art ]
|
|
631
|
-
nullability[ $art ]?
|
|
632
|
-
requiredSemi
|
|
633
|
-
|
|
|
634
|
-
typeAssociationBase[ $art, true ]
|
|
635
|
-
// #ATN: path could start with MANY or ONE - make sure a token follows in same rule!
|
|
636
|
-
(
|
|
637
|
-
typeStruct[ $art.target, true ] optionalSemi
|
|
638
|
-
|
|
|
639
|
-
one=ONE
|
|
640
|
-
{ this.setMaxCardinality( $art, this.numberLiteral( $one, null, '1' ) ); }
|
|
641
|
-
typeCompoStruct[ $art.target ] optionalSemi
|
|
642
|
-
|
|
|
643
|
-
many=MANY
|
|
644
|
-
{ this.setMaxCardinality( $art, { literal: 'string', val: '*' }, $many ); }
|
|
645
|
-
typeCompoStruct[ $art.target ] optionalSemi
|
|
646
|
-
|
|
|
647
|
-
// we do not support `Composition of many { e }` - ambiguity ad-hoc target versus foreign keys!
|
|
648
|
-
typeToMany[ $art ] typeAssociationElementCont[ $art ]
|
|
649
|
-
|
|
|
650
|
-
typeToOne[ $art ] typeAssociationElementCont[ $art ]
|
|
651
|
-
|
|
|
652
|
-
simplePath[ $art.target, 'artref' ] typeAssociationElementCont[ $art ]
|
|
653
|
-
)
|
|
654
|
-
|
|
|
655
|
-
(
|
|
656
|
-
array=ARRAY of=OF
|
|
657
|
-
{ $art.items = { location: this.tokenLocation( $array, $of ) }; }
|
|
658
|
-
| many=MANY
|
|
659
|
-
{ $art.items = { location: this.tokenLocation( $many ) };}
|
|
660
|
-
)
|
|
661
|
-
( typeStruct[ $art.items ]
|
|
662
|
-
nullability[ $art.items ]?
|
|
663
|
-
| // #ATN: typeRefOptArgs/typeTypeOf can start with TYPE
|
|
664
|
-
( typeTypeOf[ $art.items ] | typeRefOptArgs[ $art.items ] )
|
|
665
|
-
nullability[ $art.items ]?
|
|
666
|
-
{ this.docComment( $art ); }
|
|
667
|
-
annotationAssignment_ll1[ $art ]*
|
|
668
|
-
(
|
|
669
|
-
ENUM '{' { $art.items.enum = this.createDict(); }
|
|
670
|
-
enumSymbolDef[ $art.items ]*
|
|
671
|
-
'}' { this.finalizeDictOrArray( $art.items.enum ); }
|
|
672
|
-
nullability[ $art.items ]?
|
|
673
|
-
)?
|
|
674
|
-
)
|
|
675
|
-
requiredSemi // also req after struct/enum
|
|
676
|
-
|
|
|
677
|
-
l=LOCALIZED { $art.localized = this.valueWithTokenLocation( true, $l ); }
|
|
678
|
-
typeRefOptArgs[ $art ]
|
|
679
|
-
optInvisibleNullability[ $art ]
|
|
680
|
-
{ this.docComment( $art ); }
|
|
681
|
-
annotationAssignment_ll1[ $art ]*
|
|
682
|
-
( elementProperties[ $art ]
|
|
683
|
-
{ this.docComment( $art ); }
|
|
684
|
-
annotationAssignment_ll1[ $art ]*
|
|
685
|
-
)?
|
|
686
|
-
requiredSemi
|
|
687
|
-
|
|
|
688
|
-
typeTypeOf[ $art ] // Note: Same as the typeRefOptArgs rule below
|
|
689
|
-
optInvisibleNullability[ $art ]
|
|
690
|
-
{ this.docComment( $art ); }
|
|
691
|
-
annotationAssignment_ll1[ $art ]*
|
|
692
|
-
(
|
|
693
|
-
ENUM '{' { $art.enum = this.createDict(); }
|
|
694
|
-
enumSymbolDef[ $art ]*
|
|
695
|
-
'}' { this.finalizeDictOrArray( $art.enum ); }
|
|
696
|
-
elementProperties[ $art ]?
|
|
697
|
-
|
|
|
698
|
-
elementProperties[ $art ]
|
|
699
|
-
{ this.docComment( $art ); }
|
|
700
|
-
annotationAssignment_ll1[ $art ]*
|
|
701
|
-
)?
|
|
702
|
-
requiredSemi // also req after foreign key spec
|
|
703
|
-
|
|
|
704
|
-
typeRefOptArgs[ $art ] // Note: Same as the typeTypeOf rule above
|
|
705
|
-
optInvisibleNullability[ $art ]
|
|
706
|
-
{ this.docComment( $art ); }
|
|
707
|
-
annotationAssignment_ll1[ $art ]*
|
|
708
|
-
(
|
|
709
|
-
ENUM '{' { $art.enum = this.createDict(); }
|
|
710
|
-
enumSymbolDef[ $art ]*
|
|
711
|
-
'}' { this.finalizeDictOrArray( $art.enum ); }
|
|
712
|
-
elementProperties[ $art ]?
|
|
713
|
-
|
|
|
714
|
-
elementProperties[ $art ]
|
|
715
|
-
{ this.docComment( $art ); }
|
|
716
|
-
annotationAssignment_ll1[ $art ]*
|
|
717
|
-
)?
|
|
718
|
-
requiredSemi // also req after enum spec
|
|
719
|
-
;
|
|
720
|
-
|
|
721
|
-
elementProperties[ elem ]
|
|
722
|
-
:
|
|
723
|
-
defaultAndNullability[ $elem ]
|
|
724
|
-
|
|
|
725
|
-
'=' e=expression
|
|
726
|
-
stored=STORED?
|
|
727
|
-
{ $elem.value = $e.expr;
|
|
728
|
-
if ($stored)
|
|
729
|
-
$elem.value.stored = this.valueWithTokenLocation( true, $stored );
|
|
730
|
-
}
|
|
731
|
-
;
|
|
732
|
-
|
|
733
|
-
defaultAndNullability[ elem ]
|
|
734
|
-
:
|
|
735
|
-
defaultValue[ $elem ]
|
|
736
|
-
nullability[ $elem ]? // placement accoring to SQL spec
|
|
737
|
-
|
|
|
738
|
-
nullability[ $elem ]
|
|
739
|
-
defaultValue[ $elem ]?
|
|
740
|
-
;
|
|
741
|
-
|
|
742
|
-
defaultValue[ art ] locals[ elem, elements = {} ]
|
|
743
|
-
:
|
|
744
|
-
// TODO: We may support structured default values here.
|
|
745
|
-
DEFAULT expr=expression { $art.default = $expr.expr; }
|
|
746
|
-
;
|
|
747
|
-
|
|
748
|
-
// Extend and annotate ----------------------------------------------------------
|
|
749
|
-
|
|
750
|
-
extendArtifact[ art, outer ] locals[ name = new parser.XsnName(), elemName = new parser.XsnName() ]
|
|
751
|
-
@after{ /* #ATN 1 */ this.attachLocation( $art ); }
|
|
752
|
-
:
|
|
753
|
-
simplePath[ $name, 'Extend' ]
|
|
754
|
-
(
|
|
755
|
-
':' simplePath[ $elemName, 'Element']
|
|
756
|
-
{ this.addExtension( $art, $outer, 'extend', $name, $elemName.path ); }
|
|
757
|
-
extendWithOptElementsOrType[ art ]
|
|
758
|
-
|
|
|
759
|
-
{ this.addExtension( $art, $outer, 'extend', $name ); }
|
|
760
|
-
extendWithOptElementsNoWith[ art ]
|
|
761
|
-
|
|
|
762
|
-
{ this.addExtension( $art, $outer, 'extend', $name ); }
|
|
763
|
-
WITH { this.noSemicolonHere(); }
|
|
764
|
-
{ this.docComment( $art ); }
|
|
765
|
-
annotationAssignment_ll1[ $art ]*
|
|
766
|
-
// #ATN: ELEMENTS, ENUM, DEFINITIONS, COLUMNS, ACTIONS are not reserved and
|
|
767
|
-
// could be includeRef
|
|
768
|
-
(
|
|
769
|
-
// all the alternatives from `extendWithOptElementsOrType` --------------
|
|
770
|
-
'{' { $art.elements = this.createDict(); }
|
|
771
|
-
elementDefOrExtend[ $art ]*
|
|
772
|
-
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
773
|
-
{ this.checkExtensionDict( $art.elements ); }
|
|
774
|
-
optionalSemi
|
|
775
|
-
|
|
|
776
|
-
requiredSemi
|
|
777
|
-
|
|
|
778
|
-
ELEMENTS { $art.elements = this.createDict(); } '{'
|
|
779
|
-
elementDefOrExtend[ $art, true ]*
|
|
780
|
-
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
781
|
-
{ this.checkExtensionDict( $art.elements ); }
|
|
782
|
-
optionalSemi
|
|
783
|
-
|
|
|
784
|
-
ENUM { $art.enum = this.createDict(); } '{'
|
|
785
|
-
enumSymbolDef[ $art ]* // TODO: no EXTEND in enum? (ok, would just allow annos)
|
|
786
|
-
'}' { this.finalizeDictOrArray( $art.enum ); }
|
|
787
|
-
optionalSemi
|
|
788
|
-
|
|
|
789
|
-
// extend Art with (length: 10);
|
|
790
|
-
// `with` is required, or we could have `extend String(length:10);`.
|
|
791
|
-
// future `extend Action with (param: Type)` now has ambiguity
|
|
792
|
-
typeNamedArgList[ $art ]
|
|
793
|
-
requiredSemi
|
|
794
|
-
|
|
|
795
|
-
// extension alternatives for main definitions --------------------------
|
|
796
|
-
includeRef[ $art ] ( ',' includeRef[ $art ] )*
|
|
797
|
-
requiredSemi
|
|
798
|
-
|
|
|
799
|
-
DEFINITIONS { $art.artifacts = this.createDict(); } '{'
|
|
800
|
-
artifactDefOrExtend[ $art, 'definitions' ]*
|
|
801
|
-
'}' { this.finalizeDictOrArray( $art.artifacts ); }
|
|
802
|
-
optionalSemi
|
|
803
|
-
|
|
|
804
|
-
COLUMNS { $art.columns = this.createArray(); } '{'
|
|
805
|
-
(
|
|
806
|
-
selectItemDef[ $art.columns ]
|
|
807
|
-
( ',' { if (this.isStraightBefore("}")) break; } // allow ',' before '}'
|
|
808
|
-
selectItemDef[ $art.columns ]
|
|
809
|
-
)*
|
|
810
|
-
)?
|
|
811
|
-
'}' { this.finalizeDictOrArray( $art.columns ); }
|
|
812
|
-
optionalSemi
|
|
813
|
-
|
|
|
814
|
-
ACTIONS { $art.actions = this.createDict(); } '{'
|
|
815
|
-
actionFunctionDef[ $art ]* // TODO: no EXTEND in actions? (ok, would just allow annos)
|
|
816
|
-
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
817
|
-
optionalSemi
|
|
818
|
-
)
|
|
819
|
-
// TODO: what about adding both ELEMENTS and ACTIONS? (TODO: csn input test & to-cdl)
|
|
820
|
-
)
|
|
821
|
-
;
|
|
822
|
-
|
|
823
|
-
extendService[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
824
|
-
@after { this.attachLocation( $art ); }
|
|
825
|
-
:
|
|
826
|
-
SERVICE { $art.expectedKind = this.valueWithTokenLocation(); }
|
|
827
|
-
simplePath[ $name, 'Service' ]
|
|
828
|
-
{ $art.name = $name; this.addItem( $art, $outer, 'extensions', 'extend' ); }
|
|
829
|
-
( WITH { this.noSemicolonHere(); } )?
|
|
830
|
-
optArtifactsBlock[ art, 'service' ]
|
|
831
|
-
;
|
|
832
|
-
|
|
833
|
-
extendContext[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
834
|
-
@after { this.attachLocation( $art ); }
|
|
835
|
-
:
|
|
836
|
-
CONTEXT { $art.expectedKind = this.valueWithTokenLocation(); }
|
|
837
|
-
simplePath[ $name, 'Context' ]
|
|
838
|
-
{ $art.name = $name; this.addItem( $art, $outer, 'extensions', 'extend' ); }
|
|
839
|
-
( WITH { this.noSemicolonHere(); } )?
|
|
840
|
-
optArtifactsBlock[ art, 'context' ]
|
|
841
|
-
;
|
|
842
|
-
|
|
843
|
-
extendEntityOrAspect[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
844
|
-
@after { /* #ATN 1 */ this.attachLocation( $art ); }
|
|
845
|
-
:
|
|
846
|
-
(ASPECT | ENTITY) { $art.expectedKind = this.valueWithTokenLocation(); }
|
|
847
|
-
simplePath[ $name, 'Extend' ]
|
|
848
|
-
{ $art.name = $name;
|
|
849
|
-
this.addItem( $art, $outer, 'extensions', 'extend' );
|
|
850
|
-
}
|
|
851
|
-
(
|
|
852
|
-
WITH { this.noSemicolonHere(); this.docComment( $art ); }
|
|
853
|
-
annotationAssignment_ll1[ $art ]*
|
|
854
|
-
// ATN: the ref can start with ACTIONS
|
|
855
|
-
(
|
|
856
|
-
includeRef[ $art ] ( ',' includeRef[ $art ] )*
|
|
857
|
-
requiredSemi
|
|
858
|
-
|
|
|
859
|
-
extendForEntity[ $art ]
|
|
860
|
-
)
|
|
861
|
-
|
|
|
862
|
-
{ this.docComment( $art ); }
|
|
863
|
-
annotationAssignment_ll1[ $art ]*
|
|
864
|
-
extendForEntity[ $art ]
|
|
865
|
-
)
|
|
866
|
-
;
|
|
867
|
-
|
|
868
|
-
extendForEntity[ art ]
|
|
869
|
-
:
|
|
870
|
-
'{' { $art.elements = this.createDict(); }
|
|
871
|
-
elementDefOrExtend[ $art ]*
|
|
872
|
-
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
873
|
-
(
|
|
874
|
-
ACTIONS { $art.actions = this.createDict(); } '{'
|
|
875
|
-
actionFunctionDef[ $art ]*
|
|
876
|
-
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
877
|
-
)?
|
|
878
|
-
optionalSemi
|
|
879
|
-
|
|
|
880
|
-
ACTIONS { $art.actions = this.createDict(); } '{'
|
|
881
|
-
actionFunctionDef[ $art ]*
|
|
882
|
-
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
883
|
-
optionalSemi
|
|
884
|
-
|
|
|
885
|
-
requiredSemi
|
|
886
|
-
;
|
|
887
|
-
|
|
888
|
-
extendProjection[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
889
|
-
@after { this.attachLocation( $art ); }
|
|
890
|
-
:
|
|
891
|
-
PROJECTION { $art.expectedKind = this.valueWithTokenLocation( 'entity' ); }
|
|
892
|
-
simplePath[ $name, 'Extend' ]
|
|
893
|
-
{ $art.name = $name;
|
|
894
|
-
this.addItem( $art, $outer, 'extensions', 'extend' );
|
|
895
|
-
}
|
|
896
|
-
( WITH { this.noSemicolonHere(); } )?
|
|
897
|
-
{ this.docComment( $art ); }
|
|
898
|
-
annotationAssignment_ll1[ $art ]*
|
|
899
|
-
(
|
|
900
|
-
'{' { $art.columns = this.createArray(); }
|
|
901
|
-
(
|
|
902
|
-
selectItemDef[ $art.columns ]
|
|
903
|
-
( ',' { if (this.isStraightBefore("}")) break; } // allow ',' before '}'
|
|
904
|
-
selectItemDef[ $art.columns ]
|
|
905
|
-
)*
|
|
906
|
-
)?
|
|
907
|
-
'}' { this.finalizeDictOrArray( $art.columns ); }
|
|
908
|
-
(
|
|
909
|
-
ACTIONS { $art.actions = this.createDict(); } '{'
|
|
910
|
-
actionFunctionDef[ $art ]*
|
|
911
|
-
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
912
|
-
)?
|
|
913
|
-
optionalSemi
|
|
914
|
-
|
|
|
915
|
-
ACTIONS { $art.actions = this.createDict(); } '{'
|
|
916
|
-
actionFunctionDef[ $art ]*
|
|
917
|
-
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
918
|
-
optionalSemi
|
|
919
|
-
|
|
|
920
|
-
requiredSemi
|
|
921
|
-
)
|
|
922
|
-
;
|
|
923
|
-
|
|
924
|
-
extendType[ art, outer ] locals[ name = new parser.XsnName() ]
|
|
925
|
-
@after { this.attachLocation( $art ); }
|
|
926
|
-
:
|
|
927
|
-
TYPE { $art.expectedKind = this.valueWithTokenLocation(); }
|
|
928
|
-
simplePath[ $name, 'Extend' ]
|
|
929
|
-
{ $art.name = $name;
|
|
930
|
-
this.addItem( $art, $outer, 'extensions', 'extend' );
|
|
931
|
-
}
|
|
932
|
-
// extendWithOptElementsOrType + includeRef:
|
|
933
|
-
(
|
|
934
|
-
extendWithOptElementsNoWith[ art ]
|
|
935
|
-
|
|
|
936
|
-
WITH { this.noSemicolonHere(); this.docComment( $art ); }
|
|
937
|
-
annotationAssignment_ll1[ $art ]*
|
|
938
|
-
(
|
|
939
|
-
'{' { $art.elements = this.createDict(); }
|
|
940
|
-
elementDefOrExtend[ $art ]*
|
|
941
|
-
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
942
|
-
{ this.checkExtensionDict( $art.elements ); }
|
|
943
|
-
optionalSemi
|
|
944
|
-
|
|
|
945
|
-
// extend type Art with (length: 10);
|
|
946
|
-
typeNamedArgList[ $art ]
|
|
947
|
-
requiredSemi
|
|
948
|
-
|
|
|
949
|
-
requiredSemi
|
|
950
|
-
|
|
|
951
|
-
includeRef[ $art ] ( ',' includeRef[ $art ] )*
|
|
952
|
-
requiredSemi
|
|
953
|
-
)
|
|
954
|
-
)
|
|
955
|
-
;
|
|
956
|
-
|
|
957
|
-
extendWithOptElementsOrType[ art ]
|
|
958
|
-
:
|
|
959
|
-
extendWithOptElementsNoWith[ art ]
|
|
960
|
-
|
|
|
961
|
-
WITH { this.noSemicolonHere(); this.docComment( $art ); }
|
|
962
|
-
annotationAssignment_ll1[ $art ]*
|
|
963
|
-
(
|
|
964
|
-
'{' { $art.elements = this.createDict(); }
|
|
965
|
-
elementDefOrExtend[ $art ]*
|
|
966
|
-
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
967
|
-
{ this.checkExtensionDict( $art.elements ); }
|
|
968
|
-
optionalSemi
|
|
969
|
-
|
|
|
970
|
-
ELEMENTS { $art.elements = this.createDict(); } '{'
|
|
971
|
-
elementDefOrExtend[ $art, true ]*
|
|
972
|
-
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
973
|
-
{ this.checkExtensionDict( $art.elements ); }
|
|
974
|
-
optionalSemi
|
|
975
|
-
|
|
|
976
|
-
ENUM { $art.enum = this.createDict(); } '{'
|
|
977
|
-
enumSymbolDef[ $art ]* // TODO: no EXTEND in enum? (ok, would just allow annos)
|
|
978
|
-
'}' { this.finalizeDictOrArray( $art.enum ); }
|
|
979
|
-
optionalSemi
|
|
980
|
-
|
|
|
981
|
-
// extend type|element Art with (length: 10);
|
|
982
|
-
typeNamedArgList[ $art ]
|
|
983
|
-
requiredSemi
|
|
984
|
-
|
|
|
985
|
-
requiredSemi
|
|
986
|
-
)
|
|
987
|
-
;
|
|
988
|
-
|
|
989
|
-
extendWithOptElementsNoWith[ art ]
|
|
990
|
-
:
|
|
991
|
-
{ this.docComment( $art ); }
|
|
992
|
-
annotationAssignment_ll1[ $art ]*
|
|
993
|
-
(
|
|
994
|
-
'{' { $art.elements = this.createDict(); }
|
|
995
|
-
elementDefOrExtend[ $art ]*
|
|
996
|
-
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
997
|
-
{ this.checkExtensionDict( $art.elements ); }
|
|
998
|
-
optionalSemi
|
|
999
|
-
|
|
|
1000
|
-
requiredSemi
|
|
1001
|
-
)
|
|
1002
|
-
;
|
|
1003
|
-
|
|
1004
|
-
// For `extend … with elements` or `extend entity … with`, `extend aspect … with`,
|
|
1005
|
-
// i.e. definitions in { … } are never enums
|
|
1006
|
-
elementDefOrExtend[ outer, explicitElement = false ] locals[ art = new parser.XsnArtifact() ]
|
|
1007
|
-
@after { /* #ATN 1 */ } // if ($art) this.attachLocation( $art ); }
|
|
1008
|
-
:
|
|
1009
|
-
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
1010
|
-
annotationAssignment_ll1[ $art ]*
|
|
1011
|
-
// #ATN: element name for definition can be EXTEND
|
|
1012
|
-
(
|
|
1013
|
-
EXTEND
|
|
1014
|
-
extendElement[ $art, $outer ]
|
|
1015
|
-
|
|
|
1016
|
-
elementDefInner[ $art, $outer, $explicitElement ]
|
|
1017
|
-
)
|
|
1018
|
-
;
|
|
1019
|
-
|
|
1020
|
-
extendElement[ art, outer ]
|
|
1021
|
-
@after{ this.attachLocation( $art ); }
|
|
1022
|
-
:
|
|
1023
|
-
{ this.setLocalToken( 'ELEMENT', 'ELEMENT', /^([:{@=}()]|WITH)$/i ); }
|
|
1024
|
-
( ELEMENT { $art.expectedKind = this.valueWithTokenLocation(); } )?
|
|
1025
|
-
name=ident['Element']
|
|
1026
|
-
{ this.addDef( $art, $outer, 'elements', 'extend', $name.id ); }
|
|
1027
|
-
extendWithOptElementsOrType[ $art, $art ]
|
|
1028
|
-
;
|
|
1029
|
-
|
|
1030
|
-
annotateArtifact[ art, outer ] locals[ name = new parser.XsnName(), elemName = new parser.XsnName() ]
|
|
1031
|
-
@after { this.attachLocation( $art ); }
|
|
1032
|
-
:
|
|
1033
|
-
simplePath[ $name, 'Annotate' ]
|
|
1034
|
-
( // Element annotation
|
|
1035
|
-
':' simplePath[ $elemName, 'Element']
|
|
1036
|
-
{ this.addExtension( $art, $outer, 'annotate', $name, $elemName.path ); }
|
|
1037
|
-
( WITH { this.noSemicolonHere(); } )?
|
|
1038
|
-
{ this.docComment( $art ); }
|
|
1039
|
-
annotationAssignment_ll1[ $art ]*
|
|
1040
|
-
(
|
|
1041
|
-
'{' { $art.elements = this.createDict(); }
|
|
1042
|
-
annotateElement[ $art ]*
|
|
1043
|
-
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
1044
|
-
{ this.checkExtensionDict( $art.elements ); }
|
|
1045
|
-
optionalSemi
|
|
1046
|
-
| requiredSemi
|
|
1047
|
-
)
|
|
1048
|
-
| // Definition annotation
|
|
1049
|
-
{ this.addExtension( $art, $outer, 'annotate', $name ); }
|
|
1050
|
-
( WITH { this.noSemicolonHere(); } )?
|
|
1051
|
-
{ this.docComment( $art ); }
|
|
1052
|
-
annotationAssignment_ll1[ $art ]*
|
|
1053
|
-
(
|
|
1054
|
-
'{' { $art.elements = this.createDict(); }
|
|
1055
|
-
annotateElement[ $art ]*
|
|
1056
|
-
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
1057
|
-
{ this.checkExtensionDict( $art.elements ); }
|
|
1058
|
-
(
|
|
1059
|
-
ACTIONS { $art.actions = this.createDict(); } '{'
|
|
1060
|
-
annotateAction[ $art ]*
|
|
1061
|
-
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
1062
|
-
{ this.checkExtensionDict( $art.actions ); }
|
|
1063
|
-
)?
|
|
1064
|
-
optionalSemi
|
|
1065
|
-
|
|
|
1066
|
-
ACTIONS { $art.actions = this.createDict(); } '{'
|
|
1067
|
-
annotateAction[ $art ]*
|
|
1068
|
-
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
1069
|
-
{ this.checkExtensionDict( $art.actions ); }
|
|
1070
|
-
optionalSemi
|
|
1071
|
-
|
|
|
1072
|
-
'(' { $art.params = this.createDict(); }
|
|
1073
|
-
annotateParam[ $art ]
|
|
1074
|
-
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
1075
|
-
annotateParam[ $art ]
|
|
1076
|
-
)*
|
|
1077
|
-
')' { this.finalizeDictOrArray( $art.params ); }
|
|
1078
|
-
{ this.checkExtensionDict( $art.params ); }
|
|
1079
|
-
( annotateReturns[ $art ]
|
|
1080
|
-
| requiredSemi
|
|
1081
|
-
)
|
|
1082
|
-
|
|
|
1083
|
-
annotateReturns[ $art ]
|
|
1084
|
-
|
|
|
1085
|
-
requiredSemi
|
|
1086
|
-
)
|
|
1087
|
-
)
|
|
1088
|
-
;
|
|
1089
|
-
|
|
1090
|
-
annotateElement[ outer ] locals[ art = new parser.XsnArtifact() ]
|
|
1091
|
-
@after{ this.attachLocation( $art ); }
|
|
1092
|
-
:
|
|
1093
|
-
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
1094
|
-
annotationAssignment_ll1[ $art ]*
|
|
1095
|
-
name=ident['Element']
|
|
1096
|
-
{ this.addDef( $art, $outer, 'elements', 'annotate', $name.id );
|
|
1097
|
-
this.docComment( $art ); }
|
|
1098
|
-
annotationAssignment_ll1[ $art ]*
|
|
1099
|
-
(
|
|
1100
|
-
'{' { $art.elements = this.createDict(); }
|
|
1101
|
-
annotateElement[ $art ]*
|
|
1102
|
-
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
1103
|
-
{ this.checkExtensionDict( $art.elements ); }
|
|
1104
|
-
optionalSemi
|
|
1105
|
-
|
|
|
1106
|
-
requiredSemi
|
|
1107
|
-
)
|
|
1108
|
-
;
|
|
1109
|
-
|
|
1110
|
-
annotateAction [ outer ] locals [ art = new parser.XsnArtifact() ]
|
|
1111
|
-
@after{ this.attachLocation( $art ); }
|
|
1112
|
-
:
|
|
1113
|
-
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
1114
|
-
annotationAssignment_ll1[ $art ]*
|
|
1115
|
-
name=ident['BoundAction']
|
|
1116
|
-
{ this.addDef( $art, $outer, 'actions', 'annotate', $name.id );
|
|
1117
|
-
this.docComment( $art ); }
|
|
1118
|
-
annotationAssignment_ll1[ $art ]*
|
|
1119
|
-
(
|
|
1120
|
-
'(' { $art.params = this.createDict(); }
|
|
1121
|
-
annotateParam[ $art ]
|
|
1122
|
-
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
1123
|
-
annotateParam[ $art ]
|
|
1124
|
-
)*
|
|
1125
|
-
')' { this.finalizeDictOrArray( $art.params ); }
|
|
1126
|
-
{ this.checkExtensionDict( $art.params ); }
|
|
1127
|
-
)?
|
|
1128
|
-
(
|
|
1129
|
-
annotateReturns[ $art ]
|
|
1130
|
-
|
|
|
1131
|
-
requiredSemi
|
|
1132
|
-
)
|
|
1133
|
-
;
|
|
1134
|
-
|
|
1135
|
-
annotateReturns[ art ]
|
|
1136
|
-
@after{ this.attachLocation( $art.returns ); }
|
|
1137
|
-
:
|
|
1138
|
-
ret=RETURNS { $art.returns = new this.XsnArtifact();; $art.returns.kind = 'annotate'; }
|
|
1139
|
-
{ this.docComment( $art.returns ); }
|
|
1140
|
-
annotationAssignment_ll1[ $art.returns ]*
|
|
1141
|
-
( '{' { $art.returns.elements = this.createDict(); }
|
|
1142
|
-
annotateElement[ $art.returns ]*
|
|
1143
|
-
'}' { this.finalizeDictOrArray( $art.returns.elements ); }
|
|
1144
|
-
{ this.checkExtensionDict( $art.returns.elements ); }
|
|
1145
|
-
optionalSemi
|
|
1146
|
-
| requiredSemi
|
|
1147
|
-
)
|
|
1148
|
-
;
|
|
1149
|
-
|
|
1150
|
-
annotateParam [ outer ] locals [ art = new parser.XsnArtifact() ]
|
|
1151
|
-
@after{ this.attachLocation( $art ); }
|
|
1152
|
-
:
|
|
1153
|
-
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
1154
|
-
annotationAssignment_ll1[ $art ]*
|
|
1155
|
-
param=ident['Param']
|
|
1156
|
-
{ this.addDef( $art, $outer, 'params', 'annotate', $param.id );
|
|
1157
|
-
this.docComment( $art ); }
|
|
1158
|
-
annotationAssignment_ll1[ $art ]*
|
|
1159
|
-
;
|
|
1160
|
-
|
|
1161
|
-
// Type expressions -------------------------------------------------------------
|
|
1162
|
-
|
|
1163
|
-
includeRef[ art ] locals[ incl = {} ]
|
|
1164
|
-
:
|
|
1165
|
-
simplePath[ $incl, 'artref' ]
|
|
1166
|
-
{ if ($art.includes) $art.includes.push($incl); else $art.includes = [$incl]; }
|
|
1167
|
-
;
|
|
1168
|
-
|
|
1169
|
-
typeSpec[ art ] // for parameterDef
|
|
1170
|
-
@after{ /* #ATN 1 */ }
|
|
1171
|
-
:
|
|
1172
|
-
typeStruct[ $art ]
|
|
1173
|
-
|
|
|
1174
|
-
':'
|
|
1175
|
-
// #ATN: typeSimple can start with ARRAY or TYPE
|
|
1176
|
-
( typeStruct[ $art ]
|
|
1177
|
-
nullability[ $art ]?
|
|
1178
|
-
| typeArray[ $art ] // nullability is set in typeArray
|
|
1179
|
-
| typeTypeOf[ $art ]
|
|
1180
|
-
nullability[ $art ]?
|
|
1181
|
-
(
|
|
1182
|
-
ENUM '{' { $art.enum = this.createDict(); }
|
|
1183
|
-
enumSymbolDef[ $art ]*
|
|
1184
|
-
'}' { this.finalizeDictOrArray( $art.enum ); }
|
|
1185
|
-
nullability[ $art ]?
|
|
1186
|
-
)?
|
|
1187
|
-
// TODO: no LOCALIZED ?
|
|
1188
|
-
| typeRefOptArgs[ $art ]
|
|
1189
|
-
nullability[ $art ]?
|
|
1190
|
-
(
|
|
1191
|
-
ENUM '{' { $art.enum = this.createDict(); }
|
|
1192
|
-
enumSymbolDef[ $art ]*
|
|
1193
|
-
'}' { this.finalizeDictOrArray( $art.enum ); }
|
|
1194
|
-
nullability[ $art ]?
|
|
1195
|
-
)?
|
|
1196
|
-
)
|
|
1197
|
-
;
|
|
1198
|
-
|
|
1199
|
-
returnTypeSpec[ art ]
|
|
1200
|
-
@after{ /* #ATN 1 */ }
|
|
1201
|
-
:
|
|
1202
|
-
ret=RETURNS { $art.returns = { location: this.tokenLocation( $ret ), kind: 'param' }; }
|
|
1203
|
-
{ this.docComment( $art.returns ); }
|
|
1204
|
-
annotationAssignment_ll1[ $art.returns ]*
|
|
1205
|
-
// #ATN: typeSimple can start with ARRAY or TYPE
|
|
1206
|
-
( typeStruct[ $art.returns ]
|
|
1207
|
-
nullability[ $art.returns ]?
|
|
1208
|
-
| typeArray[ $art.returns ] // nullability is set in typeArray
|
|
1209
|
-
| typeTypeOf[ $art.returns ]
|
|
1210
|
-
nullability[ $art.returns ]?
|
|
1211
|
-
(
|
|
1212
|
-
ENUM '{' { $art.returns.enum = this.createDict(); }
|
|
1213
|
-
enumSymbolDef[ $art.returns ]*
|
|
1214
|
-
'}' { this.finalizeDictOrArray( $art.returns.enum ); }
|
|
1215
|
-
nullability[ $art.returns ]?
|
|
1216
|
-
)?
|
|
1217
|
-
// TODO: no LOCALIZED ?
|
|
1218
|
-
| typeRefOptArgs[ $art.returns ]
|
|
1219
|
-
nullability[ $art.returns ]?
|
|
1220
|
-
(
|
|
1221
|
-
ENUM '{' { $art.returns.enum = this.createDict(); }
|
|
1222
|
-
enumSymbolDef[ $art.returns ]*
|
|
1223
|
-
'}' { this.finalizeDictOrArray( $art.returns.enum ); }
|
|
1224
|
-
nullability[ $art.returns ]?
|
|
1225
|
-
)?
|
|
1226
|
-
)
|
|
1227
|
-
|
|
1228
|
-
requiredSemi // currently for all - might change if we get rid of the misplaced annos (TODO: Now removed)
|
|
1229
|
-
;
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
typeSpecSemi[ art ] // with 'includes', for type and annotation defs
|
|
1233
|
-
@after{ /* #ATN 3 */ }
|
|
1234
|
-
:
|
|
1235
|
-
typeStruct[ $art ]
|
|
1236
|
-
( nullability[ $art ]
|
|
1237
|
-
requiredSemi
|
|
1238
|
-
| optionalSemi
|
|
1239
|
-
)
|
|
1240
|
-
|
|
|
1241
|
-
':'
|
|
1242
|
-
// #ATN: typeRefOptArgs can start with ARRAY or MANY or ASSOCIATION or TYPE or LOCALIZED
|
|
1243
|
-
// Nevertheless, MANY '{' is handled by local token rewrite:
|
|
1244
|
-
{ this.setLocalToken( 'MANY', 'HelperToken1', /^[^\{]/ ); }
|
|
1245
|
-
(
|
|
1246
|
-
typeStruct[ $art ]
|
|
1247
|
-
( nullability[ $art ]
|
|
1248
|
-
requiredSemi
|
|
1249
|
-
| optionalSemi
|
|
1250
|
-
)
|
|
1251
|
-
|
|
|
1252
|
-
typeAssociationBase[ $art, false ]
|
|
1253
|
-
// #ATN: path could start with MANY or ONE - make sure a token follows in same rule!
|
|
1254
|
-
( typeToMany[ $art ] | typeToOne[ $art ] | simplePath[ $art.target, 'artref' ] )
|
|
1255
|
-
typeAssociationCont[ $art ]?
|
|
1256
|
-
requiredSemi // and if its the ';'...
|
|
1257
|
-
|
|
|
1258
|
-
many=HelperToken1 // rewritten MANY before '{'
|
|
1259
|
-
{ $art.items = { location: this.tokenLocation( $many ) };}
|
|
1260
|
-
typeStruct[ $art.items ]
|
|
1261
|
-
( nullability[ $art.items ]
|
|
1262
|
-
requiredSemi
|
|
1263
|
-
| optionalSemi
|
|
1264
|
-
)
|
|
1265
|
-
|
|
|
1266
|
-
(
|
|
1267
|
-
array=ARRAY of=OF
|
|
1268
|
-
{ $art.items = { location: this.tokenLocation( $array, $of ) }; }
|
|
1269
|
-
| many=MANY
|
|
1270
|
-
{ $art.items = { location: this.tokenLocation( $many ) };}
|
|
1271
|
-
)
|
|
1272
|
-
// #ATN: typeRefOptArgs can start with TYPE
|
|
1273
|
-
( typeStruct[ $art.items ]
|
|
1274
|
-
( nullability[ $art.items ]
|
|
1275
|
-
requiredSemi
|
|
1276
|
-
| optionalSemi
|
|
1277
|
-
)
|
|
1278
|
-
| ( typeTypeOf[ $art.items ] | typeRefOptArgs[ $art.items ] )
|
|
1279
|
-
nullability[ $art.items ]?
|
|
1280
|
-
{ this.docComment( $art ); }
|
|
1281
|
-
annotationAssignment_ll1[ $art ]*
|
|
1282
|
-
(
|
|
1283
|
-
ENUM '{' { $art.items.enum = this.createDict(); }
|
|
1284
|
-
enumSymbolDef[ $art.items ]*
|
|
1285
|
-
'}' { this.finalizeDictOrArray( $art.items.enum ); }
|
|
1286
|
-
( nullability[ $art.items ]
|
|
1287
|
-
requiredSemi
|
|
1288
|
-
| optionalSemi
|
|
1289
|
-
)
|
|
1290
|
-
| requiredSemi
|
|
1291
|
-
)
|
|
1292
|
-
)
|
|
1293
|
-
|
|
|
1294
|
-
typeTypeOf[ $art ]
|
|
1295
|
-
defaultAndNullability[ $art ]?
|
|
1296
|
-
{ this.docComment( $art ); }
|
|
1297
|
-
annotationAssignment_ll1[ $art ]*
|
|
1298
|
-
requiredSemi
|
|
1299
|
-
|
|
|
1300
|
-
l=LOCALIZED { $art.localized = this.valueWithTokenLocation( true, $l ); }
|
|
1301
|
-
typeRefOptArgs[ $art ]
|
|
1302
|
-
defaultAndNullability[ $art ]?
|
|
1303
|
-
{ this.docComment( $art ); }
|
|
1304
|
-
annotationAssignment_ll1[ $art ]*
|
|
1305
|
-
requiredSemi
|
|
1306
|
-
|
|
|
1307
|
-
// alt lookahead includes MANY '{'
|
|
1308
|
-
{ $art.type = {}; }
|
|
1309
|
-
// Can't use typeRefOptArgs because of clash with include rule below (ATN would change)
|
|
1310
|
-
simplePath[ $art.type, 'artref' ]
|
|
1311
|
-
(
|
|
1312
|
-
( typeRefArgs[ $art ]
|
|
1313
|
-
| ':' // with element, e.g. `type T : E:elem enum { ... }`
|
|
1314
|
-
{ $art.type.scope = $art.type.path.length; }
|
|
1315
|
-
simplePath[ $art.type, 'ref']
|
|
1316
|
-
)?
|
|
1317
|
-
optInvisibleNullability[ $art ]
|
|
1318
|
-
{ this.docComment( $art ); }
|
|
1319
|
-
annotationAssignment_ll1[ $art ]*
|
|
1320
|
-
(
|
|
1321
|
-
ENUM '{' { $art.enum = this.createDict(); }
|
|
1322
|
-
enumSymbolDef[ $art ]*
|
|
1323
|
-
'}' { this.finalizeDictOrArray( $art.enum ); }
|
|
1324
|
-
( optionalSemi
|
|
1325
|
-
| defaultAndNullability[ $art ]
|
|
1326
|
-
requiredSemi
|
|
1327
|
-
)
|
|
1328
|
-
| defaultAndNullability[ $art ]?
|
|
1329
|
-
requiredSemi
|
|
1330
|
-
)
|
|
1331
|
-
|
|
|
1332
|
-
// TODO: complain if used in anno def?
|
|
1333
|
-
{ $art.includes = [ $art.type ]; delete $art.type; }
|
|
1334
|
-
( ',' { if (this.isStraightBefore('{')) break; } // allow ',' before '{' // }}
|
|
1335
|
-
includeRef[ $art ]
|
|
1336
|
-
)*
|
|
1337
|
-
typeStruct[ $art ]
|
|
1338
|
-
( optionalSemi
|
|
1339
|
-
| nullability[ $art ]
|
|
1340
|
-
requiredSemi
|
|
1341
|
-
)
|
|
1342
|
-
)
|
|
1343
|
-
)
|
|
1344
|
-
;
|
|
1345
|
-
|
|
1346
|
-
typeStruct[ art, attachLoc = false ]
|
|
1347
|
-
@after { if ($attachLoc) this.attachLocation($art); }
|
|
1348
|
-
:
|
|
1349
|
-
'{' { $art.elements = this.createDict(); }
|
|
1350
|
-
elementDef[ $art ]*
|
|
1351
|
-
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
1352
|
-
;
|
|
1353
|
-
|
|
1354
|
-
typeCompoStruct[ art ]
|
|
1355
|
-
@after { this.attachLocation($art); }
|
|
1356
|
-
:
|
|
1357
|
-
COMPOSITIONofBRACE { $art.elements = this.createDict(); }
|
|
1358
|
-
elementDef[ $art ]*
|
|
1359
|
-
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
1360
|
-
;
|
|
1361
|
-
|
|
1362
|
-
typeArray[ art ]
|
|
1363
|
-
@after { /* #ATN 1 */ }
|
|
1364
|
-
:
|
|
1365
|
-
(
|
|
1366
|
-
array=ARRAY of=OF
|
|
1367
|
-
{ $art.items = { location: this.tokenLocation( $array, $of ) }; }
|
|
1368
|
-
| many=MANY
|
|
1369
|
-
{ $art.items = { location: this.tokenLocation( $many ) };}
|
|
1370
|
-
)
|
|
1371
|
-
// #ATN: typeRefOptArgs can start with TYPE
|
|
1372
|
-
( typeStruct[ $art.items ]
|
|
1373
|
-
nullability[ $art.items ]?
|
|
1374
|
-
| typeTypeOf[ $art.items ]
|
|
1375
|
-
nullability[ $art.items ]?
|
|
1376
|
-
(
|
|
1377
|
-
ENUM '{' { $art.items.enum = this.createDict(); }
|
|
1378
|
-
enumSymbolDef[ $art.items ]*
|
|
1379
|
-
'}' { this.finalizeDictOrArray( $art.items.enum ); }
|
|
1380
|
-
nullability[ $art.items ]?
|
|
1381
|
-
)?
|
|
1382
|
-
| typeRefOptArgs[ $art.items ]
|
|
1383
|
-
nullability[ $art.items ]?
|
|
1384
|
-
(
|
|
1385
|
-
ENUM '{' { $art.items.enum = this.createDict(); }
|
|
1386
|
-
enumSymbolDef[ $art.items ]*
|
|
1387
|
-
'}' { this.finalizeDictOrArray( $art.items.enum ); }
|
|
1388
|
-
nullability[ $art.items ]?
|
|
1389
|
-
)?
|
|
1390
|
-
)
|
|
1391
|
-
;
|
|
1392
|
-
|
|
1393
|
-
typeAssociationBase[ art, handleTypeCompo ] // including Composition
|
|
1394
|
-
:
|
|
1395
|
-
(
|
|
1396
|
-
assoc=ASSOCIATION cardinality[$art]? TO
|
|
1397
|
-
{{
|
|
1398
|
-
let location = this.tokenLocation($assoc);
|
|
1399
|
-
$art.type = { path: [{ id: 'cds.Association', location }], scope: 'global', location };
|
|
1400
|
-
this.handleComposition( $art.cardinality, false );
|
|
1401
|
-
}}
|
|
1402
|
-
|
|
|
1403
|
-
compo=COMPOSITION cardinality[$art]? OF
|
|
1404
|
-
{{
|
|
1405
|
-
let location = this.tokenLocation($compo);
|
|
1406
|
-
$art.type = { path: [{ id: 'cds.Composition', location }], scope: 'global', location };
|
|
1407
|
-
this.handleComposition( $art.cardinality, handleTypeCompo );
|
|
1408
|
-
}}
|
|
1409
|
-
)
|
|
1410
|
-
{ $art.target = {}; }
|
|
1411
|
-
;
|
|
1412
|
-
|
|
1413
|
-
typeAssociationCont[ art ]
|
|
1414
|
-
:
|
|
1415
|
-
(
|
|
1416
|
-
'{' { $art.foreignKeys = this.createDict(); }
|
|
1417
|
-
(
|
|
1418
|
-
foreignKey[ $art ]
|
|
1419
|
-
( ',' { if (this.isStraightBefore("}")) break; } // allow ',' before '}'
|
|
1420
|
-
foreignKey[ $art ]
|
|
1421
|
-
)*
|
|
1422
|
-
)?
|
|
1423
|
-
'}' { this.finalizeDictOrArray( $art.foreignKeys ); }
|
|
1424
|
-
defaultAndNullability[ $art ]?
|
|
1425
|
-
|
|
|
1426
|
-
ON cond=condition
|
|
1427
|
-
{ $art.on=$cond.cond; }
|
|
1428
|
-
|
|
|
1429
|
-
defaultAndNullability[ $art ]
|
|
1430
|
-
)
|
|
1431
|
-
;
|
|
1432
|
-
|
|
1433
|
-
typeAssociationElementCont[ art ] // including Composition
|
|
1434
|
-
// optional NULL / NOT NULL for managed association only
|
|
1435
|
-
:
|
|
1436
|
-
(
|
|
1437
|
-
'{' { $art.foreignKeys = this.createDict(); }
|
|
1438
|
-
(
|
|
1439
|
-
foreignKey[ $art ]
|
|
1440
|
-
( ',' { if (this.isStraightBefore("}")) break; } // allow ',' before '}'
|
|
1441
|
-
foreignKey[ $art ]
|
|
1442
|
-
)*
|
|
1443
|
-
)?
|
|
1444
|
-
'}' { this.finalizeDictOrArray( $art.foreignKeys ); }
|
|
1445
|
-
defaultAndNullability[ $art ]?
|
|
1446
|
-
|
|
|
1447
|
-
ON cond=condition
|
|
1448
|
-
{ $art.on=$cond.cond; }
|
|
1449
|
-
|
|
|
1450
|
-
defaultAndNullability[ $art ]
|
|
1451
|
-
)?
|
|
1452
|
-
{ this.docComment( $art ); }
|
|
1453
|
-
annotationAssignment_ll1[ $art ]*
|
|
1454
|
-
requiredSemi // also req after foreign key spec
|
|
1455
|
-
;
|
|
1456
|
-
|
|
1457
|
-
typeToOne[ art ]
|
|
1458
|
-
:
|
|
1459
|
-
one=ONE
|
|
1460
|
-
{ this.setMaxCardinality( $art, this.numberLiteral( $one, null, '1' ) ); }
|
|
1461
|
-
simplePath[ $art.target, 'artref' ]
|
|
1462
|
-
;
|
|
1463
|
-
|
|
1464
|
-
typeToMany[ art ]
|
|
1465
|
-
:
|
|
1466
|
-
many=MANY
|
|
1467
|
-
{ this.setMaxCardinality( $art, { literal: 'string', val: '*' }, $many ); }
|
|
1468
|
-
simplePath[ $art.target, 'artref' ]
|
|
1469
|
-
;
|
|
1470
|
-
|
|
1471
|
-
cardinality[ art ] locals[ card = {} ]
|
|
1472
|
-
@after { /* #ATN 2 */ $art.cardinality = this.attachLocation($card); }
|
|
1473
|
-
:
|
|
1474
|
-
lbrack='['
|
|
1475
|
-
{ $card.targetMax = { literal: 'string', val: '*',
|
|
1476
|
-
location: this.tokenLocation($lbrack) }; }
|
|
1477
|
-
(
|
|
1478
|
-
// #ATN: simple lookahead behind Number
|
|
1479
|
-
(
|
|
1480
|
-
srcMax=Number ','
|
|
1481
|
-
{ $card.sourceMax = this.numberLiteral( $srcMax ); }
|
|
1482
|
-
|
|
|
1483
|
-
srcMaxStar='*' ','
|
|
1484
|
-
{ $card.sourceMax = { literal: 'string', val: '*',
|
|
1485
|
-
location: this.tokenLocation($srcMaxStar) }; }
|
|
1486
|
-
)?
|
|
1487
|
-
// #ATN: simple lookahead behind Number
|
|
1488
|
-
(
|
|
1489
|
-
trgMin=Number '..'
|
|
1490
|
-
{ $card.targetMin = this.numberLiteral( $trgMin ); }
|
|
1491
|
-
)?
|
|
1492
|
-
(
|
|
1493
|
-
trgMax=Number
|
|
1494
|
-
{ $card.targetMax = this.numberLiteral( $trgMax ); }
|
|
1495
|
-
|
|
|
1496
|
-
trgMaxStar='*'
|
|
1497
|
-
{ $card.targetMax = { literal: 'string', val: '*',
|
|
1498
|
-
location: this.tokenLocation($trgMaxStar) }; }
|
|
1499
|
-
)
|
|
1500
|
-
)?
|
|
1501
|
-
']'
|
|
1502
|
-
;
|
|
1503
|
-
|
|
1504
|
-
// TO be used when NOT and NULL are already in the lookahead set:
|
|
1505
|
-
optInvisibleNullability[ art ]
|
|
1506
|
-
: { this.setLocalTokenForId( 1, { 'NOT': 'HelperToken1', 'NULL': 'HelperToken2' } ); }
|
|
1507
|
-
( n1=HelperToken1 n2=NULL { this.setNullability( $art, $n1, $n2 ); }
|
|
1508
|
-
| n1=HelperToken2 { this.setNullability( $art, $n1, null ); }
|
|
1509
|
-
)?
|
|
1510
|
-
;
|
|
1511
|
-
|
|
1512
|
-
nullability[ art ]
|
|
1513
|
-
@after{ this.setNullability( $art, $n1, $n2 ); }
|
|
1514
|
-
: n1=NOT n2=NULL
|
|
1515
|
-
| n1=NULL
|
|
1516
|
-
;
|
|
1517
|
-
|
|
1518
|
-
foreignKey[ outer ] locals[ art = new parser.XsnArtifact(), elem = {} ]
|
|
1519
|
-
@after { this.attachLocation($art); }
|
|
1520
|
-
:
|
|
1521
|
-
simplePath[ $elem, 'ref' ] { $art.targetElement = $elem; }
|
|
1522
|
-
( AS name=ident['Key'] )?
|
|
1523
|
-
{ this.addDef( $art, $outer, 'foreignKeys', 'key', ($ctx.name) ? $name.id : $elem.path ); }
|
|
1524
|
-
;
|
|
1525
|
-
|
|
1526
|
-
typeTypeOf[ art ] locals[ _sync = 'nop' ]
|
|
1527
|
-
@after { this.attachLocation($art.type); }
|
|
1528
|
-
:
|
|
1529
|
-
t=TYPE o=OF
|
|
1530
|
-
{ $art.type = { scope: 'typeOf' }; }
|
|
1531
|
-
simplePath[ $art.type, 'ref' ]
|
|
1532
|
-
( ':'
|
|
1533
|
-
// If we have too much time, we could set the category of the simple path
|
|
1534
|
-
// before to 'artref'
|
|
1535
|
-
{ $art.type.scope = $art.type.path.length; }
|
|
1536
|
-
simplePath[ $art.type, 'ref']
|
|
1537
|
-
)?
|
|
1538
|
-
// We do not use (…|) here instead (…)? due to different ANTLR code generation:
|
|
1539
|
-
// (…|) would check for follow set, which does not work with local token rewrite
|
|
1540
|
-
{ if ($art.type.scope === 'typeOf')
|
|
1541
|
-
// Better error locations and much simpler code if we consider it as a path breakout:
|
|
1542
|
-
$art.type.path.unshift( { id: 'type of', location: this.tokenLocation( $t, $o )} );
|
|
1543
|
-
}
|
|
1544
|
-
;
|
|
1545
|
-
|
|
1546
|
-
typeRefOptArgs[ art ]
|
|
1547
|
-
@init { $art.type = {}; }
|
|
1548
|
-
:
|
|
1549
|
-
simplePath[ $art.type, 'artref' ]
|
|
1550
|
-
(
|
|
1551
|
-
typeRefArgs[ $art ]
|
|
1552
|
-
|
|
|
1553
|
-
':'
|
|
1554
|
-
{ $art.type.scope = $art.type.path.length; }
|
|
1555
|
-
simplePath[ $art.type, 'ref']
|
|
1556
|
-
)?
|
|
1557
|
-
;
|
|
1558
|
-
|
|
1559
|
-
typeRefArgs[ art ]
|
|
1560
|
-
@after { this.checkTypeArgs($art); }
|
|
1561
|
-
:
|
|
1562
|
-
paren='(' { $art['$'+'typeArgs'] = this.createArray(); }
|
|
1563
|
-
(
|
|
1564
|
-
// unnamed arguments
|
|
1565
|
-
head=Number
|
|
1566
|
-
{ $art['$'+'typeArgs'].push( this.numberLiteral( $head ) ); }
|
|
1567
|
-
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
1568
|
-
(
|
|
1569
|
-
v=VARIABLE
|
|
1570
|
-
{ $art['$'+'typeArgs'].push(
|
|
1571
|
-
{ literal: 'string', val: 'variable', location: this.tokenLocation($v) } );
|
|
1572
|
-
}
|
|
1573
|
-
|
|
|
1574
|
-
f=FLOATING
|
|
1575
|
-
{ $art['$'+'typeArgs'].push(
|
|
1576
|
-
{ literal: 'string', val: 'floating', location: this.tokenLocation($f) } );
|
|
1577
|
-
}
|
|
1578
|
-
|
|
|
1579
|
-
tail=Number
|
|
1580
|
-
{ $art['$'+'typeArgs'].push( this.numberLiteral( $tail ) ); }
|
|
1581
|
-
)
|
|
1582
|
-
)*
|
|
1583
|
-
|
|
|
1584
|
-
// named arguments
|
|
1585
|
-
typeNamedArg[ $art ]
|
|
1586
|
-
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
1587
|
-
typeNamedArg[ $art ]
|
|
1588
|
-
)*
|
|
1589
|
-
)
|
|
1590
|
-
')'{ this.finalizeDictOrArray( $art['$'+'typeArgs']); }
|
|
1591
|
-
;
|
|
1592
|
-
|
|
1593
|
-
typeNamedArgList[ art ]
|
|
1594
|
-
:
|
|
1595
|
-
paren='('
|
|
1596
|
-
typeNamedArg[ $art ]
|
|
1597
|
-
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
1598
|
-
typeNamedArg[ $art ]
|
|
1599
|
-
)*
|
|
1600
|
-
')'
|
|
1601
|
-
;
|
|
1602
|
-
|
|
1603
|
-
typeNamedArg[ art ] locals[ arg = '' ]
|
|
1604
|
-
:
|
|
1605
|
-
name=ident['paramname']
|
|
1606
|
-
':'
|
|
1607
|
-
{ if ($name.id && this.checkTypeFacet( $art, $name.id ))
|
|
1608
|
-
$arg = $name.id.id;
|
|
1609
|
-
}
|
|
1610
|
-
(
|
|
1611
|
-
val=Number
|
|
1612
|
-
{ if ($arg && $art && $name.id) {
|
|
1613
|
-
$art[$arg] = this.numberLiteral( $val );
|
|
1614
|
-
}
|
|
1615
|
-
}
|
|
1616
|
-
|
|
|
1617
|
-
v=VARIABLE
|
|
1618
|
-
{ if ($arg && $art && $name.id) {
|
|
1619
|
-
$art[$arg] = { literal: 'string', val: 'variable', location: this.tokenLocation($v) };
|
|
1620
|
-
}
|
|
1621
|
-
}
|
|
1622
|
-
|
|
|
1623
|
-
f=FLOATING
|
|
1624
|
-
{ if ($arg && $art && $name.id) {
|
|
1625
|
-
$art[$arg] = { literal: 'string', val: 'floating', location: this.tokenLocation($f) };
|
|
1626
|
-
}
|
|
1627
|
-
}
|
|
1628
|
-
)
|
|
1629
|
-
;
|
|
1630
|
-
|
|
1631
|
-
// Queries: the main query structure --------------------------------------------
|
|
1632
|
-
|
|
1633
|
-
queryEOF returns [ query ]
|
|
1634
|
-
:
|
|
1635
|
-
q=queryExpression { $query = $q.query; } EOF
|
|
1636
|
-
;
|
|
1637
|
-
|
|
1638
|
-
projectionSpec returns[ query ] locals[ src ]
|
|
1639
|
-
@after { this.attachLocation($query); }
|
|
1640
|
-
:
|
|
1641
|
-
proj=PROJECTION ON
|
|
1642
|
-
// now a simplified `tableTerm`:
|
|
1643
|
-
{
|
|
1644
|
-
$src = { path: [] };
|
|
1645
|
-
$query = { op: this.valueWithTokenLocation( 'SELECT', $proj ), from: $src, location: this.startLocation() };
|
|
1646
|
-
}
|
|
1647
|
-
fromPath[ $src, 'artref']
|
|
1648
|
-
( ':'
|
|
1649
|
-
{ $src.scope = $src.path.length; }
|
|
1650
|
-
fromPath[ $src, 'ref']
|
|
1651
|
-
)?
|
|
1652
|
-
( AS aliasName=ident['FromAlias'] { $src.name = $aliasName.id } )?
|
|
1653
|
-
// ANTLR errors are better if we use ( A )? instead of ( A | ):
|
|
1654
|
-
{ if (!$src.name) this.classifyImplicitName( $src.scope ? 'FromAlias' : 'Without' ); }
|
|
1655
|
-
bracedSelectItemListDef[ $query, 'columns' ]?
|
|
1656
|
-
excludingClause[ $query ]?
|
|
1657
|
-
;
|
|
1658
|
-
|
|
1659
|
-
projectionClauses[ query ]
|
|
1660
|
-
@after { this.attachLocation($query); }
|
|
1661
|
-
:
|
|
1662
|
-
( WHERE cond=condition { $query.where = $cond.cond; } )?
|
|
1663
|
-
(
|
|
1664
|
-
GROUP BY
|
|
1665
|
-
e1=expression { $query.groupBy = [ $e1.expr ]; }
|
|
1666
|
-
( ',' en=expression { $query.groupBy.push( $en.expr ); } )*
|
|
1667
|
-
)?
|
|
1668
|
-
( HAVING having=condition { $query.having = $having.cond; } )?
|
|
1669
|
-
( ob=orderByClause[ $query ] { $query = $ob.query; } ) ?
|
|
1670
|
-
( lc=limitClause[ $query ] { $query = $lc.query; } ) ?
|
|
1671
|
-
;
|
|
1672
|
-
|
|
1673
|
-
queryExpression returns[ query ] // QLSubqueryComplex, SubqueryComplex
|
|
1674
|
-
@after{ this.attachLocation($query); }
|
|
1675
|
-
:
|
|
1676
|
-
qt1=queryTerm { $query = $qt1.query; }
|
|
1677
|
-
(
|
|
1678
|
-
( op=UNION q=( DISTINCT | ALL )?
|
|
1679
|
-
| op=EXCEPT q=DISTINCT?
|
|
1680
|
-
| op=MINUS q=DISTINCT?
|
|
1681
|
-
)
|
|
1682
|
-
qt=queryTerm
|
|
1683
|
-
{ if ($qt.query) $query = this.leftAssocBinaryOp( $query, $op, $q, $qt.query );; $ctx.q = null; }
|
|
1684
|
-
)*
|
|
1685
|
-
( ob=orderByClause[ $query ] { if ($ob.query) $query = $ob.query; } ) ?
|
|
1686
|
-
( lc=limitClause[ $query ] { if ($lc.query) $query = $lc.query; } ) ?
|
|
1687
|
-
;
|
|
1688
|
-
|
|
1689
|
-
queryTerm returns[ query ]
|
|
1690
|
-
@after{ this.attachLocation($query); }
|
|
1691
|
-
:
|
|
1692
|
-
qt1=queryPrimary { $query = $qt1.query; }
|
|
1693
|
-
(
|
|
1694
|
-
intersect=INTERSECT quantifier=DISTINCT?
|
|
1695
|
-
qt=queryPrimary
|
|
1696
|
-
{ $query = this.leftAssocBinaryOp( $query, $intersect, $quantifier, $qt.query );
|
|
1697
|
-
$ctx.quantifier = null; } // reset for loop
|
|
1698
|
-
)*
|
|
1699
|
-
;
|
|
1700
|
-
|
|
1701
|
-
queryPrimary returns[ query = {} ]
|
|
1702
|
-
@after { this.attachLocation($query); }
|
|
1703
|
-
:
|
|
1704
|
-
open='(' qe=queryExpression close=')'
|
|
1705
|
-
{ $query = this.surroundByParens( $qe.query, $open, $close ); }
|
|
1706
|
-
|
|
|
1707
|
-
select=SELECT
|
|
1708
|
-
{ $query = { op: this.valueWithTokenLocation( 'SELECT', $select ), location: this.startLocation() }; }
|
|
1709
|
-
(
|
|
1710
|
-
FROM querySource[ $query ]
|
|
1711
|
-
(
|
|
1712
|
-
mixin=MIXIN '{' { $query.mixin = this.createDict(); }
|
|
1713
|
-
mixinElementDef[ $query ]*
|
|
1714
|
-
'}' { this.finalizeDictOrArray( $query.mixin ); }
|
|
1715
|
-
INTO
|
|
1716
|
-
)?
|
|
1717
|
-
( ad=( ALL | DISTINCT ) // TODO: or directly after SELECT ?
|
|
1718
|
-
{ $query.quantifier = this.valueWithTokenLocation( $ad.text.toLowerCase(), $ad ); }
|
|
1719
|
-
)?
|
|
1720
|
-
bracedSelectItemListDef[ $query, 'columns' ]?
|
|
1721
|
-
excludingClause[ $query ]?
|
|
1722
|
-
|
|
|
1723
|
-
( ad=( ALL | DISTINCT ) // TODO: or directly after SELECT ?
|
|
1724
|
-
{ $query.quantifier = this.valueWithTokenLocation( $ad.text.toLowerCase(), $ad ); }
|
|
1725
|
-
)?
|
|
1726
|
-
{ $query.columns = []; } // set it early to avoid "wildcard" errors
|
|
1727
|
-
selectItemDef[ $query.columns ]
|
|
1728
|
-
( ',' { if (this.isStraightBefore("}")) break; } // allow ',' before '}'
|
|
1729
|
-
selectItemDef[ $query.columns ]
|
|
1730
|
-
)*
|
|
1731
|
-
FROM querySource[ $query ]
|
|
1732
|
-
)
|
|
1733
|
-
( WHERE cond=condition { $query.where = $cond.cond; } )?
|
|
1734
|
-
(
|
|
1735
|
-
GROUP BY
|
|
1736
|
-
e1=expression { $query.groupBy = [ $e1.expr ]; }
|
|
1737
|
-
( ',' en=expression { $query.groupBy.push( $en.expr ); } )*
|
|
1738
|
-
)?
|
|
1739
|
-
( HAVING having=condition { $query.having = $having.cond; } )?
|
|
1740
|
-
;
|
|
1741
|
-
|
|
1742
|
-
querySource[ query ]
|
|
1743
|
-
@after { this.attachLocation($query.from); }
|
|
1744
|
-
:
|
|
1745
|
-
t1=tableExpression { $query.from = $t1.table; }
|
|
1746
|
-
(
|
|
1747
|
-
{ const location = this.tokenLocation( this.getCurrentToken() );
|
|
1748
|
-
$query.from = { op: { val: 'join', location },
|
|
1749
|
-
join: { val: 'cross', location },
|
|
1750
|
-
args: [$t1.table] }; }
|
|
1751
|
-
( ',' tn=tableExpression { if ($tn.table) $query.from.args.push( $tn.table ); } )+
|
|
1752
|
-
)?
|
|
1753
|
-
;
|
|
1754
|
-
|
|
1755
|
-
tableExpression returns[ table ] // TableOrJoin
|
|
1756
|
-
@after { this.attachLocation($table); }
|
|
1757
|
-
:
|
|
1758
|
-
qt=tableTerm { $table = $qt.table; }
|
|
1759
|
-
(
|
|
1760
|
-
join=joinOp[ $table ] { $table = $join.table; }
|
|
1761
|
-
te=tableExpression
|
|
1762
|
-
{ if (!$table) { $table = {}; } else if ($te.table) $table.args.push( $te.table ); }
|
|
1763
|
-
ON cond=condition { $table.on = $cond.cond; }
|
|
1764
|
-
|
|
|
1765
|
-
crj=CROSS jn=JOIN tt=tableTerm
|
|
1766
|
-
{ if (!$table) { $table = {}; } $table = this.leftAssocBinaryOp( $table, $jn, $crj, $tt.table, 'join' ); }
|
|
1767
|
-
)*
|
|
1768
|
-
;
|
|
1769
|
-
|
|
1770
|
-
tableTerm returns [ table ]
|
|
1771
|
-
@after{ /* #ATN 1 */ this.attachLocation($table); }
|
|
1772
|
-
:
|
|
1773
|
-
{ $table = { path: [] }; }
|
|
1774
|
-
f=fromPath[ $table, 'artref']
|
|
1775
|
-
{ if ($f.dotAfterFilter)
|
|
1776
|
-
this.warning( 'syntax-invalid-path-separator', $f.dotAfterFilter,
|
|
1777
|
-
{ '#': 'dot', code: '.', newcode: ':' } );
|
|
1778
|
-
}
|
|
1779
|
-
( { if (!$table.scope)
|
|
1780
|
-
$table.scope = $table.path.length;
|
|
1781
|
-
else
|
|
1782
|
-
this.warning( 'syntax-invalid-path-separator', this.getCurrentToken(),
|
|
1783
|
-
{ '#': 'colon', code: ':', newcode: '.' } );
|
|
1784
|
-
}
|
|
1785
|
-
':' fromPath[ $table, 'ref']
|
|
1786
|
-
)?
|
|
1787
|
-
( AS n1=ident['FromAlias'] { $table.name = $n1.id; }
|
|
1788
|
-
| n2=identNoKeyword['FromAlias'] { $table.name = this.fragileAlias( $n2.id ); }
|
|
1789
|
-
// if we would use rule `ident`, we would either had to make all JOIN
|
|
1790
|
-
// kinds reserved or introduce ATN
|
|
1791
|
-
)?
|
|
1792
|
-
// ANTLR errors are better if we use ( A | B )? instead of ( A | B | ):
|
|
1793
|
-
{ if (!$table.name) this.classifyImplicitName( $table.scope ? 'FromAlias' : 'Without' ); }
|
|
1794
|
-
|
|
|
1795
|
-
open='('
|
|
1796
|
-
// #ATN: The following alternative is not LL1, because both can start with
|
|
1797
|
-
// left-paren, but queryExpression has SELECT after initial left-parens
|
|
1798
|
-
(
|
|
1799
|
-
qe=queryExpression close=')'
|
|
1800
|
-
{ $table = this.surroundByParens( $qe.query, $open, $close, true ); }
|
|
1801
|
-
( AS a1=ident['FromAlias'] { $table.name = $a1.id } // for defining table alias
|
|
1802
|
-
| a2=identNoKeyword['FromAlias'] { $table.name = this.fragileAlias( $a2.id, true ); }
|
|
1803
|
-
// not using ident` to have a similar behavior to above
|
|
1804
|
-
)?
|
|
1805
|
-
|
|
|
1806
|
-
te=tableExpression close=')'
|
|
1807
|
-
{ $table = this.surroundByParens( $te.table, $open, $close ); }
|
|
1808
|
-
)
|
|
1809
|
-
;
|
|
1810
|
-
|
|
1811
|
-
fromPath[ qp, idkind ] returns[ dotAfterFilter = null ]
|
|
1812
|
-
@after{ this.attachLocation($qp); }
|
|
1813
|
-
:
|
|
1814
|
-
id=ident[$idkind] { this.pushIdent( $qp.path, $id.id ); }
|
|
1815
|
-
( fromArguments[ $id.id ] cardinalityAndFilter[ $id.id ]?
|
|
1816
|
-
{ $dotAfterFilter = false; }
|
|
1817
|
-
| cardinalityAndFilter[ $id.id ]
|
|
1818
|
-
{ $dotAfterFilter = false; }
|
|
1819
|
-
)?
|
|
1820
|
-
(
|
|
1821
|
-
{ if ($dotAfterFilter === false) {
|
|
1822
|
-
$dotAfterFilter = this.getCurrentToken();
|
|
1823
|
-
if (!$qp.scope) $qp.scope = $qp.path.length;
|
|
1824
|
-
} }
|
|
1825
|
-
'.' id=ident[$idkind] { this.pushIdent( $qp.path, $id.id ); }
|
|
1826
|
-
( fromArguments[ $id.id ] cardinalityAndFilter[ $id.id ]?
|
|
1827
|
-
{ if (!$dotAfterFilter) $dotAfterFilter = false; }
|
|
1828
|
-
| cardinalityAndFilter[ $id.id ]
|
|
1829
|
-
{ if (!$dotAfterFilter) $dotAfterFilter = false; }
|
|
1830
|
-
)?
|
|
1831
|
-
)*
|
|
1832
|
-
;
|
|
1833
|
-
|
|
1834
|
-
fromArguments[ pathStep ]
|
|
1835
|
-
@init{ if (!$pathStep) $pathStep = {}; } // grammar robustness, see test/negative/parser/NamedExpression.cds
|
|
1836
|
-
:
|
|
1837
|
-
'(' { $pathStep.args = this.createDict(); $pathStep['$'+'syntax'] = ':'; } // necessary?
|
|
1838
|
-
name=ident['paramname'] ':'
|
|
1839
|
-
namedExpression[ $pathStep, $name.id ]
|
|
1840
|
-
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
1841
|
-
name=ident['paramname'] ':'
|
|
1842
|
-
namedExpression[ $pathStep, $name.id ]
|
|
1843
|
-
)*
|
|
1844
|
-
')' { this.finalizeDictOrArray( $pathStep.args ); }
|
|
1845
|
-
;
|
|
1846
|
-
|
|
1847
|
-
// Queries: columns and other clauses -------------------------------------------
|
|
1848
|
-
|
|
1849
|
-
excludingClause[ query ]
|
|
1850
|
-
:
|
|
1851
|
-
// syntax is less than ideal - EXCLUDING is only useful for `*` - with
|
|
1852
|
-
// this syntax, people wonder what happens with explicit select items
|
|
1853
|
-
EXCLUDING '{' { $query.excludingDict = this.createDict(); }
|
|
1854
|
-
projectionExclusion[ $query ]
|
|
1855
|
-
( ',' { if (this.isStraightBefore("}")) break; } // allow ',' before '}'
|
|
1856
|
-
projectionExclusion[ $query ]
|
|
1857
|
-
)*
|
|
1858
|
-
'}' { this.finalizeDictOrArray( $query.excludingDict ); }
|
|
1859
|
-
;
|
|
1860
|
-
|
|
1861
|
-
projectionExclusion[ outer ] locals[ art = {} ]
|
|
1862
|
-
@after { this.attachLocation($art); }
|
|
1863
|
-
:
|
|
1864
|
-
name=ident['ref']
|
|
1865
|
-
{ this.addDef( $art, $outer, 'excludingDict', '', $name.id ); }
|
|
1866
|
-
;
|
|
1867
|
-
|
|
1868
|
-
// Actually, this is a subset if elementDefInner...
|
|
1869
|
-
// TODO: the corresponding restrictions must also be checked in the core
|
|
1870
|
-
// compiler, as the mixin element could come via CSN
|
|
1871
|
-
mixinElementDef[ outer ] locals[ art = { target: {} } ]
|
|
1872
|
-
@after { /* #ATN 1 */ this.attachLocation($art); }
|
|
1873
|
-
:
|
|
1874
|
-
name=ident['Mixin'] ':'
|
|
1875
|
-
typeAssociationBase[ $art, false ]
|
|
1876
|
-
{ if ($art.type) this.addDef( $art, $outer, 'mixin', 'mixin', $name.id ); }
|
|
1877
|
-
// #ATN: path could start with MANY or ONE - make sure a token follows in same rule!
|
|
1878
|
-
( typeToMany[ $art ] | typeToOne[ $art ] | simplePath[ $art.target, 'artref' ] )
|
|
1879
|
-
// TODO CC: exclude every token other than ON
|
|
1880
|
-
typeAssociationCont[ $art ]? // better error reporting than simply `ON condition`
|
|
1881
|
-
requiredSemi
|
|
1882
|
-
;
|
|
1883
|
-
|
|
1884
|
-
selectItemDef[ outer ] locals[ art ]
|
|
1885
|
-
@after{ if ($art) this.attachLocation( $art ); }
|
|
1886
|
-
:
|
|
1887
|
-
star='*'
|
|
1888
|
-
{ $outer.push( this.valueWithTokenLocation( '*', $star ) ); }
|
|
1889
|
-
|
|
|
1890
|
-
{ $art = new this.XsnArtifact();; this.docComment( $art ); }
|
|
1891
|
-
annotationAssignment_atn[ $art ]*
|
|
1892
|
-
// VIRTUAL is keyword, except if before the following tokens texts:
|
|
1893
|
-
{ this.setLocalToken( 'VIRTUAL', 'VIRTUAL', /^([,.:\[@]|as)$/i ) ; } // not '{'
|
|
1894
|
-
( virtual=VIRTUAL { $art.virtual = this.valueWithTokenLocation( true, $virtual ); } )?
|
|
1895
|
-
( key=KEY { $art.key = this.valueWithTokenLocation( true, $key ); } )?
|
|
1896
|
-
selectItemDefBody[ $art, $outer ]
|
|
1897
|
-
;
|
|
1898
|
-
|
|
1899
|
-
selectItemDefBody[ art, outer ] locals[ assoc ]
|
|
1900
|
-
@after{ /* #ATN 2 */ }
|
|
1901
|
-
:
|
|
1902
|
-
{ $outer.push( $art ); }
|
|
1903
|
-
(
|
|
1904
|
-
e=expression { $art.value = $e.expr; }
|
|
1905
|
-
// we cannot use 'condition' instead, as long as we allow aliases without
|
|
1906
|
-
// AS (using rule 'ident' instead of 'identNoKeyword') -> ambiguities
|
|
1907
|
-
( as=AS n1=ident['Item'] { $art.name = $n1.id; }
|
|
1908
|
-
| n2=ident['Item'] { $art.name = this.fragileAlias( $n2.id, true ); }
|
|
1909
|
-
| { this.classifyImplicitName( 'Item', $e.expr ); }
|
|
1910
|
-
)
|
|
1911
|
-
{ if ($art.value && !$art.value.path) this.excludeExpected( ["'.'", "'{'"] );
|
|
1912
|
-
else if ($art.name) this.excludeExpected( ["'.'"] );
|
|
1913
|
-
}
|
|
1914
|
-
(
|
|
1915
|
-
{ this.reportExpandInline( $art, false ); }
|
|
1916
|
-
selectItemInlineList[ $art, 'expand' ]
|
|
1917
|
-
excludingClause[ $art ]?
|
|
1918
|
-
|
|
|
1919
|
-
{ this.reportExpandInline( $art, $as || this._input.LT(-1) ); }
|
|
1920
|
-
DOTbeforeBRACE // ...orASTERISK
|
|
1921
|
-
(
|
|
1922
|
-
selectItemInlineList[ $art, 'inline' ]
|
|
1923
|
-
excludingClause[ $art ]?
|
|
1924
|
-
|
|
|
1925
|
-
star='*'
|
|
1926
|
-
{ $art.inline = [ this.valueWithTokenLocation( '*', $star ) ]; }
|
|
1927
|
-
)
|
|
1928
|
-
)?
|
|
1929
|
-
|
|
|
1930
|
-
selectItemInlineList[ $art, 'expand' ]
|
|
1931
|
-
excludingClause[ $art ]?
|
|
1932
|
-
AS n1=ident['Item'] { $art.name = $n1.id; }
|
|
1933
|
-
)
|
|
1934
|
-
{ this.docComment( $art ); }
|
|
1935
|
-
annotationAssignment_fix[ $art ]*
|
|
1936
|
-
( ':'
|
|
1937
|
-
// #ATN: typeRefOptArgs can start with TYPE, REDIRECTED, ASSOCIATION
|
|
1938
|
-
( re=REDIRECTED to=TO
|
|
1939
|
-
{ $art.target = {}; }
|
|
1940
|
-
simplePath[ $art.target, 'artref' ]
|
|
1941
|
-
(
|
|
1942
|
-
typeAssociationCont[ $art ]
|
|
1943
|
-
|
|
|
1944
|
-
{ this.docComment( $art ); }
|
|
1945
|
-
annotationAssignment_ll1[ $art ]*
|
|
1946
|
-
)
|
|
1947
|
-
| typeTypeOf[ $art ]
|
|
1948
|
-
{ this.docComment( $art ); }
|
|
1949
|
-
annotationAssignment_ll1[ $art ]*
|
|
1950
|
-
| l=LOCALIZED { $art.localized = this.valueWithTokenLocation( true, $l ); }
|
|
1951
|
-
typeRefOptArgs[ $art ]
|
|
1952
|
-
{ this.docComment( $art ); }
|
|
1953
|
-
annotationAssignment_ll1[ $art ]*
|
|
1954
|
-
| typeRefOptArgs[ $art ]
|
|
1955
|
-
{ this.docComment( $art ); }
|
|
1956
|
-
annotationAssignment_ll1[ $art ]*
|
|
1957
|
-
|
|
|
1958
|
-
{ $assoc = this.associationInSelectItem( $art ); }
|
|
1959
|
-
typeAssociationBase[ $assoc, false ]
|
|
1960
|
-
// #ATN: path could start with MANY or ONE - make sure a token follows in same rule!
|
|
1961
|
-
( typeToMany[ $assoc ] | typeToOne[ $assoc ] | simplePath[ $assoc.target, 'artref' ] )
|
|
1962
|
-
ON cond=condition
|
|
1963
|
-
{ $assoc.on=$cond.cond; }
|
|
1964
|
-
)
|
|
1965
|
-
)?
|
|
1966
|
-
;
|
|
1967
|
-
|
|
1968
|
-
bracedSelectItemListDef[ query ]
|
|
1969
|
-
:
|
|
1970
|
-
'{' { $query.columns = this.createArray(); }
|
|
1971
|
-
(
|
|
1972
|
-
selectItemDef[ $query.columns ]
|
|
1973
|
-
( ',' { if (this.isStraightBefore("}")) break; } // allow ',' before '}'
|
|
1974
|
-
selectItemDef[ $query.columns ]
|
|
1975
|
-
)*
|
|
1976
|
-
)?
|
|
1977
|
-
'}' { this.finalizeDictOrArray( $query.columns ); }
|
|
1978
|
-
;
|
|
1979
|
-
|
|
1980
|
-
selectItemInlineList[ art, clause ]
|
|
1981
|
-
:
|
|
1982
|
-
'{' { $art[$clause] = this.createArray(); }
|
|
1983
|
-
(
|
|
1984
|
-
selectItemInlineDef[ $art[$clause] ]
|
|
1985
|
-
( ',' { if (this.isStraightBefore("}")) break; } // allow ',' before '}'
|
|
1986
|
-
selectItemInlineDef[ $art[$clause] ]
|
|
1987
|
-
)*
|
|
1988
|
-
)?
|
|
1989
|
-
'}' { this.finalizeDictOrArray( $art[$clause] ); }
|
|
1990
|
-
;
|
|
1991
|
-
|
|
1992
|
-
selectItemInlineDef[ outer ] locals[ art ]
|
|
1993
|
-
@after{ if ($art) this.attachLocation( $art ); }
|
|
1994
|
-
:
|
|
1995
|
-
star='*'
|
|
1996
|
-
{ $outer.push( this.valueWithTokenLocation( '*', $star ) ); }
|
|
1997
|
-
|
|
|
1998
|
-
{ $art = new this.XsnArtifact();; this.docComment( $art ); }
|
|
1999
|
-
annotationAssignment_atn[ $art ]*
|
|
2000
|
-
selectItemDefBody[ $art, $outer ]
|
|
2001
|
-
;
|
|
2002
|
-
|
|
2003
|
-
orderByClause[ inQuery ] returns [ query ]
|
|
2004
|
-
:
|
|
2005
|
-
ORDER BY { $query = this.unaryOpForParens( $inQuery, '$'+'query' ); }
|
|
2006
|
-
ob1=orderBySpec { $query.orderBy = [ $ob1.ob ]; }
|
|
2007
|
-
( ',' obn=orderBySpec { $query.orderBy.push( $obn.ob ); } )*
|
|
2008
|
-
;
|
|
2009
|
-
|
|
2010
|
-
limitClause[ inQuery ] returns [ query ]
|
|
2011
|
-
:
|
|
2012
|
-
limkw=LIMIT { $query = this.unaryOpForParens( $inQuery, '$'+'query' ); }
|
|
2013
|
-
lim=expression { $query.limit = { rows: $lim.expr }; }
|
|
2014
|
-
( OFFSET off=expression { $query.limit.offset = $off.expr; } )? // unsigned integer
|
|
2015
|
-
;
|
|
2016
|
-
|
|
2017
|
-
orderBySpec returns[ ob ]
|
|
2018
|
-
:
|
|
2019
|
-
e=expression { $ob = $e.expr; }
|
|
2020
|
-
( asc=ASC { $ob.sort = this.valueWithTokenLocation( 'asc', $asc ); }
|
|
2021
|
-
| desc=DESC { $ob.sort = this.valueWithTokenLocation( 'desc', $desc ); }
|
|
2022
|
-
)?
|
|
2023
|
-
( nb=NULLS ne=( FIRST | LAST )
|
|
2024
|
-
{ $ob.nulls = this.valueWithTokenLocation( $ne.text.toLowerCase(), $nb, $ne ); }
|
|
2025
|
-
)?
|
|
2026
|
-
;
|
|
2027
|
-
|
|
2028
|
-
joinOp[ left ] returns[ table ] locals [ join ]
|
|
2029
|
-
:
|
|
2030
|
-
( op=JOIN { $join = 'inner'; }
|
|
2031
|
-
| t1=INNER c=joinCardinality? op=JOIN { $join = 'inner' }
|
|
2032
|
-
| t1=LEFT t2=OUTER? c=joinCardinality? op=JOIN { $join = 'left' }
|
|
2033
|
-
| t1=RIGHT t2=OUTER? c=joinCardinality? op=JOIN { $join = 'right' }
|
|
2034
|
-
| t1=FULL t2=OUTER? c=joinCardinality? op=JOIN { $join = 'full' }
|
|
2035
|
-
)
|
|
2036
|
-
{ $table = { op: this.valueWithTokenLocation( 'join', $op ),
|
|
2037
|
-
join: this.valueWithTokenLocation( $join, $t1 || $op, $t2 ),
|
|
2038
|
-
args: ($left ? [$left] : []),
|
|
2039
|
-
location: $left && $left.location };
|
|
2040
|
-
if ($ctx.c) $table.cardinality = $c.joinCard; }
|
|
2041
|
-
;
|
|
2042
|
-
|
|
2043
|
-
joinCardinality returns [ joinCard ]
|
|
2044
|
-
@init { $joinCard = {}; }
|
|
2045
|
-
@after { this.attachLocation($joinCard); }
|
|
2046
|
-
:
|
|
2047
|
-
(
|
|
2048
|
-
srcExact=EXACT?
|
|
2049
|
-
srcMaxOne=ONE
|
|
2050
|
-
{ if($srcExact)
|
|
2051
|
-
$joinCard.sourceMin = { literal: 'number', val: 1,
|
|
2052
|
-
location: this.tokenLocation($srcExact) };
|
|
2053
|
-
$joinCard.sourceMax = { literal: 'number', val: 1,
|
|
2054
|
-
location: this.tokenLocation($srcMaxOne) }; }
|
|
2055
|
-
|
|
|
2056
|
-
srcMaxMany=MANY
|
|
2057
|
-
{ $joinCard.sourceMax = { literal: 'string', val: '*',
|
|
2058
|
-
location: this.tokenLocation($srcMaxMany) }; }
|
|
2059
|
-
)
|
|
2060
|
-
TO
|
|
2061
|
-
(
|
|
2062
|
-
tgtExact=EXACT? tgtMaxOne=ONE
|
|
2063
|
-
{ if($tgtExact)
|
|
2064
|
-
$joinCard.targetMin = { literal: 'number', val: 1,
|
|
2065
|
-
location: this.tokenLocation($tgtExact) };
|
|
2066
|
-
$joinCard.targetMax = { literal: 'number', val: 1,
|
|
2067
|
-
location: this.tokenLocation($tgtMaxOne) }; }
|
|
2068
|
-
|
|
|
2069
|
-
tgtMaxMany=MANY
|
|
2070
|
-
{ $joinCard.targetMax = { literal: 'string', val: '*',
|
|
2071
|
-
location: this.tokenLocation($tgtMaxMany) }; }
|
|
2072
|
-
)
|
|
2073
|
-
;
|
|
2074
|
-
|
|
2075
|
-
// Conditions and expressions ---------------------------------------------------
|
|
2076
|
-
|
|
2077
|
-
// With "separate" `condition` and `expression` rules, we have long LL
|
|
2078
|
-
// ambiguities (not so with LALR used in Bison) with initial left parentheses:
|
|
2079
|
-
// ( ( ( a.b.c + d.e.f
|
|
2080
|
-
// ) // now we know: 3rd left-paren for expression
|
|
2081
|
-
// = // now we know: 1st and 2nd left-paren for condition
|
|
2082
|
-
// 3 ) ) )
|
|
2083
|
-
//
|
|
2084
|
-
// To avoid expensive parsing, we "combine" both rules, i.e. inside '('…')' of
|
|
2085
|
-
// rule `expressionTerm`, we recursively refer to `condition`, not
|
|
2086
|
-
// `expression`. With that, the existence of relations/predicates in rule
|
|
2087
|
-
// `conditionTerm` must be optional. Correct conditions and expressions must
|
|
2088
|
-
// be then ensured by code (either in actions of the grammar or in a check
|
|
2089
|
-
// phase - to be discussed).
|
|
2090
|
-
//
|
|
2091
|
-
// We cannot generally allow `condition` where `expression` is written:
|
|
2092
|
-
// - IN is also used in non-standard function `args` and as predicate:
|
|
2093
|
-
// - AND is boolean operator and also used for BETWEEN…AND
|
|
2094
|
-
//
|
|
2095
|
-
// ANTLR4s left-recursion feature cannot be used as we will have rule
|
|
2096
|
-
// arguments.
|
|
2097
|
-
|
|
2098
|
-
conditionEOF returns [ cond ]
|
|
2099
|
-
:
|
|
2100
|
-
c=condition { $cond = $c.cond; } EOF
|
|
2101
|
-
;
|
|
2102
|
-
|
|
2103
|
-
condition returns [ cond ] locals [ args = [], orl = [] ]
|
|
2104
|
-
@after{ $cond = this.argsExpression( $args, $ctx.e2 ? '?:' : true ); }
|
|
2105
|
-
:
|
|
2106
|
-
c1=conditionOr { $args.push($c1.cond); }
|
|
2107
|
-
(
|
|
2108
|
-
// '?' is not mentioned in code completion, see errorStrategy.js#intervalSetToArray
|
|
2109
|
-
q='?' { this.pushXprToken( $args ); }
|
|
2110
|
-
e2=expression { $args.push($e2.expr); }
|
|
2111
|
-
colon=':' { this.pushXprToken( $args ); }
|
|
2112
|
-
e3=expression { $args.push($e3.expr); }
|
|
2113
|
-
)?
|
|
2114
|
-
;
|
|
2115
|
-
|
|
2116
|
-
conditionOr returns [ cond ] locals [ args = [], orl = [] ]
|
|
2117
|
-
@after{ $cond = this.argsExpression( $args, 'or' ); }
|
|
2118
|
-
:
|
|
2119
|
-
c1=conditionAnd { $args.push($c1.cond); }
|
|
2120
|
-
(
|
|
2121
|
-
or=OR { this.pushXprToken( $args ); }
|
|
2122
|
-
c2=conditionAnd { $args.push($c2.cond); }
|
|
2123
|
-
)*
|
|
2124
|
-
;
|
|
2125
|
-
|
|
2126
|
-
conditionAnd returns [ cond ] locals[ args = [] ]
|
|
2127
|
-
@after{ $cond = this.argsExpression( $args, 'and' ); } // 'and' used by A2J and checks
|
|
2128
|
-
:
|
|
2129
|
-
c1=conditionTerm { $args.push($c1.cond); }
|
|
2130
|
-
(
|
|
2131
|
-
and=AND { this.pushXprToken( $args ); }
|
|
2132
|
-
c2=conditionTerm { $args.push($c2.cond); }
|
|
2133
|
-
)*
|
|
2134
|
-
;
|
|
2135
|
-
|
|
2136
|
-
// Note: New operators need to be added to functionExpressionOperatorsRequireParentheses[] in toCdl.js.
|
|
2137
|
-
conditionTerm returns [ cond ] locals[ args = [] ]
|
|
2138
|
-
@after{ $cond = this.argsExpression( $args, '=' ); }// op: '=' (not nary) used by A2J and checks
|
|
2139
|
-
:
|
|
2140
|
-
nt=NOT { this.pushXprToken( $args ); }
|
|
2141
|
-
ct=conditionTerm { $args.push( $ct.cond ); }
|
|
2142
|
-
|
|
|
2143
|
-
EXISTS { this.pushXprToken( $args ); }
|
|
2144
|
-
(
|
|
2145
|
-
open='(' qe=queryExpression close=')'
|
|
2146
|
-
{ $args.push( this.surroundByParens( $qe.query, $open, $close, true ) ); }
|
|
2147
|
-
|
|
|
2148
|
-
qm=( HideAlternatives | '?' )
|
|
2149
|
-
{ $args.push( { param: this.valueWithTokenLocation( '?', $qm ), scope: 'param' } );
|
|
2150
|
-
this.csnParseOnly( 'syntax-unsupported-param', [ $qm ], { '#': 'dynamic', code: '?' } );
|
|
2151
|
-
}
|
|
2152
|
-
|
|
|
2153
|
-
ep=valuePath[ 'ref' ] { $args.push( $ep.qp ); }
|
|
2154
|
-
{ $ep.qp['$'+'expected'] = 'exists'; } // hm, really in parser? what about CSN input?
|
|
2155
|
-
)
|
|
2156
|
-
|
|
|
2157
|
-
expr=expression { $args.push( $expr.expr ); }
|
|
2158
|
-
(
|
|
2159
|
-
( '=' | '<>' | '>' | '>=' | '<' | '<=' | '!=' ) { this.pushXprToken( $args ); }
|
|
2160
|
-
( ( ANY | SOME | ALL ) { this.pushXprToken( $args ); } )?
|
|
2161
|
-
e2=expression { $args.push( $e2.expr ); }
|
|
2162
|
-
|
|
|
2163
|
-
IS { this.pushXprToken( $args ); }
|
|
2164
|
-
( NOT { this.pushXprToken( $args ); } )?
|
|
2165
|
-
NULL { this.pushXprToken( $args ); }
|
|
2166
|
-
|
|
|
2167
|
-
NOT { this.pushXprToken( $args ); }
|
|
2168
|
-
predicate[ $args ]
|
|
2169
|
-
|
|
|
2170
|
-
predicate[ $args ]
|
|
2171
|
-
)? // optional: for conditions in parentheses
|
|
2172
|
-
;
|
|
2173
|
-
|
|
2174
|
-
// Note: New operators need to be added to functionExpressionOperatorsRequireParentheses[] in toCdl.js.
|
|
2175
|
-
predicate[ args ]
|
|
2176
|
-
:
|
|
2177
|
-
IN { this.pushXprToken( $args ); }
|
|
2178
|
-
// TODO: do we really allow it not to start with `(`? - TODO: try with warning
|
|
2179
|
-
e1=expression { $args.push( this.secureParens( $e1.expr ) ); } // including ExpressionList
|
|
2180
|
-
|
|
|
2181
|
-
BETWEEN { this.pushXprToken( $args ); }
|
|
2182
|
-
e2=expression { $args.push( $e2.expr ); }
|
|
2183
|
-
AND { this.pushXprToken( $args ); }
|
|
2184
|
-
e3=expression { $args.push( $e3.expr ); }
|
|
2185
|
-
|
|
|
2186
|
-
LIKE { this.pushXprToken( $args ); }
|
|
2187
|
-
e4=expression { $args.push( $e4.expr ); }
|
|
2188
|
-
( ESCAPE { this.pushXprToken( $args ); }
|
|
2189
|
-
e5=expression { $args.push( $e5.expr ); }
|
|
2190
|
-
)?
|
|
2191
|
-
;
|
|
2192
|
-
|
|
2193
|
-
expression returns [ expr ] locals [ args = [] ]
|
|
2194
|
-
@after{ $expr = this.argsExpression( $args, true ); }
|
|
2195
|
-
:
|
|
2196
|
-
e1=expressionSum { $args.push( $e1.expr ); }
|
|
2197
|
-
(
|
|
2198
|
-
'||' { this.pushXprToken( $args ); }
|
|
2199
|
-
e2=expressionSum { $args.push( $e2.expr ); }
|
|
2200
|
-
)*
|
|
2201
|
-
;
|
|
2202
|
-
|
|
2203
|
-
expressionSum returns [ expr ] locals [ args = [] ]
|
|
2204
|
-
@after{ $expr = this.argsExpression( $args, true ); }
|
|
2205
|
-
:
|
|
2206
|
-
e1=expressionFactor { $args.push( $e1.expr ); }
|
|
2207
|
-
(
|
|
2208
|
-
( '+' | '-' ) { this.pushXprToken( $args ); }
|
|
2209
|
-
e2=expressionFactor { $args.push( $e2.expr ); }
|
|
2210
|
-
)*
|
|
2211
|
-
;
|
|
2212
|
-
|
|
2213
|
-
expressionFactor returns [ expr ] locals [ args = [] ]
|
|
2214
|
-
@after{ $expr = this.argsExpression( $args, true ); }
|
|
2215
|
-
:
|
|
2216
|
-
e1=expressionTerm { $args.push( $e1.expr ); }
|
|
2217
|
-
(
|
|
2218
|
-
( '*' | '/' ) { this.pushXprToken( $args ); }
|
|
2219
|
-
e2=expressionTerm { $args.push( $e2.expr ); }
|
|
2220
|
-
)*
|
|
2221
|
-
;
|
|
2222
|
-
|
|
2223
|
-
expressionTerm returns [ expr ] locals [ args = [] ]
|
|
2224
|
-
@after{ /* #ATN 1 */ $expr = this.argsExpression( $args, false ); }
|
|
2225
|
-
:
|
|
2226
|
-
( '+' | '-' ) { this.pushXprToken( $args ); }
|
|
2227
|
-
e1=expressionTerm // prefix op or part of the number
|
|
2228
|
-
{ this.signedExpression( $args, $e1.expr ); }
|
|
2229
|
-
|
|
|
2230
|
-
val=literalValue { $args.push( $val.val ); }
|
|
2231
|
-
|
|
|
2232
|
-
sf=specialFunction { $args.push( $sf.ret ); }
|
|
2233
|
-
|
|
|
2234
|
-
CASE { this.pushXprToken( $args ); }
|
|
2235
|
-
(
|
|
2236
|
-
e2=expression { $args.push( $e2.expr ); }
|
|
2237
|
-
( WHEN { this.pushXprToken( $args ); }
|
|
2238
|
-
ew=expression { $args.push( $ew.expr ); }
|
|
2239
|
-
THEN { this.pushXprToken( $args ); }
|
|
2240
|
-
e3=expression { $args.push( $e3.expr ); }
|
|
2241
|
-
)+
|
|
2242
|
-
|
|
|
2243
|
-
(
|
|
2244
|
-
WHEN { this.pushXprToken( $args ); }
|
|
2245
|
-
c=condition { $args.push( $c.cond ); }
|
|
2246
|
-
THEN { this.pushXprToken( $args ); }
|
|
2247
|
-
e3=expression { $args.push( $e3.expr ); }
|
|
2248
|
-
)+
|
|
2249
|
-
)
|
|
2250
|
-
(
|
|
2251
|
-
ELSE { this.pushXprToken( $args ); }
|
|
2252
|
-
e4=expression { $args.push( $e4.expr ); }
|
|
2253
|
-
)?
|
|
2254
|
-
END { this.pushXprToken( $args ); }
|
|
2255
|
-
|
|
|
2256
|
-
ne=NEW { this.pushXprToken( $args ); } // token rewrite for NEW
|
|
2257
|
-
nqp=valuePath[ 'ref', null ]
|
|
2258
|
-
{ $args.push( this.valuePathAst( $nqp.qp ) ); }
|
|
2259
|
-
{ this.fixNewKeywordPlacement( $args ); }
|
|
2260
|
-
|
|
|
2261
|
-
vp=valuePath[ 'ref', null ] { $args.push( this.valuePathAst( $vp.qp ) ); }
|
|
2262
|
-
{ this.setLocalTokenIfBefore( 'OVER', 'OVER', /^\($/i ); }
|
|
2263
|
-
(
|
|
2264
|
-
{ $args[0].suffix = []; }
|
|
2265
|
-
OVER { this.pushXprToken( $args[0].suffix ); }
|
|
2266
|
-
open='(' over=overClause close=')'
|
|
2267
|
-
{ $args[0].suffix.push( this.surroundByParens( $over.over, $open, $close ) ); }
|
|
2268
|
-
)?
|
|
2269
|
-
|
|
|
2270
|
-
colon=':' { this.reportUnexpectedSpace( $colon ); }
|
|
2271
|
-
(
|
|
2272
|
-
vp=valuePath[ 'paramref', this.startLocation() ]
|
|
2273
|
-
{{ const par = $vp.qp;; par.scope = 'param';; $args.push( par ); }}
|
|
2274
|
-
|
|
|
2275
|
-
pp=Number
|
|
2276
|
-
// TODO: no extra XSN property `param` for this, re-use `val`
|
|
2277
|
-
{ $args.push( { param: this.numberLiteral( $pp ), scope: 'param' } );
|
|
2278
|
-
this.csnParseOnly( 'syntax-unsupported-param', [ $pp ], { '#': 'positional', code: ':' + $pp.text } );
|
|
2279
|
-
}
|
|
2280
|
-
)
|
|
2281
|
-
|
|
|
2282
|
-
qm= '?' // is automatically not mentioned as CC candidate
|
|
2283
|
-
// if we have an HideAlternatives here, we would block it to use it in
|
|
2284
|
-
// parallel to an expression (would produce adaptivePredict() otherwise)
|
|
2285
|
-
// TODO: no extra XSN property `param` for this, re-use `val`
|
|
2286
|
-
{ $args.push( { param: this.valueWithTokenLocation( '?', $qm ), scope: 'param' } );
|
|
2287
|
-
this.csnParseOnly( 'syntax-unsupported-param', [ $qm ], { '#': 'dynamic', code: '?' } );
|
|
2288
|
-
}
|
|
2289
|
-
|
|
|
2290
|
-
open='('
|
|
2291
|
-
// #ATN: The following alternative is not LL1, because both can start with
|
|
2292
|
-
// left-paren, but queryExpression has SELECT after initial left-parens
|
|
2293
|
-
(
|
|
2294
|
-
qe=queryExpression close=')'
|
|
2295
|
-
{ $args.push( this.surroundByParens( $qe.query, $open, $close, true ) ); }
|
|
2296
|
-
|
|
|
2297
|
-
c1=condition { $args = [ $c1.cond ]; }
|
|
2298
|
-
( ',' { if ($args.length > 1 && this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
2299
|
-
cn=expression { if ($cn.expr) $args.push($cn.expr); }
|
|
2300
|
-
)*
|
|
2301
|
-
close=')'
|
|
2302
|
-
{
|
|
2303
|
-
if ($args.length > 1)
|
|
2304
|
-
$args = [ { op: this.valueWithTokenLocation( 'list', $open ), args: $args,
|
|
2305
|
-
location: this.tokenLocation( $open, $close ) } ];
|
|
2306
|
-
else if ($args[0]) // can be `null` if condition failed to parse
|
|
2307
|
-
$args = [ this.surroundByParens( $args[0], $open, $close ) ];
|
|
2308
|
-
}
|
|
2309
|
-
)
|
|
2310
|
-
;
|
|
2311
|
-
|
|
2312
|
-
specialFunction returns [ ret = {} ] locals[ art = new parser.XsnArtifact() ]
|
|
2313
|
-
:
|
|
2314
|
-
ca=CAST '(' // see createArray() in action
|
|
2315
|
-
{
|
|
2316
|
-
$ret = {
|
|
2317
|
-
op: this.valueWithTokenLocation( 'cast', $ca ),
|
|
2318
|
-
args: this.createArray(),
|
|
2319
|
-
location: this.tokenLocation( $ca )
|
|
2320
|
-
};
|
|
2321
|
-
}
|
|
2322
|
-
e=expression AS typeRefOptArgs[ $ret ]
|
|
2323
|
-
{
|
|
2324
|
-
$ret.args.push( $e.expr );
|
|
2325
|
-
}
|
|
2326
|
-
')' { this.finalizeDictOrArray( $ret.args ); }
|
|
2327
|
-
;
|
|
2328
|
-
|
|
2329
|
-
// Paths and functions: ---------------------------------------------------------
|
|
2330
|
-
|
|
2331
|
-
simplePath[ art, category ] locals[ _sync = 'nop' ]
|
|
2332
|
-
@after { this.attachLocation($art); }
|
|
2333
|
-
// Due to error recovery, rule `ident` can return with value `null`. Set the
|
|
2334
|
-
// path as broken in this case.
|
|
2335
|
-
:
|
|
2336
|
-
head=ident[ $category ]
|
|
2337
|
-
{ if (!$art.path) $art.path = []; this.pushIdent( $art.path, $head.id ); }
|
|
2338
|
-
(
|
|
2339
|
-
'.' tail=ident[ $category ] { this.pushIdent( $art.path, $tail.id ); }
|
|
2340
|
-
)*
|
|
2341
|
-
;
|
|
2342
|
-
|
|
2343
|
-
valuePath[ category, location = null ] returns[ qp = { path: [] } ] locals[ _sync = 'nop' ]
|
|
2344
|
-
@init { $qp.location = location || this.startLocation(); }
|
|
2345
|
-
@after{ this.attachLocation($qp); }
|
|
2346
|
-
:
|
|
2347
|
-
id=ident[ $category ]
|
|
2348
|
-
{ this.pushIdent( $qp.path, $id.id ); }
|
|
2349
|
-
( pathArguments[ $id.id, $id.id ] cardinalityAndFilter[ $id.id ]?
|
|
2350
|
-
| cardinalityAndFilter[ $id.id ]
|
|
2351
|
-
)?
|
|
2352
|
-
(
|
|
2353
|
-
'.' id=ident['ref'] // yes 'ref', not $category
|
|
2354
|
-
{ this.pushIdent( $qp.path, $id.id ); }
|
|
2355
|
-
( pathArguments[ $id.id ] cardinalityAndFilter[ $id.id ]?
|
|
2356
|
-
| cardinalityAndFilter[ $id.id ]
|
|
2357
|
-
)?
|
|
2358
|
-
)*
|
|
2359
|
-
;
|
|
2360
|
-
|
|
2361
|
-
pathArguments[ pathStep, considerSpecial ]
|
|
2362
|
-
@init{
|
|
2363
|
-
if (!$pathStep) $pathStep = {}; // grammar robustness, see test/negative/parser/NamedExpression.cds
|
|
2364
|
-
this.genericFunctionsStack.push( this['$'+'genericKeywords'] );
|
|
2365
|
-
}
|
|
2366
|
-
:
|
|
2367
|
-
{ this.excludeExpected([ 'ORDER' ]); }
|
|
2368
|
-
'(' // dict or array, see below
|
|
2369
|
-
// Make sure that we do not introduce A:B paths in expressions!
|
|
2370
|
-
// Need to avoid adaptPredict(), otherwise Generic keywords won't work in funcExpression
|
|
2371
|
-
//
|
|
2372
|
-
// For code completion, we need to handle generic tokens directly after the
|
|
2373
|
-
// '('. To avoid invalidating an assoc `trim` to an entity with parameter
|
|
2374
|
-
// `leading` (ok, a bit constructed), we do not do it with named parameters.
|
|
2375
|
-
{ if (!this.setLocalTokenForId( 2, { ':': 'HelperToken1', '=>': 'HelperToken2' } ))
|
|
2376
|
-
this.prepareGenericKeywords( $considerSpecial ); }
|
|
2377
|
-
(
|
|
2378
|
-
{ $pathStep.args = this.createDict(); $pathStep['$'+'syntax'] = ':'; }
|
|
2379
|
-
id=HelperToken1 ':'
|
|
2380
|
-
namedExpression[ $pathStep, this.identAst( $id, 'paramname', true ) ]
|
|
2381
|
-
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
2382
|
-
name=ident['paramname'] ':'
|
|
2383
|
-
namedExpression[ $pathStep, $name.id ]
|
|
2384
|
-
)*
|
|
2385
|
-
|
|
|
2386
|
-
{ $pathStep.args = this.createDict(); } // TODO: XSN func path cleanup
|
|
2387
|
-
id=HelperToken2 '=>'
|
|
2388
|
-
namedExpression[ $pathStep, this.identAst( $id, 'paramname', true ) ]
|
|
2389
|
-
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
2390
|
-
name=ident['paramname'] '=>'
|
|
2391
|
-
namedExpression[ $pathStep, $name.id ]
|
|
2392
|
-
)*
|
|
2393
|
-
|
|
|
2394
|
-
{ $pathStep.args = this.createArray(); }
|
|
2395
|
-
funcExpression[ $pathStep, $considerSpecial ]
|
|
2396
|
-
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
2397
|
-
funcExpression[ $pathStep, $considerSpecial ]
|
|
2398
|
-
)*
|
|
2399
|
-
// Note: We can't move this into funcExpression, or we would increase the ATN count because of `,` amiguity.
|
|
2400
|
-
( ob=funcOrderByClause[ [ $pathStep.args[$pathStep.args.length - 1] ] ]
|
|
2401
|
-
// Remove the last entry which was copied to $ob.expr and push $ob.expr:
|
|
2402
|
-
{ $pathStep.args[$pathStep.args.length - 1] = $ob.expr; }
|
|
2403
|
-
)?
|
|
2404
|
-
|
|
|
2405
|
-
{ $pathStep.args = this.createArray(); }
|
|
2406
|
-
)
|
|
2407
|
-
')' { this.finalizeDictOrArray( $pathStep.args ); }
|
|
2408
|
-
;
|
|
2409
|
-
finally { // see @init
|
|
2410
|
-
if (!$pathStep.args) $pathStep.args = [];
|
|
2411
|
-
this['$'+'genericKeywords'] = this.genericFunctionsStack.pop();
|
|
2412
|
-
}
|
|
2413
|
-
|
|
2414
|
-
namedExpression[ pathStep, id ]
|
|
2415
|
-
:
|
|
2416
|
-
elem=expression
|
|
2417
|
-
{ if ($pathStep && $id) {
|
|
2418
|
-
this.addDef( ($ctx.elem && $elem.expr) ? $elem.expr : { location: $id.location },
|
|
2419
|
-
$pathStep, 'args', 0, $id );
|
|
2420
|
-
}
|
|
2421
|
-
}
|
|
2422
|
-
;
|
|
2423
|
-
|
|
2424
|
-
funcExpression[ pathStep, considerSpecial ] locals[ args = [] ]
|
|
2425
|
-
@init { this.prepareGenericKeywords( $considerSpecial ); }
|
|
2426
|
-
@after{ $pathStep.args.push( this.argsExpression( $args, false ) ); }
|
|
2427
|
-
:
|
|
2428
|
-
(
|
|
2429
|
-
expr=expression
|
|
2430
|
-
{ $args.push( $expr.expr ); }
|
|
2431
|
-
|
|
|
2432
|
-
GenericExpr // keyword as replacement for expression, like '*'
|
|
2433
|
-
{ this.pushXprToken( $args ); }
|
|
2434
|
-
|
|
|
2435
|
-
GenericIntro // keyword as introduction of expression, like DISTINCT
|
|
2436
|
-
{ this.pushXprToken( $args ); }
|
|
2437
|
-
expr=expression { $args.push( $expr.expr ); }
|
|
2438
|
-
|
|
|
2439
|
-
// Rule 'pathArguments' makes a decision based on the first two lookahead
|
|
2440
|
-
// tokens of this rule → we need to list tokens which would be changed to
|
|
2441
|
-
// GenericExpr or GenericIntro, and are not already covered by 'expression'
|
|
2442
|
-
{ this.reportErrorForGenericKeyword(); }
|
|
2443
|
-
( HideAlternatives | '*' | ALL | DISTINCT ) { this.pushXprToken( $args ); }
|
|
2444
|
-
// now continue parsing like GenericExpr:
|
|
2445
|
-
)
|
|
2446
|
-
(
|
|
2447
|
-
(
|
|
2448
|
-
{ this.prepareGenericKeywords( $considerSpecial, 'separator' ); }
|
|
2449
|
-
(
|
|
2450
|
-
GenericSeparator
|
|
2451
|
-
|
|
|
2452
|
-
// For ANTLR's lookahead calculations, we need to list tokens here
|
|
2453
|
-
// which could be changed to GenericSeparator. Do not invent a
|
|
2454
|
-
// keyword token which is just used here (Identifier does work
|
|
2455
|
-
// perfectly)! If we want, we could add all non-reserved keywords
|
|
2456
|
-
// except ORDER, and most reserved.
|
|
2457
|
-
{ this.reportErrorForGenericKeyword(); }
|
|
2458
|
-
( HideAlternatives | Identifier | FROM | IN | WITH | GROUP )
|
|
2459
|
-
)
|
|
2460
|
-
{ this.pushXprToken( $args );
|
|
2461
|
-
this.prepareGenericKeywords( $considerSpecial, 'expr' ); }
|
|
2462
|
-
(
|
|
2463
|
-
expr=expression { $args.push( $expr.expr ); }
|
|
2464
|
-
|
|
|
2465
|
-
GenericExpr { this.pushXprToken( $args ); }
|
|
2466
|
-
|
|
|
2467
|
-
{ this.reportErrorForGenericKeyword(); }
|
|
2468
|
-
// Again, we need to list tokens which could make it to GenericExpr
|
|
2469
|
-
// and which do not start an expression
|
|
2470
|
-
( HideAlternatives | ALL ) { this.pushXprToken( $args ); }
|
|
2471
|
-
)
|
|
2472
|
-
)+
|
|
2473
|
-
)?
|
|
2474
|
-
;
|
|
2475
|
-
|
|
2476
|
-
overClause returns[ over ] locals[ args = [] ]
|
|
2477
|
-
@after{ $over = this.argsExpression( $args, false ); }
|
|
2478
|
-
:
|
|
2479
|
-
( PARTITION { this.pushXprToken( $args ); } BY { this.pushXprToken( $args ); }
|
|
2480
|
-
pb=partitionByClause { $args.push( $pb.expr ); }
|
|
2481
|
-
)?
|
|
2482
|
-
( ORDER { this.pushXprToken( $args ); } BY { this.pushXprToken( $args ); }
|
|
2483
|
-
ob=exprOrderByClause { $args.push( $ob.expr ); }
|
|
2484
|
-
)?
|
|
2485
|
-
( ROWS { this.pushXprToken( $args ); }
|
|
2486
|
-
wf=windowFrameClause { $args.push( $wf.wf ); }
|
|
2487
|
-
)?
|
|
2488
|
-
;
|
|
2489
|
-
|
|
2490
|
-
partitionByClause returns [ expr ] locals[ args = [] ]
|
|
2491
|
-
@after{ $expr = this.argsExpression( $args, false ); }
|
|
2492
|
-
:
|
|
2493
|
-
e1=expression { $args.push( $e1.expr ); }
|
|
2494
|
-
( ',' { this.pushXprToken( $args ); }
|
|
2495
|
-
en=expression { $args.push( $en.expr ); }
|
|
2496
|
-
)*
|
|
2497
|
-
;
|
|
2498
|
-
|
|
2499
|
-
// ORDER BY clause in generic functions, e.g. `first_value(id order by name)`
|
|
2500
|
-
funcOrderByClause[ args ] returns[ expr ]
|
|
2501
|
-
@after{ $expr = this.argsExpression( $args, false, $args[0]?.location ); }
|
|
2502
|
-
:
|
|
2503
|
-
ORDER { this.pushXprToken( $args ); } BY { this.pushXprToken( $args ); }
|
|
2504
|
-
ob=exprOrderByClause { $args.push( $ob.expr ); }
|
|
2505
|
-
;
|
|
2506
|
-
|
|
2507
|
-
// ORDER BY clause in generic functions or OVER clause
|
|
2508
|
-
exprOrderByClause returns[ expr ] locals[ args = [] ]
|
|
2509
|
-
@after{ $expr = this.argsExpression( $args, false ); }
|
|
2510
|
-
:
|
|
2511
|
-
orderBySpecInExpr[ $args ]
|
|
2512
|
-
( ',' { this.pushXprToken( $args ); } orderBySpecInExpr[ $args ] )*
|
|
2513
|
-
;
|
|
2514
|
-
|
|
2515
|
-
orderBySpecInExpr[ args ]
|
|
2516
|
-
:
|
|
2517
|
-
e=expression { $args.push( $e.expr ); }
|
|
2518
|
-
( ASC { this.pushXprToken( $args ); }
|
|
2519
|
-
| DESC { this.pushXprToken( $args ); }
|
|
2520
|
-
)?
|
|
2521
|
-
( NULLS { this.pushXprToken( $args ); }
|
|
2522
|
-
( FIRST | LAST ) { this.pushXprToken( $args ); }
|
|
2523
|
-
)?
|
|
2524
|
-
;
|
|
2525
|
-
|
|
2526
|
-
windowFrameClause returns[ wf ] locals[ args = [] ]
|
|
2527
|
-
@after{ $wf = this.argsExpression( $args, false ); }
|
|
2528
|
-
:
|
|
2529
|
-
(
|
|
2530
|
-
windowFrameStartSpec[ $args ]
|
|
2531
|
-
|
|
|
2532
|
-
BETWEEN { this.pushXprToken( $args ); }
|
|
2533
|
-
windowFrameBoundSpec[ $args ]
|
|
2534
|
-
AND { this.pushXprToken( $args ); }
|
|
2535
|
-
windowFrameBoundSpec[ $args ]
|
|
2536
|
-
)
|
|
2537
|
-
;
|
|
2538
|
-
|
|
2539
|
-
windowFrameBoundSpec[ args ]
|
|
2540
|
-
:
|
|
2541
|
-
UNBOUNDED { this.pushXprToken( $args ); }
|
|
2542
|
-
( FOLLOWING | PRECEDING ) { this.pushXprToken( $args ); }
|
|
2543
|
-
|
|
|
2544
|
-
n=Number { $args.push( this.numberLiteral( $n ) ); }
|
|
2545
|
-
( FOLLOWING | PRECEDING ) { this.pushXprToken( $args ); }
|
|
2546
|
-
|
|
|
2547
|
-
CURRENT { this.pushXprToken( $args ); } ROW { this.pushXprToken( $args ); }
|
|
2548
|
-
;
|
|
2549
|
-
|
|
2550
|
-
windowFrameStartSpec[ args = [] ]
|
|
2551
|
-
:
|
|
2552
|
-
UNBOUNDED { this.pushXprToken( $args ); }
|
|
2553
|
-
PRECEDING { this.pushXprToken( $args ); }
|
|
2554
|
-
|
|
|
2555
|
-
n=Number { $args.push( this.numberLiteral( $n ) ); }
|
|
2556
|
-
PRECEDING { this.pushXprToken( $args ); }
|
|
2557
|
-
|
|
|
2558
|
-
CURRENT { this.pushXprToken( $args ); } ROW { this.pushXprToken( $args ); }
|
|
2559
|
-
;
|
|
2560
|
-
|
|
2561
|
-
cardinalityAndFilter[ pathStep ] locals [ _sync = 'nop' ]
|
|
2562
|
-
:
|
|
2563
|
-
{ if (!$pathStep) $pathStep = {}; }
|
|
2564
|
-
openFilter='['
|
|
2565
|
-
optionalCardinality[ pathStep ]?
|
|
2566
|
-
|
|
2567
|
-
filterWhereClause[ $pathStep ] // required, see rule's comment
|
|
2568
|
-
(
|
|
2569
|
-
group=GROUP by=BY
|
|
2570
|
-
e1=expression { $pathStep.groupBy = [ $e1.expr ]; }
|
|
2571
|
-
( ',' en=expression { $pathStep.groupBy.push( $en.expr ); } )*
|
|
2572
|
-
{ this.csnParseOnly('syntax-unexpected-sql-clause', [ $group, $by ], { keyword: 'GROUP BY' }); }
|
|
2573
|
-
)?
|
|
2574
|
-
( hv=HAVING
|
|
2575
|
-
having=condition { $pathStep.having = $having.cond; }
|
|
2576
|
-
{ this.csnParseOnly('syntax-unexpected-sql-clause', [ $hv ], { keyword: 'HAVING' }); }
|
|
2577
|
-
)?
|
|
2578
|
-
( { const orderKw = this._input.LT(1); const byKw = this._input.LT(2); }
|
|
2579
|
-
ob=orderByClause[ $pathStep ] { $pathStep = $ob.query;; }
|
|
2580
|
-
{ this.csnParseOnly('syntax-unexpected-sql-clause', [ orderKw, byKw ], { keyword: 'ORDER BY' }); }
|
|
2581
|
-
)?
|
|
2582
|
-
( { const limit = this._input.LT(1); }
|
|
2583
|
-
lc=limitClause[ $pathStep ] { $pathStep = $lc.query;; }
|
|
2584
|
-
{ this.csnParseOnly('syntax-unexpected-sql-clause', [ limit ], { keyword: 'LIMIT' }); }
|
|
2585
|
-
)?
|
|
2586
|
-
|
|
2587
|
-
closeFilter=']'
|
|
2588
|
-
;
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
optionalCardinality[ pathStep ]
|
|
2592
|
-
@after { if ($pathStep && $pathStep.cardinality) this.attachLocation($pathStep.cardinality); }
|
|
2593
|
-
:
|
|
2594
|
-
// Make sure to test second token to allow expressions starting with Number
|
|
2595
|
-
// without introducing WHERE - that would be @options{k=2}. The code
|
|
2596
|
-
// completion just produces `:` after having inserted a Number - TODO.
|
|
2597
|
-
{ if (this._input.LT(2).text !== ':') return $ctx; }
|
|
2598
|
-
( trgMax=Number ':'
|
|
2599
|
-
{ if ($pathStep) $pathStep.cardinality = { targetMax: this.numberLiteral( $trgMax ), location: this.startLocation() }; }
|
|
2600
|
-
)
|
|
2601
|
-
;
|
|
2602
|
-
|
|
2603
|
-
filterWhereClause[ pathStep ]
|
|
2604
|
-
:
|
|
2605
|
-
// NOTE: Keep in sync with optionalWhereForFilter!
|
|
2606
|
-
//
|
|
2607
|
-
// For ANTLR, WHERE is required, but the generated parser may skip `match(WHERE)` in
|
|
2608
|
-
// `optionalWhereForFilter`. Because `(WHERE cond)?` would invoke adaptive predict,
|
|
2609
|
-
// we use this hack that skips parsing of the condition, if the token is a SQL clause,
|
|
2610
|
-
// but makes Antlr assume that it is required.
|
|
2611
|
-
{
|
|
2612
|
-
const tok = this.getCurrentToken();
|
|
2613
|
-
if (tok.type === languageParser.GROUP
|
|
2614
|
-
|| tok.type === languageParser.ORDER
|
|
2615
|
-
|| tok.type === languageParser.LIMIT
|
|
2616
|
-
|| tok.type === languageParser.HAVING)
|
|
2617
|
-
return $ctx;
|
|
2618
|
-
}
|
|
2619
|
-
optionalWhereForFilter cond=condition { if ($pathStep) $pathStep.where = $cond.cond; }
|
|
2620
|
-
;
|
|
2621
|
-
|
|
2622
|
-
optionalWhereForFilter
|
|
2623
|
-
:
|
|
2624
|
-
// NOTE: only call from rule filterWhereClause!
|
|
2625
|
-
//
|
|
2626
|
-
// For ANTLR, WHERE is required, but we allow the generated parser skipping
|
|
2627
|
-
// the call of match(WHERE). This hack requires that sync() at each state in
|
|
2628
|
-
// the calling rule does not throw an error if the current token does not match
|
|
2629
|
-
// one of the expected ones.
|
|
2630
|
-
{
|
|
2631
|
-
if (this.getCurrentToken().type !== languageParser.WHERE)
|
|
2632
|
-
return $ctx; // TODO: should we somehow add those keywords to $(EXPECTED)?
|
|
2633
|
-
}
|
|
2634
|
-
WHERE
|
|
2635
|
-
;
|
|
2636
|
-
|
|
2637
|
-
// Annotation assignments -------------------------------------------------------
|
|
2638
|
-
|
|
2639
|
-
// We have three versions of the annotation assignment rules:
|
|
2640
|
-
// - "fix": typically after a name if a ':' could follow
|
|
2641
|
-
// - "ll1": typically before keyword+name, after a name if no ':' could follow
|
|
2642
|
-
// - "atn": at the beginning of a column definition
|
|
2643
|
-
//
|
|
2644
|
-
// want to let the ambiguity in select items (solution: "either" possibility)
|
|
2645
|
-
//
|
|
2646
|
-
// entity E @Anno: Base { … }; // Base is include (chosen w/ warning) or @Anno value?
|
|
2647
|
-
// entity V(p) as select from E { // either: anno value "ref p", select item -x
|
|
2648
|
-
// @anno :p - x as x; // or: anno value true, select item :p-x
|
|
2649
|
-
// }
|
|
2650
|
-
|
|
2651
|
-
annotationAssignment_fix[ art ] locals[ assignment ]
|
|
2652
|
-
// value outside @(...)
|
|
2653
|
-
@after {
|
|
2654
|
-
if ($assignment) {
|
|
2655
|
-
this.assignAnnotation( $art, $assignment );
|
|
2656
|
-
this.docComment( $art );
|
|
2657
|
-
}
|
|
2658
|
-
} :
|
|
2659
|
-
at='@' { this.reportUnexpectedSpace( $at ); }
|
|
2660
|
-
(
|
|
2661
|
-
annotationAssignment_paren[ $art ]
|
|
2662
|
-
|
|
|
2663
|
-
{ $assignment = { name: new this.XsnName() }; }
|
|
2664
|
-
annotationPath[ $assignment.name, 'anno' ]
|
|
2665
|
-
( '#' annotationPathVariant[ $assignment.name ] )?
|
|
2666
|
-
{ this.warnIfColonFollows( $assignment ); }
|
|
2667
|
-
)
|
|
2668
|
-
;
|
|
2669
|
-
|
|
2670
|
-
annotationAssignment_ll1[ art ] locals[ assignment ]
|
|
2671
|
-
@after {
|
|
2672
|
-
if ($assignment) {
|
|
2673
|
-
this.assignAnnotation( $art, $assignment );
|
|
2674
|
-
this.docComment( $art );
|
|
2675
|
-
}
|
|
2676
|
-
} :
|
|
2677
|
-
at='@' { this.reportUnexpectedSpace( $at ); }
|
|
2678
|
-
(
|
|
2679
|
-
annotationAssignment_paren[ $art ]
|
|
2680
|
-
|
|
|
2681
|
-
{ $assignment = { name: new this.XsnName() }; }
|
|
2682
|
-
annotationPath[ $assignment.name, 'anno' ]
|
|
2683
|
-
( '#' annotationPathVariant[ $assignment.name ] )?
|
|
2684
|
-
(
|
|
2685
|
-
':' { this.meltKeywordToIdentifier(true); } // allow path as anno value start with reserved
|
|
2686
|
-
val=annoValue[ $assignment ]
|
|
2687
|
-
)?
|
|
2688
|
-
)
|
|
2689
|
-
;
|
|
2690
|
-
|
|
2691
|
-
// Has previously used ATN, now via local token rewrite
|
|
2692
|
-
annotationAssignment_atn[ art ] locals[ assignment ]
|
|
2693
|
-
@after {
|
|
2694
|
-
if ($assignment) {
|
|
2695
|
-
this.assignAnnotation( $art, $assignment );
|
|
2696
|
-
this.docComment( $art );
|
|
2697
|
-
}
|
|
2698
|
-
} :
|
|
2699
|
-
at='@' { this.reportUnexpectedSpace( $at ); }
|
|
2700
|
-
(
|
|
2701
|
-
annotationAssignment_paren[ $art ]
|
|
2702
|
-
|
|
|
2703
|
-
{ $assignment = { name: new this.XsnName() }; }
|
|
2704
|
-
annotationPath[ $assignment.name, 'anno' ]
|
|
2705
|
-
// '#' is in the follow set of this rule, as it is used in rule "selectItemDef"
|
|
2706
|
-
// before an "expression" which can start with a '#' for an enum value
|
|
2707
|
-
// -> used to introduce variant name if and only if in same line as previous token
|
|
2708
|
-
{ this.setLocalToken( '#', 'HelperToken1', null, true ); }
|
|
2709
|
-
( hash=HelperToken1 annotationPathVariant[ $assignment.name ] )?
|
|
2710
|
-
// ':' is in the follow set of this rule, as it is used in rule "selectItemDef"
|
|
2711
|
-
// before an "expression" which can start with a ':' for a parameter reference
|
|
2712
|
-
// -> used to introduce assignment value if and only if in same line as previous token
|
|
2713
|
-
{ this.setLocalToken( ':', 'HelperToken2', null, true ); }
|
|
2714
|
-
( HelperToken2 // ':'
|
|
2715
|
-
{ this.meltKeywordToIdentifier(true); } // allow path as anno value start with reserved
|
|
2716
|
-
(
|
|
2717
|
-
val=annoValueBase[ $assignment ]
|
|
2718
|
-
|
|
|
2719
|
-
atv='@'? annotationPath[ $assignment, 'ref', $atv ]
|
|
2720
|
-
{ this.setLocalToken( '#', 'HelperToken1', null, true ); } // see above
|
|
2721
|
-
( hash=HelperToken1 annotationPathVariant[ $assignment ] )?
|
|
2722
|
-
)
|
|
2723
|
-
)?
|
|
2724
|
-
)
|
|
2725
|
-
;
|
|
2726
|
-
|
|
2727
|
-
annotationAssignment_paren[ art ]
|
|
2728
|
-
:
|
|
2729
|
-
'('
|
|
2730
|
-
// allow completely useless `@()`; no warning anymore - who cares?
|
|
2731
|
-
{
|
|
2732
|
-
if (this.isStraightBefore(')')) {
|
|
2733
|
-
this.matchWildcard(); // we know it is the ')' - we do not reach the final match
|
|
2734
|
-
return $ctx;
|
|
2735
|
-
}
|
|
2736
|
-
this.meltKeywordToIdentifier();
|
|
2737
|
-
}
|
|
2738
|
-
annotationAssignment_1[ $art ]
|
|
2739
|
-
( ','
|
|
2740
|
-
{
|
|
2741
|
-
this.meltKeywordToIdentifier();
|
|
2742
|
-
if (this.isStraightBefore(')')) break; // allow ',' before ')'
|
|
2743
|
-
}
|
|
2744
|
-
annotationAssignment_1[ $art ]
|
|
2745
|
-
)*
|
|
2746
|
-
')'
|
|
2747
|
-
;
|
|
2748
|
-
|
|
2749
|
-
annotationAssignment_1[ art ] locals[ assignment = { name: new parser.XsnName() } ]
|
|
2750
|
-
@after { this.assignAnnotation( $art, $assignment ); }
|
|
2751
|
-
:
|
|
2752
|
-
annotationPath[ $assignment.name, 'anno' ]
|
|
2753
|
-
( '#' annotationPathVariant[ $assignment.name ] )?
|
|
2754
|
-
(
|
|
2755
|
-
':' { this.meltKeywordToIdentifier(true); } // allow path as anno value start with reserved
|
|
2756
|
-
val=annoValue[ $assignment ]
|
|
2757
|
-
)?
|
|
2758
|
-
;
|
|
2759
|
-
|
|
2760
|
-
annotationPath[ art, category, headat = null ] locals[ _sync = 'nop' ]
|
|
2761
|
-
@after { this.attachLocation($art); }
|
|
2762
|
-
// Due to error recovery, rule `ident` can return with value `null`. Set the
|
|
2763
|
-
// path as broken in this case.
|
|
2764
|
-
:
|
|
2765
|
-
head=ident[ $category ]
|
|
2766
|
-
{ $art.path = []; this.pushIdent( $art.path, $head.id, $headat ); }
|
|
2767
|
-
(
|
|
2768
|
-
'.' at='@'? tail=ident[ $category ]
|
|
2769
|
-
{ this.pushIdent( $art.path, $tail.id, $at );
|
|
2770
|
-
// Otherwise, $at may continue to be set after one `.@anno` segment.
|
|
2771
|
-
$ctx.at = null;
|
|
2772
|
-
}
|
|
2773
|
-
)*
|
|
2774
|
-
;
|
|
2775
|
-
|
|
2776
|
-
// Before calling this rule, match '#'
|
|
2777
|
-
annotationPathVariant[ art ] locals[ variant = {} ]
|
|
2778
|
-
@after { this.attachLocation($art); }
|
|
2779
|
-
:
|
|
2780
|
-
{ this.reportUnexpectedSpace();; this.meltKeywordToIdentifier(); }
|
|
2781
|
-
simplePath[ $variant, 'variant' ] { $art.variant = $variant; }
|
|
2782
|
-
;
|
|
2783
|
-
|
|
2784
|
-
annoValue[ assignment ]
|
|
2785
|
-
:
|
|
2786
|
-
base=annoValueBase[ $assignment ]
|
|
2787
|
-
|
|
|
2788
|
-
// no docComment() here
|
|
2789
|
-
// this alternative is done with token rewrite in rule "annotationAssignment_atn"
|
|
2790
|
-
at='@'? annotationPath[ $assignment, 'ref', $at ]
|
|
2791
|
-
( '#' annotationPathVariant[ $assignment ] )?
|
|
2792
|
-
;
|
|
2793
|
-
|
|
2794
|
-
annoValueBase[ assignment ] locals [ seenEllipsis = false ]
|
|
2795
|
-
@after { this.attachLocation( $assignment ); }
|
|
2796
|
-
:
|
|
2797
|
-
'{' // no location here, we flatten
|
|
2798
|
-
{ $assignment['$'+'flatten'] = []; this.meltKeywordToIdentifier(); }
|
|
2799
|
-
flattenedValue[ $assignment ]
|
|
2800
|
-
(
|
|
2801
|
-
',' {
|
|
2802
|
-
this.meltKeywordToIdentifier();
|
|
2803
|
-
if (this.isStraightBefore("}")) break; // allow ',' before ')'
|
|
2804
|
-
}
|
|
2805
|
-
flattenedValue[ $assignment ]
|
|
2806
|
-
)*
|
|
2807
|
-
'}'
|
|
2808
|
-
|
|
|
2809
|
-
'[' // no need for createArray() here, $assignment.location is set
|
|
2810
|
-
{ $assignment.val = []; $assignment.literal = 'array'; }
|
|
2811
|
-
{ this.meltKeywordToIdentifier(true); }
|
|
2812
|
-
(
|
|
2813
|
-
(
|
|
2814
|
-
head=annoSubValue { $assignment.val.push( $head.val ); }
|
|
2815
|
-
|
|
|
2816
|
-
e='...' ( UP TO upTo=annoSubValue )?
|
|
2817
|
-
{{
|
|
2818
|
-
const item = { literal: 'token', val: '...', location: this.tokenLocation($e) };
|
|
2819
|
-
$assignment.val.push( item );
|
|
2820
|
-
if ($ctx.upTo) item.upTo = $upTo.val;
|
|
2821
|
-
$seenEllipsis = !$ctx.upTo || 'upTo';
|
|
2822
|
-
}}
|
|
2823
|
-
)
|
|
2824
|
-
(
|
|
2825
|
-
',' { if (this.isStraightBefore(']')) break; } // allow ',' before ']'
|
|
2826
|
-
{ this.meltKeywordToIdentifier(true); }
|
|
2827
|
-
(
|
|
2828
|
-
tail=annoSubValue { $assignment.val.push( $tail.val ); }
|
|
2829
|
-
|
|
|
2830
|
-
{ $ctx.upTo = null; } // is not reset
|
|
2831
|
-
e='...' ( UP TO upTo=annoSubValue )?
|
|
2832
|
-
{{
|
|
2833
|
-
const item = { literal: 'token', val: '...', location: this.tokenLocation($e) };
|
|
2834
|
-
if ($ctx.upTo) item.upTo = $upTo.val;
|
|
2835
|
-
$assignment.val.push( item );
|
|
2836
|
-
if ($seenEllipsis === true)
|
|
2837
|
-
this.error( 'syntax-unexpected-ellipsis', $e,
|
|
2838
|
-
{ '#': 'duplicate', code: '...', keyword: 'up to' } );
|
|
2839
|
-
else
|
|
2840
|
-
$seenEllipsis = !$ctx.upTo || 'upTo';
|
|
2841
|
-
}}
|
|
2842
|
-
)
|
|
2843
|
-
)*
|
|
2844
|
-
)?
|
|
2845
|
-
cb=']'
|
|
2846
|
-
{
|
|
2847
|
-
if ($seenEllipsis === 'upTo')
|
|
2848
|
-
this.error( 'syntax-missing-ellipsis', $cb, // at closing bracket
|
|
2849
|
-
{ code: '... up to', newcode: '...' } );
|
|
2850
|
-
}
|
|
2851
|
-
|
|
|
2852
|
-
v1=literalValue { Object.assign( $assignment, $v1.val ); }
|
|
2853
|
-
|
|
|
2854
|
-
( plus='+' | min='-' ) num=Number
|
|
2855
|
-
{ Object.assign( $assignment, this.numberLiteral( $num, $plus||$min ) ); }
|
|
2856
|
-
|
|
|
2857
|
-
'('
|
|
2858
|
-
cond=condition // 'condition' is also used in 'expression' inside '()'.
|
|
2859
|
-
// TODO: (1,2,3) not supported, yet, only ((1,2,3)); we could support it via:
|
|
2860
|
-
// (',' condition)*
|
|
2861
|
-
{ this.expressionAsAnnotationValue( $assignment, $ctx.cond ); }
|
|
2862
|
-
')'
|
|
2863
|
-
;
|
|
2864
|
-
|
|
2865
|
-
flattenedValue[ assignment ] locals[ val = { name: new parser.XsnName() } ]
|
|
2866
|
-
:
|
|
2867
|
-
at='@'? annotationPath[ $val.name, 'name', $at ]
|
|
2868
|
-
( '#' annotationPathVariant[ $val.name ] )?
|
|
2869
|
-
(
|
|
2870
|
-
':' { this.meltKeywordToIdentifier(true); } // allow path as anno value start with reserved
|
|
2871
|
-
annoValue[ $val ]
|
|
2872
|
-
)?
|
|
2873
|
-
{ $assignment['$'+'flatten'].push( $val ); }
|
|
2874
|
-
;
|
|
2875
|
-
|
|
2876
|
-
namedValue[ struct ] locals[ val = { name: new parser.XsnName() } ]
|
|
2877
|
-
:
|
|
2878
|
-
at='@'? annotationPath[ $val.name, 'name', $at ]
|
|
2879
|
-
( ':' { this.meltKeywordToIdentifier(true); }
|
|
2880
|
-
sub=annoSubValue { Object.assign( $val, $sub.val ); } )?
|
|
2881
|
-
{
|
|
2882
|
-
if (!$val.location) $val.location = $val.name.location;
|
|
2883
|
-
this.addDef( $val, $struct, 'struct', null, $val.name ); // TODO: re-check name
|
|
2884
|
-
}
|
|
2885
|
-
;
|
|
2886
|
-
|
|
2887
|
-
annoSubValue returns[ val = {} ]
|
|
2888
|
-
@after { this.attachLocation($val); }
|
|
2889
|
-
:
|
|
2890
|
-
'{' // no need for createDict() here, $val.location is set
|
|
2891
|
-
{ $val.struct = Object.create(null); $val.literal = 'struct'; }
|
|
2892
|
-
{ this.meltKeywordToIdentifier(); }
|
|
2893
|
-
namedValue[ $val ]
|
|
2894
|
-
( ','
|
|
2895
|
-
{
|
|
2896
|
-
this.meltKeywordToIdentifier();
|
|
2897
|
-
if (this.isStraightBefore("}")) break; // allow ',' before '}'
|
|
2898
|
-
}
|
|
2899
|
-
namedValue[ $val ]
|
|
2900
|
-
)*
|
|
2901
|
-
'}'
|
|
2902
|
-
|
|
|
2903
|
-
'[' // no need for createArray() here, $val.location is set
|
|
2904
|
-
{ $val.val = []; $val.literal = 'array'; }
|
|
2905
|
-
{ this.meltKeywordToIdentifier(true); }
|
|
2906
|
-
( head=annoSubValue { $val.val.push( $head.val ); }
|
|
2907
|
-
( ',' { if (this.isStraightBefore(']')) break; } // allow ',' before ']'
|
|
2908
|
-
{ this.meltKeywordToIdentifier(true); }
|
|
2909
|
-
tail=annoSubValue { $val.val.push( $tail.val ); }
|
|
2910
|
-
)*
|
|
2911
|
-
)?
|
|
2912
|
-
']'
|
|
2913
|
-
|
|
|
2914
|
-
v1=literalValue { Object.assign( $val, $v1.val ); }
|
|
2915
|
-
|
|
|
2916
|
-
( plus='+' | min='-' ) num=Number
|
|
2917
|
-
{ Object.assign( $val, this.numberLiteral( $num, $plus||$min ) ); }
|
|
2918
|
-
|
|
|
2919
|
-
at='@'? annotationPath[ $val, 'ref', $at ]
|
|
2920
|
-
( '#' annotationPathVariant[ $val ] )?
|
|
2921
|
-
|
|
|
2922
|
-
'('
|
|
2923
|
-
cond=condition
|
|
2924
|
-
{ this.expressionAsAnnotationValue( $val, $ctx.cond ); }
|
|
2925
|
-
')'
|
|
2926
|
-
;
|
|
2927
|
-
|
|
2928
|
-
// Literal values and identifiers -----------------------------------------------
|
|
2929
|
-
|
|
2930
|
-
literalValue returns[ val ] locals[ tok ]
|
|
2931
|
-
@init{ $tok = this.getCurrentToken(); }
|
|
2932
|
-
@after { this.attachLocation($val); }
|
|
2933
|
-
:
|
|
2934
|
-
hash='#' { this.reportUnexpectedSpace( $hash );; this.meltKeywordToIdentifier(); }
|
|
2935
|
-
name=ident['enumref'] // TODO v4: remove from this rule (not in enum!)
|
|
2936
|
-
{ $val = { literal: 'enum', sym: $name.id } }
|
|
2937
|
-
|
|
|
2938
|
-
NULL
|
|
2939
|
-
{ $val = { literal: 'null', val: null }; }
|
|
2940
|
-
|
|
|
2941
|
-
Boolean
|
|
2942
|
-
{ $val = { literal: 'boolean', val: $tok.text.toLowerCase() != 'false' }; }
|
|
2943
|
-
|
|
|
2944
|
-
Number
|
|
2945
|
-
{ $val = this.numberLiteral( $tok, '' ); } // allow float and large number
|
|
2946
|
-
|
|
|
2947
|
-
String
|
|
2948
|
-
{ $val = this.quotedLiteral( $tok, 'string' ); }
|
|
2949
|
-
|
|
|
2950
|
-
QuotedLiteral // x'12', date'...', time'...', timestamp'...'
|
|
2951
|
-
{ $val = this.quotedLiteral( $tok ); }
|
|
2952
|
-
;
|
|
2953
|
-
|
|
2954
|
-
// #IDENT - keep this comment here, used in scripts/linter/lintGrammar.js
|
|
2955
|
-
|
|
2956
|
-
identNoKeyword[ category ] returns[ id ] // for aliases without AS
|
|
2957
|
-
@after{ $id = this.identAst( $stop, $category ); }
|
|
2958
|
-
:
|
|
2959
|
-
Identifier
|
|
2960
|
-
;
|
|
2961
|
-
|
|
2962
|
-
// The `ident` rule matches `Identifier` and all non-reserved keywords. List
|
|
2963
|
-
// all non-reserved keywords directly, do not use an indirection via a rule
|
|
2964
|
-
// like `nonReservedKeywords`.
|
|
2965
|
-
ident[ category ] returns[ id ]
|
|
2966
|
-
@after{ $id = this.identAst( $stop, $category ); }
|
|
2967
|
-
:
|
|
2968
|
-
Identifier
|
|
2969
|
-
| ABSTRACT
|
|
2970
|
-
| ACTION
|
|
2971
|
-
| ACTIONS
|
|
2972
|
-
| AND
|
|
2973
|
-
| ANNOTATE
|
|
2974
|
-
| ANNOTATION
|
|
2975
|
-
| ARRAY
|
|
2976
|
-
| ASC
|
|
2977
|
-
| ASPECT
|
|
2978
|
-
| ASSOCIATION
|
|
2979
|
-
| BETWEEN
|
|
2980
|
-
| COLUMNS
|
|
2981
|
-
| COMPOSITION
|
|
2982
|
-
| CONTEXT
|
|
2983
|
-
| CROSS
|
|
2984
|
-
| CURRENT
|
|
2985
|
-
| DEFAULT
|
|
2986
|
-
| DEFINE
|
|
2987
|
-
| DEFINITIONS
|
|
2988
|
-
| DESC
|
|
2989
|
-
| ELEMENTS
|
|
2990
|
-
| ELSE
|
|
2991
|
-
| END
|
|
2992
|
-
| ENTITY
|
|
2993
|
-
| ENUM
|
|
2994
|
-
| ESCAPE
|
|
2995
|
-
| EVENT
|
|
2996
|
-
| EXACT
|
|
2997
|
-
| EXCEPT
|
|
2998
|
-
| EXCLUDING
|
|
2999
|
-
| EXTEND
|
|
3000
|
-
| FIRST
|
|
3001
|
-
| FLOATING
|
|
3002
|
-
| FOLLOWING
|
|
3003
|
-
| FULL
|
|
3004
|
-
| FUNCTION
|
|
3005
|
-
| GROUP
|
|
3006
|
-
| HAVING
|
|
3007
|
-
| INNER
|
|
3008
|
-
| INTERSECT
|
|
3009
|
-
| INTO
|
|
3010
|
-
| IS
|
|
3011
|
-
| JOIN
|
|
3012
|
-
| LAST
|
|
3013
|
-
| LEFT
|
|
3014
|
-
| LIKE
|
|
3015
|
-
| LIMIT
|
|
3016
|
-
| LOCALIZED
|
|
3017
|
-
| MANY
|
|
3018
|
-
| MINUS
|
|
3019
|
-
| MIXIN
|
|
3020
|
-
| NAMESPACE
|
|
3021
|
-
| NULLS
|
|
3022
|
-
| OFFSET
|
|
3023
|
-
| ONE
|
|
3024
|
-
| OR
|
|
3025
|
-
| ORDER
|
|
3026
|
-
| OUTER
|
|
3027
|
-
| PARAMETERS
|
|
3028
|
-
| PARTITION
|
|
3029
|
-
| PRECEDING
|
|
3030
|
-
| PROJECTION
|
|
3031
|
-
| REDIRECTED
|
|
3032
|
-
| RETURNS
|
|
3033
|
-
| RIGHT
|
|
3034
|
-
| ROW
|
|
3035
|
-
| ROWS
|
|
3036
|
-
| STORED
|
|
3037
|
-
| SERVICE
|
|
3038
|
-
| THEN
|
|
3039
|
-
| UNION
|
|
3040
|
-
| UP
|
|
3041
|
-
| TO
|
|
3042
|
-
| TYPE
|
|
3043
|
-
| USING
|
|
3044
|
-
| UNBOUNDED
|
|
3045
|
-
| VARIABLE
|
|
3046
|
-
| VIEW
|
|
3047
|
-
;
|
|
3048
|
-
|
|
3049
|
-
// LEXER ------------------------------------------------------------------------
|
|
3050
|
-
|
|
3051
|
-
WhiteSpace // like \s in JavaScript RegExp
|
|
3052
|
-
: // LineTerminator | [\t\f\v\u00A0\uFEFF] | Zs
|
|
3053
|
-
[\r\n\u2028\u2029 \t\f\u000B\u00A0\u1680\u180e\u2000-\u200A\u202F\u205F\u3000\uFEFF]+
|
|
3054
|
-
-> skip ;
|
|
3055
|
-
|
|
3056
|
-
DocComment : '/**' .*? '*/' -> channel(HIDDEN);
|
|
3057
|
-
|
|
3058
|
-
Comment : '/*' .*? '*/' -> channel(HIDDEN);
|
|
3059
|
-
|
|
3060
|
-
LineComment : '//' ~[\r\n\u2028\u2029]* -> channel(HIDDEN);
|
|
3061
|
-
|
|
3062
|
-
// Literal values ---------------------------------------------------------------
|
|
3063
|
-
|
|
3064
|
-
// for syntactic code-completion: Combine all three string styles
|
|
3065
|
-
// Note: Use rule `string` instead as that also parses escape sequences! (TODO: ???)
|
|
3066
|
-
String : SingleLineString
|
|
3067
|
-
| MultiLineString
|
|
3068
|
-
| MutlLineStringBlock;
|
|
3069
|
-
|
|
3070
|
-
fragment SingleLineString
|
|
3071
|
-
:
|
|
3072
|
-
// \u0027 = '\''
|
|
3073
|
-
// \u2028 = LS (Line Separator)
|
|
3074
|
-
// \u2029 = PS (Paragraph Separator)
|
|
3075
|
-
( '\'' ~[\u0027\n\r\u2028\u2029]* '\'' )+ //
|
|
3076
|
-
;
|
|
3077
|
-
|
|
3078
|
-
fragment MultiLineString
|
|
3079
|
-
:
|
|
3080
|
-
('`' ( MultiLineStringContentChar | EscapeSequence )* '`' )
|
|
3081
|
-
;
|
|
3082
|
-
|
|
3083
|
-
fragment MutlLineStringBlock
|
|
3084
|
-
:
|
|
3085
|
-
('```' ( MultiLineStringContentChar | EscapeSequence )* '```')
|
|
3086
|
-
;
|
|
3087
|
-
|
|
3088
|
-
fragment EscapeSequence
|
|
3089
|
-
:
|
|
3090
|
-
// we could list each escape sequence explicitly, but we already
|
|
3091
|
-
// decode them in genericAntlrParser.js, so no need to do work twice.
|
|
3092
|
-
'\\' .
|
|
3093
|
-
;
|
|
3094
|
-
|
|
3095
|
-
fragment MultiLineStringContentChar
|
|
3096
|
-
:
|
|
3097
|
-
(~[\u0060\\]) // \u0060 = '`'
|
|
3098
|
-
;
|
|
3099
|
-
|
|
3100
|
-
QuotedLiteral
|
|
3101
|
-
:
|
|
3102
|
-
( [xX] | [dD][aA][tT][eE] | [tT][iI][mM][eE] ( [sS][tT][aA][mM][pP] )? )
|
|
3103
|
-
( '\'' ~[\u0027\n\r\u2028\u2029]* '\'' )+ // \u0027 = '\''
|
|
3104
|
-
;
|
|
3105
|
-
|
|
3106
|
-
// This literal improves error messages for unterminated literals.
|
|
3107
|
-
UnterminatedLiteral
|
|
3108
|
-
:
|
|
3109
|
-
( [xX] | [dD][aA][tT][eE] | [tT][iI][mM][eE] ( [sS][tT][aA][mM][pP] )? )?
|
|
3110
|
-
'\'' ~[\u0027\n\r\u2028\u2029]* // \u0027 = '\''
|
|
3111
|
-
|
|
|
3112
|
-
('`' ( MultiLineStringContentChar | EscapeSequence )* )
|
|
3113
|
-
|
|
|
3114
|
-
('```' ( MultiLineStringContentChar | EscapeSequence )* )
|
|
3115
|
-
;
|
|
3116
|
-
|
|
3117
|
-
UnterminatedDelimitedIdentifier
|
|
3118
|
-
:
|
|
3119
|
-
'"' ~[\u0022\n\r\u2028\u2029]* ( '""' ~[\u0022\n\r\u2028\u2029]* )* // \u0022 = '"'
|
|
3120
|
-
| '![' ~[\u005d\n\r\u2028\u2029]* ( ']]' ~[\u005d\n\r\u2028\u2029]* )* // \u005d = ']'
|
|
3121
|
-
// \u005d = ']'
|
|
3122
|
-
;
|
|
3123
|
-
|
|
3124
|
-
Boolean // TMP?
|
|
3125
|
-
: [tT][rR][uU][eE] | [fF][aA][lL][sS][eE]
|
|
3126
|
-
;
|
|
3127
|
-
|
|
3128
|
-
// Reserved keywords (are case-insensitive): ---------------------------------
|
|
3129
|
-
|
|
3130
|
-
ALL : [aA][lL][lL] ;
|
|
3131
|
-
ANY : [aA][nN][yY] ;
|
|
3132
|
-
AS : [aA][sS] ;
|
|
3133
|
-
BY : [bB][yY] ;
|
|
3134
|
-
CASE : [cC][aA][sS][eE] ;
|
|
3135
|
-
CAST : [cC][aA][sS][tT] ;
|
|
3136
|
-
DISTINCT : [dD][iI][sS][tT][iI][nN][cC][tT] ;
|
|
3137
|
-
EXISTS : [eE][xX][iI][sS][tT][sS] ;
|
|
3138
|
-
// FALSE: see Boolean
|
|
3139
|
-
FROM : [fF][rR][oO][mM] ;
|
|
3140
|
-
IN : [iI][nN] ;
|
|
3141
|
-
KEY : [kK][eE][yY] ;
|
|
3142
|
-
NEW : [nN][eE][wW] ; // token rewrite for NEW -> not reserved (also not in SQL)
|
|
3143
|
-
NOT : [nN][oO][tT] ;
|
|
3144
|
-
NULL : [nN][uU][lL][lL] ;
|
|
3145
|
-
OF : [oO][fF] ;
|
|
3146
|
-
ON : [oO][nN] ;
|
|
3147
|
-
SELECT : [sS][eE][lL][eE][cC][tT] ;
|
|
3148
|
-
SOME : [sS][oO][mM][eE] ;
|
|
3149
|
-
WHEN : [wW][hH][eE][nN] ;
|
|
3150
|
-
// TRUE: see Boolean
|
|
3151
|
-
WHERE : [wW][hH][eE][rR][eE] ;
|
|
3152
|
-
WITH : [wW][iI][tT][hH] ;
|
|
3153
|
-
|
|
3154
|
-
// Fixed Token which is defined DIRECTLY BEFORE the unreserved keywords ------
|
|
3155
|
-
|
|
3156
|
-
Number // DO NOT RENAME OR MOVE THIS RULE !!!
|
|
3157
|
-
: [0-9]+ // no initial sign
|
|
3158
|
-
( '.' [0-9]+ )?
|
|
3159
|
-
( [eE] ('+'|'-')? [0-9]+ )?
|
|
3160
|
-
;
|
|
3161
|
-
|
|
3162
|
-
// Unreserved keywords (are case-insensitive): -------------------------------
|
|
3163
|
-
// Do not add keywords just for specialFunctions!
|
|
3164
|
-
|
|
3165
|
-
ABSTRACT : [aA][bB][sS][tT][rR][aA][cC][tT] ;
|
|
3166
|
-
ACTION : [aA][cC][tT][iI][oO][nN] ;
|
|
3167
|
-
ACTIONS : [aA][cC][tT][iI][oO][nN][sS] ;
|
|
3168
|
-
AND : [aA][nN][dD] ;
|
|
3169
|
-
ANNOTATE : [aA][nN][nN][oO][tT][aA][tT][eE] ;
|
|
3170
|
-
ANNOTATION : [aA][nN][nN][oO][tT][aA][tT][iI][oO][nN] ;
|
|
3171
|
-
ARRAY : [aA][rR][rR][aA][yY] ;
|
|
3172
|
-
ASC : [aA][sS][cC] ;
|
|
3173
|
-
ASPECT : [aA][sS][pP][eE][cC][tT] ;
|
|
3174
|
-
ASSOCIATION : [aA][sS][sS][oO][cC][iI][aA][tT][iI][oO][nN] ;
|
|
3175
|
-
BETWEEN : [bB][eE][tT][wW][eE][eE][nN] ;
|
|
3176
|
-
COLUMNS : [cC][oO][lL][uU][mM][nN][sS];
|
|
3177
|
-
COMPOSITION : [cC][oO][mM][pP][oO][sS][iI][tT][iI][oO][nN] ;
|
|
3178
|
-
CONTEXT : [cC][oO][nN][tT][eE][xX][tT] ;
|
|
3179
|
-
CROSS : [cC][rR][oO][sS][sS] ;
|
|
3180
|
-
CURRENT : [cC][uU][rR][rR][eE][nN][tT] ;
|
|
3181
|
-
DEFAULT : [dD][eE][fF][aA][uU][lL][tT] ;
|
|
3182
|
-
DEFINE : [dD][eE][fF][iI][nN][eE] ;
|
|
3183
|
-
DEFINITIONS : [dD][eE][fF][iI][nN][iI][tT][iI][oO][nN][sS] ;
|
|
3184
|
-
DESC : [dD][eE][sS][cC] ;
|
|
3185
|
-
// ELEMENT : [eE][lL][eE][mM][eE][nN][tT] ;
|
|
3186
|
-
ELEMENTS : [eE][lL][eE][mM][eE][nN][tT][sS] ;
|
|
3187
|
-
ELSE : [eE][lL][sS][eE] ;
|
|
3188
|
-
END : [eE][nN][dD] ;
|
|
3189
|
-
ENTITY : [eE][nN][tT][iI][tT][yY] ;
|
|
3190
|
-
ENUM : [eE][nN][uU][mM] ;
|
|
3191
|
-
EVENT : [eE][vV][eE][nN][tT] ;
|
|
3192
|
-
ESCAPE : [eE][sS][cC][aA][pP][eE] ;
|
|
3193
|
-
EXACT : [eE][xX][aA][cC][tT] ;
|
|
3194
|
-
EXCEPT : [eE][xX][cC][eE][pP][tT] ;
|
|
3195
|
-
EXCLUDING : [eE][xX][cC][lL][uU][dD][iI][nN][gG] ;
|
|
3196
|
-
EXTEND : [eE][xX][tT][eE][nN][dD] ;
|
|
3197
|
-
FIRST : [fF][iI][rR][sS][tT] ;
|
|
3198
|
-
FLOATING : [fF][lL][oO][aA][tT][iI][nN][gG] ;
|
|
3199
|
-
FOLLOWING : [fF][oO][lL][lL][oO][wW][iI][nN][gG] ;
|
|
3200
|
-
FULL : [fF][uU][lL][lL] ;
|
|
3201
|
-
FUNCTION : [fF][uU][nN][cC][tT][iI][oO][nN] ;
|
|
3202
|
-
GROUP : [gG][rR][oO][uU][pP] ;
|
|
3203
|
-
HAVING : [hH][aA][vV][iI][nN][gG] ;
|
|
3204
|
-
INNER : [iI][nN][nN][eE][rR] ;
|
|
3205
|
-
INTERSECT : [iI][nN][tT][eE][rR][sS][eE][cC][tT] ;
|
|
3206
|
-
INTO : [iI][nN][tT][oO] ;
|
|
3207
|
-
IS : [iI][sS] ;
|
|
3208
|
-
JOIN : [jJ][oO][iI][nN] ;
|
|
3209
|
-
LAST : [lL][aA][sS][tT] ;
|
|
3210
|
-
LEFT : [lL][eE][fF][tT] ;
|
|
3211
|
-
LIKE : [lL][iI][kK][eE] ;
|
|
3212
|
-
LIMIT : [lL][iI][mM][iI][tT] ;
|
|
3213
|
-
LOCALIZED: [lL][oO][cC][aA][lL][iI][zZ][eE][dD];
|
|
3214
|
-
MANY : [mM][aA][nN][yY] ;
|
|
3215
|
-
// MASKED : [mM][aA][sS][kK][eE][dD] ;
|
|
3216
|
-
MINUS : [mM][iI][nN][uU][sS] ;
|
|
3217
|
-
MIXIN : [mM][iI][xX][iI][nN] ;
|
|
3218
|
-
NAMESPACE : [nN][aA][mM][eE][sS][pP][aA][cC][eE] ;
|
|
3219
|
-
NULLS : [nN][uU][lL][lL][sS] ;
|
|
3220
|
-
OFFSET : [oO][fF][fF][sS][eE][tT] ;
|
|
3221
|
-
ONE : [oO][nN][eE] ;
|
|
3222
|
-
OR : [oO][rR] ;
|
|
3223
|
-
ORDER : [oO][rR][dD][eE][rR] ;
|
|
3224
|
-
OUTER : [oO][uU][tT][eE][rR] ;
|
|
3225
|
-
// OVER : [oO][vV][eE][rR] ;
|
|
3226
|
-
PARAMETERS : [pP][aA][rR][aA][mM][eE][tT][eE][rR][sS] ;
|
|
3227
|
-
PARTITION: [pP][aA][rR][tT][iI][tT][iI][oO][nN] ;
|
|
3228
|
-
PRECEDING: [pP][rR][eE][cC][eE][dD][iI][nN][gG] ;
|
|
3229
|
-
PROJECTION : [pP][rR][oO][jJ][eE][cC][tT][iI][oO][nN] ;
|
|
3230
|
-
REDIRECTED : [rR][eE][dD][iI][rR][eE][cC][tT][eE][dD] ;
|
|
3231
|
-
RETURNS : [rR][eE][tT][uU][rR][nN][sS] ;
|
|
3232
|
-
RIGHT : [rR][iI][gG][hH][tT] ;
|
|
3233
|
-
ROW : [rR][oO][wW] ;
|
|
3234
|
-
ROWS : [rR][oO][wW][sS] ;
|
|
3235
|
-
SERVICE : [sS][eE][rR][vV][iI][cC][eE] ;
|
|
3236
|
-
STORED : [sS][tT][oO][rR][eE][dD] ;
|
|
3237
|
-
THEN : [tT][hH][eE][nN] ;
|
|
3238
|
-
TO : [tT][oO] ; // or make reserved? (is in SQL-92)
|
|
3239
|
-
TYPE : [tT][yY][pP][eE] ;
|
|
3240
|
-
UNION : [uU][nN][iI][oO][nN] ;
|
|
3241
|
-
UNBOUNDED : [uU][nN][bB][oO][uU][nN][dD][eE][dD] ;
|
|
3242
|
-
UP : [uU][pP] ;
|
|
3243
|
-
USING : [uU][sS][iI][nN][gG] ;
|
|
3244
|
-
VARIABLE : [vV][aA][rR][iI][aA][bB][lL][eE] ;
|
|
3245
|
-
VIEW : [vV][iI][eE][wW] ;
|
|
3246
|
-
// VIRTUAL: [vV][iI][rR][tT][uU][aA][lL] ; see tokens {}
|
|
3247
|
-
|
|
3248
|
-
// Identifiers, must BE LAST, DIRECTLY AFTER the unreserved keywords ---------
|
|
3249
|
-
|
|
3250
|
-
Identifier // DO NOT RENAME OR MOVE THIS RULE !!!
|
|
3251
|
-
: [$_a-zA-Z][$_a-zA-Z0-9]* // i.e. including $param
|
|
3252
|
-
| ( '"' ~[\u0022\n\r\u2028\u2029]* '"' )+ // \u0022 = '"'
|
|
3253
|
-
| '![' ~[\u005d\n\r\u2028\u2029]* ']' ( ']' ~[\u005d\n\r\u2028\u2029]* ']' )* // \u005d = ']'
|
|
3254
|
-
;
|
|
3255
|
-
|
|
3256
|
-
IllegalToken : . ;
|
|
3257
|
-
|
|
3258
|
-
// Local Variables:
|
|
3259
|
-
// c-basic-offset: 2
|
|
3260
|
-
// End:
|