@sap/cds-compiler 2.15.4 → 3.0.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 +33 -1590
- package/bin/cdsc.js +36 -33
- package/doc/CHANGELOG_ARCHIVE.md +1592 -0
- package/doc/CHANGELOG_BETA.md +3 -4
- package/doc/CHANGELOG_DEPRECATED.md +35 -1
- package/doc/{DeprecatedOptions.md → DeprecatedOptions_v2.md} +3 -1
- package/doc/Versioning.md +20 -1
- package/lib/api/.eslintrc.json +2 -2
- package/lib/api/main.js +220 -103
- package/lib/api/options.js +15 -85
- package/lib/api/validate.js +6 -10
- package/lib/base/keywords.js +216 -109
- package/lib/base/message-registry.js +60 -20
- package/lib/base/messages.js +65 -24
- package/lib/base/model.js +44 -2
- package/lib/checks/actionsFunctions.js +7 -5
- package/lib/checks/annotationsOData.js +1 -1
- package/lib/checks/cdsPersistence.js +1 -0
- package/lib/checks/elements.js +6 -6
- package/lib/checks/invalidTarget.js +1 -1
- package/lib/checks/nonexpandableStructured.js +1 -1
- package/lib/checks/queryNoDbArtifacts.js +2 -1
- package/lib/checks/selectItems.js +5 -1
- package/lib/checks/types.js +4 -2
- package/lib/checks/utils.js +2 -2
- package/lib/checks/validator.js +2 -1
- package/lib/compiler/assert-consistency.js +15 -10
- package/lib/compiler/builtins.js +87 -9
- package/lib/compiler/define.js +2 -2
- package/lib/compiler/extend.js +59 -11
- package/lib/compiler/finalize-parse-cdl.js +20 -9
- package/lib/compiler/index.js +25 -11
- package/lib/compiler/moduleLayers.js +7 -0
- package/lib/compiler/populate.js +13 -13
- package/lib/compiler/propagator.js +3 -3
- package/lib/compiler/resolve.js +193 -218
- package/lib/compiler/shared.js +47 -76
- package/lib/compiler/tweak-assocs.js +9 -10
- package/lib/compiler/utils.js +5 -0
- package/lib/edm/csn2edm.js +18 -21
- package/lib/edm/edmPreprocessor.js +25 -30
- package/lib/edm/edmUtils.js +10 -24
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +8 -30
- package/lib/gen/language.tokens +105 -114
- package/lib/gen/languageLexer.interp +1 -34
- package/lib/gen/languageLexer.js +889 -1007
- package/lib/gen/languageLexer.tokens +95 -106
- package/lib/gen/languageParser.js +20632 -22313
- package/lib/json/from-csn.js +56 -49
- package/lib/json/to-csn.js +10 -8
- package/lib/language/antlrParser.js +2 -2
- package/lib/language/docCommentParser.js +61 -38
- package/lib/language/errorStrategy.js +52 -40
- package/lib/language/genericAntlrParser.js +303 -229
- package/lib/language/language.g4 +573 -629
- package/lib/language/multiLineStringParser.js +14 -42
- package/lib/language/textUtils.js +44 -0
- package/lib/main.d.ts +27 -42
- package/lib/main.js +104 -81
- package/lib/model/csnRefs.js +1 -1
- package/lib/model/csnUtils.js +170 -283
- package/lib/model/revealInternalProperties.js +28 -8
- package/lib/model/sortViews.js +32 -31
- package/lib/optionProcessor.js +12 -21
- package/lib/render/.eslintrc.json +1 -1
- package/lib/render/DuplicateChecker.js +4 -7
- package/lib/render/manageConstraints.js +70 -2
- package/lib/render/toCdl.js +334 -339
- package/lib/render/toHdbcds.js +19 -15
- package/lib/render/toRename.js +44 -22
- package/lib/render/toSql.js +53 -51
- package/lib/render/utils/common.js +15 -1
- package/lib/render/utils/sql.js +20 -19
- package/lib/sql-identifier.js +6 -0
- package/lib/transform/db/.eslintrc.json +3 -2
- package/lib/transform/db/cdsPersistence.js +5 -15
- package/lib/transform/db/constraints.js +1 -1
- package/lib/transform/db/expansion.js +7 -6
- package/lib/transform/db/flattening.js +18 -19
- package/lib/transform/db/views.js +3 -3
- package/lib/transform/draft/.eslintrc.json +2 -2
- package/lib/transform/draft/db.js +6 -6
- package/lib/transform/draft/odata.js +6 -7
- package/lib/transform/forHanaNew.js +19 -22
- package/lib/transform/forOdataNew.js +10 -12
- package/lib/transform/localized.js +22 -16
- package/lib/transform/odata/toFinalBaseType.js +10 -10
- package/lib/transform/odata/typesExposure.js +3 -3
- package/lib/transform/odata/utils.js +1 -38
- package/lib/transform/transformUtilsNew.js +63 -77
- package/lib/transform/translateAssocsToJoins.js +2 -2
- package/lib/transform/universalCsn/.eslintrc.json +2 -2
- package/lib/transform/universalCsn/coreComputed.js +11 -6
- package/lib/transform/universalCsn/universalCsnEnricher.js +33 -5
- package/lib/utils/file.js +3 -3
- package/lib/utils/timetrace.js +20 -21
- package/package.json +35 -4
- package/doc/ApiMigration.md +0 -237
- package/doc/CommandLineMigration.md +0 -58
- package/doc/ErrorMessages.md +0 -175
- package/doc/FioriAnnotations.md +0 -94
- package/doc/ODataTransformation.md +0 -273
- package/lib/backends.js +0 -529
- package/lib/fix_antlr4-8_warning.js +0 -56
package/lib/language/language.g4
CHANGED
|
@@ -125,14 +125,17 @@ tokens {
|
|
|
125
125
|
HelperToken1, // used with setLocalToken(), does not appear in messages
|
|
126
126
|
HelperToken2, // used with setLocalToken(), does not appear in messages
|
|
127
127
|
HideAlternatives, // hide alternative tokens (no token seq!)
|
|
128
|
-
|
|
128
|
+
GenericExpr, // via token rewriting according to specialFunctions
|
|
129
|
+
GenericSeparator, // via token rewriting according to specialFunctions
|
|
130
|
+
GenericIntro, // via token rewriting according to specialFunctions
|
|
129
131
|
DOTbeforeBRACE, // via token rewrite
|
|
130
132
|
COMPOSITIONofBRACE // via token rewrite in rule typeAssociationBase
|
|
131
133
|
}
|
|
132
134
|
|
|
133
135
|
// Top-Level -----------------------------------------------------------------
|
|
134
136
|
|
|
135
|
-
start returns [ source
|
|
137
|
+
start returns [ source ] locals [ _sync = 'recover' ]
|
|
138
|
+
@init{ $source = this.createSource(); }
|
|
136
139
|
:
|
|
137
140
|
usingDeclaration[$source]*
|
|
138
141
|
(
|
|
@@ -161,53 +164,46 @@ namespaceDeclaration[ source ] locals[ decl = {} ]
|
|
|
161
164
|
NAMESPACE simplePath[ $decl, 'Namespace' ] ';'
|
|
162
165
|
;
|
|
163
166
|
|
|
164
|
-
usingDeclaration[ source ] locals[ decl ]
|
|
165
|
-
@after {
|
|
167
|
+
usingDeclaration[ source ] locals[ decl = {} ]
|
|
168
|
+
@after { this.attachLocation($decl); }
|
|
166
169
|
:
|
|
170
|
+
{ $decl.location = this.startLocation(); }
|
|
167
171
|
USING
|
|
168
172
|
(
|
|
169
173
|
FROM str=String
|
|
170
|
-
{
|
|
171
|
-
if (!$source.dependencies) $source.dependencies = [];
|
|
172
|
-
$source.dependencies.push( this.quotedLiteral( $str, 'string' ) );
|
|
173
|
-
}
|
|
174
|
+
{ $source.dependencies.push( this.quotedLiteral( $str, 'string' ) ); }
|
|
174
175
|
|
|
|
175
176
|
path=externalPath
|
|
176
|
-
{
|
|
177
|
+
{ this.addItem( $decl, $source, 'usings', 'using' );; $decl.extern = $path.extern; }
|
|
177
178
|
( AS name=ident['Using'] { $decl.name = $name.id; }
|
|
178
179
|
| { this.classifyImplicitName( 'Using' ); }
|
|
179
180
|
)
|
|
180
181
|
( FROM str=String
|
|
181
|
-
{
|
|
182
|
-
if (!$source.dependencies) $source.dependencies = [];
|
|
183
|
-
$source.dependencies.push( $decl.fileDep = this.quotedLiteral( $str, 'string' ) );
|
|
184
|
-
}
|
|
182
|
+
{ $source.dependencies.push( $decl.fileDep = this.quotedLiteral( $str, 'string' ) ); }
|
|
185
183
|
)?
|
|
186
184
|
|
|
|
187
|
-
{
|
|
185
|
+
{ this.addItem( $decl, $source, 'usings', 'using' ); }
|
|
188
186
|
// We could just create "independent" USING declaration, but if we want
|
|
189
187
|
// to have some check in the future whether the external artifacts are
|
|
190
188
|
// really in the FROM source...
|
|
191
|
-
'{'
|
|
189
|
+
'{' { $decl.usings = this.createArray(); }
|
|
192
190
|
innerUsing[ $decl ]
|
|
193
191
|
( ',' { if (this.isStraightBefore("}")) break; } // allow ',' before '}'
|
|
194
192
|
innerUsing[ $decl ] )*
|
|
195
|
-
'}'
|
|
193
|
+
'}' { this.finalizeDictOrArray( $decl.usings ); }
|
|
196
194
|
( FROM str=String
|
|
197
|
-
{
|
|
198
|
-
if (!$source.dependencies) $source.dependencies = [];
|
|
199
|
-
$source.dependencies.push( $decl.fileDep = this.quotedLiteral( $str, 'string' ) );
|
|
200
|
-
}
|
|
195
|
+
{ $source.dependencies.push( $decl.fileDep = this.quotedLiteral( $str, 'string' ) ); }
|
|
201
196
|
)?
|
|
202
197
|
)
|
|
203
198
|
';'
|
|
204
199
|
;
|
|
205
200
|
|
|
206
|
-
innerUsing[ using ] locals[ decl ]
|
|
207
|
-
@after {
|
|
201
|
+
innerUsing[ using ] locals[ decl = {} ]
|
|
202
|
+
@after { this.attachLocation($decl); }
|
|
208
203
|
:
|
|
204
|
+
{ $decl.location = this.startLocation(); }
|
|
209
205
|
path=externalPath
|
|
210
|
-
{
|
|
206
|
+
{ this.addItem( $decl, $using, 'usings', 'using' );; $decl.extern = $path.extern; }
|
|
211
207
|
( AS name=ident['Using'] { $decl.name = $name.id; }
|
|
212
208
|
| { this.classifyImplicitName( 'Using' ); }
|
|
213
209
|
)
|
|
@@ -225,18 +221,18 @@ externalPath returns [ extern = {} ]
|
|
|
225
221
|
// @anno :p - x as x; // or: anno value true, select item :p-x
|
|
226
222
|
// }
|
|
227
223
|
|
|
228
|
-
annotationAssignment_1[
|
|
229
|
-
@after {
|
|
224
|
+
annotationAssignment_1[ art ] locals[ assignment = { name: {} } ]
|
|
225
|
+
@after { this.assignAnnotation( $art, $assignment ); }
|
|
230
226
|
:
|
|
231
227
|
annotationPath[ $assignment.name, 'anno' ]
|
|
232
228
|
annotationPathVariant[ $assignment.name ]?
|
|
233
229
|
(
|
|
234
230
|
':' { this.meltKeywordToIdentifier(true); } // allow path as anno value start with reserved
|
|
235
|
-
val=annoValue
|
|
231
|
+
val=annoValue[ $assignment ]
|
|
236
232
|
)?
|
|
237
233
|
;
|
|
238
234
|
|
|
239
|
-
annotationAssignment_paren[
|
|
235
|
+
annotationAssignment_paren[ art ]
|
|
240
236
|
:
|
|
241
237
|
'('
|
|
242
238
|
// allow completely useless `@()` with a warning, do not offer it for completion
|
|
@@ -251,28 +247,28 @@ annotationAssignment_paren[ annos ]
|
|
|
251
247
|
return $ctx;
|
|
252
248
|
}
|
|
253
249
|
}
|
|
254
|
-
annotationAssignment_1[ $
|
|
250
|
+
annotationAssignment_1[ $art ]
|
|
255
251
|
( ','
|
|
256
252
|
{
|
|
257
253
|
this.meltKeywordToIdentifier();
|
|
258
254
|
if (this.isStraightBefore(')')) break; // allow ',' before ')'
|
|
259
255
|
}
|
|
260
|
-
annotationAssignment_1[ $
|
|
256
|
+
annotationAssignment_1[ $art ]
|
|
261
257
|
)*
|
|
262
258
|
')'
|
|
263
259
|
;
|
|
264
260
|
|
|
265
|
-
annotationAssignment_fix[
|
|
261
|
+
annotationAssignment_fix[ art ] locals[ assignment ]
|
|
266
262
|
// value outside @(...)
|
|
267
263
|
@after {
|
|
268
264
|
if ($assignment) {
|
|
269
|
-
|
|
270
|
-
this.docComment( $
|
|
265
|
+
this.assignAnnotation( $art, $assignment );
|
|
266
|
+
this.docComment( $art );
|
|
271
267
|
}
|
|
272
268
|
} :
|
|
273
269
|
'@'
|
|
274
270
|
(
|
|
275
|
-
annotationAssignment_paren[
|
|
271
|
+
annotationAssignment_paren[ $art ]
|
|
276
272
|
|
|
|
277
273
|
{ $assignment = { name: {} }; }
|
|
278
274
|
annotationPath[ $assignment.name, 'anno' ]
|
|
@@ -287,38 +283,38 @@ annotationAssignment_fix[ annos ] locals[ assignment ]
|
|
|
287
283
|
)
|
|
288
284
|
;
|
|
289
285
|
|
|
290
|
-
annotationAssignment_ll1[
|
|
286
|
+
annotationAssignment_ll1[ art ] locals[ assignment ]
|
|
291
287
|
@after {
|
|
292
288
|
if ($assignment) {
|
|
293
|
-
|
|
294
|
-
this.docComment( $
|
|
289
|
+
this.assignAnnotation( $art, $assignment );
|
|
290
|
+
this.docComment( $art );
|
|
295
291
|
}
|
|
296
292
|
} :
|
|
297
293
|
'@'
|
|
298
294
|
(
|
|
299
|
-
annotationAssignment_paren[
|
|
295
|
+
annotationAssignment_paren[ $art ]
|
|
300
296
|
|
|
|
301
297
|
{ $assignment = { name: {} }; }
|
|
302
298
|
annotationPath[ $assignment.name, 'anno' ]
|
|
303
299
|
annotationPathVariant[ $assignment.name ]?
|
|
304
300
|
(
|
|
305
301
|
':' { this.meltKeywordToIdentifier(true); } // allow path as anno value start with reserved
|
|
306
|
-
val=annoValue
|
|
302
|
+
val=annoValue[ $assignment ]
|
|
307
303
|
)?
|
|
308
304
|
)
|
|
309
305
|
;
|
|
310
306
|
|
|
311
307
|
// Has previously used ATN, now via local token rewrite
|
|
312
|
-
annotationAssignment_atn[
|
|
308
|
+
annotationAssignment_atn[ art ] locals[ assignment ]
|
|
313
309
|
@after {
|
|
314
310
|
if ($assignment) {
|
|
315
|
-
|
|
316
|
-
this.docComment( $
|
|
311
|
+
this.assignAnnotation( $art, $assignment );
|
|
312
|
+
this.docComment( $art );
|
|
317
313
|
}
|
|
318
314
|
} :
|
|
319
315
|
'@'
|
|
320
316
|
(
|
|
321
|
-
annotationAssignment_paren[
|
|
317
|
+
annotationAssignment_paren[ $art ]
|
|
322
318
|
|
|
|
323
319
|
{ $assignment = { name: {} }; }
|
|
324
320
|
annotationPath[ $assignment.name, 'anno' ]
|
|
@@ -337,14 +333,13 @@ annotationAssignment_atn[ annos ] locals[ assignment ]
|
|
|
337
333
|
( HelperToken2 // ':'
|
|
338
334
|
{ this.meltKeywordToIdentifier(true); } // allow path as anno value start with reserved
|
|
339
335
|
(
|
|
340
|
-
val=annoValueBase
|
|
336
|
+
val=annoValueBase[ $assignment ]
|
|
341
337
|
|
|
|
342
|
-
|
|
343
|
-
at='@'? annotationPath[ $assignment.value, 'ref', $at ]
|
|
338
|
+
at='@'? annotationPath[ $assignment, 'ref', $at ]
|
|
344
339
|
{ this.setLocalToken( '#', 'HelperToken1', null, true ); } // see above
|
|
345
340
|
(
|
|
346
341
|
HelperToken1 { this.meltKeywordToIdentifier(); }
|
|
347
|
-
variant=ident['variant'] { $assignment.
|
|
342
|
+
variant=ident['variant'] { $assignment.variant = $variant.id; }
|
|
348
343
|
)?
|
|
349
344
|
)
|
|
350
345
|
)?
|
|
@@ -364,97 +359,95 @@ optionalSemi
|
|
|
364
359
|
';'?
|
|
365
360
|
;
|
|
366
361
|
|
|
367
|
-
artifactDef[ outer, defOnly = false ] locals[
|
|
362
|
+
artifactDef[ outer, defOnly = false ] locals[ art = {} ] // cannot use `parent` as parameter name!
|
|
368
363
|
@after{ /* #ATN 1 */ }
|
|
369
364
|
:
|
|
370
|
-
{ this.docComment( $
|
|
371
|
-
annotationAssignment_ll1[ $
|
|
365
|
+
{ $art.location = this.startLocation(); this.docComment( $art ); }
|
|
366
|
+
annotationAssignment_ll1[ $art ]*
|
|
372
367
|
(
|
|
373
368
|
DEFINE?
|
|
374
|
-
( contextDef[ $
|
|
375
|
-
| entityDef[ $
|
|
376
|
-
| typeDef[ $
|
|
377
|
-
| aspectDef[ $
|
|
378
|
-
| annotationDef[ $
|
|
379
|
-
| viewDef[ $
|
|
380
|
-
| eventDef[ $
|
|
381
|
-
| actionFunctionMainDef[ $
|
|
369
|
+
( contextDef[ $art, $outer, defOnly ]
|
|
370
|
+
| entityDef[ $art, $outer ]
|
|
371
|
+
| typeDef[ $art, $outer ]
|
|
372
|
+
| aspectDef[ $art, $outer ]
|
|
373
|
+
| annotationDef[ $art, $outer ]
|
|
374
|
+
| viewDef[ $art, $outer ]
|
|
375
|
+
| eventDef[ $art, $outer ]
|
|
376
|
+
| actionFunctionMainDef[ $art, $outer ]
|
|
382
377
|
)
|
|
383
378
|
|
|
|
384
379
|
extend=EXTEND
|
|
385
|
-
{ if (defOnly)
|
|
386
|
-
// another way
|
|
380
|
+
{ if (defOnly)
|
|
387
381
|
this.error( 'syntax-extend-context', $extend,
|
|
388
382
|
{ code: 'EXTEND artifact', kind: defOnly },
|
|
389
|
-
'No $(CODE) within $(KIND) extensions' );
|
|
383
|
+
'No $(CODE) within $(KIND) extensions' );
|
|
384
|
+
if (!$outer.extensions) $outer.extensions = [];
|
|
385
|
+
}
|
|
390
386
|
// #ATN: EXTEND elem, while CONTEXT, ENTITY etc are not reserved
|
|
391
|
-
( extendContext[ $
|
|
392
|
-
| extendEntity[ $
|
|
393
|
-
| extendProjection[ $
|
|
394
|
-
| extendType[ $
|
|
395
|
-
| extendAspect[ $
|
|
387
|
+
( extendContext[ $art, $outer ]
|
|
388
|
+
| extendEntity[ $art, $outer ]
|
|
389
|
+
| extendProjection[ $art, $outer ]
|
|
390
|
+
| extendType[ $art, $outer ]
|
|
391
|
+
| extendAspect[ $art, $outer ]
|
|
396
392
|
// Streamlined Syntax
|
|
397
|
-
| extendArtifact[ $
|
|
393
|
+
| extendArtifact[ $art, $outer ]
|
|
398
394
|
)
|
|
399
395
|
|
|
|
400
396
|
annotate=ANNOTATE
|
|
401
|
-
{ if (defOnly)
|
|
402
|
-
// another way
|
|
397
|
+
{ if (defOnly)
|
|
403
398
|
this.error( 'syntax-extend-context', $annotate,
|
|
404
399
|
{ code: 'ANNOTATE artifact', kind: defOnly },
|
|
405
400
|
'No $(CODE) within $(KIND) extensions' );
|
|
406
401
|
this.meltKeywordToIdentifier();
|
|
407
402
|
}
|
|
408
|
-
annotateArtifact[ $
|
|
403
|
+
annotateArtifact[ $art, $outer ] // not kind-specific
|
|
409
404
|
)
|
|
410
405
|
;
|
|
411
406
|
|
|
412
|
-
contextDef[
|
|
413
|
-
@after { this.attachLocation($art); }
|
|
407
|
+
contextDef[ art, outer, defOnly = false ] locals[ name = {} ]
|
|
408
|
+
@after { this.attachLocation( $art ); }
|
|
414
409
|
:
|
|
415
410
|
( CONTEXT | service=SERVICE ) simplePath[ $name, $service ? 'Service' : 'Context' ]
|
|
416
|
-
{
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
annotationAssignment_fix[ $annos ]*
|
|
411
|
+
{ this.addDef( $art, $outer, 'artifacts', $service ? 'service' : 'context', $name );
|
|
412
|
+
this.docComment( $art ); }
|
|
413
|
+
annotationAssignment_fix[ $art ]*
|
|
420
414
|
(
|
|
421
|
-
'{' { $art.artifacts = this.createDict(); }
|
|
415
|
+
'{' { $art.artifacts = this.createDict(); $art.extensions = []; }
|
|
422
416
|
artifactDef[ $art, defOnly ]*
|
|
423
|
-
'}' { this.
|
|
417
|
+
'}' { this.finalizeDictOrArray( $art.artifacts ); }
|
|
424
418
|
optionalSemi
|
|
425
419
|
|
|
|
426
420
|
requiredSemi
|
|
427
421
|
)
|
|
428
422
|
;
|
|
429
423
|
|
|
430
|
-
extendContext[
|
|
431
|
-
@after { this.attachLocation($art); }
|
|
424
|
+
extendContext[ art, outer ] locals[ name = {} ]
|
|
425
|
+
@after { this.attachLocation( $art ); }
|
|
432
426
|
:
|
|
433
|
-
( CONTEXT
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
$loc ); }
|
|
427
|
+
( CONTEXT { $art.expectedKind = 'context'; } | service=SERVICE { $art.expectedKind = 'service'; })
|
|
428
|
+
simplePath[ $name, $service ? 'Service' : 'Context' ] // not 'Extend' here
|
|
429
|
+
{ $art.name = $name; this.addItem( $art, $outer, 'extensions', 'extend' ); }
|
|
437
430
|
( WITH { this.noSemicolonHere(); } )?
|
|
438
|
-
{ this.docComment( $
|
|
439
|
-
annotationAssignment_ll1[ $
|
|
431
|
+
{ this.docComment( $art ); }
|
|
432
|
+
annotationAssignment_ll1[ $art ]*
|
|
440
433
|
(
|
|
441
434
|
'{' { $art.artifacts = this.createDict(); }
|
|
442
435
|
artifactDef[ $art, $service ? 'SERVICE' : 'CONTEXT' ]*
|
|
443
|
-
'}' { this.
|
|
436
|
+
'}' { this.finalizeDictOrArray( $art.artifacts ); }
|
|
444
437
|
optionalSemi
|
|
445
438
|
|
|
|
446
439
|
requiredSemi
|
|
447
440
|
)
|
|
448
441
|
;
|
|
449
442
|
|
|
450
|
-
entityDef[
|
|
451
|
-
@after { this.attachLocation($art); }
|
|
443
|
+
entityDef[ art, outer ] locals[ name = {} ]
|
|
444
|
+
@after { this.attachLocation( $art ); }
|
|
452
445
|
:
|
|
453
446
|
ENTITY simplePath[ $name, 'Entity' ]
|
|
454
|
-
{
|
|
455
|
-
this.docComment( $
|
|
456
|
-
annotationAssignment_fix[ $
|
|
457
|
-
|
|
447
|
+
{ this.addDef( $art, $outer, 'artifacts', 'entity', $name );
|
|
448
|
+
this.docComment( $art ); }
|
|
449
|
+
annotationAssignment_fix[ $art ]*
|
|
450
|
+
parameterListDef[ $art ]?
|
|
458
451
|
(
|
|
459
452
|
( ':'
|
|
460
453
|
includeRef[ $art ]
|
|
@@ -462,15 +455,14 @@ entityDef[ outer, loc, annos ] locals[ art, name = {} ]
|
|
|
462
455
|
includeRef[ $art ]
|
|
463
456
|
)*
|
|
464
457
|
)?
|
|
465
|
-
'{'
|
|
466
|
-
{ $art.elements = this.createDict(); } // better for include and annotate
|
|
458
|
+
'{' { $art.elements = this.createDict(); }
|
|
467
459
|
elementDef[ $art ]*
|
|
468
|
-
'}' { this.
|
|
460
|
+
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
469
461
|
// TODO: action definitions in a specific section?
|
|
470
462
|
(
|
|
471
463
|
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
472
464
|
actionFunctionDef[ $art ]*
|
|
473
|
-
'}' { this.
|
|
465
|
+
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
474
466
|
)?
|
|
475
467
|
optionalSemi
|
|
476
468
|
|
|
|
@@ -480,7 +472,7 @@ entityDef[ outer, loc, annos ] locals[ art, name = {} ]
|
|
|
480
472
|
(
|
|
481
473
|
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
482
474
|
actionFunctionDef[ $art ]*
|
|
483
|
-
'}' { this.
|
|
475
|
+
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
484
476
|
optionalSemi
|
|
485
477
|
| requiredSemi
|
|
486
478
|
)
|
|
@@ -490,7 +482,7 @@ entityDef[ outer, loc, annos ] locals[ art, name = {} ]
|
|
|
490
482
|
(
|
|
491
483
|
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
492
484
|
actionFunctionDef[ $art ]*
|
|
493
|
-
'}' { this.
|
|
485
|
+
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
494
486
|
)?
|
|
495
487
|
optionalSemi // TODO: not fully correct without columns or excluding
|
|
496
488
|
)
|
|
@@ -514,7 +506,7 @@ projectionSpec returns[ query ] locals[ src ]
|
|
|
514
506
|
( AS aliasName=ident['FromAlias'] { $src.name = $aliasName.id } )?
|
|
515
507
|
// ANTLR errors are better if we use ( A )? instead of ( A | ):
|
|
516
508
|
{ if (!$src.name) this.classifyImplicitName( $src.scope ? 'FromAlias' : 'Without' ); }
|
|
517
|
-
bracedSelectItemListDef[ $query ]?
|
|
509
|
+
bracedSelectItemListDef[ $query, 'columns' ]?
|
|
518
510
|
excludingClause[ $query ]?
|
|
519
511
|
;
|
|
520
512
|
|
|
@@ -541,25 +533,26 @@ excludingClause[ query ]
|
|
|
541
533
|
( ',' { if (this.isStraightBefore("}")) break; } // allow ',' before '}'
|
|
542
534
|
projectionExclusion[ $query ]
|
|
543
535
|
)*
|
|
544
|
-
'}' { this.
|
|
536
|
+
'}' { this.finalizeDictOrArray( $query.excludingDict ); }
|
|
545
537
|
;
|
|
546
538
|
|
|
547
|
-
projectionExclusion[ outer ] locals[ art ]
|
|
539
|
+
projectionExclusion[ outer ] locals[ art = {} ]
|
|
548
540
|
@after { this.attachLocation($art); }
|
|
549
541
|
:
|
|
550
542
|
name=ident['ref']
|
|
551
|
-
{
|
|
543
|
+
{ this.addDef( $art, $outer, 'excludingDict', '', $name.id ); }
|
|
552
544
|
;
|
|
553
545
|
|
|
554
|
-
extendEntity[
|
|
555
|
-
@after { /* #ATN 1 */ this.attachLocation($art); }
|
|
546
|
+
extendEntity[ art, outer ] locals[ name = {} ]
|
|
547
|
+
@after { /* #ATN 1 */ this.attachLocation( $art ); }
|
|
556
548
|
:
|
|
557
549
|
ENTITY simplePath[ $name, 'Extend' ]
|
|
558
|
-
{ $art =
|
|
559
|
-
|
|
550
|
+
{ $art.expectedKind = 'entity'; $art.name = $name;
|
|
551
|
+
this.addItem( $art, $outer, 'extensions', 'extend' );
|
|
552
|
+
}
|
|
560
553
|
(
|
|
561
|
-
WITH { this.noSemicolonHere(); this.docComment( $
|
|
562
|
-
annotationAssignment_ll1[ $
|
|
554
|
+
WITH { this.noSemicolonHere(); this.docComment( $art ); }
|
|
555
|
+
annotationAssignment_ll1[ $art ]*
|
|
563
556
|
// ATN: the ref can start with ACTIONS
|
|
564
557
|
(
|
|
565
558
|
includeRef[ $art ]
|
|
@@ -568,8 +561,8 @@ extendEntity[ outer, loc, annos ] locals[ art, name = {} ]
|
|
|
568
561
|
extendForEntity[ $art ]
|
|
569
562
|
)
|
|
570
563
|
|
|
|
571
|
-
{ this.docComment( $
|
|
572
|
-
annotationAssignment_ll1[ $
|
|
564
|
+
{ this.docComment( $art ); }
|
|
565
|
+
annotationAssignment_ll1[ $art ]*
|
|
573
566
|
extendForEntity[ $art ]
|
|
574
567
|
)
|
|
575
568
|
;
|
|
@@ -578,33 +571,32 @@ extendForEntity[ art ]
|
|
|
578
571
|
:
|
|
579
572
|
'{' { $art.elements = this.createDict(); }
|
|
580
573
|
elementDefOrExtend[ $art ]*
|
|
581
|
-
'}' { this.
|
|
574
|
+
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
582
575
|
(
|
|
583
576
|
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
584
577
|
actionFunctionDef[ $art ]*
|
|
585
|
-
'}' { this.
|
|
578
|
+
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
586
579
|
)?
|
|
587
580
|
optionalSemi
|
|
588
581
|
|
|
|
589
582
|
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
590
583
|
actionFunctionDef[ $art ]*
|
|
591
|
-
'}' { this.
|
|
584
|
+
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
592
585
|
optionalSemi
|
|
593
586
|
|
|
|
594
587
|
requiredSemi
|
|
595
588
|
;
|
|
596
589
|
|
|
597
|
-
extendProjection[
|
|
598
|
-
@after { this.attachLocation($art); }
|
|
590
|
+
extendProjection[ art, outer ] locals[ name = {} ]
|
|
591
|
+
@after { this.attachLocation( $art ); }
|
|
599
592
|
:
|
|
600
593
|
expected=PROJECTION simplePath[ $name, 'Extend' ]
|
|
601
|
-
{
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
$loc ); }
|
|
594
|
+
{ $art.expectedKind = 'entity'; $art.name = $name;
|
|
595
|
+
this.addItem( $art, $outer, 'extensions', 'extend' );
|
|
596
|
+
}
|
|
605
597
|
( WITH { this.noSemicolonHere(); } )?
|
|
606
|
-
{ this.docComment( $
|
|
607
|
-
annotationAssignment_ll1[ $
|
|
598
|
+
{ this.docComment( $art ); }
|
|
599
|
+
annotationAssignment_ll1[ $art ]*
|
|
608
600
|
(
|
|
609
601
|
'{' { $art.columns = []; }
|
|
610
602
|
(
|
|
@@ -617,13 +609,13 @@ extendProjection[ outer, loc, annos ] locals[ art, name = {} ]
|
|
|
617
609
|
(
|
|
618
610
|
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
619
611
|
actionFunctionDef[ $art ]*
|
|
620
|
-
'}' { this.
|
|
612
|
+
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
621
613
|
)?
|
|
622
614
|
optionalSemi
|
|
623
615
|
|
|
|
624
616
|
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
625
617
|
actionFunctionDef[ $art ]*
|
|
626
|
-
'}' { this.
|
|
618
|
+
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
627
619
|
optionalSemi
|
|
628
620
|
|
|
|
629
621
|
requiredSemi
|
|
@@ -631,53 +623,53 @@ extendProjection[ outer, loc, annos ] locals[ art, name = {} ]
|
|
|
631
623
|
;
|
|
632
624
|
|
|
633
625
|
// TODO: no action extension?
|
|
634
|
-
actionFunctionDef[ outer ] locals[ art
|
|
635
|
-
@after { this.attachLocation($art); }
|
|
626
|
+
actionFunctionDef[ outer ] locals[ art = {} ]
|
|
627
|
+
@after { this.attachLocation( $art ); }
|
|
636
628
|
:
|
|
637
|
-
{ this.docComment( $
|
|
638
|
-
annotationAssignment_ll1[ $
|
|
629
|
+
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
630
|
+
annotationAssignment_ll1[ $art ]*
|
|
639
631
|
(
|
|
640
632
|
ACTION name=ident['BoundAction']
|
|
641
|
-
{
|
|
642
|
-
this.docComment( $
|
|
643
|
-
annotationAssignment_fix[ $
|
|
633
|
+
{ this.addDef( $art, $outer, 'actions', 'action', $name.id );
|
|
634
|
+
this.docComment( $art ); }
|
|
635
|
+
annotationAssignment_fix[ $art ]*
|
|
644
636
|
parameterListDef[ $art ]
|
|
645
|
-
( returnTypeSpec[ $art
|
|
637
|
+
( returnTypeSpec[ $art ] | requiredSemi )
|
|
646
638
|
|
|
|
647
639
|
FUNCTION name=ident['BoundAction']
|
|
648
|
-
{
|
|
649
|
-
this.docComment( $
|
|
650
|
-
annotationAssignment_fix[ $
|
|
640
|
+
{ this.addDef( $art, $outer, 'actions', 'function', $name.id );
|
|
641
|
+
this.docComment( $art ); }
|
|
642
|
+
annotationAssignment_fix[ $art ]*
|
|
651
643
|
parameterListDef[ $art ]
|
|
652
|
-
returnTypeSpec[ $art
|
|
644
|
+
returnTypeSpec[ $art ]
|
|
653
645
|
)
|
|
654
646
|
;
|
|
655
647
|
|
|
656
|
-
actionFunctionMainDef[
|
|
657
|
-
@after { this.attachLocation($art); }
|
|
648
|
+
actionFunctionMainDef[ art, outer ] locals[ name = {} ]
|
|
649
|
+
@after { this.attachLocation( $art ); }
|
|
658
650
|
:
|
|
659
651
|
ACTION simplePath[ $name, 'Action' ]
|
|
660
|
-
{
|
|
661
|
-
this.docComment( $
|
|
662
|
-
annotationAssignment_fix[ $
|
|
652
|
+
{ this.addDef( $art, $outer, 'artifacts', 'action', $name );
|
|
653
|
+
this.docComment( $art ); }
|
|
654
|
+
annotationAssignment_fix[ $art ]*
|
|
663
655
|
parameterListDef[ $art ]
|
|
664
|
-
( returnTypeSpec[ $art
|
|
656
|
+
( returnTypeSpec[ $art ] | requiredSemi )
|
|
665
657
|
|
|
|
666
658
|
FUNCTION simplePath[ $name, 'Action' ]
|
|
667
|
-
{
|
|
668
|
-
this.docComment( $
|
|
669
|
-
annotationAssignment_fix[ $
|
|
659
|
+
{ this.addDef( $art, $outer, 'artifacts', 'function', $name );
|
|
660
|
+
this.docComment( $art ); }
|
|
661
|
+
annotationAssignment_fix[ $art ]*
|
|
670
662
|
parameterListDef[ $art ]
|
|
671
|
-
returnTypeSpec[ $art
|
|
663
|
+
returnTypeSpec[ $art ]
|
|
672
664
|
;
|
|
673
665
|
|
|
674
|
-
eventDef[
|
|
675
|
-
@after { /* #ATN 1 */ this.attachLocation($art); }
|
|
666
|
+
eventDef[ art, outer ] locals[ name = {} ]
|
|
667
|
+
@after { /* #ATN 1 */ this.attachLocation( $art ); }
|
|
676
668
|
:
|
|
677
669
|
EVENT simplePath[ $name, 'Event' ]
|
|
678
|
-
{
|
|
679
|
-
this.docComment( $
|
|
680
|
-
annotationAssignment_fix[ $
|
|
670
|
+
{ this.addDef( $art, $outer, 'artifacts', 'event', $name );
|
|
671
|
+
this.docComment( $art ); }
|
|
672
|
+
annotationAssignment_fix[ $art ]*
|
|
681
673
|
(
|
|
682
674
|
typeStruct[ $art ] optionalSemi
|
|
683
675
|
|
|
|
@@ -693,8 +685,8 @@ eventDef[ outer, loc, annos ] locals[ art, name = {} ]
|
|
|
693
685
|
)*
|
|
694
686
|
typeStruct[ $art ] optionalSemi
|
|
695
687
|
|
|
|
696
|
-
{ this.docComment( $
|
|
697
|
-
annotationAssignment_ll1[ $
|
|
688
|
+
{ this.docComment( $art ); }
|
|
689
|
+
annotationAssignment_ll1[ $art ]*
|
|
698
690
|
requiredSemi
|
|
699
691
|
)
|
|
700
692
|
|
|
|
@@ -708,18 +700,18 @@ eventDef[ outer, loc, annos ] locals[ art, name = {} ]
|
|
|
708
700
|
)
|
|
709
701
|
;
|
|
710
702
|
|
|
711
|
-
aspectDef[
|
|
712
|
-
@after { this.attachLocation($art); }
|
|
703
|
+
aspectDef[ art, outer ] locals[ name = {} ]
|
|
704
|
+
@after { this.attachLocation( $art ); }
|
|
713
705
|
:
|
|
714
706
|
( ASPECT | ( abs=ABSTRACT | HideAlternatives ) ent=ENTITY )
|
|
715
707
|
simplePath[ $name, 'Type' ]
|
|
716
|
-
{
|
|
708
|
+
{ this.addDef( $art, $outer, 'artifacts', 'aspect', $name );
|
|
717
709
|
// backends do not like ['$'+'syntax']: ($ent ? 'entity' : 'aspect')
|
|
718
710
|
if ($ent)
|
|
719
711
|
this.warning( 'syntax-deprecated-abstract', this.tokenLocation( $abs, $ent ), {},
|
|
720
712
|
'Abstract entity definitions are deprecated; use aspect definitions instead' );
|
|
721
|
-
this.docComment( $
|
|
722
|
-
annotationAssignment_fix[ $
|
|
713
|
+
this.docComment( $art ); }
|
|
714
|
+
annotationAssignment_fix[ $art ]*
|
|
723
715
|
( ':'
|
|
724
716
|
(
|
|
725
717
|
includeRef[ $art ]
|
|
@@ -730,99 +722,93 @@ aspectDef[ outer, loc, annos ] locals[ art, name = {} ]
|
|
|
730
722
|
)?
|
|
731
723
|
'{' { $art.elements = this.createDict(); }
|
|
732
724
|
( elementDef[ $art ]* )
|
|
733
|
-
'}' { this.
|
|
725
|
+
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
734
726
|
// TODO: action definitions in a specific section?
|
|
735
727
|
(
|
|
736
728
|
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
737
729
|
actionFunctionDef[ $art ]*
|
|
738
|
-
'}' { this.
|
|
730
|
+
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
739
731
|
)?
|
|
740
732
|
optionalSemi
|
|
741
733
|
;
|
|
742
734
|
|
|
743
|
-
typeDef[
|
|
744
|
-
@after { this.attachLocation($art); }
|
|
735
|
+
typeDef[ art, outer ] locals[ name = {} ]
|
|
736
|
+
@after { this.attachLocation( $art ); }
|
|
745
737
|
:
|
|
746
738
|
TYPE simplePath[ $name, 'Type' ]
|
|
747
|
-
{
|
|
748
|
-
this.docComment( $
|
|
749
|
-
annotationAssignment_fix[ $
|
|
750
|
-
typeSpecSemi[ $art
|
|
739
|
+
{ this.addDef( $art, $outer, 'artifacts', 'type', $name );
|
|
740
|
+
this.docComment( $art ); }
|
|
741
|
+
annotationAssignment_fix[ $art ]*
|
|
742
|
+
typeSpecSemi[ $art ]
|
|
751
743
|
;
|
|
752
744
|
|
|
753
|
-
extendType[
|
|
754
|
-
@after { this.attachLocation($art); }
|
|
745
|
+
extendType[ art, outer ] locals[ name = {} ]
|
|
746
|
+
@after { this.attachLocation( $art ); }
|
|
755
747
|
:
|
|
756
748
|
// aspects are types, i.e. kind is 'type' for aspects
|
|
757
749
|
TYPE simplePath[ $name, 'Extend' ]
|
|
758
|
-
{ $art =
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
extendWithOptElements[ $art, $
|
|
750
|
+
{ $art.expectedKind = 'type'; $art.name = $name;
|
|
751
|
+
this.addItem( $art, $outer, 'extensions', 'extend' );
|
|
752
|
+
}
|
|
753
|
+
extendWithOptElements[ $art, $art ]
|
|
762
754
|
;
|
|
763
755
|
|
|
764
|
-
extendAspect[
|
|
765
|
-
@after { this.attachLocation($art); }
|
|
756
|
+
extendAspect[ art, outer ] locals[ name = {} ]
|
|
757
|
+
@after { this.attachLocation( $art ); }
|
|
766
758
|
:
|
|
767
759
|
// aspects are types, i.e. kind is 'type' for aspects
|
|
768
760
|
ASPECT simplePath[ $name, 'Extend' ]
|
|
769
|
-
{ $art =
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
extendWithOptElements[ $art, $
|
|
761
|
+
{ $art.expectedKind = 'aspect'; $art.name = $name;
|
|
762
|
+
this.addItem( $art, $outer, 'extensions', 'extend' );
|
|
763
|
+
}
|
|
764
|
+
extendWithOptElements[ $art, $art ]
|
|
773
765
|
;
|
|
774
766
|
|
|
775
|
-
annotationDef[
|
|
776
|
-
@after { this.attachLocation($art); }
|
|
767
|
+
annotationDef[ art, outer ] locals[ name = {} ]
|
|
768
|
+
@after { this.attachLocation( $art ); }
|
|
777
769
|
:
|
|
778
770
|
annotation=ANNOTATION simplePath[ $name, 'AnnoDef' ]
|
|
779
771
|
{ if ($outer.kind !== 'source') { // this is a syntax restriction to avoid confusion
|
|
780
|
-
this.error( 'syntax-
|
|
781
|
-
'Annotation definitions can\'t be defined inside contexts or services' );
|
|
772
|
+
this.error( 'syntax-unexpected-vocabulary', $annotation, { '#': $outer.kind } );
|
|
782
773
|
$art = {}; }
|
|
783
|
-
else
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
774
|
+
else {
|
|
775
|
+
if (!$outer.vocabularies) $outer.vocabularies = Object.create(null);
|
|
776
|
+
this.addDef( $art, $outer, 'vocabularies', 'annotation', $name );
|
|
777
|
+
}
|
|
778
|
+
this.docComment( $art ); }
|
|
779
|
+
annotationAssignment_fix[ $art ]*
|
|
780
|
+
typeSpecSemi[ $art ] // also 'includes'...
|
|
788
781
|
;
|
|
789
782
|
|
|
790
|
-
extendArtifact[
|
|
791
|
-
@after{ /* #ATN 1 */ this.attachLocation($art); }
|
|
783
|
+
extendArtifact[ art, outer ] locals[ name = {}, elemName = {} ]
|
|
784
|
+
@after{ /* #ATN 1 */ this.attachLocation( $art ); }
|
|
792
785
|
:
|
|
793
786
|
simplePath[ $name, 'Extend' ]
|
|
787
|
+
( ':' simplePath[ $elemName, 'Element'] )?
|
|
788
|
+
{ this.addExtension( $art, $outer, 'extend', $name, $elemName.path ); }
|
|
794
789
|
(
|
|
795
|
-
{
|
|
796
|
-
|
|
797
|
-
':'
|
|
798
|
-
simplePath[ $elemName, 'ref']
|
|
799
|
-
{{
|
|
800
|
-
const def = this.addItem( $outer, 'extensions', 'extend', null, { name: $name }, $loc );
|
|
801
|
-
$art = this.artifactForElementAnnotateOrExtend( 'extend', def, $elemName.path, $annos, $loc );
|
|
802
|
-
}}
|
|
803
|
-
)
|
|
804
|
-
(
|
|
805
|
-
{ this.docComment( $annos ); }
|
|
806
|
-
annotationAssignment_ll1[ $annos ]*
|
|
790
|
+
{ this.docComment( $art ); }
|
|
791
|
+
annotationAssignment_ll1[ $art ]*
|
|
807
792
|
(
|
|
808
793
|
'{' { $art.elements = this.createDict(); }
|
|
809
794
|
elementDefOrExtend[ $art ]*
|
|
810
|
-
'}' { this.
|
|
795
|
+
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
811
796
|
optionalSemi
|
|
812
797
|
|
|
|
813
798
|
requiredSemi
|
|
814
799
|
)
|
|
815
800
|
|
|
|
816
|
-
WITH { this.noSemicolonHere(); this.docComment( $
|
|
817
|
-
annotationAssignment_ll1[ $
|
|
801
|
+
WITH { this.noSemicolonHere(); this.docComment( $art ); }
|
|
802
|
+
annotationAssignment_ll1[ $art ]*
|
|
818
803
|
// #ATN: DEFINITIONS, COLUMNS, ACTIONS etc are not reserved and could be identifiers (ref).
|
|
804
|
+
// TODO: exclude "expected" according to disallowElementExtension()
|
|
819
805
|
(
|
|
820
806
|
includeRef[ $art ]
|
|
821
807
|
requiredSemi
|
|
822
808
|
|
|
|
823
809
|
'{' { $art.elements = this.createDict(); }
|
|
824
810
|
elementDefOrExtend[ $art ]*
|
|
825
|
-
'}' { this.
|
|
811
|
+
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
826
812
|
optionalSemi
|
|
827
813
|
|
|
|
828
814
|
requiredSemi
|
|
@@ -831,7 +817,7 @@ extendArtifact[ outer, loc, annos ] locals[ art, name = {}, elemName = {} ]
|
|
|
831
817
|
DEFINITIONS
|
|
832
818
|
'{' { $art.artifacts = this.createDict(); }
|
|
833
819
|
artifactDef[ $art, true ]*
|
|
834
|
-
'}' { this.
|
|
820
|
+
'}' { this.finalizeDictOrArray( $art.artifacts ); }
|
|
835
821
|
optionalSemi
|
|
836
822
|
|
|
|
837
823
|
{ this.disallowElementExtension( $elemName, $outer, 'columns' ); }
|
|
@@ -849,84 +835,75 @@ extendArtifact[ outer, loc, annos ] locals[ art, name = {}, elemName = {} ]
|
|
|
849
835
|
{ this.disallowElementExtension( $elemName, $outer, 'actions' ); }
|
|
850
836
|
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
851
837
|
actionFunctionDef[ $art ]*
|
|
852
|
-
'}' { this.
|
|
838
|
+
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
853
839
|
optionalSemi
|
|
854
840
|
|
|
|
855
841
|
ELEMENTS '{' { $art.elements = this.createDict(); }
|
|
856
842
|
elementDefOrExtend[ $art ]*
|
|
857
|
-
'}' { this.
|
|
843
|
+
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
858
844
|
optionalSemi
|
|
859
845
|
|
|
|
860
846
|
ENUM '{' { $art.enum = this.createDict(); }
|
|
861
847
|
enumSymbolDef[ $art ]*
|
|
862
|
-
'}' { this.
|
|
848
|
+
'}' { this.finalizeDictOrArray( $art.enum ); }
|
|
863
849
|
optionalSemi
|
|
864
850
|
)
|
|
865
851
|
)
|
|
866
852
|
;
|
|
867
853
|
|
|
868
|
-
extendWithOptElements[ art
|
|
854
|
+
extendWithOptElements[ art ]
|
|
869
855
|
:
|
|
870
|
-
WITH { this.noSemicolonHere(); this.docComment( $
|
|
871
|
-
annotationAssignment_ll1[ $
|
|
856
|
+
WITH { this.noSemicolonHere(); this.docComment( $art ); }
|
|
857
|
+
annotationAssignment_ll1[ $art ]*
|
|
872
858
|
(
|
|
873
859
|
includeRef[ $art ]
|
|
874
860
|
requiredSemi
|
|
875
861
|
|
|
|
876
862
|
'{' { $art.elements = this.createDict(); }
|
|
877
863
|
elementDefOrExtend[ $art ]*
|
|
878
|
-
'}' { this.
|
|
864
|
+
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
879
865
|
optionalSemi
|
|
880
866
|
|
|
|
881
867
|
requiredSemi
|
|
882
868
|
)
|
|
883
869
|
|
|
|
884
|
-
{ this.docComment( $
|
|
885
|
-
annotationAssignment_ll1[ $
|
|
870
|
+
{ this.docComment( $art ); }
|
|
871
|
+
annotationAssignment_ll1[ $art ]*
|
|
886
872
|
(
|
|
887
873
|
'{' { $art.elements = this.createDict(); }
|
|
888
874
|
elementDefOrExtend[ $art ]*
|
|
889
|
-
'}' { this.
|
|
875
|
+
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
890
876
|
optionalSemi
|
|
891
877
|
|
|
|
892
878
|
requiredSemi
|
|
893
879
|
)
|
|
894
880
|
;
|
|
895
881
|
|
|
896
|
-
annotateArtifact[
|
|
897
|
-
@after { this.attachLocation($art); }
|
|
882
|
+
annotateArtifact[ art, outer ] locals[ name = {}, elemName = {} ]
|
|
883
|
+
@after { this.attachLocation( $art ); }
|
|
898
884
|
:
|
|
899
885
|
simplePath[ $name, 'Annotate' ]
|
|
900
|
-
(
|
|
901
|
-
|
|
902
|
-
|
|
|
903
|
-
':'
|
|
904
|
-
simplePath[ $elemName, 'ref']
|
|
905
|
-
{{
|
|
906
|
-
const def = this.addItem( $outer, 'extensions', 'annotate', null, { name: $name }, $loc );
|
|
907
|
-
$art = this.artifactForElementAnnotateOrExtend( 'annotate', def, $elemName.path, $annos, $loc );
|
|
908
|
-
}}
|
|
909
|
-
)
|
|
910
|
-
|
|
886
|
+
( ':' simplePath[ $elemName, 'Element'] )?
|
|
887
|
+
{ this.addExtension( $art, $outer, 'annotate', $name, $elemName.path ); }
|
|
911
888
|
( WITH { this.noSemicolonHere(); } )?
|
|
912
|
-
{ this.docComment( $
|
|
913
|
-
annotationAssignment_ll1[ $
|
|
889
|
+
{ this.docComment( $art ); }
|
|
890
|
+
annotationAssignment_ll1[ $art ]*
|
|
914
891
|
(
|
|
915
892
|
'{' { $art.elements = this.createDict(); }
|
|
916
893
|
annotateElement[ $art ]*
|
|
917
|
-
'}' { this.
|
|
894
|
+
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
918
895
|
(
|
|
919
896
|
ACTIONS
|
|
920
897
|
'{' { $art.actions = this.createDict(); }
|
|
921
898
|
annotateAction[ $art ]*
|
|
922
|
-
'}' { this.
|
|
899
|
+
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
923
900
|
)?
|
|
924
901
|
optionalSemi
|
|
925
902
|
|
|
|
926
903
|
ACTIONS
|
|
927
904
|
'{' { $art.actions = this.createDict(); }
|
|
928
905
|
annotateAction[ $art ]*
|
|
929
|
-
'}' { this.
|
|
906
|
+
'}' { this.finalizeDictOrArray( $art.actions ); }
|
|
930
907
|
optionalSemi
|
|
931
908
|
|
|
|
932
909
|
'(' { $art.params = this.createDict(); }
|
|
@@ -934,12 +911,12 @@ annotateArtifact[ outer, loc, annos ] locals[ art, name = {}, elemName = {} ]
|
|
|
934
911
|
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
935
912
|
annotateParam[ $art ]
|
|
936
913
|
)*
|
|
937
|
-
')' { this.
|
|
914
|
+
')' { this.finalizeDictOrArray( $art.params ); }
|
|
938
915
|
(
|
|
939
916
|
RETURNS { $art['$'+'syntax'] = 'returns'; }
|
|
940
917
|
'{' { $art.elements = this.createDict(); }
|
|
941
918
|
annotateElement[ $art ]*
|
|
942
|
-
'}' { this.
|
|
919
|
+
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
943
920
|
optionalSemi
|
|
944
921
|
|
|
|
945
922
|
requiredSemi
|
|
@@ -948,7 +925,7 @@ annotateArtifact[ outer, loc, annos ] locals[ art, name = {}, elemName = {} ]
|
|
|
948
925
|
RETURNS { $art['$'+'syntax'] = 'returns'; }
|
|
949
926
|
'{' { $art.elements = this.createDict(); }
|
|
950
927
|
annotateElement[ $art ]*
|
|
951
|
-
'}' { this.
|
|
928
|
+
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
952
929
|
optionalSemi
|
|
953
930
|
|
|
954
931
|
|
|
|
@@ -956,74 +933,74 @@ annotateArtifact[ outer, loc, annos ] locals[ art, name = {}, elemName = {} ]
|
|
|
956
933
|
)
|
|
957
934
|
;
|
|
958
935
|
|
|
959
|
-
annotateElement[ outer ] locals[ art
|
|
960
|
-
@after{ this.attachLocation($art); }
|
|
936
|
+
annotateElement[ outer ] locals[ art = {} ]
|
|
937
|
+
@after{ this.attachLocation( $art ); }
|
|
961
938
|
:
|
|
962
|
-
{ this.docComment( $
|
|
963
|
-
annotationAssignment_ll1[ $
|
|
939
|
+
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
940
|
+
annotationAssignment_ll1[ $art ]*
|
|
964
941
|
name=ident['Element']
|
|
965
|
-
{
|
|
966
|
-
this.docComment( $
|
|
967
|
-
annotationAssignment_ll1[ $
|
|
942
|
+
{ this.addDef( $art, $outer, 'elements', 'annotate', $name.id );
|
|
943
|
+
this.docComment( $art ); }
|
|
944
|
+
annotationAssignment_ll1[ $art ]*
|
|
968
945
|
(
|
|
969
946
|
'{' { $art.elements = this.createDict(); }
|
|
970
947
|
annotateElement[ $art ]*
|
|
971
|
-
'}' { this.
|
|
948
|
+
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
972
949
|
optionalSemi
|
|
973
950
|
|
|
|
974
951
|
requiredSemi
|
|
975
952
|
)
|
|
976
953
|
;
|
|
977
954
|
|
|
978
|
-
annotateAction [ outer ] locals [ art
|
|
979
|
-
@after{ this.attachLocation($art); }
|
|
955
|
+
annotateAction [ outer ] locals [ art = {} ]
|
|
956
|
+
@after{ this.attachLocation( $art ); }
|
|
980
957
|
:
|
|
981
|
-
{ this.docComment( $
|
|
982
|
-
annotationAssignment_ll1[ $
|
|
958
|
+
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
959
|
+
annotationAssignment_ll1[ $art ]*
|
|
983
960
|
name=ident['BoundAction']
|
|
984
|
-
{
|
|
985
|
-
this.docComment( $
|
|
986
|
-
annotationAssignment_ll1[ $
|
|
961
|
+
{ this.addDef( $art, $outer, 'actions', 'annotate', $name.id );
|
|
962
|
+
this.docComment( $art ); }
|
|
963
|
+
annotationAssignment_ll1[ $art ]*
|
|
987
964
|
(
|
|
988
965
|
'(' { $art.params = this.createDict(); }
|
|
989
966
|
annotateParam[ $art ]
|
|
990
967
|
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
991
968
|
annotateParam[ $art ]
|
|
992
969
|
)*
|
|
993
|
-
')' { this.
|
|
970
|
+
')' { this.finalizeDictOrArray( $art.params ); }
|
|
994
971
|
)?
|
|
995
972
|
(
|
|
996
973
|
RETURNS '{' { $art.elements = this.createDict(); }
|
|
997
974
|
annotateElement[ $art ]*
|
|
998
|
-
'}' { this.
|
|
975
|
+
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
999
976
|
optionalSemi
|
|
1000
977
|
|
|
|
1001
978
|
requiredSemi
|
|
1002
979
|
)
|
|
1003
980
|
;
|
|
1004
981
|
|
|
1005
|
-
annotateParam [ outer ] locals [ art
|
|
1006
|
-
@after{ this.attachLocation($art); }
|
|
982
|
+
annotateParam [ outer ] locals [ art = {} ]
|
|
983
|
+
@after{ this.attachLocation( $art ); }
|
|
1007
984
|
:
|
|
1008
|
-
{ this.docComment( $
|
|
1009
|
-
annotationAssignment_ll1[ $
|
|
985
|
+
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
986
|
+
annotationAssignment_ll1[ $art ]*
|
|
1010
987
|
param=ident['Param']
|
|
1011
|
-
{
|
|
1012
|
-
this.docComment( $
|
|
1013
|
-
annotationAssignment_ll1[ $
|
|
988
|
+
{ this.addDef( $art, $outer, 'params', 'annotate', $param.id );
|
|
989
|
+
this.docComment( $art ); }
|
|
990
|
+
annotationAssignment_ll1[ $art ]*
|
|
1014
991
|
;
|
|
1015
992
|
|
|
1016
993
|
// Element definition and its helpers ----------------------------------------
|
|
1017
994
|
|
|
1018
|
-
enumSymbolDef[ outer ] locals[ art
|
|
1019
|
-
@after { this.attachLocation($art); }
|
|
995
|
+
enumSymbolDef[ outer ] locals[ art = {} ]
|
|
996
|
+
@after { this.attachLocation( $art ); }
|
|
1020
997
|
:
|
|
1021
|
-
{ this.docComment( $
|
|
1022
|
-
annotationAssignment_ll1[ $
|
|
998
|
+
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
999
|
+
annotationAssignment_ll1[ $art ]*
|
|
1023
1000
|
name=ident['Enum']
|
|
1024
|
-
{
|
|
1025
|
-
this.docComment( $
|
|
1026
|
-
annotationAssignment_ll1[ $
|
|
1001
|
+
{ this.addDef( $art, $outer, 'enum', 'enum', $name.id );
|
|
1002
|
+
this.docComment( $art ); }
|
|
1003
|
+
annotationAssignment_ll1[ $art ]*
|
|
1027
1004
|
( '='
|
|
1028
1005
|
{ this.excludeExpected( ['Boolean', 'QuotedLiteral', "'#'", 'NULL'] ); }
|
|
1029
1006
|
(
|
|
@@ -1033,8 +1010,8 @@ enumSymbolDef[ outer ] locals[ art, annos = [] ]
|
|
|
1033
1010
|
( plus='+' | min='-' ) num=Number
|
|
1034
1011
|
{ $art.value = this.numberLiteral( $num, $plus||$min ); }
|
|
1035
1012
|
)
|
|
1036
|
-
{ this.docComment( $
|
|
1037
|
-
annotationAssignment_ll1[ $
|
|
1013
|
+
{ this.docComment( $art ); }
|
|
1014
|
+
annotationAssignment_ll1[ $art ]*
|
|
1038
1015
|
)?
|
|
1039
1016
|
requiredSemi
|
|
1040
1017
|
;
|
|
@@ -1045,37 +1022,35 @@ defaultValue[ art ] locals[ elem, elements = {} ]
|
|
|
1045
1022
|
DEFAULT expr=expression { $art.default = $expr.expr; }
|
|
1046
1023
|
;
|
|
1047
1024
|
|
|
1048
|
-
elementDefOrExtend[ outer ] locals[
|
|
1049
|
-
@after { /* #ATN 1 */ if ($
|
|
1050
|
-
// tool complains if I test for ($art)
|
|
1025
|
+
elementDefOrExtend[ outer ] locals[ art = {} ]
|
|
1026
|
+
@after { /* #ATN 1 */ } // if ($art) this.attachLocation( $art ); }
|
|
1051
1027
|
:
|
|
1052
|
-
{ this.docComment( $
|
|
1053
|
-
annotationAssignment_ll1[ $
|
|
1028
|
+
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
1029
|
+
annotationAssignment_ll1[ $art ]*
|
|
1054
1030
|
// #ATN: element name for definition can be EXTEND
|
|
1055
1031
|
(
|
|
1056
1032
|
EXTEND
|
|
1057
|
-
extendElement[ $
|
|
1033
|
+
extendElement[ $art, $outer ]
|
|
1058
1034
|
|
|
|
1059
|
-
|
|
1035
|
+
elementDefInner[ $art, $outer, true ]
|
|
1060
1036
|
)
|
|
1061
1037
|
;
|
|
1062
1038
|
|
|
1063
|
-
elementDef[ outer ] locals[
|
|
1064
|
-
@after { this.attachLocation($art.art); }
|
|
1039
|
+
elementDef[ outer ] locals[ $art = {} ]
|
|
1065
1040
|
:
|
|
1066
|
-
{ this.docComment( $
|
|
1067
|
-
annotationAssignment_ll1[ $
|
|
1068
|
-
|
|
1041
|
+
{ $art.location = this.startLocation();; this.docComment( $art ); }
|
|
1042
|
+
annotationAssignment_ll1[ $art ]*
|
|
1043
|
+
elementDefInner[ $art, $outer, false ]
|
|
1069
1044
|
;
|
|
1070
1045
|
|
|
1071
1046
|
// Actually, this is a subset if elementDefInner...
|
|
1072
1047
|
// TODO: the corresponding restrictions must also be checked in the core
|
|
1073
1048
|
// compiler, as the mixin element could come via CSN
|
|
1074
|
-
mixinElementDef[ outer ] locals[ art ]
|
|
1049
|
+
mixinElementDef[ outer ] locals[ art = {} ]
|
|
1075
1050
|
@after { /* #ATN 2 */ this.attachLocation($art); }
|
|
1076
1051
|
:
|
|
1077
1052
|
name=ident['Mixin']
|
|
1078
|
-
{
|
|
1053
|
+
{ this.addDef( $art, $outer, 'mixin', 'mixin', $name.id ); }
|
|
1079
1054
|
(
|
|
1080
1055
|
':'
|
|
1081
1056
|
// #ATN: referenced type name can be ASSOCIATION or COMPOSITION
|
|
@@ -1097,33 +1072,30 @@ mixinElementDef[ outer ] locals[ art ]
|
|
|
1097
1072
|
requiredSemi
|
|
1098
1073
|
;
|
|
1099
1074
|
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
// No docComment() here
|
|
1103
|
-
annotationAssignment_ll1[ $annos ]+
|
|
1104
|
-
{ if ($messageId) // issue specified in central registry
|
|
1105
|
-
this.message( messageId, this.tokenLocation( $ctx.start, this.getCurrentToken() ) );
|
|
1106
|
-
}
|
|
1107
|
-
;
|
|
1108
|
-
|
|
1109
|
-
elementDefInner[ outer, loc, annos, allowEq ] returns[ art ]
|
|
1110
|
-
@after{ /* #ATN 5 */ }
|
|
1075
|
+
elementDefInner[ art, outer, allowEq ]
|
|
1076
|
+
@after{ /* #ATN 5 */ this.attachLocation( $art ); }
|
|
1111
1077
|
:
|
|
1112
1078
|
// TODO: it would be excellent to remove ELEMENT...
|
|
1113
1079
|
// or have a special ident rule without the ELEMENT
|
|
1114
1080
|
// Reason: it would be good for error recovery to start a major block without LL1 ambiguity
|
|
1115
1081
|
// VIRTUAL is keyword, except if before the following tokens texts:
|
|
1116
1082
|
{ this.setLocalToken( 'VIRTUAL', 'VIRTUAL', /^[:{@=}]$/ ); }
|
|
1117
|
-
virtual=VIRTUAL
|
|
1083
|
+
( virtual=VIRTUAL { $art.virtual = this.valueWithTokenLocation( true, $virtual ); } )?
|
|
1084
|
+
( key=KEY { $art.key = this.valueWithTokenLocation( true, $key ); } )?
|
|
1118
1085
|
// #ATN: element name can be MASKED or ELEMENT (2x)
|
|
1119
|
-
masked=MASKED
|
|
1086
|
+
( masked=MASKED
|
|
1087
|
+
{
|
|
1088
|
+
$art.masked = this.valueWithTokenLocation( true, $masked ) ;
|
|
1089
|
+
this.message( 'syntax-invalid-masked', $masked, { keyword: 'masked' },
|
|
1090
|
+
'Keyword $(KEYWORD) not supported' );
|
|
1091
|
+
}
|
|
1092
|
+
)?
|
|
1093
|
+
// TODO: order?
|
|
1120
1094
|
ELEMENT?
|
|
1121
1095
|
name=ident['Element']
|
|
1122
|
-
{
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
this.docComment( $annos ); }
|
|
1126
|
-
annotationAssignment_fix[ $annos ]*
|
|
1096
|
+
{ this.addDef( $art, $outer, 'elements', 'element', $name.id );
|
|
1097
|
+
this.docComment( $art ); }
|
|
1098
|
+
annotationAssignment_fix[ $art ]*
|
|
1127
1099
|
// TODO: we can think of making the typeSpec optional and do checks instead:
|
|
1128
1100
|
// type optional with '=', type required otherwise
|
|
1129
1101
|
(
|
|
@@ -1138,7 +1110,6 @@ elementDefInner[ outer, loc, annos, allowEq ] returns[ art ]
|
|
|
1138
1110
|
(
|
|
1139
1111
|
typeStruct[ $art ]
|
|
1140
1112
|
nullability[ $art ]?
|
|
1141
|
-
misplacedAnnotations[ $annos, 'syntax-anno-after-struct' ]?
|
|
1142
1113
|
requiredSemi
|
|
1143
1114
|
|
|
|
1144
1115
|
typeAssociationBase[ $art, true ]
|
|
@@ -1155,11 +1126,11 @@ elementDefInner[ outer, loc, annos, allowEq ] returns[ art ]
|
|
|
1155
1126
|
typeCompoStruct[ $art.target ] optionalSemi
|
|
1156
1127
|
|
|
|
1157
1128
|
// we do not support `Composition of many { e }` - ambiguity ad-hoc target versus foreign keys!
|
|
1158
|
-
typeToMany[ $art ] typeAssociationElementCont[ $art
|
|
1129
|
+
typeToMany[ $art ] typeAssociationElementCont[ $art ]
|
|
1159
1130
|
|
|
|
1160
|
-
typeToOne[ $art ] typeAssociationElementCont[ $art
|
|
1131
|
+
typeToOne[ $art ] typeAssociationElementCont[ $art ]
|
|
1161
1132
|
|
|
|
1162
|
-
simplePath[ $art.target, 'artref' ] typeAssociationElementCont[ $art
|
|
1133
|
+
simplePath[ $art.target, 'artref' ] typeAssociationElementCont[ $art ]
|
|
1163
1134
|
)
|
|
1164
1135
|
|
|
|
1165
1136
|
(
|
|
@@ -1171,52 +1142,55 @@ elementDefInner[ outer, loc, annos, allowEq ] returns[ art ]
|
|
|
1171
1142
|
// #ATN: typeRefOptArgs can start with TYPE
|
|
1172
1143
|
( typeStruct[ $art.items ]
|
|
1173
1144
|
nullability[ $art.items ]?
|
|
1174
|
-
misplacedAnnotations[ $annos, 'syntax-anno-after-struct' ]?
|
|
1175
1145
|
| typeTypeOf[ $art.items ]
|
|
1176
1146
|
nullability[ $art.items ]?
|
|
1177
|
-
{ this.docComment( $
|
|
1178
|
-
annotationAssignment_ll1[ $
|
|
1147
|
+
{ this.docComment( $art ); }
|
|
1148
|
+
annotationAssignment_ll1[ $art ]*
|
|
1179
1149
|
| typeRefOptArgs[ $art.items ]
|
|
1180
|
-
nullability[ $art.items ]?
|
|
1181
|
-
{ this.docComment( $
|
|
1182
|
-
annotationAssignment_ll1[ $
|
|
1150
|
+
nullability[ $art.items ]? // only if not followed by `enum`
|
|
1151
|
+
{ this.docComment( $art ); }
|
|
1152
|
+
annotationAssignment_ll1[ $art ]*
|
|
1183
1153
|
(
|
|
1154
|
+
{ if ($art.items.notNull) {
|
|
1155
|
+
this.message( 'syntax-unexpected-null', $art.items.notNull.location,
|
|
1156
|
+
{ keyword: $art.items.notNull.val ? 'not null' : 'null' } );
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1184
1159
|
ENUM '{' { $art.items.enum = this.createDict(); }
|
|
1185
1160
|
enumSymbolDef[ $art.items ]*
|
|
1186
|
-
'}' { this.
|
|
1187
|
-
|
|
1161
|
+
'}' { this.finalizeDictOrArray( $art.items.enum ); }
|
|
1162
|
+
nullability[ $art.items ]?
|
|
1188
1163
|
)?
|
|
1189
1164
|
)
|
|
1190
1165
|
requiredSemi // also req after struct/enum
|
|
1191
1166
|
|
|
|
1192
1167
|
typeTypeOf[ $art ] elementProperties[ $art ]?
|
|
1193
|
-
{ this.docComment( $
|
|
1194
|
-
annotationAssignment_ll1[ $
|
|
1168
|
+
{ this.docComment( $art ); }
|
|
1169
|
+
annotationAssignment_ll1[ $art ]*
|
|
1195
1170
|
requiredSemi // also req after foreign key spec
|
|
1196
1171
|
|
|
|
1197
1172
|
l=LOCALIZED { $art.localized = this.valueWithTokenLocation( true, $l ); }
|
|
1198
1173
|
typeRefOptArgs[ $art ]
|
|
1199
|
-
{ this.docComment( $
|
|
1200
|
-
annotationAssignment_ll1[ $
|
|
1174
|
+
{ this.docComment( $art ); }
|
|
1175
|
+
annotationAssignment_ll1[ $art ]*
|
|
1201
1176
|
( elementProperties[ $art ]
|
|
1202
|
-
{ this.docComment( $
|
|
1203
|
-
annotationAssignment_ll1[ $
|
|
1177
|
+
{ this.docComment( $art ); }
|
|
1178
|
+
annotationAssignment_ll1[ $art ]*
|
|
1204
1179
|
)?
|
|
1205
1180
|
requiredSemi
|
|
1206
1181
|
|
|
|
1207
1182
|
typeRefOptArgs[ $art ]
|
|
1208
|
-
{ this.docComment( $
|
|
1209
|
-
annotationAssignment_ll1[ $
|
|
1183
|
+
{ this.docComment( $art ); }
|
|
1184
|
+
annotationAssignment_ll1[ $art ]*
|
|
1210
1185
|
(
|
|
1211
1186
|
ENUM '{' { $art.enum = this.createDict(); }
|
|
1212
1187
|
enumSymbolDef[ $art ]*
|
|
1213
|
-
'}' { this.
|
|
1188
|
+
'}' { this.finalizeDictOrArray( $art.enum ); }
|
|
1214
1189
|
elementProperties[ $art ]?
|
|
1215
|
-
misplacedAnnotations[ $annos, 'syntax-anno-after-enum' ]?
|
|
1216
1190
|
|
|
|
1217
1191
|
elementProperties[ $art ]
|
|
1218
|
-
{ this.docComment( $
|
|
1219
|
-
annotationAssignment_ll1[ $
|
|
1192
|
+
{ this.docComment( $art ); }
|
|
1193
|
+
annotationAssignment_ll1[ $art ]*
|
|
1220
1194
|
)?
|
|
1221
1195
|
requiredSemi // also req after enum spec
|
|
1222
1196
|
)
|
|
@@ -1229,65 +1203,45 @@ elementDefInner[ outer, loc, annos, allowEq ] returns[ art ]
|
|
|
1229
1203
|
else if ($e.expr)
|
|
1230
1204
|
$art.value = $e.expr;
|
|
1231
1205
|
}
|
|
1232
|
-
{ this.docComment( $
|
|
1233
|
-
annotationAssignment_ll1[ $
|
|
1206
|
+
{ this.docComment( $art ); }
|
|
1207
|
+
annotationAssignment_ll1[ $art ]* // for enum symbol def via EXTEND
|
|
1234
1208
|
requiredSemi
|
|
1235
1209
|
)
|
|
1236
1210
|
;
|
|
1237
1211
|
|
|
1238
|
-
extendElement[
|
|
1239
|
-
@after{ /* #ATN 1 */ this.attachLocation($art); }
|
|
1212
|
+
extendElement[ art, outer ]
|
|
1213
|
+
@after{ /* #ATN 1 */ this.attachLocation( $art ); }
|
|
1240
1214
|
:
|
|
1241
1215
|
// #ATN: element name can be ELEMENT
|
|
1242
|
-
expected=ELEMENT
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
extendWithOptElements[ $art, $annos ]
|
|
1247
|
-
;
|
|
1248
|
-
|
|
1249
|
-
bracedSelectItemListDef[ query ]
|
|
1250
|
-
:
|
|
1251
|
-
'{'
|
|
1252
|
-
{ if (!$query.columns) $query.columns = []; } // set it early to avoid "wildcard" errors
|
|
1253
|
-
(
|
|
1254
|
-
selectItemDef[ $query.columns ]
|
|
1255
|
-
( ',' { if (this.isStraightBefore("}")) break; } // allow ',' before '}'
|
|
1256
|
-
selectItemDef[ $query.columns ]
|
|
1257
|
-
)*
|
|
1258
|
-
)?
|
|
1259
|
-
'}'
|
|
1216
|
+
( expected=ELEMENT { $art.expectedKind = 'element'; } )?
|
|
1217
|
+
name=ident['Element']
|
|
1218
|
+
{ this.addDef( $art, $outer, 'elements', 'extend', $name.id ); }
|
|
1219
|
+
extendWithOptElements[ $art, $art ]
|
|
1260
1220
|
;
|
|
1261
1221
|
|
|
1262
|
-
selectItemDef[ outer ] locals[
|
|
1263
|
-
@after{ if ($
|
|
1222
|
+
selectItemDef[ outer ] locals[ art ]
|
|
1223
|
+
@after{ if ($art) this.attachLocation( $art ); }
|
|
1264
1224
|
:
|
|
1265
1225
|
star='*'
|
|
1266
1226
|
{ $outer.push( this.valueWithTokenLocation( '*', $star ) ); }
|
|
1267
1227
|
|
|
|
1268
|
-
{ this.docComment( $
|
|
1269
|
-
annotationAssignment_atn[ $
|
|
1228
|
+
{ $art = {};; this.docComment( $art ); }
|
|
1229
|
+
annotationAssignment_atn[ $art ]*
|
|
1270
1230
|
// VIRTUAL is keyword, except if before the following tokens texts:
|
|
1271
1231
|
{ this.setLocalToken( 'VIRTUAL', 'VIRTUAL', /^([,.:\[@]|as)$/i ) ; } // not '{'
|
|
1272
|
-
virtual=VIRTUAL?
|
|
1273
|
-
key=KEY?
|
|
1274
|
-
|
|
1275
|
-
{
|
|
1276
|
-
if ($virtual) $art.art.virtual = this.valueWithTokenLocation( true, $virtual );
|
|
1277
|
-
if ($key) $art.art.key = this.valueWithTokenLocation( true, $key );
|
|
1278
|
-
}
|
|
1232
|
+
( virtual=VIRTUAL { $art.virtual = this.valueWithTokenLocation( true, $virtual ); } )?
|
|
1233
|
+
( key=KEY { $art.key = this.valueWithTokenLocation( true, $key ); } )?
|
|
1234
|
+
selectItemDefBody[ $art, $outer ]
|
|
1279
1235
|
;
|
|
1280
1236
|
|
|
1281
|
-
selectItemDefBody[
|
|
1282
|
-
@after{ /* #ATN 2 */
|
|
1237
|
+
selectItemDefBody[ art, outer ]
|
|
1238
|
+
@after{ /* #ATN 2 */ }
|
|
1283
1239
|
:
|
|
1240
|
+
{ $outer.push( $art ); }
|
|
1284
1241
|
(
|
|
1285
|
-
e=expression
|
|
1242
|
+
e=expression { $art.value = $e.expr; }
|
|
1286
1243
|
// we cannot use 'condition' instead, as long as we allow aliases without
|
|
1287
1244
|
// AS (using rule 'ident' instead of 'identNoKeyword') -> ambiguities
|
|
1288
|
-
{
|
|
1289
|
-
$art = this.addItem( $outer, null, null, $annos, { value: $e.expr } );
|
|
1290
|
-
}
|
|
1291
1245
|
( AS n1=ident['Item'] { $art.name = $n1.id }
|
|
1292
1246
|
| n2=ident['Item'] { $art.name = this.fragileAlias( $n2.id, true ); }
|
|
1293
1247
|
| { if (this.getCurrentToken().text !== '.') this.classifyImplicitName( 'Item', $e.expr ); }
|
|
@@ -1311,13 +1265,12 @@ selectItemDefBody[ outer, annos ] returns[ art = {} ]
|
|
|
1311
1265
|
)
|
|
1312
1266
|
)?
|
|
1313
1267
|
|
|
|
1314
|
-
{ $art = this.addItem( $outer, null, null, $annos ); }
|
|
1315
1268
|
selectItemInlineList[ $art, 'expand' ]
|
|
1316
1269
|
excludingClause[ $art ]?
|
|
1317
1270
|
AS n1=ident['Item'] { $art.name = $n1.id }
|
|
1318
1271
|
)
|
|
1319
|
-
{ this.docComment( $
|
|
1320
|
-
annotationAssignment_fix[ $
|
|
1272
|
+
{ this.docComment( $art ); }
|
|
1273
|
+
annotationAssignment_fix[ $art ]*
|
|
1321
1274
|
( ':'
|
|
1322
1275
|
// #ATN: typeRefOptArgs can start with TYPE, REDIRECTED
|
|
1323
1276
|
( re=REDIRECTED to=TO
|
|
@@ -1326,15 +1279,15 @@ selectItemDefBody[ outer, annos ] returns[ art = {} ]
|
|
|
1326
1279
|
(
|
|
1327
1280
|
typeAssociationCont[ $art ]
|
|
1328
1281
|
|
|
|
1329
|
-
{ this.docComment( $
|
|
1330
|
-
annotationAssignment_ll1[ $
|
|
1282
|
+
{ this.docComment( $art ); }
|
|
1283
|
+
annotationAssignment_ll1[ $art ]*
|
|
1331
1284
|
)
|
|
1332
1285
|
| typeTypeOf[ $art ]
|
|
1333
|
-
{ this.docComment( $
|
|
1334
|
-
annotationAssignment_ll1[ $
|
|
1335
|
-
| typeRefOptArgs[ $art ]
|
|
1336
|
-
{ this.docComment( $
|
|
1337
|
-
annotationAssignment_ll1[ $
|
|
1286
|
+
{ this.docComment( $art ); }
|
|
1287
|
+
annotationAssignment_ll1[ $art ]*
|
|
1288
|
+
| typeRefOptArgs[ $art ]
|
|
1289
|
+
{ this.docComment( $art ); }
|
|
1290
|
+
annotationAssignment_ll1[ $art ]*
|
|
1338
1291
|
|
|
|
1339
1292
|
typeAssociationBase[ $art, false ]
|
|
1340
1293
|
// #ATN: path could start with MANY or ONE - make sure a token follows in same rule!
|
|
@@ -1345,28 +1298,39 @@ selectItemDefBody[ outer, annos ] returns[ art = {} ]
|
|
|
1345
1298
|
)?
|
|
1346
1299
|
;
|
|
1347
1300
|
|
|
1301
|
+
bracedSelectItemListDef[ query ]
|
|
1302
|
+
:
|
|
1303
|
+
'{' { $query.columns = this.createArray(); }
|
|
1304
|
+
(
|
|
1305
|
+
selectItemDef[ $query.columns ]
|
|
1306
|
+
( ',' { if (this.isStraightBefore("}")) break; } // allow ',' before '}'
|
|
1307
|
+
selectItemDef[ $query.columns ]
|
|
1308
|
+
)*
|
|
1309
|
+
)?
|
|
1310
|
+
'}' { this.finalizeDictOrArray( $query.columns ); }
|
|
1311
|
+
;
|
|
1312
|
+
|
|
1348
1313
|
selectItemInlineList[ art, clause ]
|
|
1349
1314
|
:
|
|
1350
|
-
'{'
|
|
1351
|
-
{ $art[$clause] = []; }
|
|
1315
|
+
'{' { $art[$clause] = this.createArray(); }
|
|
1352
1316
|
(
|
|
1353
1317
|
selectItemInlineDef[ $art[$clause] ]
|
|
1354
1318
|
( ',' { if (this.isStraightBefore("}")) break; } // allow ',' before '}'
|
|
1355
1319
|
selectItemInlineDef[ $art[$clause] ]
|
|
1356
1320
|
)*
|
|
1357
1321
|
)?
|
|
1358
|
-
'}'
|
|
1322
|
+
'}' { this.finalizeDictOrArray( $art[$clause] ); }
|
|
1359
1323
|
;
|
|
1360
1324
|
|
|
1361
|
-
selectItemInlineDef[ outer ] locals[
|
|
1362
|
-
@after{ if ($
|
|
1325
|
+
selectItemInlineDef[ outer ] locals[ art ]
|
|
1326
|
+
@after{ if ($art) this.attachLocation( $art ); }
|
|
1363
1327
|
:
|
|
1364
1328
|
star='*'
|
|
1365
1329
|
{ $outer.push( this.valueWithTokenLocation( '*', $star ) ); }
|
|
1366
1330
|
|
|
|
1367
|
-
{ this.docComment( $
|
|
1368
|
-
annotationAssignment_atn[ $
|
|
1369
|
-
|
|
1331
|
+
{ $art = {};; this.docComment( $art ); }
|
|
1332
|
+
annotationAssignment_atn[ $art ]*
|
|
1333
|
+
selectItemDefBody[ $art, $outer ]
|
|
1370
1334
|
;
|
|
1371
1335
|
|
|
1372
1336
|
parameterListDef[ art ]
|
|
@@ -1380,51 +1344,22 @@ parameterListDef[ art ]
|
|
|
1380
1344
|
parameterDef[ $art ]
|
|
1381
1345
|
)*
|
|
1382
1346
|
)?
|
|
1383
|
-
')' { this.
|
|
1347
|
+
')' { this.finalizeDictOrArray( $art.params ); }
|
|
1384
1348
|
;
|
|
1385
1349
|
|
|
1386
|
-
parameterDef[ outer ] locals[ art
|
|
1387
|
-
@after { this.attachLocation($art); }
|
|
1350
|
+
parameterDef[ outer ] locals[ art = {} ]
|
|
1351
|
+
@after { this.attachLocation( $art ); }
|
|
1388
1352
|
:
|
|
1389
|
-
{ this.docComment( $
|
|
1390
|
-
annotationAssignment_ll1[ $
|
|
1353
|
+
{ this.docComment( $art ); }
|
|
1354
|
+
annotationAssignment_ll1[ $art ]*
|
|
1391
1355
|
name=ident['Param']
|
|
1392
|
-
{
|
|
1393
|
-
this.docComment( $
|
|
1394
|
-
annotationAssignment_fix[ $
|
|
1356
|
+
{ this.addDef( $art, $outer, 'params', 'param', $name.id );
|
|
1357
|
+
this.docComment( $art ); }
|
|
1358
|
+
annotationAssignment_fix[ $art ]*
|
|
1395
1359
|
typeSpec[ $art ]
|
|
1396
1360
|
defaultValue[ $art ]?
|
|
1397
|
-
{ this.docComment( $
|
|
1398
|
-
annotationAssignment_ll1[ $
|
|
1399
|
-
;
|
|
1400
|
-
|
|
1401
|
-
entityParameters[ art ]
|
|
1402
|
-
:
|
|
1403
|
-
'(' { $art.params = this.createDict(); }
|
|
1404
|
-
// also empty param list (we might do some hacking later to allow reserved words)
|
|
1405
|
-
// see annotationAssignment_paren
|
|
1406
|
-
(
|
|
1407
|
-
entityParameterDef[ $art ]
|
|
1408
|
-
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
1409
|
-
entityParameterDef[ $art ]
|
|
1410
|
-
)*
|
|
1411
|
-
)?
|
|
1412
|
-
')' { this.setDictEndLocation( $art.params ); }
|
|
1413
|
-
;
|
|
1414
|
-
|
|
1415
|
-
entityParameterDef[ outer ] locals[ art, annos = [] ]
|
|
1416
|
-
@after { this.attachLocation($art); }
|
|
1417
|
-
:
|
|
1418
|
-
{ this.docComment( $annos ); }
|
|
1419
|
-
annotationAssignment_ll1[ $annos ]*
|
|
1420
|
-
name=ident['Param']
|
|
1421
|
-
{ $art = this.addDef( $outer, 'params', 'param', $name.id, $annos );
|
|
1422
|
-
this.docComment( $annos ); }
|
|
1423
|
-
annotationAssignment_fix[ $annos ]*
|
|
1424
|
-
typeSpec[ $art ]
|
|
1425
|
-
defaultValue[ $art ]?
|
|
1426
|
-
{ this.docComment( $annos ); }
|
|
1427
|
-
annotationAssignment_ll1[ $annos ]*
|
|
1361
|
+
{ this.docComment( $art ); }
|
|
1362
|
+
annotationAssignment_ll1[ $art ]*
|
|
1428
1363
|
;
|
|
1429
1364
|
|
|
1430
1365
|
nullability[ art ]
|
|
@@ -1451,21 +1386,25 @@ elementProperties[ elem ]
|
|
|
1451
1386
|
|
|
1452
1387
|
// View definitions ----------------------------------------------------------
|
|
1453
1388
|
|
|
1454
|
-
viewDef[
|
|
1455
|
-
@after { this.attachLocation($art); }
|
|
1389
|
+
viewDef[ art, outer ] locals[ name = {} ]
|
|
1390
|
+
@after { this.attachLocation( $art ); }
|
|
1456
1391
|
:
|
|
1457
1392
|
v=VIEW simplePath[ $name, 'Entity' ]
|
|
1458
|
-
{ $art
|
|
1459
|
-
this.
|
|
1460
|
-
|
|
1393
|
+
{ $art['$'+'syntax'] = 'view';
|
|
1394
|
+
this.addDef( $art, $outer, 'artifacts', 'entity', $name );
|
|
1395
|
+
this.docComment( $art ); }
|
|
1396
|
+
annotationAssignment_fix[ $art ]*
|
|
1461
1397
|
(
|
|
1462
|
-
|
|
1398
|
+
parameterListDef[ $art ]
|
|
1463
1399
|
|
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1400
|
+
// TODO: warning deprecated?
|
|
1401
|
+
( HideAlternatives | WITH ) { $art.params = this.createDict(); }
|
|
1402
|
+
PARAMETERS
|
|
1403
|
+
parameterDef[ $art ]
|
|
1404
|
+
( ',' parameterDef[ $art ] )* // no optional final ',' here
|
|
1405
|
+
{ this.finalizeDictOrArray( $art.params ); }
|
|
1467
1406
|
)?
|
|
1468
|
-
AS qe=queryExpression { $art.query = $qe.query; }
|
|
1407
|
+
AS qe=queryExpression { $art.query = $qe.query; }
|
|
1469
1408
|
// TODO check ANTLR: bad msg with 'view V as'<eof> but 'view V as FOO' is fine
|
|
1470
1409
|
requiredSemi
|
|
1471
1410
|
;
|
|
@@ -1496,12 +1435,12 @@ typeSpec[ art ] // for params
|
|
|
1496
1435
|
(
|
|
1497
1436
|
ENUM '{' { $art.enum = this.createDict(); }
|
|
1498
1437
|
enumSymbolDef[ $art ]*
|
|
1499
|
-
'}' { this.
|
|
1438
|
+
'}' { this.finalizeDictOrArray( $art.enum ); }
|
|
1500
1439
|
)?
|
|
1501
1440
|
)
|
|
1502
1441
|
;
|
|
1503
1442
|
|
|
1504
|
-
returnTypeSpec[ art
|
|
1443
|
+
returnTypeSpec[ art ]
|
|
1505
1444
|
@after{ /* #ATN 1 */ }
|
|
1506
1445
|
:
|
|
1507
1446
|
ret=RETURNS { $art.returns = { location: this.tokenLocation( $ret ), kind: 'param' }; }
|
|
@@ -1517,17 +1456,15 @@ returnTypeSpec[ art, annos ]
|
|
|
1517
1456
|
(
|
|
1518
1457
|
ENUM '{' { $art.returns.enum = this.createDict(); }
|
|
1519
1458
|
enumSymbolDef[ $art.returns ]*
|
|
1520
|
-
'}' { this.
|
|
1521
|
-
|
|
|
1522
|
-
misplacedAnnotations[ $annos, 'syntax-anno-after-params' ]
|
|
1459
|
+
'}' { this.finalizeDictOrArray( $art.returns.enum ); }
|
|
1523
1460
|
)?
|
|
1524
1461
|
)
|
|
1525
1462
|
|
|
1526
|
-
requiredSemi // currently for all - might change if we get rid of the misplaced annos
|
|
1463
|
+
requiredSemi // currently for all - might change if we get rid of the misplaced annos (TODO: Now removed)
|
|
1527
1464
|
;
|
|
1528
1465
|
|
|
1529
1466
|
|
|
1530
|
-
typeSpecSemi[ art
|
|
1467
|
+
typeSpecSemi[ art ] // with 'includes', for type and annotation defs
|
|
1531
1468
|
@after{ /* #ATN 3 */ }
|
|
1532
1469
|
:
|
|
1533
1470
|
typeStruct[ $art ]
|
|
@@ -1565,18 +1502,28 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
|
|
|
1565
1502
|
optionalSemi
|
|
1566
1503
|
| typeTypeOf[ $art.items ]
|
|
1567
1504
|
nullability[ $art.items ]?
|
|
1568
|
-
{ this.docComment( $
|
|
1569
|
-
annotationAssignment_ll1[ $
|
|
1505
|
+
{ this.docComment( $art ); }
|
|
1506
|
+
annotationAssignment_ll1[ $art ]*
|
|
1570
1507
|
requiredSemi
|
|
1571
1508
|
| typeRefOptArgs[ $art.items ]
|
|
1572
|
-
nullability[ $art.items ]?
|
|
1573
|
-
{ this.docComment( $
|
|
1574
|
-
annotationAssignment_ll1[ $
|
|
1509
|
+
nullability[ $art.items ]? // only if not followed by `enum`
|
|
1510
|
+
{ this.docComment( $art ); }
|
|
1511
|
+
annotationAssignment_ll1[ $art ]*
|
|
1575
1512
|
(
|
|
1513
|
+
{ if ($art.items.notNull) {
|
|
1514
|
+
this.message( 'syntax-unexpected-null', $art.items.notNull.location,
|
|
1515
|
+
{ keyword: $art.items.notNull.val ? 'not null' : 'null' } );
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1576
1518
|
ENUM '{' { $art.items.enum = this.createDict(); }
|
|
1577
1519
|
enumSymbolDef[ $art.items ]*
|
|
1578
|
-
'}' { this.
|
|
1579
|
-
|
|
1520
|
+
'}' { this.finalizeDictOrArray( $art.items.enum ); }
|
|
1521
|
+
(
|
|
1522
|
+
nullability[ $art.items ]
|
|
1523
|
+
requiredSemi
|
|
1524
|
+
|
|
|
1525
|
+
optionalSemi
|
|
1526
|
+
)
|
|
1580
1527
|
|
|
|
1581
1528
|
requiredSemi
|
|
1582
1529
|
)
|
|
@@ -1584,14 +1531,14 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
|
|
|
1584
1531
|
|
|
|
1585
1532
|
typeTypeOf[ $art ]
|
|
1586
1533
|
defaultValue[ $art ]?
|
|
1587
|
-
{ this.docComment( $
|
|
1588
|
-
annotationAssignment_ll1[ $
|
|
1534
|
+
{ this.docComment( $art ); }
|
|
1535
|
+
annotationAssignment_ll1[ $art ]* requiredSemi
|
|
1589
1536
|
|
|
|
1590
1537
|
l=LOCALIZED { $art.localized = this.valueWithTokenLocation( true, $l ); }
|
|
1591
1538
|
typeRefOptArgs[ $art ]
|
|
1592
1539
|
defaultValue[ $art ]?
|
|
1593
|
-
{ this.docComment( $
|
|
1594
|
-
annotationAssignment_ll1[ $
|
|
1540
|
+
{ this.docComment( $art ); }
|
|
1541
|
+
annotationAssignment_ll1[ $art ]*
|
|
1595
1542
|
requiredSemi
|
|
1596
1543
|
|
|
|
1597
1544
|
// alt lookahead includes MANY '{'
|
|
@@ -1599,12 +1546,12 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
|
|
|
1599
1546
|
simplePath[ $art.type, 'artref' ]
|
|
1600
1547
|
(
|
|
1601
1548
|
typeRefArgs[ $art ]
|
|
1602
|
-
{ this.docComment( $
|
|
1603
|
-
annotationAssignment_ll1[ $
|
|
1549
|
+
{ this.docComment( $art ); }
|
|
1550
|
+
annotationAssignment_ll1[ $art ]*
|
|
1604
1551
|
(
|
|
1605
1552
|
ENUM '{' { $art.enum = this.createDict(); }
|
|
1606
1553
|
enumSymbolDef[ $art ]*
|
|
1607
|
-
'}' { this.
|
|
1554
|
+
'}' { this.finalizeDictOrArray( $art.enum ); }
|
|
1608
1555
|
(
|
|
1609
1556
|
optionalSemi
|
|
1610
1557
|
|
|
|
@@ -1619,12 +1566,12 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
|
|
|
1619
1566
|
':' // with element, e.g. `type T : E:elem enum { ... }`
|
|
1620
1567
|
{ $art.type.scope = $art.type.path.length; }
|
|
1621
1568
|
simplePath[ $art.type, 'ref']
|
|
1622
|
-
{ this.docComment( $
|
|
1623
|
-
annotationAssignment_ll1[ $
|
|
1569
|
+
{ this.docComment( $art ); }
|
|
1570
|
+
annotationAssignment_ll1[ $art ]*
|
|
1624
1571
|
(
|
|
1625
1572
|
ENUM '{' { $art.enum = this.createDict(); }
|
|
1626
1573
|
enumSymbolDef[ $art ]*
|
|
1627
|
-
'}' { this.
|
|
1574
|
+
'}' { this.finalizeDictOrArray( $art.enum ); }
|
|
1628
1575
|
(
|
|
1629
1576
|
optionalSemi
|
|
1630
1577
|
|
|
|
@@ -1636,12 +1583,12 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
|
|
|
1636
1583
|
requiredSemi
|
|
1637
1584
|
)
|
|
1638
1585
|
|
|
|
1639
|
-
{ this.docComment( $
|
|
1640
|
-
annotationAssignment_ll1[ $
|
|
1586
|
+
{ this.docComment( $art ); }
|
|
1587
|
+
annotationAssignment_ll1[ $art ]*
|
|
1641
1588
|
(
|
|
1642
1589
|
ENUM '{' { $art.enum = this.createDict(); }
|
|
1643
1590
|
enumSymbolDef[ $art ]*
|
|
1644
|
-
'}' { this.
|
|
1591
|
+
'}' { this.finalizeDictOrArray( $art.enum ); }
|
|
1645
1592
|
(
|
|
1646
1593
|
optionalSemi
|
|
1647
1594
|
|
|
|
@@ -1669,7 +1616,7 @@ typeStruct[ art, attachLoc = false ]
|
|
|
1669
1616
|
:
|
|
1670
1617
|
'{' { $art.elements = this.createDict(); }
|
|
1671
1618
|
elementDef[ $art ]*
|
|
1672
|
-
'}' { this.
|
|
1619
|
+
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
1673
1620
|
;
|
|
1674
1621
|
|
|
1675
1622
|
typeCompoStruct[ art ]
|
|
@@ -1677,7 +1624,7 @@ typeCompoStruct[ art ]
|
|
|
1677
1624
|
:
|
|
1678
1625
|
COMPOSITIONofBRACE { $art.elements = this.createDict(); }
|
|
1679
1626
|
elementDef[ $art ]*
|
|
1680
|
-
'}' { this.
|
|
1627
|
+
'}' { this.finalizeDictOrArray( $art.elements ); }
|
|
1681
1628
|
;
|
|
1682
1629
|
|
|
1683
1630
|
typeArray[ art ]
|
|
@@ -1699,7 +1646,7 @@ typeArray[ art ]
|
|
|
1699
1646
|
(
|
|
1700
1647
|
ENUM '{' { $art.items.enum = this.createDict(); }
|
|
1701
1648
|
enumSymbolDef[ $art.items ]*
|
|
1702
|
-
'}' { this.
|
|
1649
|
+
'}' { this.finalizeDictOrArray( $art.items.enum ); }
|
|
1703
1650
|
)?
|
|
1704
1651
|
)
|
|
1705
1652
|
;
|
|
@@ -1728,33 +1675,31 @@ typeAssociationCont[ art ]
|
|
|
1728
1675
|
:
|
|
1729
1676
|
(
|
|
1730
1677
|
'{' { $art.foreignKeys = this.createDict(); }
|
|
1731
|
-
{ this.addDef( $art, 'foreignKeys' ); }
|
|
1732
1678
|
(
|
|
1733
1679
|
foreignKey[ $art ]
|
|
1734
1680
|
( ',' { if (this.isStraightBefore("}")) break; } // allow ',' before '}'
|
|
1735
1681
|
foreignKey[ $art ]
|
|
1736
1682
|
)*
|
|
1737
1683
|
)?
|
|
1738
|
-
'}' { this.
|
|
1684
|
+
'}' { this.finalizeDictOrArray( $art.foreignKeys ); }
|
|
1739
1685
|
|
|
|
1740
1686
|
ON cond=condition
|
|
1741
1687
|
{ $art.on=$cond.cond; }
|
|
1742
1688
|
)
|
|
1743
1689
|
;
|
|
1744
1690
|
|
|
1745
|
-
typeAssociationElementCont[ art
|
|
1691
|
+
typeAssociationElementCont[ art ] // including Composition
|
|
1746
1692
|
// optional NULL / NOT NULL for managed association only
|
|
1747
1693
|
:
|
|
1748
1694
|
(
|
|
1749
1695
|
'{' { $art.foreignKeys = this.createDict(); }
|
|
1750
|
-
{ this.addDef( $art, 'foreignKeys' ); }
|
|
1751
1696
|
(
|
|
1752
1697
|
foreignKey[ $art ]
|
|
1753
1698
|
( ',' { if (this.isStraightBefore("}")) break; } // allow ',' before '}'
|
|
1754
1699
|
foreignKey[ $art ]
|
|
1755
1700
|
)*
|
|
1756
1701
|
)?
|
|
1757
|
-
'}' { this.
|
|
1702
|
+
'}' { this.finalizeDictOrArray( $art.foreignKeys ); }
|
|
1758
1703
|
nullability[ $art ]?
|
|
1759
1704
|
|
|
|
1760
1705
|
ON cond=condition
|
|
@@ -1762,8 +1707,8 @@ typeAssociationElementCont[ art, annos ] // including Composition
|
|
|
1762
1707
|
|
|
|
1763
1708
|
nullability[ $art ]
|
|
1764
1709
|
)?
|
|
1765
|
-
{ this.docComment( $
|
|
1766
|
-
annotationAssignment_ll1[ $
|
|
1710
|
+
{ this.docComment( $art ); }
|
|
1711
|
+
annotationAssignment_ll1[ $art ]*
|
|
1767
1712
|
requiredSemi // also req after foreign key spec
|
|
1768
1713
|
;
|
|
1769
1714
|
|
|
@@ -1817,10 +1762,9 @@ cardinality[ art ] locals[ card = {} ]
|
|
|
1817
1762
|
foreignKey[ outer ] locals[ art = {}, elem = {} ]
|
|
1818
1763
|
@after { this.attachLocation($art); }
|
|
1819
1764
|
:
|
|
1820
|
-
simplePath[ $elem, 'ref' ]
|
|
1765
|
+
simplePath[ $elem, 'ref' ] { $art.targetElement = $elem; }
|
|
1821
1766
|
( AS name=ident['Key'] )?
|
|
1822
|
-
{
|
|
1823
|
-
undefined, { targetElement: $elem } ); }
|
|
1767
|
+
{ this.addDef( $art, $outer, 'foreignKeys', 'key', ($ctx.name) ? $name.id : $elem.path ); }
|
|
1824
1768
|
;
|
|
1825
1769
|
|
|
1826
1770
|
typeTypeOf[ art ] locals[ _sync = 'nop' ]
|
|
@@ -1852,11 +1796,11 @@ typeRefOptArgs[ art ]
|
|
|
1852
1796
|
|
|
1853
1797
|
typeRefArgs[ art ]
|
|
1854
1798
|
:
|
|
1855
|
-
paren='('
|
|
1799
|
+
paren='(' { $art['$'+'typeArgs'] = this.createArray(); }
|
|
1856
1800
|
(
|
|
1857
1801
|
// unnamed arguments
|
|
1858
1802
|
head=Number
|
|
1859
|
-
{ $art['$'+'typeArgs']
|
|
1803
|
+
{ $art['$'+'typeArgs'].push( this.numberLiteral( $head ) ); }
|
|
1860
1804
|
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
1861
1805
|
(
|
|
1862
1806
|
v=VARIABLE
|
|
@@ -1880,7 +1824,7 @@ typeRefArgs[ art ]
|
|
|
1880
1824
|
typeNamedArg[ $art ]
|
|
1881
1825
|
)*
|
|
1882
1826
|
)
|
|
1883
|
-
')'
|
|
1827
|
+
')'{ this.finalizeDictOrArray( $art['$'+'typeArgs']); }
|
|
1884
1828
|
;
|
|
1885
1829
|
|
|
1886
1830
|
typeNamedArg[ art ] locals[ arg = '' ]
|
|
@@ -2026,7 +1970,7 @@ overClause returns [ over ]
|
|
|
2026
1970
|
@after { this.attachLocation( $over ); }
|
|
2027
1971
|
:
|
|
2028
1972
|
o=OVER { $over = { op: this.valueWithTokenLocation( 'over', $o ) , args: [] } }
|
|
2029
|
-
'('
|
|
1973
|
+
'(' // TODO: check whether an extra location could be useful
|
|
2030
1974
|
( pb=partitionByClause { $over.args.push( $pb.expr ); } )?
|
|
2031
1975
|
( ob=overOrderByClause { $over.args.push( $ob.expr ); } )?
|
|
2032
1976
|
( wf=windowFrameClause { $over.args.push( $wf.wf ); } )?
|
|
@@ -2079,13 +2023,13 @@ queryPrimary returns[ query = {} ]
|
|
|
2079
2023
|
(
|
|
2080
2024
|
mixin=MIXIN '{' { $query.mixin = this.createDict(); }
|
|
2081
2025
|
mixinElementDef[ $query ]*
|
|
2082
|
-
'}' { this.
|
|
2026
|
+
'}' { this.finalizeDictOrArray( $query.mixin ); }
|
|
2083
2027
|
INTO
|
|
2084
2028
|
)?
|
|
2085
2029
|
( ad=( ALL | DISTINCT ) // TODO: or directly after SELECT ?
|
|
2086
2030
|
{ $query.quantifier = this.valueWithTokenLocation( $ad.text.toLowerCase(), $ad ); }
|
|
2087
2031
|
)?
|
|
2088
|
-
bracedSelectItemListDef[ $query ]?
|
|
2032
|
+
bracedSelectItemListDef[ $query, 'columns' ]?
|
|
2089
2033
|
excludingClause[ $query ]?
|
|
2090
2034
|
|
|
|
2091
2035
|
( ad=( ALL | DISTINCT ) // TODO: or directly after SELECT ?
|
|
@@ -2429,7 +2373,9 @@ expressionTerm returns [ expr ] locals [ op, args = [] ]
|
|
|
2429
2373
|
}
|
|
2430
2374
|
)
|
|
2431
2375
|
|
|
|
2432
|
-
qm=
|
|
2376
|
+
qm= '?' // is automatically not mentioned as CC candidate
|
|
2377
|
+
// if we have an HideAlternatives here, we would block it to use it in
|
|
2378
|
+
// parallel to an expression (would produce adaptivePredict() otherwise)
|
|
2433
2379
|
{ $expr = { param: this.valueWithTokenLocation( '?', $qm ), scope: 'param' };
|
|
2434
2380
|
this.csnParseOnly( 'Dynamic parameter "?" is not supported', $qm );
|
|
2435
2381
|
}
|
|
@@ -2457,39 +2403,12 @@ expressionTerm returns [ expr ] locals [ op, args = [] ]
|
|
|
2457
2403
|
;
|
|
2458
2404
|
|
|
2459
2405
|
specialFunction returns [ ret = { } ] locals[ art = {} ]
|
|
2460
|
-
@after{ /* #ATN 1 */ }
|
|
2461
2406
|
:
|
|
2462
|
-
|
|
2463
|
-
{ $ret = this.functionAst( $fun, $open ); }
|
|
2464
|
-
// #ATN: we do not want to reserve these three optional keywords
|
|
2465
|
-
(
|
|
2466
|
-
t=( LEADING | TRAILING | BOTH ) { $ret.args[0].args.push( $t.text ); }
|
|
2467
|
-
( e=expression { $ret.args[0].args.push( $e.expr ); } )?
|
|
2468
|
-
t=FROM e=expression { $ret.args[0].args.push( $t.text, $e.expr ); }
|
|
2469
|
-
|
|
|
2470
|
-
e=expression
|
|
2471
|
-
(
|
|
2472
|
-
{ $ret.args[0].args.push( $e.expr ); }
|
|
2473
|
-
t=FROM e=expression
|
|
2474
|
-
{ $ret.args[0].args.push( $t.text, $e.expr ); }
|
|
2475
|
-
|
|
|
2476
|
-
{ $ret.args[0] = $e.expr; }
|
|
2477
|
-
)
|
|
2478
|
-
)
|
|
2479
|
-
')'
|
|
2480
|
-
|
|
|
2481
|
-
fun=EXTRACT open='('
|
|
2482
|
-
{ $ret = this.functionAst( $fun, $open ); }
|
|
2483
|
-
t=( YEAR | MONTH | DAY | HOUR | MINUTE | SECOND )
|
|
2484
|
-
f=FROM e=expression
|
|
2485
|
-
{ $ret.args[0].args.push( $t.text, $f.text, $e.expr ); }
|
|
2486
|
-
')'
|
|
2487
|
-
|
|
|
2488
|
-
ca=CAST open='('
|
|
2407
|
+
ca=CAST '(' // see createArray() in action
|
|
2489
2408
|
{
|
|
2490
2409
|
$ret = {
|
|
2491
2410
|
op: this.valueWithTokenLocation( 'cast', $ca ),
|
|
2492
|
-
args:
|
|
2411
|
+
args: this.createArray(),
|
|
2493
2412
|
location: this.tokenLocation( $ca )
|
|
2494
2413
|
};
|
|
2495
2414
|
}
|
|
@@ -2497,8 +2416,7 @@ specialFunction returns [ ret = { } ] locals[ art = {} ]
|
|
|
2497
2416
|
{
|
|
2498
2417
|
$ret.args.push( $e.expr );
|
|
2499
2418
|
}
|
|
2500
|
-
')'
|
|
2501
|
-
// TODO: ROUND - see also resolver.js
|
|
2419
|
+
')' { this.finalizeDictOrArray( $ret.args ); }
|
|
2502
2420
|
;
|
|
2503
2421
|
|
|
2504
2422
|
// query path includes aggregation:
|
|
@@ -2524,36 +2442,47 @@ valuePath[ category, location = null ] returns[ qp = { path: [] } ] locals[ _syn
|
|
|
2524
2442
|
;
|
|
2525
2443
|
|
|
2526
2444
|
fromArguments[ pathStep ]
|
|
2445
|
+
@init{ if (!$pathStep) $pathStep = {}; } // grammar robustness, see test/negative/parser/NamedExpression.cds
|
|
2527
2446
|
:
|
|
2528
|
-
|
|
2529
|
-
|
|
2447
|
+
'(' { $pathStep.args = this.createDict(); $pathStep['$'+'syntax'] = ':'; } // necessary?
|
|
2448
|
+
name=ident['paramname'] ':'
|
|
2449
|
+
namedExpression[ $pathStep, $name.id ]
|
|
2530
2450
|
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
2531
|
-
|
|
2451
|
+
name=ident['paramname'] ':'
|
|
2452
|
+
namedExpression[ $pathStep, $name.id ]
|
|
2532
2453
|
)*
|
|
2533
|
-
')'
|
|
2454
|
+
')' { this.finalizeDictOrArray( $pathStep.args ); }
|
|
2534
2455
|
;
|
|
2535
2456
|
|
|
2536
2457
|
pathArguments[ pathStep, considerSpecial ]
|
|
2537
|
-
@
|
|
2458
|
+
@init{
|
|
2459
|
+
if (!$pathStep) $pathStep = {}; // grammar robustness, see test/negative/parser/NamedExpression.cds
|
|
2460
|
+
this.genericFunctionsStack.push( this['$'+'genericKeywords'] );
|
|
2461
|
+
}
|
|
2538
2462
|
:
|
|
2539
2463
|
{ this.excludeExpected([ 'ORDER' ]); }
|
|
2540
|
-
|
|
2541
|
-
{ this.prepareGenericKeywords( $considerSpecial ); }
|
|
2542
|
-
// ATN, LL2: Identifier can start both named arguments and the positional.
|
|
2464
|
+
'(' // dict or array, see below
|
|
2543
2465
|
// Make sure that we do not introduce A:B paths in expressions!
|
|
2466
|
+
// Need to avoid adaptPredict(), otherwise Generic keywords won't work in funcExpression
|
|
2467
|
+
{ this.setLocalTokenForId( { ':': 'HelperToken1', '=>': 'HelperToken2' } ); }
|
|
2544
2468
|
(
|
|
2545
|
-
|
|
2469
|
+
{ $pathStep.args = this.createDict(); $pathStep['$'+'syntax'] = ':'; }
|
|
2470
|
+
id=HelperToken1 ':'
|
|
2471
|
+
namedExpression[ $pathStep, this.identAst( $id, 'paramname', true ) ]
|
|
2546
2472
|
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
2547
|
-
|
|
2473
|
+
name=ident['paramname'] ':'
|
|
2474
|
+
namedExpression[ $pathStep, $name.id ]
|
|
2548
2475
|
)*
|
|
2549
2476
|
|
|
|
2550
|
-
{ $pathStep.args =
|
|
2551
|
-
|
|
2477
|
+
{ $pathStep.args = this.createDict(); } // TODO: XSN func path cleanup
|
|
2478
|
+
id=HelperToken2 '=>'
|
|
2479
|
+
namedExpression[ $pathStep, this.identAst( $id, 'paramname', true ) ]
|
|
2552
2480
|
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
2553
|
-
|
|
2481
|
+
name=ident['paramname'] '=>'
|
|
2482
|
+
namedExpression[ $pathStep, $name.id ]
|
|
2554
2483
|
)*
|
|
2555
2484
|
|
|
|
2556
|
-
{ $pathStep.args =
|
|
2485
|
+
{ $pathStep.args = this.createArray(); }
|
|
2557
2486
|
funcExpression[ $pathStep, $considerSpecial ]
|
|
2558
2487
|
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
2559
2488
|
funcExpression[ $pathStep, $considerSpecial ]
|
|
@@ -2566,47 +2495,82 @@ pathArguments[ pathStep, considerSpecial ]
|
|
|
2566
2495
|
}
|
|
2567
2496
|
)?
|
|
2568
2497
|
|
|
|
2569
|
-
|
|
2570
|
-
e1=expression { $pathStep.args = [ $e1.expr ]; }
|
|
2571
|
-
|
|
|
2572
|
-
d=DISTINCT { $pathStep.quantifier = this.valueWithTokenLocation( 'distinct', $d ); }
|
|
2573
|
-
e1=expression { $pathStep.args = [ $e1.expr ]; }
|
|
2574
|
-
( ',' e2=expression { $pathStep.args.push( $e2.expr ); } )*
|
|
2575
|
-
|
|
|
2576
|
-
star='*'
|
|
2577
|
-
{ $pathStep.args = [ { location: this.tokenLocation( $star ), val: '*', literal: 'token' } ]; }
|
|
2578
|
-
|
|
|
2579
|
-
{ $pathStep.args = []; }
|
|
2498
|
+
{ $pathStep.args = this.createArray(); }
|
|
2580
2499
|
)
|
|
2581
|
-
')'
|
|
2500
|
+
')' { this.finalizeDictOrArray( $pathStep.args ); }
|
|
2582
2501
|
;
|
|
2502
|
+
finally { // see @init
|
|
2503
|
+
if (!$pathStep.args) $pathStep.args = [];
|
|
2504
|
+
this['$'+'genericKeywords'] = this.genericFunctionsStack.pop();
|
|
2505
|
+
}
|
|
2583
2506
|
|
|
2584
|
-
namedExpression[ pathStep ]
|
|
2507
|
+
namedExpression[ pathStep, id ]
|
|
2585
2508
|
:
|
|
2586
|
-
|
|
2587
|
-
{ if ($pathStep && $
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
$pathStep['$'+'syntax'] = ':';
|
|
2509
|
+
elem=expression
|
|
2510
|
+
{ if ($pathStep && $id) {
|
|
2511
|
+
this.addDef( ($ctx.elem) ? $elem.expr : { location: $id.location },
|
|
2512
|
+
$pathStep, 'args', 0, $id );
|
|
2591
2513
|
}
|
|
2592
2514
|
}
|
|
2593
2515
|
;
|
|
2594
2516
|
|
|
2595
|
-
|
|
2596
|
-
:
|
|
2597
|
-
name=ident['paramname'] a='=>' elem=expression
|
|
2598
|
-
{ if ($name.id) this.addDef( $pathStep, 'args', 0, $name.id, true,
|
|
2599
|
-
($ctx.elem) ? $elem.expr : { location: $name.id.location } ); }
|
|
2600
|
-
;
|
|
2601
|
-
|
|
2602
|
-
funcExpression[ pathStep, considerSpecial ]
|
|
2517
|
+
funcExpression[ pathStep, considerSpecial ] locals[ args ]
|
|
2603
2518
|
@init { this.prepareGenericKeywords( $considerSpecial ); }
|
|
2604
2519
|
:
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2520
|
+
(
|
|
2521
|
+
expr=expression
|
|
2522
|
+
{ $pathStep.args.push( $expr.expr ); }
|
|
2523
|
+
|
|
|
2524
|
+
GenericExpr // keyword as replacement for expression, like '*'
|
|
2525
|
+
{ $pathStep.args.push( this.xprToken() ); }
|
|
2526
|
+
|
|
|
2527
|
+
GenericIntro // keyword as introduction of expression, like DISTINCT
|
|
2528
|
+
{ $pathStep.args.push( this.xprToken() ); }
|
|
2529
|
+
expr=expression
|
|
2530
|
+
{ $args = this.setLastAsXpr( $pathStep.args );
|
|
2531
|
+
$args.push( $expr.expr ); }
|
|
2532
|
+
|
|
|
2533
|
+
// Rule 'pathArguments' makes a decision based on the first two lookahead
|
|
2534
|
+
// tokens of this rule → we need to list tokens which would be changed to
|
|
2535
|
+
// GenericExpr or GenericIntro, and are not already covered by 'expression'
|
|
2536
|
+
{ this.reportErrorForGenericKeyword(); }
|
|
2537
|
+
( HideAlternatives | '*' | ALL | DISTINCT )
|
|
2538
|
+
// now continue parsing like GenericExpr:
|
|
2539
|
+
{ $pathStep.args.push( this.xprToken() ); }
|
|
2540
|
+
)
|
|
2541
|
+
(
|
|
2542
|
+
{ if (!$args) $args = this.setLastAsXpr( $pathStep.args ); }
|
|
2543
|
+
(
|
|
2544
|
+
{ this.prepareGenericKeywords( $considerSpecial, 'separator' ); }
|
|
2545
|
+
(
|
|
2546
|
+
GenericSeparator
|
|
2547
|
+
|
|
|
2548
|
+
// For ANTLR's lookahead calculations, we need to list tokens here
|
|
2549
|
+
// which could be changed to GenericSeparator. Do not invent a
|
|
2550
|
+
// keyword token which is just used here (Identifier does work
|
|
2551
|
+
// perfectly)! If we want, we could add all non-reserved keywords
|
|
2552
|
+
// except ORDER, and most reserved.
|
|
2553
|
+
{ this.reportErrorForGenericKeyword(); }
|
|
2554
|
+
( HideAlternatives | Identifier | FROM | IN | WITH | GROUP )
|
|
2555
|
+
)
|
|
2556
|
+
{ $args.push( this.xprToken() );
|
|
2557
|
+
this.prepareGenericKeywords( $considerSpecial, 'expr' );
|
|
2558
|
+
}
|
|
2559
|
+
(
|
|
2560
|
+
expr=expression
|
|
2561
|
+
{ $args.push( $expr.expr ); }
|
|
2562
|
+
|
|
|
2563
|
+
GenericExpr
|
|
2564
|
+
{ $args.push( this.xprToken() ); }
|
|
2565
|
+
|
|
|
2566
|
+
{ this.reportErrorForGenericKeyword(); }
|
|
2567
|
+
// Again, we need to list tokens which could make it to GenericExpr
|
|
2568
|
+
// and which do not start an expression
|
|
2569
|
+
( HideAlternatives | ALL )
|
|
2570
|
+
{ $args.push( this.xprToken() ); }
|
|
2571
|
+
)
|
|
2572
|
+
)+
|
|
2573
|
+
)?
|
|
2610
2574
|
;
|
|
2611
2575
|
|
|
2612
2576
|
cardinalityAndFilter[ pathStep ] locals [ _sync = 'nop' ]
|
|
@@ -2648,32 +2612,41 @@ optionalWhereForFilter
|
|
|
2648
2612
|
|
|
2649
2613
|
// Simple paths and values ---------------------------------------------------
|
|
2650
2614
|
|
|
2651
|
-
|
|
2652
|
-
@after { this.attachLocation($val); }
|
|
2615
|
+
annoValue[ assignment ]
|
|
2653
2616
|
:
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2617
|
+
base=annoValueBase[ $assignment ]
|
|
2618
|
+
|
|
|
2619
|
+
// no docComment() here
|
|
2620
|
+
// this alternative is done with token rewrite in rule "annotationAssignment_atn"
|
|
2621
|
+
at='@'? annotationPath[ $assignment, 'ref', $at ]
|
|
2622
|
+
annotationPathVariant[ $assignment ]?
|
|
2623
|
+
;
|
|
2624
|
+
|
|
2625
|
+
annoValueBase[ assignment ] locals [ seenEllipsis = false ]
|
|
2626
|
+
@after { this.attachLocation( $assignment ); }
|
|
2627
|
+
:
|
|
2628
|
+
'{' // no location here, we flatten
|
|
2629
|
+
{ $assignment['$'+'flatten'] = []; this.meltKeywordToIdentifier(); }
|
|
2630
|
+
flattenedValue[ $assignment ]
|
|
2658
2631
|
(
|
|
2659
2632
|
',' {
|
|
2660
2633
|
this.meltKeywordToIdentifier();
|
|
2661
2634
|
if (this.isStraightBefore("}")) break; // allow ',' before ')'
|
|
2662
2635
|
}
|
|
2663
|
-
|
|
2636
|
+
flattenedValue[ $assignment ]
|
|
2664
2637
|
)*
|
|
2665
2638
|
'}'
|
|
2666
2639
|
|
|
|
2667
|
-
|
|
2668
|
-
|
|
2640
|
+
'[' // no need for createArray() here, $assignment.location is set
|
|
2641
|
+
{ $assignment.val = []; $assignment.literal = 'array'; }
|
|
2669
2642
|
(
|
|
2670
2643
|
(
|
|
2671
|
-
head=
|
|
2644
|
+
head=annoSubValue { $assignment.val.push( $head.val ); }
|
|
2672
2645
|
|
|
|
2673
|
-
e='...' ( UP TO upTo=
|
|
2646
|
+
e='...' ( UP TO upTo=annoSubValue )?
|
|
2674
2647
|
{{
|
|
2675
2648
|
const item = { literal: 'token', val: '...', location: this.tokenLocation($e) };
|
|
2676
|
-
$
|
|
2649
|
+
$assignment.val.push( item );
|
|
2677
2650
|
if ($ctx.upTo) item.upTo = $upTo.val;
|
|
2678
2651
|
$seenEllipsis = !$ctx.upTo || 'upTo';
|
|
2679
2652
|
}}
|
|
@@ -2681,17 +2654,16 @@ annoValueBase returns[ val ] locals [ seenEllipsis = false ]
|
|
|
2681
2654
|
(
|
|
2682
2655
|
',' { if (this.isStraightBefore(']')) break; } // allow ',' before ']'
|
|
2683
2656
|
(
|
|
2684
|
-
tail=
|
|
2657
|
+
tail=annoSubValue { $assignment.val.push( $tail.val ); }
|
|
2685
2658
|
|
|
|
2686
2659
|
{ $ctx.upTo = null; } // is not reset
|
|
2687
|
-
e='...' ( UP TO upTo=
|
|
2660
|
+
e='...' ( UP TO upTo=annoSubValue )?
|
|
2688
2661
|
{{
|
|
2689
2662
|
const item = { literal: 'token', val: '...', location: this.tokenLocation($e) };
|
|
2690
2663
|
if ($ctx.upTo) item.upTo = $upTo.val;
|
|
2691
|
-
$
|
|
2664
|
+
$assignment.val.push( item );
|
|
2692
2665
|
if ($seenEllipsis === true) // TODO: adapt msg to UP TO
|
|
2693
|
-
this.error( 'syntax-unexpected-ellipsis', $e, { code: '...' }
|
|
2694
|
-
'Expected no more than one $(CODE)' );
|
|
2666
|
+
this.error( 'syntax-unexpected-ellipsis', $e, { '#': 'std', code: '...' } );
|
|
2695
2667
|
else
|
|
2696
2668
|
$seenEllipsis = !$ctx.upTo || 'upTo';
|
|
2697
2669
|
}}
|
|
@@ -2706,67 +2678,66 @@ annoValueBase returns[ val ] locals [ seenEllipsis = false ]
|
|
|
2706
2678
|
'Expecting an array item $(NEWCODE) after an item with $(CODE)' );
|
|
2707
2679
|
}
|
|
2708
2680
|
|
|
|
2709
|
-
v1=literalValue { $
|
|
2681
|
+
v1=literalValue { Object.assign( $assignment, $v1.val ); }
|
|
2710
2682
|
|
|
|
2711
2683
|
( plus='+' | min='-' ) num=Number
|
|
2712
|
-
{ $
|
|
2684
|
+
{ Object.assign( $assignment, this.numberLiteral( $num, $plus||$min ) ); }
|
|
2713
2685
|
;
|
|
2714
2686
|
|
|
2715
|
-
|
|
2687
|
+
flattenedValue[ assignment ] locals[ val = { name: {} } ]
|
|
2716
2688
|
:
|
|
2717
|
-
|
|
2718
|
-
|
|
|
2719
|
-
{ $val = {}; } // TODO: think about expression value representation
|
|
2720
|
-
at='@'? annotationPath[ $val, 'ref', $at ]
|
|
2721
|
-
annotationPathVariant[ $val ]?
|
|
2722
|
-
;
|
|
2723
|
-
|
|
2724
|
-
namedValue[ struct ] locals[ namedVal = { name: {} } ]
|
|
2725
|
-
:
|
|
2726
|
-
at='@'? annotationPath[ $namedVal.name, 'name', $at ]
|
|
2689
|
+
at='@'? annotationPath[ $val.name, 'name', $at ]
|
|
2727
2690
|
(
|
|
2728
2691
|
'#' { this.meltKeywordToIdentifier(); }
|
|
2729
|
-
variant=ident['variant'] { $
|
|
2692
|
+
variant=ident['variant'] { $val.name.variant = $variant.id; }
|
|
2730
2693
|
)?
|
|
2731
2694
|
(
|
|
2732
2695
|
':' { this.meltKeywordToIdentifier(true); } // allow path as anno value start with reserved
|
|
2733
|
-
|
|
2696
|
+
annoValue[ $val ]
|
|
2734
2697
|
)?
|
|
2735
|
-
{
|
|
2736
|
-
($ctx.elem) ? Object.assign($namedVal, $elem.val) : $namedVal ); }
|
|
2698
|
+
{ $assignment['$'+'flatten'].push( $val ); }
|
|
2737
2699
|
;
|
|
2738
2700
|
|
|
2739
|
-
|
|
2701
|
+
namedValue[ struct ] locals[ val = { name: {} } ]
|
|
2702
|
+
:
|
|
2703
|
+
at='@'? annotationPath[ $val.name, 'name', $at ]
|
|
2704
|
+
( ':' sub=annoSubValue { Object.assign( $val, $sub.val ); } )?
|
|
2705
|
+
{
|
|
2706
|
+
if (!$val.location) $val.location = $val.name.location;
|
|
2707
|
+
this.addDef( $val, $struct, 'struct', null, $val.name ); // TODO: re-check name
|
|
2708
|
+
}
|
|
2709
|
+
;
|
|
2710
|
+
|
|
2711
|
+
annoSubValue returns[ val = {} ]
|
|
2740
2712
|
@after { this.attachLocation($val); }
|
|
2741
2713
|
:
|
|
2742
|
-
{
|
|
2743
|
-
|
|
2714
|
+
'{' // no need for createDict() here, $val.location is set
|
|
2715
|
+
{ $val.struct = Object.create(null); $val.literal = 'struct'; }
|
|
2744
2716
|
{ this.meltKeywordToIdentifier(); }
|
|
2745
|
-
|
|
2717
|
+
namedValue[ $val ]
|
|
2746
2718
|
( ','
|
|
2747
2719
|
{
|
|
2748
2720
|
this.meltKeywordToIdentifier();
|
|
2749
2721
|
if (this.isStraightBefore("}")) break; // allow ',' before '}'
|
|
2750
2722
|
}
|
|
2751
|
-
|
|
2723
|
+
namedValue[ $val ]
|
|
2752
2724
|
)*
|
|
2753
2725
|
'}'
|
|
2754
2726
|
|
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
( head=
|
|
2727
|
+
'[' // no need for createArray() here, $val.location is set
|
|
2728
|
+
{ $val.val = []; $val.literal = 'array'; }
|
|
2729
|
+
( head=annoSubValue { $val.val.push( $head.val ); }
|
|
2758
2730
|
( ',' { if (this.isStraightBefore(']')) break; } // allow ',' before ']'
|
|
2759
|
-
tail=
|
|
2731
|
+
tail=annoSubValue { $val.val.push( $tail.val ); }
|
|
2760
2732
|
)*
|
|
2761
2733
|
)?
|
|
2762
2734
|
']'
|
|
2763
2735
|
|
|
|
2764
|
-
v1=literalValue { $val
|
|
2736
|
+
v1=literalValue { Object.assign( $val, $v1.val ); }
|
|
2765
2737
|
|
|
|
2766
2738
|
( plus='+' | min='-' ) num=Number
|
|
2767
|
-
{ $val
|
|
2739
|
+
{ Object.assign( $val, this.numberLiteral( $num, $plus||$min ) ); }
|
|
2768
2740
|
|
|
|
2769
|
-
{ $val = {}; } // TODO: think about expression value representation
|
|
2770
2741
|
at='@'? annotationPath[ $val, 'ref', $at ]
|
|
2771
2742
|
(
|
|
2772
2743
|
'#' { this.meltKeywordToIdentifier(); }
|
|
@@ -2774,14 +2745,6 @@ arrayValue returns[ val ]
|
|
|
2774
2745
|
)?
|
|
2775
2746
|
;
|
|
2776
2747
|
|
|
2777
|
-
namedValueInArray[ struct ] locals[ name = {} ]
|
|
2778
|
-
:
|
|
2779
|
-
at='@'? annotationPath[ $name, 'name', $at ]
|
|
2780
|
-
( ':' elem=arrayValue )?
|
|
2781
|
-
{ this.addDef( $struct, 'struct', null, $name, true,
|
|
2782
|
-
($ctx.elem) ? $elem.val : { location: $name.location } ); }
|
|
2783
|
-
;
|
|
2784
|
-
|
|
2785
2748
|
literalValue returns[ val ] locals[ tok ]
|
|
2786
2749
|
@init{ $tok = this.getCurrentToken(); }
|
|
2787
2750
|
@after { this.attachLocation($val); }
|
|
@@ -2840,7 +2803,7 @@ annotationPath[ art, category, headat = null ] locals[ _sync = 'nop' ]
|
|
|
2840
2803
|
annotationPathVariant[ art ]
|
|
2841
2804
|
@after { this.attachLocation($art); }
|
|
2842
2805
|
:
|
|
2843
|
-
// TODO: warning for space
|
|
2806
|
+
// TODO: warning for space after '#'
|
|
2844
2807
|
'#' { this.meltKeywordToIdentifier(); }
|
|
2845
2808
|
variant=ident['variant'] { $art.variant = $variant.id; }
|
|
2846
2809
|
;
|
|
@@ -2871,13 +2834,11 @@ ident[ category ] returns[ id ]
|
|
|
2871
2834
|
| ASPECT
|
|
2872
2835
|
| ASSOCIATION
|
|
2873
2836
|
| BETWEEN
|
|
2874
|
-
| BOTH
|
|
2875
2837
|
| COLUMNS
|
|
2876
2838
|
| COMPOSITION
|
|
2877
2839
|
| CONTEXT
|
|
2878
2840
|
| CROSS
|
|
2879
2841
|
| CURRENT
|
|
2880
|
-
| DAY
|
|
2881
2842
|
| DEFAULT
|
|
2882
2843
|
| DEFINE
|
|
2883
2844
|
| DEFINITIONS
|
|
@@ -2901,14 +2862,12 @@ ident[ category ] returns[ id ]
|
|
|
2901
2862
|
| FUNCTION
|
|
2902
2863
|
| GROUP
|
|
2903
2864
|
| HAVING
|
|
2904
|
-
| HOUR
|
|
2905
2865
|
| INNER
|
|
2906
2866
|
| INTERSECT
|
|
2907
2867
|
| INTO
|
|
2908
2868
|
| IS
|
|
2909
2869
|
| JOIN
|
|
2910
2870
|
| LAST
|
|
2911
|
-
| LEADING
|
|
2912
2871
|
| LEFT
|
|
2913
2872
|
| LIKE
|
|
2914
2873
|
| LIMIT
|
|
@@ -2916,9 +2875,7 @@ ident[ category ] returns[ id ]
|
|
|
2916
2875
|
| MANY
|
|
2917
2876
|
| MASKED
|
|
2918
2877
|
| MINUS
|
|
2919
|
-
| MINUTE
|
|
2920
2878
|
| MIXIN
|
|
2921
|
-
| MONTH
|
|
2922
2879
|
| NAMESPACE
|
|
2923
2880
|
| NULLS
|
|
2924
2881
|
| OFFSET
|
|
@@ -2935,10 +2892,8 @@ ident[ category ] returns[ id ]
|
|
|
2935
2892
|
| RIGHT
|
|
2936
2893
|
| ROW
|
|
2937
2894
|
| ROWS
|
|
2938
|
-
| SECOND
|
|
2939
2895
|
| SERVICE
|
|
2940
2896
|
| THEN
|
|
2941
|
-
| TRAILING
|
|
2942
2897
|
| UNION
|
|
2943
2898
|
| UP
|
|
2944
2899
|
| TO
|
|
@@ -2947,7 +2902,6 @@ ident[ category ] returns[ id ]
|
|
|
2947
2902
|
| UNBOUNDED
|
|
2948
2903
|
| VARIABLE
|
|
2949
2904
|
| VIEW
|
|
2950
|
-
| YEAR
|
|
2951
2905
|
;
|
|
2952
2906
|
|
|
2953
2907
|
//----------------------------------------------------------------------------
|
|
@@ -3039,7 +2993,6 @@ CASE : [cC][aA][sS][eE] ;
|
|
|
3039
2993
|
CAST : [cC][aA][sS][tT] ;
|
|
3040
2994
|
DISTINCT : [dD][iI][sS][tT][iI][nN][cC][tT] ;
|
|
3041
2995
|
EXISTS : [eE][xX][iI][sS][tT][sS] ;
|
|
3042
|
-
EXTRACT : [eE][xX][tT][rR][aA][cC][tT] ;
|
|
3043
2996
|
// FALSE: see Boolean
|
|
3044
2997
|
FROM : [fF][rR][oO][mM] ;
|
|
3045
2998
|
IN : [iI][nN] ;
|
|
@@ -3052,7 +3005,6 @@ ON : [oO][nN] ;
|
|
|
3052
3005
|
SELECT : [sS][eE][lL][eE][cC][tT] ;
|
|
3053
3006
|
SOME : [sS][oO][mM][eE] ;
|
|
3054
3007
|
WHEN : [wW][hH][eE][nN] ;
|
|
3055
|
-
TRIM : [tT][rR][iI][mM] ;
|
|
3056
3008
|
// TRUE: see Boolean
|
|
3057
3009
|
WHERE : [wW][hH][eE][rR][eE] ;
|
|
3058
3010
|
WITH : [wW][iI][tT][hH] ;
|
|
@@ -3066,6 +3018,7 @@ Number // DO NOT RENAME OR MOVE THIS RULE !!!
|
|
|
3066
3018
|
;
|
|
3067
3019
|
|
|
3068
3020
|
// Unreserved keywords (are case-insensitive): -------------------------------
|
|
3021
|
+
// Do not add keywords just for specialFunctions!
|
|
3069
3022
|
|
|
3070
3023
|
ABSTRACT : [aA][bB][sS][tT][rR][aA][cC][tT] ;
|
|
3071
3024
|
ACTION : [aA][cC][tT][iI][oO][nN] ;
|
|
@@ -3078,13 +3031,11 @@ ASC : [aA][sS][cC] ;
|
|
|
3078
3031
|
ASPECT : [aA][sS][pP][eE][cC][tT] ;
|
|
3079
3032
|
ASSOCIATION : [aA][sS][sS][oO][cC][iI][aA][tT][iI][oO][nN] ;
|
|
3080
3033
|
BETWEEN : [bB][eE][tT][wW][eE][eE][nN] ;
|
|
3081
|
-
BOTH : [bB][oO][tT][hH] ;
|
|
3082
3034
|
COLUMNS : [cC][oO][lL][uU][mM][nN][sS];
|
|
3083
3035
|
COMPOSITION : [cC][oO][mM][pP][oO][sS][iI][tT][iI][oO][nN] ;
|
|
3084
3036
|
CONTEXT : [cC][oO][nN][tT][eE][xX][tT] ;
|
|
3085
3037
|
CROSS : [cC][rR][oO][sS][sS] ;
|
|
3086
3038
|
CURRENT : [cC][uU][rR][rR][eE][nN][tT] ;
|
|
3087
|
-
DAY : [dD][aA][yY] ;
|
|
3088
3039
|
DEFAULT : [dD][eE][fF][aA][uU][lL][tT] ;
|
|
3089
3040
|
DEFINE : [dD][eE][fF][iI][nN][eE] ;
|
|
3090
3041
|
DEFINITIONS : [dD][eE][fF][iI][nN][iI][tT][iI][oO][nN][sS] ;
|
|
@@ -3108,14 +3059,12 @@ FULL : [fF][uU][lL][lL] ;
|
|
|
3108
3059
|
FUNCTION : [fF][uU][nN][cC][tT][iI][oO][nN] ;
|
|
3109
3060
|
GROUP : [gG][rR][oO][uU][pP] ;
|
|
3110
3061
|
HAVING : [hH][aA][vV][iI][nN][gG] ;
|
|
3111
|
-
HOUR : [hH][oO][uU][rR] ;
|
|
3112
3062
|
INNER : [iI][nN][nN][eE][rR] ;
|
|
3113
3063
|
INTERSECT : [iI][nN][tT][eE][rR][sS][eE][cC][tT] ;
|
|
3114
3064
|
INTO : [iI][nN][tT][oO] ;
|
|
3115
3065
|
IS : [iI][sS] ;
|
|
3116
3066
|
JOIN : [jJ][oO][iI][nN] ;
|
|
3117
3067
|
LAST : [lL][aA][sS][tT] ;
|
|
3118
|
-
LEADING : [lL][eE][aA][dD][iI][nN][gG] ;
|
|
3119
3068
|
LEFT : [lL][eE][fF][tT] ;
|
|
3120
3069
|
LIKE : [lL][iI][kK][eE] ;
|
|
3121
3070
|
LIMIT : [lL][iI][mM][iI][tT] ;
|
|
@@ -3123,9 +3072,7 @@ LOCALIZED: [lL][oO][cC][aA][lL][iI][zZ][eE][dD];
|
|
|
3123
3072
|
MANY : [mM][aA][nN][yY] ;
|
|
3124
3073
|
MASKED : [mM][aA][sS][kK][eE][dD] ;
|
|
3125
3074
|
MINUS : [mM][iI][nN][uU][sS] ;
|
|
3126
|
-
MINUTE : [mM][iI][nN][uU][tT][eE] ;
|
|
3127
3075
|
MIXIN : [mM][iI][xX][iI][nN] ;
|
|
3128
|
-
MONTH : [mM][oO][nN][tT][hH] ;
|
|
3129
3076
|
NAMESPACE : [nN][aA][mM][eE][sS][pP][aA][cC][eE] ;
|
|
3130
3077
|
NULLS : [nN][uU][lL][lL][sS] ;
|
|
3131
3078
|
OFFSET : [oO][fF][fF][sS][eE][tT] ;
|
|
@@ -3143,10 +3090,8 @@ RETURNS : [rR][eE][tT][uU][rR][nN][sS] ;
|
|
|
3143
3090
|
RIGHT : [rR][iI][gG][hH][tT] ;
|
|
3144
3091
|
ROW : [rR][oO][wW] ;
|
|
3145
3092
|
ROWS : [rR][oO][wW][sS] ;
|
|
3146
|
-
SECOND : [sS][eE][cC][oO][nN][dD] ;
|
|
3147
3093
|
SERVICE : [sS][eE][rR][vV][iI][cC][eE] ;
|
|
3148
3094
|
THEN : [tT][hH][eE][nN] ;
|
|
3149
|
-
TRAILING : [tT][rR][aA][iI][lL][iI][nN][gG] ;
|
|
3150
3095
|
TO : [tT][oO] ; // or make reserved? (is in SQL-92)
|
|
3151
3096
|
TYPE : [tT][yY][pP][eE] ;
|
|
3152
3097
|
UNION : [uU][nN][iI][oO][nN] ;
|
|
@@ -3156,7 +3101,6 @@ USING : [uU][sS][iI][nN][gG] ;
|
|
|
3156
3101
|
VARIABLE : [vV][aA][rR][iI][aA][bB][lL][eE] ;
|
|
3157
3102
|
VIEW : [vV][iI][eE][wW] ;
|
|
3158
3103
|
// VIRTUAL: [vV][iI][rR][tT][uU][aA][lL] ; see tokens {}
|
|
3159
|
-
YEAR : [yY][eE][aA][rR] ;
|
|
3160
3104
|
|
|
3161
3105
|
// Identifiers, must BE LAST, DIRECTLY AFTER the unreserved keywords ---------
|
|
3162
3106
|
|