@sap/cds-compiler 5.3.2 → 5.4.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 +23 -2
- package/bin/cdsc.js +1 -1
- package/doc/CHANGELOG_BETA.md +2 -2
- package/lib/api/options.js +4 -2
- package/lib/base/builtins.js +0 -10
- package/lib/base/keywords.js +3 -31
- package/lib/base/message-registry.js +23 -5
- package/lib/base/messages.js +1 -1
- package/lib/checks/existsMustEndInAssoc.js +7 -2
- package/lib/checks/foreignKeys.js +12 -7
- package/lib/compiler/assert-consistency.js +11 -3
- package/lib/compiler/builtins.js +2 -0
- package/lib/compiler/checks.js +88 -38
- package/lib/compiler/define.js +2 -2
- package/lib/compiler/shared.js +9 -10
- package/lib/compiler/xpr-rewrite.js +11 -0
- package/lib/compiler/xsn-model.js +1 -1
- package/lib/edm/csn2edm.js +2 -0
- package/lib/edm/edm.js +2 -1
- package/lib/edm/edmPreprocessor.js +14 -1
- package/lib/edm/edmUtils.js +17 -2
- package/lib/gen/BaseParser.js +291 -197
- package/lib/gen/CdlParser.js +1631 -1605
- package/lib/gen/Dictionary.json +74 -6
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +1 -1
- package/lib/gen/languageParser.js +1808 -1804
- package/lib/language/antlrParser.js +8 -4
- package/lib/language/genericAntlrParser.js +3 -3
- package/lib/model/csnUtils.js +6 -1
- package/lib/optionProcessor.js +4 -0
- package/lib/parsers/AstBuildingParser.js +172 -108
- package/lib/parsers/CdlGrammar.g4 +154 -134
- package/lib/parsers/Lexer.js +3 -3
- package/lib/parsers/identifiers.js +59 -0
- package/lib/render/toCdl.js +5 -5
- package/lib/render/utils/common.js +5 -0
- package/lib/render/utils/delta.js +23 -5
- package/lib/transform/db/expansion.js +2 -1
- package/lib/transform/db/transformExists.js +10 -9
- package/lib/transform/effective/annotations.js +147 -0
- package/lib/transform/effective/main.js +16 -2
- package/lib/transform/forOdata.js +53 -10
- package/lib/transform/forRelationalDB.js +7 -0
- package/lib/transform/odata/createForeignKeys.js +180 -0
- package/lib/transform/odata/flattening.js +135 -19
- package/lib/transform/odata/typesExposure.js +4 -3
- package/lib/transform/transformUtils.js +6 -6
- package/package.json +1 -1
|
@@ -44,22 +44,22 @@ start returns[ source = new XsnSource( 'cdl' ) ]
|
|
|
44
44
|
(
|
|
45
45
|
( <cond=namespaceRestriction> namespaceDeclaration[ $source ]
|
|
46
46
|
| usingDeclaration[ $source ]
|
|
47
|
-
| artifactDefOrExtend[ $source ] <
|
|
47
|
+
| artifactDefOrExtend[ $source ] <prepare=namespaceRestriction>
|
|
48
48
|
)
|
|
49
|
-
( ';' | <exitLoop> | <repeatLoop=afterBrace> { this.noAssignmentInSameLine(); } )
|
|
49
|
+
( ';' | <exitLoop> | <repeatLoop, cond=afterBrace> { this.noAssignmentInSameLine(); } )
|
|
50
50
|
)*
|
|
51
51
|
EOF { this.docComment( null ); }
|
|
52
52
|
;
|
|
53
53
|
|
|
54
54
|
artifactsBlock[ art, start = undefined ]
|
|
55
55
|
:
|
|
56
|
-
'{'<
|
|
56
|
+
'{'<prepare=vocabularyRestriction>
|
|
57
57
|
{ $art.artifacts = this.createDict( $start ); $art.extensions = []; }
|
|
58
58
|
(
|
|
59
59
|
artifactDefOrExtend[ $art ]
|
|
60
|
-
( ';' | <exitLoop> | <repeatLoop=afterBrace> { this.noAssignmentInSameLine(); } )
|
|
60
|
+
( ';' | <exitLoop> | <repeatLoop, cond=afterBrace> { this.noAssignmentInSameLine(); } )
|
|
61
61
|
)*
|
|
62
|
-
'}'<
|
|
62
|
+
'}'<prepare=afterBrace>
|
|
63
63
|
{ this.finalizeDictOrArray( $art.artifacts ); }
|
|
64
64
|
;
|
|
65
65
|
|
|
@@ -125,7 +125,7 @@ usingDeclaration[ source ] locals[ decl = { kind: 'using' } ] // TODO: XsnArtifa
|
|
|
125
125
|
( usingProxy[ $decl, { kind: 'using' } ]
|
|
126
126
|
( ',' | <exitLoop> )
|
|
127
127
|
)+
|
|
128
|
-
'}'<
|
|
128
|
+
'}'<prepare=afterBrace>
|
|
129
129
|
{ this.finalizeDictOrArray( $decl.usings ); }
|
|
130
130
|
( FROM String
|
|
131
131
|
{ $source.dependencies.push( $decl.fileDep = this.quotedLiteral() ); }
|
|
@@ -186,7 +186,8 @@ annotationDef[ art, outer ]
|
|
|
186
186
|
@finally{ this.attachLocation( $art ); }
|
|
187
187
|
:
|
|
188
188
|
ANNOTATION name=namePath[ 'AnnoDef' ]
|
|
189
|
-
|
|
189
|
+
// make it also work with ignored <cond=vocabularyRestriction>:
|
|
190
|
+
{ this.addDef( $art, $outer, ($outer.kind === 'source' ? 'vocabularies' : 'artifacts'), 'annotation', $name ); }
|
|
190
191
|
{ this.docComment( $art ); } annoAssignMid[ $art ]*
|
|
191
192
|
typeOrIncludesSpec[ $art ]
|
|
192
193
|
;
|
|
@@ -338,9 +339,9 @@ actionsBlock[ art ]
|
|
|
338
339
|
ACTIONS { $art.actions = this.createDict(); } '{'
|
|
339
340
|
(
|
|
340
341
|
boundActionFunctionDef[ $art ]
|
|
341
|
-
( ';' | <exitLoop> | <repeatLoop=afterBrace> { this.noAssignmentInSameLine(); } )
|
|
342
|
+
( ';' | <exitLoop> | <repeatLoop, cond=afterBrace> { this.noAssignmentInSameLine(); } )
|
|
342
343
|
)*
|
|
343
|
-
'}'<
|
|
344
|
+
'}'<prepare=afterBrace>
|
|
344
345
|
{ this.finalizeDictOrArray( $art.actions ); }
|
|
345
346
|
;
|
|
346
347
|
|
|
@@ -390,9 +391,9 @@ paramDef[ outer ] locals[ art = new XsnArtifact() ]
|
|
|
390
391
|
;
|
|
391
392
|
|
|
392
393
|
returnsSpec[ outer ] locals[ art = new XsnArtifact() ]
|
|
393
|
-
@finally{ this.attachLocation( $art ); }
|
|
394
|
+
@finally{ this.attachLocation( $art ); if ($ret) art.location.tokenIndex = $ret.location.tokenIndex; }
|
|
394
395
|
:
|
|
395
|
-
RETURNS<
|
|
396
|
+
ret=RETURNS <prepare=elementRestriction, arg=default>
|
|
396
397
|
{ $art.kind = 'param'; $outer.returns = $art; }
|
|
397
398
|
{ this.docComment( $art ); } annoAssignStd[ $art ]*
|
|
398
399
|
typeExpression[ $art ]
|
|
@@ -404,10 +405,10 @@ elementsBlock[ art ]
|
|
|
404
405
|
( elementDef[ $art ]
|
|
405
406
|
( ';'
|
|
406
407
|
| <exitLoop>
|
|
407
|
-
| <repeatLoop=afterBrace, restrict=Id> { this.noAssignmentInSameLine(); }
|
|
408
|
+
| <repeatLoop, cond=afterBrace, restrict=Id> { this.noAssignmentInSameLine(); }
|
|
408
409
|
)
|
|
409
410
|
)*
|
|
410
|
-
'}'<
|
|
411
|
+
'}'<prepare=afterBrace>
|
|
411
412
|
{ this.finalizeDictOrArray( $art.elements ); }
|
|
412
413
|
;
|
|
413
414
|
|
|
@@ -421,29 +422,27 @@ elementDef[ outer, art = undefined ]
|
|
|
421
422
|
( MASKED { $art.masked = this.valueWithLocation( true ); }
|
|
422
423
|
{ this.message( 'syntax-unsupported-masked', this.lb(), { keyword: 'masked' } ); } )?
|
|
423
424
|
( ELEMENT { $art.$syntax = 'element'; } )?
|
|
424
|
-
Id['Element']
|
|
425
|
+
Id['Element'] <prepare=elementRestriction, arg=elem>
|
|
425
426
|
{ this.addDef( $art, $outer, 'elements', 'element', this.identAst() ); }
|
|
426
427
|
{ this.docComment( $art ); } annoAssignMid[ $art ]*
|
|
427
428
|
(
|
|
428
429
|
elementsBlock[ $art ]
|
|
429
430
|
nullability[ $art ]?
|
|
430
431
|
|
|
|
431
|
-
':'
|
|
432
|
-
|
|
433
|
-
|
|
|
434
|
-
// <setCondition=elementRestriction> // TODO TOOL: allow this
|
|
435
|
-
{ this.elementRestriction(); }<always> // workaround
|
|
436
|
-
)
|
|
432
|
+
':' typeExpression[ $art ] // was elementType, with NOT? NULL / DEFAULT
|
|
433
|
+
)?
|
|
437
434
|
(
|
|
438
|
-
<cond=
|
|
435
|
+
<cond=elementRestriction, arg=calc> '='
|
|
439
436
|
// TODO TOOL: add to "expected set" if failing here? Or have some "do not
|
|
440
437
|
// consider for rule exit if condition failure on `=`"?
|
|
441
438
|
expr=expression { $art.value = $expr; }
|
|
442
439
|
( STORED { $art.value.stored = this.valueWithLocation( true ); } )?
|
|
443
440
|
// TODO: why have `stored` as property of the value?
|
|
444
|
-
{ this.docComment( $art ); }
|
|
445
|
-
( <cond=elementRestriction> annoAssignStd[ $art ] )*
|
|
446
|
-
|
|
441
|
+
{ if (this.elementRestriction( true, 'anno' )) this.docComment( $art ); }
|
|
442
|
+
( <cond=elementRestriction, arg=anno> annoAssignStd[ $art ] )*
|
|
443
|
+
|
|
|
444
|
+
{ this.docComment( $art, 'type' ); } // delayed from type expression
|
|
445
|
+
)
|
|
447
446
|
;
|
|
448
447
|
|
|
449
448
|
enumSymbolsBlock[ art ]
|
|
@@ -452,7 +451,7 @@ enumSymbolsBlock[ art ]
|
|
|
452
451
|
( enumSymbolDef[ $art ]
|
|
453
452
|
( ';' | <exitLoop> )
|
|
454
453
|
)*
|
|
455
|
-
'}'<
|
|
454
|
+
'}'<prepare=afterBrace>
|
|
456
455
|
{ this.finalizeDictOrArray( $art.enum ); }
|
|
457
456
|
;
|
|
458
457
|
|
|
@@ -521,17 +520,17 @@ mixinElementDef[ outer ] locals[ art = new XsnArtifact() ]
|
|
|
521
520
|
// Annotate and Extend: main definitions ----------------------------------------
|
|
522
521
|
|
|
523
522
|
annotateArtifact[ art, outer ]
|
|
524
|
-
@finally{ this.attachLocation( $art ); }
|
|
523
|
+
@finally{ this.checkWith( $keyword ); this.attachLocation( $art ); }
|
|
525
524
|
:
|
|
526
525
|
name=namePath[ 'Ext' ]
|
|
527
526
|
( // direct element annotation:
|
|
528
527
|
':' elemName=namePath[ 'ExtElement']
|
|
529
528
|
{ this.addExtension( $art, $outer, 'annotate', $name, $elemName.path ); }
|
|
530
|
-
WITH?
|
|
529
|
+
keyword=WITH?
|
|
531
530
|
{ this.docComment( $art ); } annoAssignStd[ $art ]*
|
|
532
531
|
annotateElementsBlock[ $art ]?
|
|
533
532
|
| // definition annotation
|
|
534
|
-
WITH?
|
|
533
|
+
keyword=WITH?
|
|
535
534
|
// <cond=noRuleExitAfterWith>), or as rule option,
|
|
536
535
|
// this.noSemicolonHere() had the issues: DocComment, before `}`/EOF
|
|
537
536
|
{ this.addExtension( $art, $outer, 'annotate', $name ); }
|
|
@@ -547,13 +546,13 @@ annotateArtifact[ art, outer ]
|
|
|
547
546
|
;
|
|
548
547
|
|
|
549
548
|
extendArtifact[ art, outer ]
|
|
550
|
-
@finally{ this.attachLocation( $art ); }
|
|
549
|
+
@finally{ this.checkWith( $keyword ); this.attachLocation( $art ); }
|
|
551
550
|
:
|
|
552
551
|
name=namePath[ 'Ext' ]
|
|
553
552
|
( // direct element annotation:
|
|
554
553
|
':' elemName=namePath[ 'ExtElement']
|
|
555
554
|
{ this.addExtension( $art, $outer, 'extend', $name, $elemName.path ); }
|
|
556
|
-
WITH?
|
|
555
|
+
keyword=WITH?
|
|
557
556
|
{ this.docComment( $art ); } annoAssignStd[ $art ]*
|
|
558
557
|
(
|
|
559
558
|
elements=ELEMENTS? extendElementsBlock[ $art, $elements ]
|
|
@@ -569,7 +568,7 @@ extendArtifact[ art, outer ]
|
|
|
569
568
|
actionsBlock[ $art ]?
|
|
570
569
|
)?
|
|
571
570
|
|
|
|
572
|
-
WITH
|
|
571
|
+
keyword=WITH
|
|
573
572
|
{ this.addExtension( $art, $outer, 'extend', $name ); }
|
|
574
573
|
{ this.docComment( $art ); } annoAssignStd[ $art ]*
|
|
575
574
|
(
|
|
@@ -595,12 +594,12 @@ extendArtifact[ art, outer ]
|
|
|
595
594
|
;
|
|
596
595
|
|
|
597
596
|
extendService[ art, outer ]
|
|
598
|
-
@finally{ this.attachLocation( $art ); }
|
|
597
|
+
@finally{ this.checkWith( $keyword ); this.attachLocation( $art ); }
|
|
599
598
|
:
|
|
600
599
|
SERVICE { $art.expectedKind = this.valueWithLocation(); }
|
|
601
600
|
name=namePath[ 'ExtService' ]
|
|
602
601
|
{ $art.name = $name; $outer.extensions.push( $art ); }
|
|
603
|
-
WITH?
|
|
602
|
+
keyword=WITH?
|
|
604
603
|
// <cond=noRuleExitAfterWith>), or as rule option,
|
|
605
604
|
// this.noSemicolonHere() had the issues: DocComment, before `}`/EOF
|
|
606
605
|
{ this.docComment( $art ); } annoAssignStd[ $art ]*
|
|
@@ -608,12 +607,12 @@ extendService[ art, outer ]
|
|
|
608
607
|
;
|
|
609
608
|
|
|
610
609
|
extendContext[ art, outer ]
|
|
611
|
-
@finally{ this.attachLocation( $art ); }
|
|
610
|
+
@finally{ this.checkWith( $keyword ); this.attachLocation( $art ); }
|
|
612
611
|
:
|
|
613
612
|
CONTEXT { $art.expectedKind = this.valueWithLocation(); }
|
|
614
613
|
name=namePath[ 'ExtContext' ]
|
|
615
614
|
{ $art.name = $name; $outer.extensions.push( $art ); }
|
|
616
|
-
WITH?
|
|
615
|
+
keyword=WITH?
|
|
617
616
|
// <cond=noRuleExitAfterWith>), or as rule option,
|
|
618
617
|
// this.noSemicolonHere() had the issues: DocComment, before `}`/EOF
|
|
619
618
|
{ this.docComment( $art ); } annoAssignStd[ $art ]*
|
|
@@ -621,7 +620,7 @@ extendContext[ art, outer ]
|
|
|
621
620
|
;
|
|
622
621
|
|
|
623
622
|
extendType[ art, outer ]
|
|
624
|
-
@finally{ this.attachLocation( $art ); }
|
|
623
|
+
@finally{ this.checkWith( $keyword ); this.attachLocation( $art ); }
|
|
625
624
|
:
|
|
626
625
|
TYPE { $art.expectedKind = this.valueWithLocation(); }
|
|
627
626
|
name=namePath[ 'Ext' ]
|
|
@@ -630,7 +629,7 @@ extendType[ art, outer ]
|
|
|
630
629
|
{ this.docComment( $art ); } annoAssignStd[ $art ]*
|
|
631
630
|
extendElementsBlock[ $art ]?
|
|
632
631
|
|
|
|
633
|
-
WITH
|
|
632
|
+
keyword=WITH
|
|
634
633
|
{ this.docComment( $art ); } annoAssignStd[ $art ]*
|
|
635
634
|
(
|
|
636
635
|
incl=simplePath { $art.includes = [ $incl ]; }
|
|
@@ -647,7 +646,7 @@ extendType[ art, outer ]
|
|
|
647
646
|
;
|
|
648
647
|
|
|
649
648
|
extendEntityOrAspect[ art, outer ]
|
|
650
|
-
@finally{ this.attachLocation( $art ); }
|
|
649
|
+
@finally{ this.checkWith( $keyword ); this.attachLocation( $art ); }
|
|
651
650
|
:
|
|
652
651
|
ASPECT/ENTITY { $art.expectedKind = this.valueWithLocation(); }
|
|
653
652
|
name=namePath[ 'Ext' ]
|
|
@@ -655,7 +654,7 @@ extendEntityOrAspect[ art, outer ]
|
|
|
655
654
|
(
|
|
656
655
|
{ this.docComment( $art ); } annoAssignStd[ $art ]*
|
|
657
656
|
|
|
|
658
|
-
WITH
|
|
657
|
+
keyword=WITH
|
|
659
658
|
{ this.docComment( $art ); } annoAssignStd[ $art ]*
|
|
660
659
|
(
|
|
661
660
|
incl=simplePath { $art.includes = [ $incl ]; }
|
|
@@ -667,12 +666,12 @@ extendEntityOrAspect[ art, outer ]
|
|
|
667
666
|
;
|
|
668
667
|
|
|
669
668
|
extendProjection[ art, outer ]
|
|
670
|
-
@finally{ this.attachLocation( $art ); }
|
|
669
|
+
@finally{ this.checkWith( $keyword ); this.attachLocation( $art ); }
|
|
671
670
|
:
|
|
672
671
|
PROJECTION { $art.expectedKind = this.valueWithLocation(); }
|
|
673
672
|
name=namePath[ 'Ext' ]
|
|
674
673
|
{ $art.name = $name; $outer.extensions.push( $art ); }
|
|
675
|
-
WITH ?
|
|
674
|
+
keyword=WITH ?
|
|
676
675
|
{ this.docComment( $art ); } annoAssignStd[ $art ]*
|
|
677
676
|
selectItemsList[ $art ]?
|
|
678
677
|
actionsBlock[ $art ]?
|
|
@@ -684,9 +683,9 @@ annotateActionsBlock[ art ]
|
|
|
684
683
|
:
|
|
685
684
|
ACTIONS { $art.actions = this.createDict(); } '{'
|
|
686
685
|
( annotateBoundAction[ $art ]
|
|
687
|
-
( ';' | <exitLoop> | <repeatLoop=afterBrace> { this.noAssignmentInSameLine(); } )
|
|
686
|
+
( ';' | <exitLoop> | <repeatLoop, cond=afterBrace> { this.noAssignmentInSameLine(); } )
|
|
688
687
|
)*
|
|
689
|
-
'}'<
|
|
688
|
+
'}'<prepare=afterBrace>
|
|
690
689
|
{ this.finalizeExtensionsDict( $art.actions ); }
|
|
691
690
|
;
|
|
692
691
|
|
|
@@ -722,9 +721,9 @@ annotateParam[ outer ] locals[ art = new XsnArtifact() ]
|
|
|
722
721
|
;
|
|
723
722
|
|
|
724
723
|
annotateReturns[ outer ] locals[ art = new XsnArtifact() ]
|
|
725
|
-
@finally{ this.attachLocation( $art ); }
|
|
724
|
+
@finally{ this.attachLocation( $art ); if ($ret) art.location.tokenIndex = $ret.location.tokenIndex; }
|
|
726
725
|
:
|
|
727
|
-
RETURNS { $outer.returns = $art; $art.kind = 'annotate'; }
|
|
726
|
+
ret=RETURNS { $outer.returns = $art; $art.kind = 'annotate'; }
|
|
728
727
|
{ this.docComment( $art ); } annoAssignStd[ $art ]*
|
|
729
728
|
annotateElementsBlock[ $art ]?
|
|
730
729
|
;
|
|
@@ -735,10 +734,10 @@ annotateElementsBlock[ art ]
|
|
|
735
734
|
( annotateElement[ $art ]
|
|
736
735
|
( ';'
|
|
737
736
|
| <exitLoop>
|
|
738
|
-
| <repeatLoop=afterBrace, restrict=Id> { this.noAssignmentInSameLine(); }
|
|
737
|
+
| <repeatLoop, cond=afterBrace, restrict=Id> { this.noAssignmentInSameLine(); }
|
|
739
738
|
)
|
|
740
739
|
)*
|
|
741
|
-
'}'<
|
|
740
|
+
'}'<prepare=afterBrace>
|
|
742
741
|
{ this.finalizeExtensionsDict( $art.elements ); }
|
|
743
742
|
;
|
|
744
743
|
|
|
@@ -758,13 +757,14 @@ extendElementsBlock[ art, start = undefined ]
|
|
|
758
757
|
( elementDefOrExtend[ $art ]
|
|
759
758
|
( ';'
|
|
760
759
|
| <exitLoop>
|
|
761
|
-
| <repeatLoop=afterBrace, restrict=Id> { this.noAssignmentInSameLine(); } )
|
|
760
|
+
| <repeatLoop, cond=afterBrace, restrict=Id> { this.noAssignmentInSameLine(); } )
|
|
762
761
|
)*
|
|
763
|
-
'}'<
|
|
762
|
+
'}'<prepare=afterBrace>
|
|
764
763
|
{ this.finalizeExtensionsDict( $art.elements ); }
|
|
765
764
|
;
|
|
766
765
|
|
|
767
766
|
elementDefOrExtend[ outer ] locals[ art = new XsnArtifact() ]
|
|
767
|
+
@finally{ this.checkWith( $keyword ); this.attachLocation( $art ); }
|
|
768
768
|
:
|
|
769
769
|
{ this.docComment( $art ); } annoAssignStd[ $art ]*
|
|
770
770
|
(
|
|
@@ -778,7 +778,7 @@ elementDefOrExtend[ outer ] locals[ art = new XsnArtifact() ]
|
|
|
778
778
|
{ this.docComment( $art ); } annoAssignStd[ $art ]*
|
|
779
779
|
extendElementsBlock[ $art ]?
|
|
780
780
|
|
|
|
781
|
-
WITH
|
|
781
|
+
keyword=WITH
|
|
782
782
|
{ this.docComment( $art ); } annoAssignStd[ $art ]*
|
|
783
783
|
(
|
|
784
784
|
elements=ELEMENTS? extendElementsBlock[ art, $elements ]
|
|
@@ -848,71 +848,84 @@ typeOrIncludesSpec[ art ]
|
|
|
848
848
|
typeExpression[ art ]
|
|
849
849
|
// TODO: really introduce <exitRule>
|
|
850
850
|
:
|
|
851
|
-
elementsBlock[ $art ]
|
|
851
|
+
elementsBlock[ $art ] <prepare=elementRestriction, arg=calc>
|
|
852
852
|
nullability[ $art ]?
|
|
853
853
|
|
|
|
854
854
|
( typeRefOptArgs[ $art ] | typeTypeOf[ $art ] )
|
|
855
855
|
(<altRuleStart>)
|
|
856
856
|
nullability[ $art ]?
|
|
857
|
-
// <setCondition=calcOrDefaultRestriction> // TODO TOOL: allow this
|
|
858
|
-
{ this.calcOrDefaultRestriction(); }<always> // workaround
|
|
859
857
|
(
|
|
860
858
|
nullabilityAndDefault[ $art ]
|
|
861
|
-
|
|
859
|
+
// TODO TOOL: with <exitRule>, we could move the following to the end
|
|
860
|
+
(
|
|
861
|
+
{ this.elementRestriction( false, 'calc' ); }
|
|
862
|
+
// <prepare=elementRestriction, arg=calc>
|
|
863
|
+
{ this.docComment( $art ); } annoAssignStd[ $art ]+
|
|
864
|
+
|
|
|
865
|
+
// We could still have the calc expression after this → delay
|
|
866
|
+
{ this.docComment( $art, 'elem' ); }
|
|
867
|
+
)
|
|
862
868
|
|
|
|
863
|
-
|
|
864
|
-
nullabilityAndDefault[ $art ]?
|
|
869
|
+
{ this.docComment( $art, 'elem' ); }
|
|
865
870
|
|
|
|
866
|
-
{ this.docComment( $art ); } annoAssignStd[ $art ]+
|
|
867
|
-
( enumSymbolsBlock[ $art ]
|
|
868
|
-
//
|
|
869
|
-
{ this.calcOrDefaultRestriction(); }<always> // workaround
|
|
871
|
+
{ this.docComment( $art ); } annoAssignStd[ $art ]+ // +!
|
|
872
|
+
( enumSymbolsBlock[ $art ] <prepare=elementRestriction, arg=anno>
|
|
873
|
+
// TODO TOOL: written?
|
|
870
874
|
nullabilityAndDefault[ $art ]?
|
|
871
875
|
)?
|
|
872
876
|
|
|
|
873
877
|
{ this.docComment( $art ); }
|
|
878
|
+
enumSymbolsBlock[ $art ] <prepare=elementRestriction, arg=anno>
|
|
879
|
+
nullabilityAndDefault[ $art ]?
|
|
874
880
|
)
|
|
875
881
|
|
|
|
876
882
|
LOCALIZED
|
|
877
883
|
{ $art.localized = this.valueWithLocation( true ); }
|
|
878
884
|
typeRefOptArgs[ $art ] // TODO: why no TYPE OF ?
|
|
879
|
-
// <setCondition=calcOrDefaultRestriction> // TODO TOOL: allow this
|
|
880
|
-
{ this.calcOrDefaultRestriction(); }<always> // workaround
|
|
881
885
|
nullabilityAndDefault[ $art ]?
|
|
882
|
-
|
|
886
|
+
// TODO TOOL: with <exitRule>, we could move the following to the end
|
|
887
|
+
(
|
|
888
|
+
{ this.elementRestriction( false, 'calc' ); }
|
|
889
|
+
// <prepare=elementRestriction, arg=calc>
|
|
890
|
+
{ this.docComment( $art ); } annoAssignStd[ $art ]+
|
|
891
|
+
|
|
|
892
|
+
{ this.docComment( $art, 'elem' ); }
|
|
893
|
+
)
|
|
883
894
|
|
|
|
884
|
-
assoc=ASSOCIATION
|
|
895
|
+
assoc=ASSOCIATION <prepare=elementRestriction, arg=calc>
|
|
896
|
+
cardinality[ $art ]? TO card=ONE/MANY?
|
|
885
897
|
target=simplePath { this.setAssocAndComposition( $art, $assoc, $card, $target ); }
|
|
886
|
-
// final anno assignments allowed also with fkeys (also in ANTLR-based parser)
|
|
887
|
-
// <prepare=calcOrDefaultRestriction,arg=true> // TODO TOOL: allow this
|
|
888
|
-
{ this.calcOrDefaultRestriction(false,true); }<always> // workaround
|
|
889
|
-
|
|
890
898
|
( ON cond=condition { $art.on = $cond; }
|
|
891
899
|
| foreignKeysBlock[ $art ]?
|
|
892
900
|
nullabilityAndDefault[ $art ]?
|
|
893
|
-
// scalar default - hm..., what about calc expression?
|
|
901
|
+
// scalar default ? - hm..., what about calc expression?
|
|
894
902
|
)
|
|
903
|
+
// final anno assignments allowed also with fkeys (no auto-`;` after them):
|
|
904
|
+
// (the "TODO TOOL" code for doc/annos would also be fine)
|
|
895
905
|
{ this.docComment( $art ); } annoAssignStd[ $art ]*
|
|
896
906
|
|
|
|
897
|
-
assoc=COMPOSITION
|
|
907
|
+
assoc=COMPOSITION <prepare=elementRestriction, arg=calc>
|
|
908
|
+
cardinality[ $art ]? OF card=ONE/MANY?
|
|
898
909
|
(
|
|
899
910
|
target=simplePath { this.setAssocAndComposition( $art, $assoc, $card, $target ); }
|
|
900
|
-
// final anno assignments allowed also with fkeys (also in ANTLR-based parser) - TODO: really?
|
|
901
|
-
// <prepare=calcOrDefaultRestriction,arg=true> // TODO TOOL: allow this
|
|
902
|
-
{ this.calcOrDefaultRestriction(false,true); }<always> // workaround
|
|
903
911
|
( ON cond=condition { $art.on = $cond; }
|
|
904
912
|
| foreignKeysBlock[ $art ]?
|
|
905
913
|
nullabilityAndDefault[ $art ]?
|
|
906
914
|
)
|
|
915
|
+
// final anno assignments allowed also with fkeys (no auto-`;` after them):
|
|
916
|
+
// (the "TODO TOOL" code for doc/annos would also be fine)
|
|
907
917
|
{ this.docComment( $art ); } annoAssignStd[ $art ]*
|
|
908
918
|
|
|
|
909
|
-
{ $target = {
|
|
919
|
+
{ $target = { location: this.startLocation( this.la() ) };
|
|
920
|
+
this.setAssocAndComposition( $art, $assoc, $card, $target ); }
|
|
910
921
|
elementsBlock[ $target ]
|
|
911
922
|
{ $target.location = $target.elements[Symbol.for('cds.$location')]; }
|
|
912
923
|
)
|
|
913
924
|
|
|
|
914
|
-
( ARRAY
|
|
915
|
-
|
|
925
|
+
( ARRAY <prepare=elementRestriction, arg=calc>
|
|
926
|
+
OF { $art.items = { location: this.locationOfPrevTokens( 2 ) }; }
|
|
927
|
+
| MANY <prepare=elementRestriction, arg=calc>
|
|
928
|
+
{ $art.items = { location: this.lb().location }; }
|
|
916
929
|
)
|
|
917
930
|
(
|
|
918
931
|
elementsBlock[ $art.items ]
|
|
@@ -921,9 +934,14 @@ typeExpression[ art ]
|
|
|
921
934
|
( typeRefOptArgs[ $art.items ] | typeTypeOf[ $art.items ] )
|
|
922
935
|
nullability[ $art.items ]?
|
|
923
936
|
( enumSymbolsBlock[ $art.items ]
|
|
924
|
-
nullability[ $art.items ]?
|
|
937
|
+
nullability[ $art.items ]?
|
|
925
938
|
|
|
|
926
|
-
|
|
939
|
+
// TODO TOOL: with <exitRule>, we could move the following to the end
|
|
940
|
+
{ this.elementRestriction( false, 'calc' ); }
|
|
941
|
+
// <prepare=elementRestriction, arg=calc>
|
|
942
|
+
{ this.docComment( $art ); } annoAssignStd[ $art ]+
|
|
943
|
+
|
|
|
944
|
+
{ this.docComment( $art, 'elem' ); }
|
|
927
945
|
)
|
|
928
946
|
)
|
|
929
947
|
;
|
|
@@ -969,6 +987,7 @@ typeRefOptArgs[ art ] locals[ type = $art.type ]
|
|
|
969
987
|
| <exitLoop>
|
|
970
988
|
)
|
|
971
989
|
)* // TODO: really as loop?
|
|
990
|
+
{ this.checkTypeArgs( $art ); } // might reset $art.$typeArgs
|
|
972
991
|
|
|
|
973
992
|
{ $art.$typeArgs = this.createDict( $open ); }
|
|
974
993
|
(
|
|
@@ -976,7 +995,7 @@ typeRefOptArgs[ art ] locals[ type = $art.type ]
|
|
|
976
995
|
( ',' | <exitLoop> )
|
|
977
996
|
)+ // TODO: really as loop?
|
|
978
997
|
)
|
|
979
|
-
')' { this.finalizeDictOrArray( $art.$typeArgs ); }
|
|
998
|
+
')' { if ($art.$typeArgs) this.finalizeDictOrArray( $art.$typeArgs ); }
|
|
980
999
|
)?
|
|
981
1000
|
;
|
|
982
1001
|
|
|
@@ -1043,11 +1062,11 @@ targetCardinality[ card, atAlt = false ]
|
|
|
1043
1062
|
nullabilityAndDefault[ art ]
|
|
1044
1063
|
:
|
|
1045
1064
|
nullability[ $art ]
|
|
1046
|
-
( <cond=
|
|
1065
|
+
( <cond=elementRestriction, arg=default> DEFAULT expr=expression
|
|
1047
1066
|
{ $art.default = $expr; }
|
|
1048
1067
|
)?
|
|
1049
1068
|
|
|
|
1050
|
-
<cond=
|
|
1069
|
+
<cond=elementRestriction, arg=default> DEFAULT expr=expression
|
|
1051
1070
|
{ $art.default = $expr; }
|
|
1052
1071
|
nullability[ $art ]?
|
|
1053
1072
|
// TODO TOOL: when `followUnion` does not contain `Id`, `RuleEnd_` does not
|
|
@@ -1074,9 +1093,10 @@ projectionSpec returns[ default query = {} ]
|
|
|
1074
1093
|
// TODO, currently just with simple ref
|
|
1075
1094
|
PROJECTION { $query = { op: this.valueWithLocation( 'SELECT' ) }; }
|
|
1076
1095
|
ON
|
|
1077
|
-
|
|
1078
|
-
//
|
|
1079
|
-
|
|
1096
|
+
tab=fromRefWithOptAlias
|
|
1097
|
+
// TODO: this <prepare=afterBrace> is extremely strange... v6 forbid.
|
|
1098
|
+
// Deliberately set this via action (→ interpreter will not accept this)
|
|
1099
|
+
{ this.afterBrace(); }<always>
|
|
1080
1100
|
{ $query.from = tab; }
|
|
1081
1101
|
selectItemsList[ $query ]?
|
|
1082
1102
|
excludingClause[ $query ]?
|
|
@@ -1158,7 +1178,7 @@ querySource[ query ]
|
|
|
1158
1178
|
)?
|
|
1159
1179
|
;
|
|
1160
1180
|
|
|
1161
|
-
tableExpression returns[ default expr ] // TableOrJoin
|
|
1181
|
+
tableExpression returns[ default expr = {} ] // TableOrJoin
|
|
1162
1182
|
:
|
|
1163
1183
|
( tableOrQueryParens[ ...$ ]
|
|
1164
1184
|
(<altRuleStart> { $expr = this.taggedIfQuery( $expr ); } )
|
|
@@ -1174,12 +1194,11 @@ tableExpression returns[ default expr ] // TableOrJoin
|
|
|
1174
1194
|
)
|
|
1175
1195
|
|
|
|
1176
1196
|
( ( join=INNER | join=LEFT/RIGHT/FULL OUTER? )
|
|
1177
|
-
card=joinCardinality?
|
|
1178
|
-
| { $join = undefined; }
|
|
1197
|
+
card=joinCardinality? JOIN
|
|
1198
|
+
| JOIN { $join = undefined; }
|
|
1179
1199
|
)
|
|
1180
|
-
JOIN
|
|
1200
|
+
// TODO TOOL: allow zero-alt in choice in outer alt → JOIN can be moved outside
|
|
1181
1201
|
{ $expr = { op: this.valueWithLocation(), join: this.valueWithLocation( $join?.keyword || 'inner', $join ), args: [ $expr ] }; if ($card) $expr.cardinality = $card; $card = undefined; }
|
|
1182
|
-
{ $join = undefined; } // TODO TOOL bug workaround, see above
|
|
1183
1202
|
tab=tableExpression
|
|
1184
1203
|
{ $expr.args.push( $tab ); this.attachLocation( $expr ); }
|
|
1185
1204
|
ON cond=condition { $expr.on = $cond; }
|
|
@@ -1189,26 +1208,22 @@ tableExpression returns[ default expr ] // TableOrJoin
|
|
|
1189
1208
|
|
|
1190
1209
|
tableOrQueryParens returns[ default expr ]
|
|
1191
1210
|
:
|
|
1192
|
-
'('
|
|
1211
|
+
'(' <prepare=queryOnLeft>
|
|
1193
1212
|
( <priority> tableOrQueryParens[ ...$ ]
|
|
1194
|
-
(
|
|
1195
|
-
| <
|
|
1213
|
+
( tableExpression[ ...$ ]<atAltStart, prepare=queryOnLeft, arg=table>
|
|
1214
|
+
| <cond=queryOnLeft> queryExpression[ ...$ ]<atAltStart>
|
|
1196
1215
|
)?
|
|
1197
|
-
|
|
|
1198
|
-
|
|
|
1216
|
+
| tableExpression[ ...$ ] <prepare=queryOnLeft, arg=table>
|
|
1217
|
+
| queryExpression[ ...$ ]
|
|
1199
1218
|
)
|
|
1200
1219
|
')'
|
|
1201
1220
|
{ this.surroundByParens( $expr ); }
|
|
1202
|
-
( <
|
|
1203
|
-
<setCondition=setPrecInCallingRule>
|
|
1221
|
+
( <cond=queryOnLeft, arg=table> AS Id['FromAlias']
|
|
1204
1222
|
{ $expr = this.taggedIfQuery( $expr ); $expr.name = this.identAst(); }
|
|
1205
|
-
| <
|
|
1206
|
-
|
|
1223
|
+
| <cond=queryOnLeft, arg=tableWithoutAs> Id_restricted['FromAlias']
|
|
1224
|
+
// TODO TOOL: shouldn't we have generated `default: this.giR()`?
|
|
1207
1225
|
{ $expr = this.taggedIfQuery( $expr ); $expr.name = this.fragileAlias(); }
|
|
1208
|
-
|
|
1209
|
-
// <setCondition=setPrecInCallingRule> // TODO TOOL: allow this
|
|
1210
|
-
{ this.setPrecInCallingRule(); }<always> // workaround
|
|
1211
|
-
)
|
|
1226
|
+
)?
|
|
1212
1227
|
; // change #10799 for ANTLR-based parser
|
|
1213
1228
|
|
|
1214
1229
|
joinCardinality returns[ sourceMax, targetMax ]
|
|
@@ -1229,9 +1244,10 @@ joinCardinality returns[ sourceMax, targetMax ]
|
|
|
1229
1244
|
)
|
|
1230
1245
|
;
|
|
1231
1246
|
|
|
1232
|
-
fromRefWithOptAlias returns[ default expr = {
|
|
1247
|
+
fromRefWithOptAlias returns[ default expr = {} ]
|
|
1233
1248
|
@finally{ this.attachLocation( $expr ); }
|
|
1234
1249
|
:
|
|
1250
|
+
{ $expr.path = []; }
|
|
1235
1251
|
fromPath[ $expr, 'artref' ]
|
|
1236
1252
|
(
|
|
1237
1253
|
':' { if (!$expr.scope) $expr.scope = $expr.path.length; else {
|
|
@@ -1243,7 +1259,8 @@ fromRefWithOptAlias returns[ default expr = { path: [] } ]
|
|
|
1243
1259
|
(
|
|
1244
1260
|
AS Id['FromAlias'] { $expr.name = this.identAst(); }
|
|
1245
1261
|
|
|
|
1246
|
-
<
|
|
1262
|
+
<cond=tableWithoutAs>
|
|
1263
|
+
// TODO: probably not necessary, TOOL already uses `default: this.giR()`
|
|
1247
1264
|
Id_restricted['FromAlias']
|
|
1248
1265
|
{ $expr.name = this.fragileAlias(); }
|
|
1249
1266
|
|
|
|
@@ -1335,13 +1352,13 @@ excludingClause[ query ]
|
|
|
1335
1352
|
{ this.addDef( { location: this.lb().location }, $query, 'excludingDict', '', this.identAst() ); }
|
|
1336
1353
|
( ',' | <exitLoop> )
|
|
1337
1354
|
)+
|
|
1338
|
-
'}'<
|
|
1355
|
+
'}'<prepare=afterBrace>
|
|
1339
1356
|
{ this.finalizeDictOrArray( $query.excludingDict ); }
|
|
1340
1357
|
;
|
|
1341
1358
|
|
|
1342
1359
|
selectItemsList[ query, start = undefined ]
|
|
1343
1360
|
:
|
|
1344
|
-
'{'<
|
|
1361
|
+
'{'<prepare=inSelectItem, arg=top>
|
|
1345
1362
|
{ $query.columns = this.createArray( $start ); }
|
|
1346
1363
|
(
|
|
1347
1364
|
( '*' { $query.columns.push( this.valueWithLocation() ); }
|
|
@@ -1349,13 +1366,13 @@ selectItemsList[ query, start = undefined ]
|
|
|
1349
1366
|
)
|
|
1350
1367
|
( ',' | <exitLoop> )
|
|
1351
1368
|
)*
|
|
1352
|
-
'}'<
|
|
1369
|
+
'}'<prepare=afterBrace>
|
|
1353
1370
|
{ this.finalizeDictOrArray( $query.columns ); }
|
|
1354
1371
|
;
|
|
1355
1372
|
|
|
1356
1373
|
nestedSelectItemsList[ query, clause ]
|
|
1357
1374
|
:
|
|
1358
|
-
'{'<
|
|
1375
|
+
'{'<prepare=inSelectItem, arg=nested>
|
|
1359
1376
|
{ $query[$clause] = this.createArray(); }
|
|
1360
1377
|
(
|
|
1361
1378
|
( '*' { $query[$clause].push( this.valueWithLocation() ); }
|
|
@@ -1363,7 +1380,7 @@ nestedSelectItemsList[ query, clause ]
|
|
|
1363
1380
|
)
|
|
1364
1381
|
( ',' | <exitLoop> )
|
|
1365
1382
|
)*
|
|
1366
|
-
'}'<
|
|
1383
|
+
'}'<prepare=afterBrace>
|
|
1367
1384
|
{ this.finalizeDictOrArray( $query[$clause] ); }
|
|
1368
1385
|
;
|
|
1369
1386
|
|
|
@@ -1372,9 +1389,9 @@ selectItemDef[ columns ] locals[ art = new XsnArtifact(), alias ]
|
|
|
1372
1389
|
:
|
|
1373
1390
|
{ $columns.push( $art ); } // TODO: probably too early
|
|
1374
1391
|
{ this.docComment( $art ); } annoAssignCol[ $art ]*
|
|
1375
|
-
( <cond=
|
|
1392
|
+
( <cond=modifierRestriction> VIRTUAL
|
|
1376
1393
|
{ $art.virtual = this.valueWithLocation( true ); } )?
|
|
1377
|
-
( <cond=
|
|
1394
|
+
( <cond=modifierRestriction> KEY
|
|
1378
1395
|
{ $art.key = this.valueWithLocation( true ); } )?
|
|
1379
1396
|
(
|
|
1380
1397
|
expr=expression { $art.value = $expr; }
|
|
@@ -1389,6 +1406,7 @@ selectItemDef[ columns ] locals[ art = new XsnArtifact(), alias ]
|
|
|
1389
1406
|
excludingClause[ $art ]?
|
|
1390
1407
|
|
|
|
1391
1408
|
'.'
|
|
1409
|
+
{ this.reportUnexpectedSpace( this.lb(), this.la().location, true ); } // TODO: no ERR
|
|
1392
1410
|
{ this.reportExpandInline( $art, $as || true ); }
|
|
1393
1411
|
{ if ($alias) $alias.token.parsedAs = $alias.parsedAs; }
|
|
1394
1412
|
(
|
|
@@ -1423,7 +1441,6 @@ selectItemDef[ columns ] locals[ art = new XsnArtifact(), alias ]
|
|
|
1423
1441
|
| assoc=COMPOSITION { this.associationInSelectItem( $art ); }
|
|
1424
1442
|
cardinality[ $art ]? OF
|
|
1425
1443
|
)
|
|
1426
|
-
// { this.classifyImplicitName( 'ItemAssoc', $art.value ); } TODO: do we need this?
|
|
1427
1444
|
card=ONE/MANY? target=simplePath
|
|
1428
1445
|
{ this.setAssocAndComposition( $art, $assoc, $card, $target ); }
|
|
1429
1446
|
ON expr=condition { $art.on = $expr; }
|
|
@@ -1497,7 +1514,7 @@ valuePath returns[ default expr = { path: [] } ] locals[ pathItem ]
|
|
|
1497
1514
|
;
|
|
1498
1515
|
|
|
1499
1516
|
// TODO: ? params
|
|
1500
|
-
expression returns[ default expr ]
|
|
1517
|
+
expression returns[ default expr = {} ]
|
|
1501
1518
|
//@finally{ if (!$expr?.$parens) this.attachLocation( $expr ); }
|
|
1502
1519
|
:
|
|
1503
1520
|
(
|
|
@@ -1576,7 +1593,7 @@ expression returns[ default expr ]
|
|
|
1576
1593
|
| <prec=10, postfix=once> IS { $expr = this.applyOpToken( $expr ); }
|
|
1577
1594
|
( NOT { this.pushXprToken( $expr ); } )?
|
|
1578
1595
|
NULL { this.pushXprToken( $expr ); }
|
|
1579
|
-
| ( <cond=isNegatedRelation> NOT { $expr = this.applyOpToken( $expr ); }
|
|
1596
|
+
| ( <arg=10, cond=isNegatedRelation> NOT { $expr = this.applyOpToken( $expr ); }
|
|
1580
1597
|
// TODO: condition, because there might be NOT NULL after DEFAULT expression
|
|
1581
1598
|
| <prec=10, postfix=once>
|
|
1582
1599
|
{ $expr = { op: { val: 'ixpr', location: this.la().location }, args: [ $expr ] }; }
|
|
@@ -1601,19 +1618,18 @@ expression returns[ default expr ]
|
|
|
1601
1618
|
|
|
1602
1619
|
expressionOrQueryParens returns[ default expr ]
|
|
1603
1620
|
:
|
|
1604
|
-
'('
|
|
1621
|
+
'(' <prepare=queryOnLeft>
|
|
1605
1622
|
( <priority> expressionOrQueryParens[ ...$ ]
|
|
1606
|
-
(
|
|
1623
|
+
( expression[ ...$ ]<atAltStart, prepare=queryOnLeft, arg=expr>
|
|
1607
1624
|
continueExpressionslist[ ...$ ]?
|
|
1608
|
-
| <
|
|
1609
|
-
|
|
1610
|
-
| <prec=-1, postfix> queryExpression[ ...$ ]<atAltStart>
|
|
1625
|
+
| continueExpressionslist[ ...$ ] <prepare=queryOnLeft, arg=expr>
|
|
1626
|
+
| <cond=queryOnLeft> queryExpression[ ...$ ]<atAltStart>
|
|
1611
1627
|
)?
|
|
1612
|
-
|
|
|
1628
|
+
| expression[ ...$ ] <prepare=queryOnLeft, arg=expr>
|
|
1613
1629
|
continueExpressionslist[ ...$ ]?
|
|
1614
|
-
|
|
|
1630
|
+
| queryExpression[ ...$ ]
|
|
1615
1631
|
)
|
|
1616
|
-
')'
|
|
1632
|
+
')'
|
|
1617
1633
|
{ this.surroundByParens( $expr ); }
|
|
1618
1634
|
;
|
|
1619
1635
|
|
|
@@ -1636,10 +1652,10 @@ newAndValuePath returns[ default expr ]
|
|
|
1636
1652
|
{ if ($e.op?.val !== 'ixpr') $expr.args.push( $e ); else $expr.args.push( ...e.args ); }
|
|
1637
1653
|
;
|
|
1638
1654
|
|
|
1639
|
-
caseExpression returns[ default expr
|
|
1655
|
+
caseExpression returns[ default expr ]
|
|
1640
1656
|
@finally{ this.attachLocation( $expr ); }
|
|
1641
1657
|
:
|
|
1642
|
-
CASE {
|
|
1658
|
+
CASE { $expr.op = { val: 'ixpr', location: this.lb().location }; $expr.args = []; this.pushXprToken( $expr ); }
|
|
1643
1659
|
( e=expression { $expr.args.push( $e ); } )?
|
|
1644
1660
|
(
|
|
1645
1661
|
WHEN { this.pushXprToken( $expr ); }
|
|
@@ -1654,7 +1670,7 @@ caseExpression returns[ default expr = { op: { val: 'ixpr' }, args: [] } ]
|
|
|
1654
1670
|
END { this.pushXprToken( $expr ); }
|
|
1655
1671
|
;
|
|
1656
1672
|
|
|
1657
|
-
castFunction returns[ default expr
|
|
1673
|
+
castFunction returns[ default expr ]
|
|
1658
1674
|
@finally{ this.attachLocation( $expr ); }
|
|
1659
1675
|
:
|
|
1660
1676
|
CAST { $expr.op = this.valueWithLocation(); }
|
|
@@ -1669,7 +1685,7 @@ argumentsAndFilter[ pathStep ]
|
|
|
1669
1685
|
options{ minTokensMatched = 1 }
|
|
1670
1686
|
:
|
|
1671
1687
|
(
|
|
1672
|
-
open='(' <
|
|
1688
|
+
open='(' <prepare=prepareSpecialFunction>
|
|
1673
1689
|
{ $pathStep.args = this.createArray(); }
|
|
1674
1690
|
// action here, default action won't be executed with failed condition (TODO
|
|
1675
1691
|
// TOOL? at least msg)
|
|
@@ -1678,7 +1694,7 @@ options{ minTokensMatched = 1 }
|
|
|
1678
1694
|
(
|
|
1679
1695
|
expr=funcExpression { $pathStep.args.push( $expr ); }
|
|
1680
1696
|
(
|
|
1681
|
-
','<
|
|
1697
|
+
','<prepare=nextFunctionArgument>
|
|
1682
1698
|
( expr=funcExpression { $pathStep.args.push( $expr ); }
|
|
1683
1699
|
| <exitLoop> // <cond>: only before `)`
|
|
1684
1700
|
)
|
|
@@ -1750,12 +1766,14 @@ funcExpression returns[ default expr ] locals[ args ]
|
|
|
1750
1766
|
)*
|
|
1751
1767
|
;
|
|
1752
1768
|
|
|
1769
|
+
// TODO: check Id_all - necessary if generic token is a reserved word?
|
|
1753
1770
|
GenericExpr
|
|
1754
1771
|
: Id_all | '*' ;
|
|
1755
1772
|
GenericIntro
|
|
1756
1773
|
: Id_all ;
|
|
1757
1774
|
GenericSeparator
|
|
1758
|
-
:
|
|
1775
|
+
: Id_restricted ; // otherwise expression ops use keyword prediction
|
|
1776
|
+
// TODO TOOL: use `<restrict=Id> GenericSeparator` instead and back to Id_all or Id
|
|
1759
1777
|
|
|
1760
1778
|
overClause[ outer ] locals[ over = [] ]
|
|
1761
1779
|
@finally{ $outer.push( this.surroundByParens( this.ixprAst( $over ) ) ); }
|
|
@@ -1862,7 +1880,7 @@ literalValue returns[ default expr = {} ]
|
|
|
1862
1880
|
annoAssignStd[ art ]
|
|
1863
1881
|
@finally{ this.docComment( $art ); }
|
|
1864
1882
|
:
|
|
1865
|
-
'@'<
|
|
1883
|
+
'@'<prepare=annoInSameLine> { this.reportUnexpectedSpace(); }
|
|
1866
1884
|
( annoAssignParen[ ...$ ]
|
|
1867
1885
|
| annoAssignBase[ ...$ ]
|
|
1868
1886
|
)
|
|
@@ -1880,7 +1898,7 @@ annoAssignCol[ art ]
|
|
|
1880
1898
|
annoAssignMid[ art ]
|
|
1881
1899
|
@finally{ this.docComment( $art ); }
|
|
1882
1900
|
:
|
|
1883
|
-
'@'<
|
|
1901
|
+
'@'<prepare=annoInSameLine> { this.reportUnexpectedSpace(); }
|
|
1884
1902
|
( annoAssignParen[ ...$ ]
|
|
1885
1903
|
| name=annoNamePath // !
|
|
1886
1904
|
{ this.assignAnnotation( $art, {}, $name ); this.warnIfColonFollows( $name ); }
|
|
@@ -1889,7 +1907,7 @@ annoAssignMid[ art ]
|
|
|
1889
1907
|
|
|
1890
1908
|
annoAssignParen[ art ]
|
|
1891
1909
|
:
|
|
1892
|
-
'('<
|
|
1910
|
+
'('<prepare=annoInSameLine>
|
|
1893
1911
|
( annoAssignBase[ $art ]
|
|
1894
1912
|
( ',' | <exitLoop> )
|
|
1895
1913
|
)*
|
|
@@ -1982,15 +2000,17 @@ annoValue returns[ default value = {} ]
|
|
|
1982
2000
|
}
|
|
1983
2001
|
( ',' | <exitLoop> )
|
|
1984
2002
|
)*
|
|
1985
|
-
'}'
|
|
2003
|
+
// ( <cond=TODO> '}' ) // TODO TOOL - workaround:
|
|
2004
|
+
{ this.ec( 'arrayAnno', 'orNotEmpty' ); } '}'
|
|
2005
|
+
// Do NOT use <prepare=afterBrace> here!
|
|
1986
2006
|
|
|
|
1987
|
-
'['<
|
|
2007
|
+
'['<prepare=arrayAnno>
|
|
1988
2008
|
{ $value.val = []; $value.literal = 'array' }
|
|
1989
2009
|
// no need for createArray() here, $value.location is set above
|
|
1990
2010
|
(
|
|
1991
2011
|
( sub=annoValue { $value.val.push( $sub ) }
|
|
1992
2012
|
|
|
|
1993
|
-
<cond=
|
|
2013
|
+
<cond=arrayAnno, arg=ellipsis> ellipsis='...'
|
|
1994
2014
|
( UP TO upTo=annoValue | { $upTo = undefined; } )
|
|
1995
2015
|
{ $value.val.push( { literal: 'token', val: '...', location: $ellipsis.location, upTo: $upTo } ); }
|
|
1996
2016
|
)
|