@sap/cds-compiler 2.11.2 → 2.13.6
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 +175 -2
- package/bin/.eslintrc.json +1 -2
- package/bin/cds_update_identifiers.js +10 -8
- package/bin/cdsc.js +23 -17
- package/bin/cdsse.js +2 -2
- package/bin/cdsv2m.js +3 -2
- package/doc/CHANGELOG_ARCHIVE.md +1 -1
- package/doc/CHANGELOG_BETA.md +25 -6
- package/doc/CHANGELOG_DEPRECATED.md +22 -6
- package/doc/NameResolution.md +21 -16
- package/lib/api/main.js +32 -79
- package/lib/api/options.js +3 -2
- package/lib/api/validate.js +2 -1
- package/lib/backends.js +16 -26
- package/lib/base/dictionaries.js +0 -8
- package/lib/base/error.js +26 -0
- package/lib/base/keywords.js +10 -19
- package/lib/base/location.js +9 -4
- package/lib/base/message-registry.js +75 -9
- package/lib/base/messages.js +31 -35
- package/lib/base/model.js +2 -62
- package/lib/base/optionProcessorHelper.js +246 -183
- package/lib/checks/.eslintrc.json +2 -0
- package/lib/checks/actionsFunctions.js +2 -1
- package/lib/checks/annotationsOData.js +1 -1
- package/lib/checks/cdsPersistence.js +2 -1
- package/lib/checks/emptyOrOnlyVirtual.js +2 -2
- package/lib/checks/enricher.js +17 -1
- package/lib/checks/foreignKeys.js +4 -4
- package/lib/checks/invalidTarget.js +3 -1
- package/lib/checks/managedInType.js +4 -4
- package/lib/checks/managedWithoutKeys.js +3 -1
- package/lib/checks/queryNoDbArtifacts.js +1 -3
- package/lib/checks/selectItems.js +4 -4
- package/lib/checks/sql-snippets.js +94 -0
- package/lib/checks/types.js +1 -1
- package/lib/checks/unknownMagic.js +1 -1
- package/lib/checks/validator.js +12 -7
- package/lib/compiler/assert-consistency.js +12 -8
- package/lib/compiler/base.js +0 -1
- package/lib/compiler/builtins.js +42 -21
- package/lib/compiler/checks.js +46 -12
- package/lib/compiler/cycle-detector.js +1 -1
- package/lib/compiler/define.js +1103 -0
- package/lib/compiler/extend.js +983 -0
- package/lib/compiler/finalize-parse-cdl.js +231 -0
- package/lib/compiler/index.js +46 -39
- package/lib/compiler/kick-start.js +190 -0
- package/lib/compiler/moduleLayers.js +4 -4
- package/lib/compiler/populate.js +1226 -0
- package/lib/compiler/propagator.js +113 -47
- package/lib/compiler/resolve.js +1433 -0
- package/lib/compiler/shared.js +100 -65
- package/lib/compiler/tweak-assocs.js +529 -0
- package/lib/compiler/utils.js +215 -33
- package/lib/edm/.eslintrc.json +5 -0
- package/lib/edm/annotations/genericTranslation.js +38 -25
- package/lib/edm/annotations/preprocessAnnotations.js +3 -3
- package/lib/edm/csn2edm.js +10 -9
- package/lib/edm/edm.js +19 -20
- package/lib/edm/edmPreprocessor.js +166 -95
- package/lib/edm/edmUtils.js +127 -34
- package/lib/gen/Dictionary.json +92 -43
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +11 -1
- package/lib/gen/language.tokens +86 -82
- package/lib/gen/languageLexer.interp +18 -1
- package/lib/gen/languageLexer.js +925 -847
- package/lib/gen/languageLexer.tokens +78 -74
- package/lib/gen/languageParser.js +5434 -4298
- package/lib/json/from-csn.js +59 -17
- package/lib/json/to-csn.js +189 -71
- package/lib/language/antlrParser.js +3 -3
- package/lib/language/docCommentParser.js +3 -3
- package/lib/language/errorStrategy.js +26 -8
- package/lib/language/genericAntlrParser.js +144 -53
- package/lib/language/language.g4 +424 -200
- package/lib/language/multiLineStringParser.js +536 -0
- package/lib/main.d.ts +550 -61
- package/lib/main.js +38 -11
- package/lib/model/api.js +3 -1
- package/lib/model/csnRefs.js +322 -198
- package/lib/model/csnUtils.js +226 -370
- package/lib/model/enrichCsn.js +124 -69
- package/lib/model/revealInternalProperties.js +29 -7
- package/lib/model/sortViews.js +10 -2
- package/lib/modelCompare/compare.js +17 -12
- package/lib/optionProcessor.js +8 -3
- package/lib/render/.eslintrc.json +1 -2
- package/lib/render/DuplicateChecker.js +1 -1
- package/lib/render/manageConstraints.js +36 -33
- package/lib/render/toCdl.js +174 -275
- package/lib/render/toHdbcds.js +203 -122
- package/lib/render/toRename.js +7 -10
- package/lib/render/toSql.js +161 -82
- package/lib/render/utils/common.js +22 -8
- package/lib/render/utils/sql.js +10 -7
- package/lib/render/utils/stringEscapes.js +111 -0
- package/lib/sql-identifier.js +1 -1
- package/lib/transform/.eslintrc.json +5 -0
- package/lib/transform/braceExpression.js +4 -2
- package/lib/transform/db/.eslintrc.json +2 -0
- package/lib/transform/db/applyTransformations.js +212 -0
- package/lib/transform/db/assertUnique.js +1 -1
- package/lib/transform/db/associations.js +187 -0
- package/lib/transform/db/cdsPersistence.js +150 -0
- package/lib/transform/db/constraints.js +61 -56
- package/lib/transform/db/expansion.js +50 -29
- package/lib/transform/db/flattening.js +556 -106
- package/lib/transform/db/groupByOrderBy.js +3 -1
- package/lib/transform/db/temporal.js +236 -0
- package/lib/transform/db/transformExists.js +103 -28
- package/lib/transform/db/views.js +92 -44
- package/lib/transform/draft/.eslintrc.json +38 -0
- package/lib/transform/{db/draft.js → draft/db.js} +9 -7
- package/lib/transform/draft/odata.js +227 -0
- package/lib/transform/forHanaNew.js +98 -783
- package/lib/transform/forOdataNew.js +22 -175
- package/lib/transform/localized.js +36 -32
- package/lib/transform/odata/generateForeignKeyElements.js +3 -3
- package/lib/transform/odata/referenceFlattener.js +95 -89
- package/lib/transform/odata/structureFlattener.js +1 -1
- package/lib/transform/odata/toFinalBaseType.js +86 -12
- package/lib/transform/odata/typesExposure.js +5 -5
- package/lib/transform/odata/utils.js +2 -2
- package/lib/transform/transformUtilsNew.js +47 -33
- package/lib/transform/translateAssocsToJoins.js +13 -30
- package/lib/transform/universalCsn/.eslintrc.json +36 -0
- package/lib/transform/universalCsn/coreComputed.js +170 -0
- package/lib/transform/universalCsn/universalCsnEnricher.js +715 -0
- package/lib/transform/universalCsn/utils.js +63 -0
- package/lib/utils/file.js +8 -3
- package/lib/utils/objectUtils.js +30 -0
- package/lib/utils/timetrace.js +8 -2
- package/package.json +1 -1
- package/share/messages/README.md +26 -0
- package/lib/compiler/definer.js +0 -2349
- package/lib/compiler/resolver.js +0 -2922
- package/lib/transform/db/helpers.js +0 -58
- package/lib/transform/universalCsnEnricher.js +0 -67
package/lib/language/language.g4
CHANGED
|
@@ -393,7 +393,7 @@ artifactDef[ outer, defOnly = false ] locals[ annos = [] ] // cannot use `parent
|
|
|
393
393
|
| extendProjection[ $outer, this.startLocation(), $annos ]
|
|
394
394
|
| extendType[ $outer, this.startLocation(), $annos ]
|
|
395
395
|
| extendAspect[ $outer, this.startLocation(), $annos ]
|
|
396
|
-
|
|
396
|
+
// Streamlined Syntax
|
|
397
397
|
| extendArtifact[ $outer, this.startLocation(), $annos ]
|
|
398
398
|
)
|
|
399
399
|
|
|
|
@@ -418,7 +418,9 @@ contextDef[ outer, loc, annos, defOnly = false ] locals[ art, name = {} ]
|
|
|
418
418
|
this.docComment( $annos ); }
|
|
419
419
|
annotationAssignment_fix[ $annos ]*
|
|
420
420
|
(
|
|
421
|
-
'{'
|
|
421
|
+
'{' { $art.artifacts = this.createDict(); }
|
|
422
|
+
artifactDef[ $art, defOnly ]*
|
|
423
|
+
'}' { this.setDictEndLocation( $art.artifacts ); }
|
|
422
424
|
optionalSemi
|
|
423
425
|
|
|
|
424
426
|
requiredSemi
|
|
@@ -436,9 +438,9 @@ extendContext[ outer, loc, annos ] locals[ art, name = {} ]
|
|
|
436
438
|
{ this.docComment( $annos ); }
|
|
437
439
|
annotationAssignment_ll1[ $annos ]*
|
|
438
440
|
(
|
|
439
|
-
'{'
|
|
440
|
-
artifactDef[ $art, $service ? 'SERVICE' : 'CONTEXT'
|
|
441
|
-
'}'
|
|
441
|
+
'{' { $art.artifacts = this.createDict(); }
|
|
442
|
+
artifactDef[ $art, $service ? 'SERVICE' : 'CONTEXT' ]*
|
|
443
|
+
'}' { this.setDictEndLocation( $art.artifacts ); }
|
|
442
444
|
optionalSemi
|
|
443
445
|
|
|
|
444
446
|
requiredSemi
|
|
@@ -461,23 +463,35 @@ entityDef[ outer, loc, annos ] locals[ art, name = {} ]
|
|
|
461
463
|
)*
|
|
462
464
|
)?
|
|
463
465
|
'{'
|
|
464
|
-
{ $art.elements =
|
|
466
|
+
{ $art.elements = this.createDict(); } // better for include and annotate
|
|
465
467
|
elementDef[ $art ]*
|
|
466
|
-
'}'
|
|
468
|
+
'}' { this.setDictEndLocation( $art.elements ); }
|
|
467
469
|
// TODO: action definitions in a specific section?
|
|
468
|
-
(
|
|
470
|
+
(
|
|
471
|
+
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
472
|
+
actionFunctionDef[ $art ]*
|
|
473
|
+
'}' { this.setDictEndLocation( $art.actions ); }
|
|
474
|
+
)?
|
|
469
475
|
optionalSemi
|
|
470
476
|
|
|
|
471
477
|
AS
|
|
472
478
|
( qe=queryExpression
|
|
473
479
|
{ $art.query = $qe.query; $art['$'+'syntax'] = 'entity' }
|
|
474
|
-
(
|
|
480
|
+
(
|
|
481
|
+
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
482
|
+
actionFunctionDef[ $art ]*
|
|
483
|
+
'}' { this.setDictEndLocation( $art.actions ); }
|
|
484
|
+
optionalSemi
|
|
475
485
|
| requiredSemi
|
|
476
486
|
)
|
|
477
487
|
| qp=projectionSpec
|
|
478
488
|
{ $art.query = $qp.query; $art['$'+'syntax'] = 'projection'; }
|
|
479
489
|
projectionClauses[ $qp.query ]
|
|
480
|
-
(
|
|
490
|
+
(
|
|
491
|
+
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
492
|
+
actionFunctionDef[ $art ]*
|
|
493
|
+
'}' { this.setDictEndLocation( $art.actions ); }
|
|
494
|
+
)?
|
|
481
495
|
optionalSemi // TODO: not fully correct without columns or excluding
|
|
482
496
|
)
|
|
483
497
|
)
|
|
@@ -490,7 +504,7 @@ projectionSpec returns[ query ] locals[ src ]
|
|
|
490
504
|
// now a simplified `tableTerm`:
|
|
491
505
|
{
|
|
492
506
|
$src = { path: [], scope: 0 };
|
|
493
|
-
$query = { op: this.
|
|
507
|
+
$query = { op: this.valueWithTokenLocation( 'SELECT', $proj ), from: $src, location: this.startLocation() };
|
|
494
508
|
}
|
|
495
509
|
fromPath[ $src, 'artref']
|
|
496
510
|
( ':'
|
|
@@ -522,12 +536,12 @@ excludingClause[ query ]
|
|
|
522
536
|
:
|
|
523
537
|
// syntax is less than ideal - EXCLUDING is only useful for `*` - with
|
|
524
538
|
// this syntax, people wonder what happens with explicit select items
|
|
525
|
-
EXCLUDING '{'
|
|
539
|
+
EXCLUDING '{' { $query.excludingDict = this.createDict(); }
|
|
526
540
|
projectionExclusion[ $query ]
|
|
527
541
|
( ',' { if (this.isStraightBefore("}")) break; } // allow ',' before '}'
|
|
528
542
|
projectionExclusion[ $query ]
|
|
529
543
|
)*
|
|
530
|
-
'}'
|
|
544
|
+
'}' { this.setDictEndLocation( $query.excludingDict ); }
|
|
531
545
|
;
|
|
532
546
|
|
|
533
547
|
projectionExclusion[ outer ] locals[ art ]
|
|
@@ -562,13 +576,19 @@ extendEntity[ outer, loc, annos ] locals[ art, name = {} ]
|
|
|
562
576
|
|
|
563
577
|
extendForEntity[ art ]
|
|
564
578
|
:
|
|
565
|
-
'{'
|
|
579
|
+
'{' { $art.elements = this.createDict(); }
|
|
566
580
|
elementDefOrExtend[ $art ]*
|
|
567
|
-
'}'
|
|
568
|
-
(
|
|
581
|
+
'}' { this.setDictEndLocation( $art.elements ); }
|
|
582
|
+
(
|
|
583
|
+
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
584
|
+
actionFunctionDef[ $art ]*
|
|
585
|
+
'}' { this.setDictEndLocation( $art.actions ); }
|
|
586
|
+
)?
|
|
569
587
|
optionalSemi
|
|
570
588
|
|
|
|
571
|
-
ACTIONS '{'
|
|
589
|
+
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
590
|
+
actionFunctionDef[ $art ]*
|
|
591
|
+
'}' { this.setDictEndLocation( $art.actions ); }
|
|
572
592
|
optionalSemi
|
|
573
593
|
|
|
|
574
594
|
requiredSemi
|
|
@@ -594,10 +614,16 @@ extendProjection[ outer, loc, annos ] locals[ art, name = {} ]
|
|
|
594
614
|
)*
|
|
595
615
|
)?
|
|
596
616
|
'}'
|
|
597
|
-
(
|
|
617
|
+
(
|
|
618
|
+
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
619
|
+
actionFunctionDef[ $art ]*
|
|
620
|
+
'}' { this.setDictEndLocation( $art.actions ); }
|
|
621
|
+
)?
|
|
598
622
|
optionalSemi
|
|
599
623
|
|
|
|
600
|
-
ACTIONS '{'
|
|
624
|
+
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
625
|
+
actionFunctionDef[ $art ]*
|
|
626
|
+
'}' { this.setDictEndLocation( $art.actions ); }
|
|
601
627
|
optionalSemi
|
|
602
628
|
|
|
|
603
629
|
requiredSemi
|
|
@@ -702,12 +728,15 @@ aspectDef[ outer, loc, annos ] locals[ art, name = {} ]
|
|
|
702
728
|
)*
|
|
703
729
|
)?
|
|
704
730
|
)?
|
|
705
|
-
'{'
|
|
706
|
-
{ $art.elements = Object.create(null); } // better for include and annotate
|
|
731
|
+
'{' { $art.elements = this.createDict(); }
|
|
707
732
|
( elementDef[ $art ]* )
|
|
708
|
-
'}'
|
|
733
|
+
'}' { this.setDictEndLocation( $art.elements ); }
|
|
709
734
|
// TODO: action definitions in a specific section?
|
|
710
|
-
(
|
|
735
|
+
(
|
|
736
|
+
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
737
|
+
actionFunctionDef[ $art ]*
|
|
738
|
+
'}' { this.setDictEndLocation( $art.actions ); }
|
|
739
|
+
)?
|
|
711
740
|
optionalSemi
|
|
712
741
|
;
|
|
713
742
|
|
|
@@ -758,13 +787,82 @@ annotationDef[ outer, loc, annos ] locals[ art, name = {} ]
|
|
|
758
787
|
typeSpecSemi[ $art, $annos ] // also 'includes'...
|
|
759
788
|
;
|
|
760
789
|
|
|
761
|
-
extendArtifact[ outer, loc, annos ] locals[ art, name = {} ]
|
|
762
|
-
@after
|
|
790
|
+
extendArtifact[ outer, loc, annos ] locals[ art, name = {}, elemName = {} ]
|
|
791
|
+
@after{ /* #ATN 1 */ this.attachLocation($art); }
|
|
763
792
|
:
|
|
764
793
|
simplePath[ $name, 'Extend' ]
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
794
|
+
(
|
|
795
|
+
{ $art = this.addItem( $outer, 'extensions', 'extend', $annos, { name: $name }, $loc ); }
|
|
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 ]*
|
|
807
|
+
(
|
|
808
|
+
'{' { $art.elements = this.createDict(); }
|
|
809
|
+
elementDefOrExtend[ $art ]*
|
|
810
|
+
'}' { this.setDictEndLocation( $art.elements ); }
|
|
811
|
+
optionalSemi
|
|
812
|
+
|
|
|
813
|
+
requiredSemi
|
|
814
|
+
)
|
|
815
|
+
|
|
|
816
|
+
WITH { this.noSemicolonHere(); this.docComment( $annos ); }
|
|
817
|
+
annotationAssignment_ll1[ $annos ]*
|
|
818
|
+
// #ATN: DEFINITIONS, COLUMNS, ACTIONS etc are not reserved and could be identifiers (ref).
|
|
819
|
+
(
|
|
820
|
+
includeRef[ $art ]
|
|
821
|
+
requiredSemi
|
|
822
|
+
|
|
|
823
|
+
'{' { $art.elements = this.createDict(); }
|
|
824
|
+
elementDefOrExtend[ $art ]*
|
|
825
|
+
'}' { this.setDictEndLocation( $art.elements ); }
|
|
826
|
+
optionalSemi
|
|
827
|
+
|
|
|
828
|
+
requiredSemi
|
|
829
|
+
|
|
|
830
|
+
{ this.disallowElementExtension( $elemName, $outer, 'definitions' ); }
|
|
831
|
+
DEFINITIONS
|
|
832
|
+
'{' { $art.artifacts = this.createDict(); }
|
|
833
|
+
artifactDef[ $art, true ]*
|
|
834
|
+
'}' { this.setDictEndLocation( $art.artifacts ); }
|
|
835
|
+
optionalSemi
|
|
836
|
+
|
|
|
837
|
+
{ this.disallowElementExtension( $elemName, $outer, 'columns' ); }
|
|
838
|
+
COLUMNS
|
|
839
|
+
'{' { $art.columns = []; }
|
|
840
|
+
(
|
|
841
|
+
selectItemDef[ $art.columns ]
|
|
842
|
+
( ',' { if (this.isStraightBefore("}")) break; } // allow ',' before '}'
|
|
843
|
+
selectItemDef[ $art.columns ]
|
|
844
|
+
)*
|
|
845
|
+
)?
|
|
846
|
+
'}'
|
|
847
|
+
optionalSemi
|
|
848
|
+
|
|
|
849
|
+
{ this.disallowElementExtension( $elemName, $outer, 'actions' ); }
|
|
850
|
+
ACTIONS '{' { $art.actions = this.createDict(); }
|
|
851
|
+
actionFunctionDef[ $art ]*
|
|
852
|
+
'}' { this.setDictEndLocation( $art.actions ); }
|
|
853
|
+
optionalSemi
|
|
854
|
+
|
|
|
855
|
+
ELEMENTS '{' { $art.elements = this.createDict(); }
|
|
856
|
+
elementDefOrExtend[ $art ]*
|
|
857
|
+
'}' { this.setDictEndLocation( $art.elements ); }
|
|
858
|
+
optionalSemi
|
|
859
|
+
|
|
|
860
|
+
ENUM '{' { $art.enum = this.createDict(); }
|
|
861
|
+
enumSymbolDef[ $art ]*
|
|
862
|
+
'}' { this.setDictEndLocation( $art.enum ); }
|
|
863
|
+
optionalSemi
|
|
864
|
+
)
|
|
865
|
+
)
|
|
768
866
|
;
|
|
769
867
|
|
|
770
868
|
extendWithOptElements[ art, annos ]
|
|
@@ -775,9 +873,9 @@ extendWithOptElements[ art, annos ]
|
|
|
775
873
|
includeRef[ $art ]
|
|
776
874
|
requiredSemi
|
|
777
875
|
|
|
|
778
|
-
'{'
|
|
876
|
+
'{' { $art.elements = this.createDict(); }
|
|
779
877
|
elementDefOrExtend[ $art ]*
|
|
780
|
-
'}'
|
|
878
|
+
'}' { this.setDictEndLocation( $art.elements ); }
|
|
781
879
|
optionalSemi
|
|
782
880
|
|
|
|
783
881
|
requiredSemi
|
|
@@ -786,59 +884,71 @@ extendWithOptElements[ art, annos ]
|
|
|
786
884
|
{ this.docComment( $annos ); }
|
|
787
885
|
annotationAssignment_ll1[ $annos ]*
|
|
788
886
|
(
|
|
789
|
-
'{'
|
|
887
|
+
'{' { $art.elements = this.createDict(); }
|
|
790
888
|
elementDefOrExtend[ $art ]*
|
|
791
|
-
'}'
|
|
889
|
+
'}' { this.setDictEndLocation( $art.elements ); }
|
|
792
890
|
optionalSemi
|
|
793
891
|
|
|
|
794
892
|
requiredSemi
|
|
795
893
|
)
|
|
796
894
|
;
|
|
797
895
|
|
|
798
|
-
annotateArtifact[ outer, loc, annos ] locals[ art, name = {} ]
|
|
896
|
+
annotateArtifact[ outer, loc, annos ] locals[ art, name = {}, elemName = {} ]
|
|
799
897
|
@after { this.attachLocation($art); }
|
|
800
898
|
:
|
|
801
899
|
simplePath[ $name, 'Annotate' ]
|
|
802
|
-
|
|
900
|
+
(
|
|
901
|
+
{ $art = this.addItem( $outer, 'extensions', 'annotate', $annos, { name: $name }, $loc ); }
|
|
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
|
+
|
|
803
911
|
( WITH { this.noSemicolonHere(); } )?
|
|
804
912
|
{ this.docComment( $annos ); }
|
|
805
913
|
annotationAssignment_ll1[ $annos ]*
|
|
806
914
|
(
|
|
807
|
-
'{'
|
|
915
|
+
'{' { $art.elements = this.createDict(); }
|
|
808
916
|
annotateElement[ $art ]*
|
|
809
|
-
'}'
|
|
917
|
+
'}' { this.setDictEndLocation( $art.elements ); }
|
|
810
918
|
(
|
|
811
919
|
ACTIONS
|
|
812
|
-
'{'
|
|
920
|
+
'{' { $art.actions = this.createDict(); }
|
|
813
921
|
annotateAction[ $art ]*
|
|
814
|
-
'}'
|
|
922
|
+
'}' { this.setDictEndLocation( $art.actions ); }
|
|
815
923
|
)?
|
|
816
924
|
optionalSemi
|
|
817
925
|
|
|
|
818
926
|
ACTIONS
|
|
819
|
-
'{'
|
|
927
|
+
'{' { $art.actions = this.createDict(); }
|
|
820
928
|
annotateAction[ $art ]*
|
|
821
|
-
'}'
|
|
929
|
+
'}' { this.setDictEndLocation( $art.actions ); }
|
|
822
930
|
optionalSemi
|
|
823
931
|
|
|
|
824
|
-
'('
|
|
932
|
+
'(' { $art.params = this.createDict(); }
|
|
825
933
|
annotateParam[ $art ]
|
|
826
934
|
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
827
935
|
annotateParam[ $art ]
|
|
828
936
|
)*
|
|
829
|
-
')'
|
|
937
|
+
')' { this.setDictEndLocation( $art.params ); }
|
|
830
938
|
(
|
|
831
|
-
RETURNS
|
|
939
|
+
RETURNS { $art['$'+'syntax'] = 'returns'; }
|
|
940
|
+
'{' { $art.elements = this.createDict(); }
|
|
832
941
|
annotateElement[ $art ]*
|
|
833
|
-
'}'
|
|
942
|
+
'}' { this.setDictEndLocation( $art.elements ); }
|
|
834
943
|
optionalSemi
|
|
835
944
|
|
|
|
836
945
|
requiredSemi
|
|
837
946
|
)
|
|
838
947
|
|
|
|
839
|
-
RETURNS
|
|
948
|
+
RETURNS { $art['$'+'syntax'] = 'returns'; }
|
|
949
|
+
'{' { $art.elements = this.createDict(); }
|
|
840
950
|
annotateElement[ $art ]*
|
|
841
|
-
'}'
|
|
951
|
+
'}' { this.setDictEndLocation( $art.elements ); }
|
|
842
952
|
optionalSemi
|
|
843
953
|
|
|
844
954
|
|
|
|
@@ -856,9 +966,9 @@ annotateElement[ outer ] locals[ art, annos = [] ]
|
|
|
856
966
|
this.docComment( $annos ); }
|
|
857
967
|
annotationAssignment_ll1[ $annos ]*
|
|
858
968
|
(
|
|
859
|
-
'{'
|
|
969
|
+
'{' { $art.elements = this.createDict(); }
|
|
860
970
|
annotateElement[ $art ]*
|
|
861
|
-
'}'
|
|
971
|
+
'}' { this.setDictEndLocation( $art.elements ); }
|
|
862
972
|
optionalSemi
|
|
863
973
|
|
|
|
864
974
|
requiredSemi
|
|
@@ -875,17 +985,17 @@ annotateAction [ outer ] locals [ art, annos = [] ]
|
|
|
875
985
|
this.docComment( $annos ); }
|
|
876
986
|
annotationAssignment_ll1[ $annos ]*
|
|
877
987
|
(
|
|
878
|
-
'('
|
|
988
|
+
'(' { $art.params = this.createDict(); }
|
|
879
989
|
annotateParam[ $art ]
|
|
880
990
|
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
881
991
|
annotateParam[ $art ]
|
|
882
992
|
)*
|
|
883
|
-
')'
|
|
993
|
+
')' { this.setDictEndLocation( $art.params ); }
|
|
884
994
|
)?
|
|
885
995
|
(
|
|
886
|
-
RETURNS '{'
|
|
996
|
+
RETURNS '{' { $art.elements = this.createDict(); }
|
|
887
997
|
annotateElement[ $art ]*
|
|
888
|
-
'}'
|
|
998
|
+
'}' { this.setDictEndLocation( $art.elements ); }
|
|
889
999
|
optionalSemi
|
|
890
1000
|
|
|
|
891
1001
|
requiredSemi
|
|
@@ -929,6 +1039,12 @@ enumSymbolDef[ outer ] locals[ art, annos = [] ]
|
|
|
929
1039
|
requiredSemi
|
|
930
1040
|
;
|
|
931
1041
|
|
|
1042
|
+
defaultValue[ art ] locals[ elem, elements = {} ]
|
|
1043
|
+
:
|
|
1044
|
+
// TODO: We may support structured default values here.
|
|
1045
|
+
DEFAULT expr=expression { $art.default = $expr.expr; }
|
|
1046
|
+
;
|
|
1047
|
+
|
|
932
1048
|
elementDefOrExtend[ outer ] locals[ annos = [] ]
|
|
933
1049
|
@after { /* #ATN 1 */ if ($ctx.art) this.attachLocation($art.art); }
|
|
934
1050
|
// tool complains if I test for ($art)
|
|
@@ -983,6 +1099,7 @@ mixinElementDef[ outer ] locals[ art ]
|
|
|
983
1099
|
|
|
984
1100
|
misplacedAnnotations[ annos, messageId ]
|
|
985
1101
|
:
|
|
1102
|
+
// No docComment() here
|
|
986
1103
|
annotationAssignment_ll1[ $annos ]+
|
|
987
1104
|
{ if ($messageId) // issue specified in central registry
|
|
988
1105
|
this.message( messageId, this.tokenLocation( $ctx.start, this.getCurrentToken() ) );
|
|
@@ -994,7 +1111,7 @@ elementDefInner[ outer, loc, annos, allowEq ] returns[ art ]
|
|
|
994
1111
|
:
|
|
995
1112
|
// TODO: it would be excellent to remove ELEMENT...
|
|
996
1113
|
// or have a special ident rule without the ELEMENT
|
|
997
|
-
// Reason: it would be good for error
|
|
1114
|
+
// Reason: it would be good for error recovery to start a major block without LL1 ambiguity
|
|
998
1115
|
// VIRTUAL is keyword, except if before the following tokens texts:
|
|
999
1116
|
{ this.setLocalToken( 'VIRTUAL', 'VIRTUAL', /^[:{@=}]$/ ); }
|
|
1000
1117
|
virtual=VIRTUAL? key=KEY?
|
|
@@ -1046,7 +1163,7 @@ elementDefInner[ outer, loc, annos, allowEq ] returns[ art ]
|
|
|
1046
1163
|
)
|
|
1047
1164
|
|
|
|
1048
1165
|
(
|
|
1049
|
-
array=ARRAY of=OF
|
|
1166
|
+
array=ARRAY of=OF
|
|
1050
1167
|
{ $art.items = { location: this.tokenLocation( $array, $of ) }; }
|
|
1051
1168
|
| many=MANY
|
|
1052
1169
|
{ $art.items = { location: this.tokenLocation( $many ) };}
|
|
@@ -1064,10 +1181,9 @@ elementDefInner[ outer, loc, annos, allowEq ] returns[ art ]
|
|
|
1064
1181
|
{ this.docComment( $annos ); }
|
|
1065
1182
|
annotationAssignment_ll1[ $annos ]*
|
|
1066
1183
|
(
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
'}'
|
|
1184
|
+
ENUM '{' { $art.items.enum = this.createDict(); }
|
|
1185
|
+
enumSymbolDef[ $art.items ]*
|
|
1186
|
+
'}' { this.setDictEndLocation( $art.items.enum ); }
|
|
1071
1187
|
misplacedAnnotations[ $annos, 'syntax-anno-after-enum' ]?
|
|
1072
1188
|
)?
|
|
1073
1189
|
)
|
|
@@ -1078,7 +1194,7 @@ elementDefInner[ outer, loc, annos, allowEq ] returns[ art ]
|
|
|
1078
1194
|
annotationAssignment_ll1[ $annos ]*
|
|
1079
1195
|
requiredSemi // also req after foreign key spec
|
|
1080
1196
|
|
|
|
1081
|
-
l=LOCALIZED { $art.localized = this.
|
|
1197
|
+
l=LOCALIZED { $art.localized = this.valueWithTokenLocation( true, $l ); }
|
|
1082
1198
|
typeRefOptArgs[ $art ]
|
|
1083
1199
|
{ this.docComment( $annos ); }
|
|
1084
1200
|
annotationAssignment_ll1[ $annos ]*
|
|
@@ -1091,13 +1207,14 @@ elementDefInner[ outer, loc, annos, allowEq ] returns[ art ]
|
|
|
1091
1207
|
typeRefOptArgs[ $art ]
|
|
1092
1208
|
{ this.docComment( $annos ); }
|
|
1093
1209
|
annotationAssignment_ll1[ $annos ]*
|
|
1094
|
-
(
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
'}'
|
|
1210
|
+
(
|
|
1211
|
+
ENUM '{' { $art.enum = this.createDict(); }
|
|
1212
|
+
enumSymbolDef[ $art ]*
|
|
1213
|
+
'}' { this.setDictEndLocation( $art.enum ); }
|
|
1098
1214
|
elementProperties[ $art ]?
|
|
1099
1215
|
misplacedAnnotations[ $annos, 'syntax-anno-after-enum' ]?
|
|
1100
|
-
|
|
|
1216
|
+
|
|
|
1217
|
+
elementProperties[ $art ]
|
|
1101
1218
|
{ this.docComment( $annos ); }
|
|
1102
1219
|
annotationAssignment_ll1[ $annos ]*
|
|
1103
1220
|
)?
|
|
@@ -1146,7 +1263,7 @@ selectItemDef[ outer ] locals[ annos = [] ]
|
|
|
1146
1263
|
@after{ if ($ctx.art) this.attachLocation($art.art); }
|
|
1147
1264
|
:
|
|
1148
1265
|
star='*'
|
|
1149
|
-
{ $outer.push( this.
|
|
1266
|
+
{ $outer.push( this.valueWithTokenLocation( '*', $star ) ); }
|
|
1150
1267
|
|
|
|
1151
1268
|
{ this.docComment( $annos ); }
|
|
1152
1269
|
annotationAssignment_atn[ $annos ]*
|
|
@@ -1156,8 +1273,8 @@ selectItemDef[ outer ] locals[ annos = [] ]
|
|
|
1156
1273
|
key=KEY?
|
|
1157
1274
|
art=selectItemDefBody[ $outer, $annos ]
|
|
1158
1275
|
{
|
|
1159
|
-
if ($virtual) $art.art.virtual = this.
|
|
1160
|
-
if ($key) $art.art.key = this.
|
|
1276
|
+
if ($virtual) $art.art.virtual = this.valueWithTokenLocation( true, $virtual );
|
|
1277
|
+
if ($key) $art.art.key = this.valueWithTokenLocation( true, $key );
|
|
1161
1278
|
}
|
|
1162
1279
|
;
|
|
1163
1280
|
|
|
@@ -1190,7 +1307,7 @@ selectItemDefBody[ outer, annos ] returns[ art = {} ]
|
|
|
1190
1307
|
excludingClause[ $art ]?
|
|
1191
1308
|
|
|
|
1192
1309
|
star='*'
|
|
1193
|
-
{ $art.inline = [ this.
|
|
1310
|
+
{ $art.inline = [ this.valueWithTokenLocation( '*', $star ) ]; }
|
|
1194
1311
|
)
|
|
1195
1312
|
)?
|
|
1196
1313
|
|
|
|
@@ -1239,7 +1356,7 @@ selectItemInlineDef[ outer ] locals[ annos = [] ]
|
|
|
1239
1356
|
@after{ if ($ctx.art) this.attachLocation($art.art); }
|
|
1240
1357
|
:
|
|
1241
1358
|
star='*'
|
|
1242
|
-
{ $outer.push( this.
|
|
1359
|
+
{ $outer.push( this.valueWithTokenLocation( '*', $star ) ); }
|
|
1243
1360
|
|
|
|
1244
1361
|
{ this.docComment( $annos ); }
|
|
1245
1362
|
annotationAssignment_atn[ $annos ]*
|
|
@@ -1248,7 +1365,7 @@ selectItemInlineDef[ outer ] locals[ annos = [] ]
|
|
|
1248
1365
|
|
|
1249
1366
|
parameterListDef[ art ]
|
|
1250
1367
|
:
|
|
1251
|
-
'('
|
|
1368
|
+
'(' { $art.params = this.createDict(); }
|
|
1252
1369
|
// also empty param list (we might do some hacking later to allow reserved words)
|
|
1253
1370
|
// see annotationAssignment_paren
|
|
1254
1371
|
(
|
|
@@ -1257,7 +1374,7 @@ parameterListDef[ art ]
|
|
|
1257
1374
|
parameterDef[ $art ]
|
|
1258
1375
|
)*
|
|
1259
1376
|
)?
|
|
1260
|
-
')'
|
|
1377
|
+
')' { this.setDictEndLocation( $art.params ); }
|
|
1261
1378
|
;
|
|
1262
1379
|
|
|
1263
1380
|
parameterDef[ outer ] locals[ art, annos = [] ]
|
|
@@ -1270,14 +1387,14 @@ parameterDef[ outer ] locals[ art, annos = [] ]
|
|
|
1270
1387
|
this.docComment( $annos ); }
|
|
1271
1388
|
annotationAssignment_fix[ $annos ]*
|
|
1272
1389
|
typeSpec[ $art ]
|
|
1273
|
-
|
|
1390
|
+
defaultValue[ $art ]?
|
|
1274
1391
|
{ this.docComment( $annos ); }
|
|
1275
1392
|
annotationAssignment_ll1[ $annos ]*
|
|
1276
1393
|
;
|
|
1277
1394
|
|
|
1278
1395
|
entityParameters[ art ]
|
|
1279
1396
|
:
|
|
1280
|
-
'('
|
|
1397
|
+
'(' { $art.params = this.createDict(); }
|
|
1281
1398
|
// also empty param list (we might do some hacking later to allow reserved words)
|
|
1282
1399
|
// see annotationAssignment_paren
|
|
1283
1400
|
(
|
|
@@ -1286,7 +1403,7 @@ entityParameters[ art ]
|
|
|
1286
1403
|
entityParameterDef[ $art ]
|
|
1287
1404
|
)*
|
|
1288
1405
|
)?
|
|
1289
|
-
')'
|
|
1406
|
+
')' { this.setDictEndLocation( $art.params ); }
|
|
1290
1407
|
;
|
|
1291
1408
|
|
|
1292
1409
|
entityParameterDef[ outer ] locals[ art, annos = [] ]
|
|
@@ -1299,31 +1416,27 @@ entityParameterDef[ outer ] locals[ art, annos = [] ]
|
|
|
1299
1416
|
this.docComment( $annos ); }
|
|
1300
1417
|
annotationAssignment_fix[ $annos ]*
|
|
1301
1418
|
typeSpec[ $art ]
|
|
1302
|
-
|
|
1419
|
+
defaultValue[ $art ]?
|
|
1420
|
+
{ this.docComment( $annos ); }
|
|
1421
|
+
annotationAssignment_ll1[ $annos ]*
|
|
1303
1422
|
;
|
|
1304
1423
|
|
|
1305
1424
|
nullability[ art ]
|
|
1306
1425
|
:
|
|
1307
1426
|
not=NOT n1=NULL
|
|
1308
|
-
{ $art.notNull = this.
|
|
1427
|
+
{ $art.notNull = this.valueWithTokenLocation( true, $not, $n1 ); }
|
|
1309
1428
|
|
|
|
1310
1429
|
n2=NULL
|
|
1311
|
-
{ $art.notNull = this.
|
|
1430
|
+
{ $art.notNull = this.valueWithTokenLocation( false, $n2 ); }
|
|
1312
1431
|
;
|
|
1313
1432
|
|
|
1314
1433
|
elementProperties[ elem ]
|
|
1315
1434
|
:
|
|
1316
|
-
nullability[$elem]
|
|
1317
|
-
|
|
1318
|
-
DEFAULT expr=expression
|
|
1319
|
-
{ $elem.default = $expr.expr; }
|
|
1320
|
-
)?
|
|
1435
|
+
nullability[ $elem ]
|
|
1436
|
+
defaultValue[ $elem ]?
|
|
1321
1437
|
|
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
{ $elem.default = $expr.expr; }
|
|
1325
|
-
)
|
|
1326
|
-
nullability[$elem]?
|
|
1438
|
+
defaultValue[ $elem ]
|
|
1439
|
+
nullability[ $elem ]?
|
|
1327
1440
|
|
|
|
1328
1441
|
eq='='
|
|
1329
1442
|
{ this.notSupportedYet( 'Calculated fields are not supported yet', $eq ); }
|
|
@@ -1374,10 +1487,10 @@ typeSpec[ art ] // for params
|
|
|
1374
1487
|
// TODO: no LOCALIZED ?
|
|
1375
1488
|
| typeRefOptArgs[ $art ]
|
|
1376
1489
|
nullability[ $art ]?
|
|
1377
|
-
(
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
'}'
|
|
1490
|
+
(
|
|
1491
|
+
ENUM '{' { $art.enum = this.createDict(); }
|
|
1492
|
+
enumSymbolDef[ $art ]*
|
|
1493
|
+
'}' { this.setDictEndLocation( $art.enum ); }
|
|
1381
1494
|
)?
|
|
1382
1495
|
)
|
|
1383
1496
|
;
|
|
@@ -1387,7 +1500,7 @@ returnTypeSpec[ art, annos ]
|
|
|
1387
1500
|
:
|
|
1388
1501
|
ret=RETURNS { $art.returns = { location: this.tokenLocation( $ret ), kind: 'param' }; }
|
|
1389
1502
|
// #ATN: typeSimple can start with ARRAY or TYPE
|
|
1390
|
-
( typeStruct[ $art.returns ]
|
|
1503
|
+
( typeStruct[ $art.returns ]
|
|
1391
1504
|
nullability[ $art.returns ]?
|
|
1392
1505
|
| typeArray[ $art.returns ] // nullability is set in typeArray
|
|
1393
1506
|
| typeTypeOf[ $art.returns ]
|
|
@@ -1395,11 +1508,12 @@ returnTypeSpec[ art, annos ]
|
|
|
1395
1508
|
// TODO: no LOCALIZED ?
|
|
1396
1509
|
| typeRefOptArgs[ $art.returns ]
|
|
1397
1510
|
nullability[ $art.returns ]?
|
|
1398
|
-
(
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
'}'
|
|
1402
|
-
|
|
|
1511
|
+
(
|
|
1512
|
+
ENUM '{' { $art.returns.enum = this.createDict(); }
|
|
1513
|
+
enumSymbolDef[ $art.returns ]*
|
|
1514
|
+
'}' { this.setDictEndLocation( $art.returns.enum ); }
|
|
1515
|
+
|
|
|
1516
|
+
misplacedAnnotations[ $annos, 'syntax-anno-after-params' ]
|
|
1403
1517
|
)?
|
|
1404
1518
|
)
|
|
1405
1519
|
|
|
@@ -1440,7 +1554,7 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
|
|
|
1440
1554
|
{ $art.items = { location: this.tokenLocation( $many ) };}
|
|
1441
1555
|
)
|
|
1442
1556
|
// #ATN: typeRefOptArgs can start with TYPE
|
|
1443
|
-
( typeStruct[ $art.items ]
|
|
1557
|
+
( typeStruct[ $art.items ]
|
|
1444
1558
|
nullability[ $art.items ]?
|
|
1445
1559
|
optionalSemi
|
|
1446
1560
|
| typeTypeOf[ $art.items ]
|
|
@@ -1452,21 +1566,24 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
|
|
|
1452
1566
|
nullability[ $art.items ]?
|
|
1453
1567
|
{ this.docComment( $annos ); }
|
|
1454
1568
|
annotationAssignment_ll1[ $annos ]*
|
|
1455
|
-
(
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
'}'
|
|
1459
|
-
optionalSemi
|
|
1460
|
-
|
|
|
1569
|
+
(
|
|
1570
|
+
ENUM '{' { $art.items.enum = this.createDict(); }
|
|
1571
|
+
enumSymbolDef[ $art.items ]*
|
|
1572
|
+
'}' { this.setDictEndLocation( $art.items.enum ); }
|
|
1573
|
+
optionalSemi
|
|
1574
|
+
|
|
|
1575
|
+
requiredSemi
|
|
1461
1576
|
)
|
|
1462
1577
|
)
|
|
1463
1578
|
|
|
|
1464
1579
|
typeTypeOf[ $art ]
|
|
1580
|
+
defaultValue[ $art ]?
|
|
1465
1581
|
{ this.docComment( $annos ); }
|
|
1466
1582
|
annotationAssignment_ll1[ $annos ]* requiredSemi
|
|
1467
1583
|
|
|
|
1468
|
-
l=LOCALIZED { $art.localized = this.
|
|
1584
|
+
l=LOCALIZED { $art.localized = this.valueWithTokenLocation( true, $l ); }
|
|
1469
1585
|
typeRefOptArgs[ $art ]
|
|
1586
|
+
defaultValue[ $art ]?
|
|
1470
1587
|
{ this.docComment( $annos ); }
|
|
1471
1588
|
annotationAssignment_ll1[ $annos ]*
|
|
1472
1589
|
requiredSemi
|
|
@@ -1497,11 +1614,19 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
|
|
|
1497
1614
|
')'
|
|
1498
1615
|
{ this.docComment( $annos ); }
|
|
1499
1616
|
annotationAssignment_ll1[ $annos ]*
|
|
1500
|
-
(
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
'}'
|
|
1504
|
-
|
|
1617
|
+
(
|
|
1618
|
+
ENUM '{' { $art.enum = this.createDict(); }
|
|
1619
|
+
enumSymbolDef[ $art ]*
|
|
1620
|
+
'}' { this.setDictEndLocation( $art.enum ); }
|
|
1621
|
+
(
|
|
1622
|
+
optionalSemi
|
|
1623
|
+
|
|
|
1624
|
+
defaultValue[ $art ]
|
|
1625
|
+
requiredSemi
|
|
1626
|
+
)
|
|
1627
|
+
|
|
|
1628
|
+
defaultValue[ $art ]?
|
|
1629
|
+
requiredSemi
|
|
1505
1630
|
)
|
|
1506
1631
|
|
|
|
1507
1632
|
':' // with element, e.g. `type T : E:elem enum { ... }`
|
|
@@ -1509,20 +1634,36 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
|
|
|
1509
1634
|
simplePath[ $art.type, 'ref']
|
|
1510
1635
|
{ this.docComment( $annos ); }
|
|
1511
1636
|
annotationAssignment_ll1[ $annos ]*
|
|
1512
|
-
(
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
'}'
|
|
1516
|
-
|
|
1637
|
+
(
|
|
1638
|
+
ENUM '{' { $art.enum = this.createDict(); }
|
|
1639
|
+
enumSymbolDef[ $art ]*
|
|
1640
|
+
'}' { this.setDictEndLocation( $art.enum ); }
|
|
1641
|
+
(
|
|
1642
|
+
optionalSemi
|
|
1643
|
+
|
|
|
1644
|
+
defaultValue[ $art ]
|
|
1645
|
+
requiredSemi
|
|
1646
|
+
)
|
|
1647
|
+
|
|
|
1648
|
+
defaultValue[ $art ]?
|
|
1649
|
+
requiredSemi
|
|
1517
1650
|
)
|
|
1518
1651
|
|
|
|
1519
1652
|
{ this.docComment( $annos ); }
|
|
1520
1653
|
annotationAssignment_ll1[ $annos ]*
|
|
1521
|
-
(
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
'}'
|
|
1525
|
-
|
|
1654
|
+
(
|
|
1655
|
+
ENUM '{' { $art.enum = this.createDict(); }
|
|
1656
|
+
enumSymbolDef[ $art ]*
|
|
1657
|
+
'}' { this.setDictEndLocation( $art.enum ); }
|
|
1658
|
+
(
|
|
1659
|
+
optionalSemi
|
|
1660
|
+
|
|
|
1661
|
+
defaultValue[ $art ]
|
|
1662
|
+
requiredSemi
|
|
1663
|
+
)
|
|
1664
|
+
|
|
|
1665
|
+
defaultValue[ $art ]?
|
|
1666
|
+
requiredSemi
|
|
1526
1667
|
)
|
|
1527
1668
|
|
|
|
1528
1669
|
// TODO: complain if used in anno def?
|
|
@@ -1539,15 +1680,17 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
|
|
|
1539
1680
|
typeStruct[ art, attachLoc = false ]
|
|
1540
1681
|
@after { if ($attachLoc) this.attachLocation($art); }
|
|
1541
1682
|
:
|
|
1542
|
-
{ $art.elements =
|
|
1543
|
-
|
|
1683
|
+
'{' { $art.elements = this.createDict(); }
|
|
1684
|
+
elementDef[ $art ]*
|
|
1685
|
+
'}' { this.setDictEndLocation( $art.elements ); }
|
|
1544
1686
|
;
|
|
1545
1687
|
|
|
1546
1688
|
typeCompoStruct[ art ]
|
|
1547
1689
|
@after { this.attachLocation($art); }
|
|
1548
1690
|
:
|
|
1549
|
-
{ $art.elements =
|
|
1550
|
-
|
|
1691
|
+
COMPOSITIONofBRACE { $art.elements = this.createDict(); }
|
|
1692
|
+
elementDef[ $art ]*
|
|
1693
|
+
'}' { this.setDictEndLocation( $art.elements ); }
|
|
1551
1694
|
;
|
|
1552
1695
|
|
|
1553
1696
|
typeArray[ art ]
|
|
@@ -1566,10 +1709,10 @@ typeArray[ art ]
|
|
|
1566
1709
|
nullability[ $art.items ]?
|
|
1567
1710
|
| typeRefOptArgs[ $art.items ]
|
|
1568
1711
|
nullability[ $art.items ]?
|
|
1569
|
-
(
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
'}'
|
|
1712
|
+
(
|
|
1713
|
+
ENUM '{' { $art.items.enum = this.createDict(); }
|
|
1714
|
+
enumSymbolDef[ $art.items ]*
|
|
1715
|
+
'}' { this.setDictEndLocation( $art.items.enum ); }
|
|
1573
1716
|
)?
|
|
1574
1717
|
)
|
|
1575
1718
|
;
|
|
@@ -1597,7 +1740,7 @@ typeAssociationBase[ art, handleTypeCompo ] // including Composition
|
|
|
1597
1740
|
typeAssociationCont[ art ]
|
|
1598
1741
|
:
|
|
1599
1742
|
(
|
|
1600
|
-
'{'
|
|
1743
|
+
'{' { $art.foreignKeys = this.createDict(); }
|
|
1601
1744
|
{ this.addDef( $art, 'foreignKeys' ); }
|
|
1602
1745
|
(
|
|
1603
1746
|
foreignKey[ $art ]
|
|
@@ -1605,7 +1748,7 @@ typeAssociationCont[ art ]
|
|
|
1605
1748
|
foreignKey[ $art ]
|
|
1606
1749
|
)*
|
|
1607
1750
|
)?
|
|
1608
|
-
'}'
|
|
1751
|
+
'}' { this.setDictEndLocation( $art.foreignKeys ); }
|
|
1609
1752
|
|
|
|
1610
1753
|
ON cond=condition
|
|
1611
1754
|
{ $art.on=$cond.cond; }
|
|
@@ -1616,7 +1759,7 @@ typeAssociationElementCont[ art, annos ] // including Composition
|
|
|
1616
1759
|
// optional NULL / NOT NULL for managed association only
|
|
1617
1760
|
:
|
|
1618
1761
|
(
|
|
1619
|
-
'{'
|
|
1762
|
+
'{' { $art.foreignKeys = this.createDict(); }
|
|
1620
1763
|
{ this.addDef( $art, 'foreignKeys' ); }
|
|
1621
1764
|
(
|
|
1622
1765
|
foreignKey[ $art ]
|
|
@@ -1624,7 +1767,7 @@ typeAssociationElementCont[ art, annos ] // including Composition
|
|
|
1624
1767
|
foreignKey[ $art ]
|
|
1625
1768
|
)*
|
|
1626
1769
|
)?
|
|
1627
|
-
'}'
|
|
1770
|
+
'}' { this.setDictEndLocation( $art.foreignKeys ); }
|
|
1628
1771
|
nullability[ $art ]?
|
|
1629
1772
|
|
|
|
1630
1773
|
ON cond=condition
|
|
@@ -1764,33 +1907,47 @@ orderByClause[ inQuery ] returns [ query ]
|
|
|
1764
1907
|
( ',' obn=orderBySpec { $query.orderBy.push( $obn.ob ); } )*
|
|
1765
1908
|
;
|
|
1766
1909
|
|
|
1910
|
+
// Generic function ORDER BY clause, e.g. `first_value(id order by name)`
|
|
1911
|
+
// lhsExpr is the left expression of the ORDER BY clause.
|
|
1912
|
+
functionOrderByClause[ lhsExpr ] returns [ expr ]
|
|
1913
|
+
@after { this.attachLocation( $expr ); }
|
|
1914
|
+
:
|
|
1915
|
+
o=ORDER b=BY { $expr = { op: this.valueWithTokenLocation( 'orderBy', $o, $b ) , args: [ $lhsExpr ] }}
|
|
1916
|
+
ob1=orderBySpec { $expr.args.push( $ob1.ob ); }
|
|
1917
|
+
( ',' obn=orderBySpec { $expr.args.push( $obn.ob ); } )*
|
|
1918
|
+
;
|
|
1919
|
+
|
|
1767
1920
|
overOrderByClause returns [ expr ]
|
|
1921
|
+
@after { this.attachLocation( $expr ); }
|
|
1768
1922
|
:
|
|
1769
|
-
o=ORDER b=BY { $expr = { op: this.
|
|
1923
|
+
o=ORDER b=BY { $expr = { op: this.valueWithTokenLocation( 'overOrderBy', $o, $b ) , args: [] }}
|
|
1770
1924
|
ob1=orderBySpec { $expr.args.push( $ob1.ob ); }
|
|
1771
1925
|
( ',' obn=orderBySpec { $expr.args.push( $obn.ob ); } )*
|
|
1772
1926
|
;
|
|
1773
1927
|
|
|
1774
1928
|
partitionByClause returns [ expr ]
|
|
1929
|
+
@after { this.attachLocation( $expr ); }
|
|
1775
1930
|
:
|
|
1776
|
-
p=PARTITION b=BY { $expr = { op: this.
|
|
1931
|
+
p=PARTITION b=BY { $expr = { op: this.valueWithTokenLocation( 'partitionBy', $p, $b ) , args: [] }}
|
|
1777
1932
|
e1=expression { $expr.args.push( $e1.expr ); }
|
|
1778
1933
|
( ',' en=expression { $expr.args.push( $en.expr ); } )*
|
|
1779
1934
|
;
|
|
1780
1935
|
|
|
1781
1936
|
windowFrameClause returns [ wf ]
|
|
1937
|
+
@after { this.attachLocation( $wf ); }
|
|
1782
1938
|
:
|
|
1783
|
-
r=ROWS { $wf = { op: this.
|
|
1939
|
+
r=ROWS { $wf = { op: this.valueWithTokenLocation( 'rows', $r ) , args: [] }}
|
|
1784
1940
|
wfe=windowFrameExtentSpec { $wf.args.push( $wfe.wfe ); }
|
|
1785
1941
|
;
|
|
1786
1942
|
|
|
1787
1943
|
windowFrameExtentSpec returns[ wfe ]
|
|
1944
|
+
@after { this.attachLocation( $wfe ); }
|
|
1788
1945
|
:
|
|
1789
1946
|
{ $wfe = {} }
|
|
1790
1947
|
windowFrameStartSpec [ $wfe ]
|
|
1791
1948
|
|
|
|
1792
1949
|
b=BETWEEN
|
|
1793
|
-
{ $wfe = { op: this.
|
|
1950
|
+
{ $wfe = { op: this.valueWithTokenLocation( 'frameBetween', $b ), args: [] } }
|
|
1794
1951
|
wfb1=windowFrameBoundSpec { $wfe.args.push( $wfb1.wfb ); }
|
|
1795
1952
|
AND
|
|
1796
1953
|
wfb2=windowFrameBoundSpec { $wfe.args.push( $wfb2.wfb ); }
|
|
@@ -1802,42 +1959,43 @@ windowFrameBoundSpec returns [ wfb ]
|
|
|
1802
1959
|
// #ATN: Not ll1 because `UNBOUNDED` could also be part of the windowFrameStartSpec
|
|
1803
1960
|
// `UNBOUNDED` would then be immediately followed by `PRECEDING`
|
|
1804
1961
|
u=UNBOUNDED f=FOLLOWING
|
|
1805
|
-
{ $wfb = { op: this.
|
|
1962
|
+
{ $wfb = { op: this.valueWithTokenLocation( 'unboundedFollowing', $u, $f ), args: []} }
|
|
1806
1963
|
|
|
|
1807
1964
|
// #ATN: Not ll1 because `Number` could also be part of the windowFrameStartSpec
|
|
1808
1965
|
// `Number` would then be immediately followed by `PRECEDING`
|
|
1809
1966
|
n=Number f=FOLLOWING
|
|
1810
|
-
{ $wfb = { op: this.
|
|
1967
|
+
{ $wfb = { op: this.valueWithTokenLocation( 'following', $n, $f ), args: [ this.numberLiteral( $n ) ]} }
|
|
1811
1968
|
|
|
|
1812
1969
|
{ $wfb = {} }
|
|
1813
1970
|
windowFrameStartSpec [ $wfb ]
|
|
1814
1971
|
;
|
|
1815
1972
|
|
|
1816
1973
|
windowFrameStartSpec [ wf ]
|
|
1974
|
+
@after { this.attachLocation( $wf ); }
|
|
1817
1975
|
:
|
|
1818
1976
|
u=UNBOUNDED p=PRECEDING
|
|
1819
1977
|
{
|
|
1820
|
-
$wf.op = this.
|
|
1978
|
+
$wf.op = this.valueWithTokenLocation( 'unboundedPreceding', $u, $p );
|
|
1821
1979
|
$wf.args = [];
|
|
1822
1980
|
}
|
|
1823
1981
|
|
|
|
1824
1982
|
n=Number p=PRECEDING
|
|
1825
1983
|
{
|
|
1826
|
-
$wf.op = this.
|
|
1984
|
+
$wf.op = this.valueWithTokenLocation( 'preceding', $p );
|
|
1827
1985
|
$wf.args = [ this.numberLiteral( $n ) ];
|
|
1828
1986
|
}
|
|
1829
|
-
|
|
|
1987
|
+
|
|
|
1830
1988
|
c=CURRENT r=ROW
|
|
1831
1989
|
{
|
|
1832
|
-
$wf.op = this.
|
|
1990
|
+
$wf.op = this.valueWithTokenLocation( 'currentRow', $c, $r );
|
|
1833
1991
|
$wf.args = [];
|
|
1834
1992
|
}
|
|
1835
1993
|
;
|
|
1836
1994
|
|
|
1837
1995
|
overClause returns [ over ]
|
|
1838
|
-
@after { this.attachLocation($over); }
|
|
1996
|
+
@after { this.attachLocation( $over ); }
|
|
1839
1997
|
:
|
|
1840
|
-
o=OVER { $over = { op: this.
|
|
1998
|
+
o=OVER { $over = { op: this.valueWithTokenLocation( 'over', $o ) , args: [] } }
|
|
1841
1999
|
'('
|
|
1842
2000
|
( pb=partitionByClause { $over.args.push( $pb.expr ); } )?
|
|
1843
2001
|
( ob=overOrderByClause { $over.args.push( $ob.expr ); } )?
|
|
@@ -1858,11 +2016,11 @@ limitClause[ inQuery ] returns [ query ]
|
|
|
1858
2016
|
orderBySpec returns[ ob ]
|
|
1859
2017
|
:
|
|
1860
2018
|
e=expression { $ob = $e.expr; }
|
|
1861
|
-
( asc=ASC { $ob.sort = this.
|
|
1862
|
-
| desc=DESC { $ob.sort = this.
|
|
2019
|
+
( asc=ASC { $ob.sort = this.valueWithTokenLocation( 'asc', $asc ); }
|
|
2020
|
+
| desc=DESC { $ob.sort = this.valueWithTokenLocation( 'desc', $desc ); }
|
|
1863
2021
|
)?
|
|
1864
2022
|
( nb=NULLS ne=( FIRST | LAST )
|
|
1865
|
-
{ $ob.nulls = this.
|
|
2023
|
+
{ $ob.nulls = this.valueWithTokenLocation( $ne.text.toLowerCase(), $nb, $ne ); }
|
|
1866
2024
|
)?
|
|
1867
2025
|
;
|
|
1868
2026
|
|
|
@@ -1885,22 +2043,23 @@ queryPrimary returns[ query = {} ]
|
|
|
1885
2043
|
{ $query = this.surroundByParens( $qe.query, $open, $close ); }
|
|
1886
2044
|
|
|
|
1887
2045
|
select=SELECT
|
|
1888
|
-
{ $query = { op: this.
|
|
2046
|
+
{ $query = { op: this.valueWithTokenLocation( 'SELECT', $select ), location: this.startLocation() }; }
|
|
1889
2047
|
(
|
|
1890
2048
|
FROM querySource[ $query ]
|
|
1891
2049
|
(
|
|
1892
|
-
mixin=MIXIN '{'
|
|
2050
|
+
mixin=MIXIN '{' { $query.mixin = this.createDict(); }
|
|
1893
2051
|
mixinElementDef[ $query ]*
|
|
1894
|
-
'}'
|
|
2052
|
+
'}' { this.setDictEndLocation( $query.mixin ); }
|
|
2053
|
+
INTO
|
|
1895
2054
|
)?
|
|
1896
2055
|
( ad=( ALL | DISTINCT ) // TODO: or directly after SELECT ?
|
|
1897
|
-
{ $query.quantifier = this.
|
|
2056
|
+
{ $query.quantifier = this.valueWithTokenLocation( $ad.text.toLowerCase(), $ad ); }
|
|
1898
2057
|
)?
|
|
1899
2058
|
bracedSelectItemListDef[ $query ]?
|
|
1900
2059
|
excludingClause[ $query ]?
|
|
1901
2060
|
|
|
|
1902
2061
|
( ad=( ALL | DISTINCT ) // TODO: or directly after SELECT ?
|
|
1903
|
-
{ $query.quantifier = this.
|
|
2062
|
+
{ $query.quantifier = this.valueWithTokenLocation( $ad.text.toLowerCase(), $ad ); }
|
|
1904
2063
|
)?
|
|
1905
2064
|
{ $query.columns = []; } // set it early to avoid "wildcard" errors
|
|
1906
2065
|
selectItemDef[ $query.columns ]
|
|
@@ -1954,8 +2113,8 @@ joinOp[ left ] returns[ table ] locals [ join ]
|
|
|
1954
2113
|
| t1=RIGHT t2=OUTER? c=joinCardinality? op=JOIN { $join = 'right' }
|
|
1955
2114
|
| t1=FULL t2=OUTER? c=joinCardinality? op=JOIN { $join = 'full' }
|
|
1956
2115
|
)
|
|
1957
|
-
{ $table = { op: this.
|
|
1958
|
-
join: this.
|
|
2116
|
+
{ $table = { op: this.valueWithTokenLocation( 'join', $op ),
|
|
2117
|
+
join: this.valueWithTokenLocation( $join, $t1 || $op, $t2 ),
|
|
1959
2118
|
args: ($left ? [$left] : []),
|
|
1960
2119
|
location: $left && $left.location };
|
|
1961
2120
|
if ($ctx.c) $table.cardinality = $c.joinCard; }
|
|
@@ -2062,24 +2221,24 @@ fromPath[ qp, idkind ]
|
|
|
2062
2221
|
|
|
2063
2222
|
condition returns [ cond ] locals [ args = [], orl = [] ]
|
|
2064
2223
|
@after{
|
|
2065
|
-
$cond = ($args.length
|
|
2224
|
+
$cond = ($args.length === 1)
|
|
2066
2225
|
? this.attachLocation( $args[0] )
|
|
2067
2226
|
: this.attachLocation({ op: $orl[0], args: $args });
|
|
2068
2227
|
}
|
|
2069
2228
|
:
|
|
2070
2229
|
c1=conditionAnd { $args.push($c1.cond); }
|
|
2071
|
-
( or=OR c2=conditionAnd { $args.push($c2.cond); $orl.push(this.
|
|
2230
|
+
( or=OR c2=conditionAnd { $args.push($c2.cond); $orl.push(this.valueWithTokenLocation( 'or', $or ))} )*
|
|
2072
2231
|
;
|
|
2073
2232
|
|
|
2074
2233
|
conditionAnd returns [ cond ] locals [ args = [], andl = [] ]
|
|
2075
2234
|
@after{
|
|
2076
|
-
$cond = ($args.length
|
|
2235
|
+
$cond = ($args.length === 1)
|
|
2077
2236
|
? $args[0]
|
|
2078
2237
|
: this.attachLocation({ op: $andl[0], args: $args });
|
|
2079
2238
|
}
|
|
2080
2239
|
:
|
|
2081
2240
|
c1=conditionTerm { $args.push($c1.cond); }
|
|
2082
|
-
( and=AND c2=conditionTerm { $args.push($c2.cond); $andl.push(this.
|
|
2241
|
+
( and=AND c2=conditionTerm { $args.push($c2.cond); $andl.push(this.valueWithTokenLocation( 'and', $and )) } )*
|
|
2083
2242
|
;
|
|
2084
2243
|
|
|
2085
2244
|
conditionTerm returns [ cond ]
|
|
@@ -2088,38 +2247,38 @@ conditionTerm returns [ cond ]
|
|
|
2088
2247
|
}
|
|
2089
2248
|
:
|
|
2090
2249
|
nt=NOT ct=conditionTerm
|
|
2091
|
-
{ $cond = { op: this.
|
|
2250
|
+
{ $cond = { op: this.valueWithTokenLocation( 'not', $nt ), args: [ $ct.cond ] }; }
|
|
2092
2251
|
|
|
|
2093
2252
|
ex=EXISTS
|
|
2094
2253
|
(
|
|
2095
2254
|
open='(' qe=queryExpression close=')'
|
|
2096
|
-
{ $cond = { op: this.
|
|
2255
|
+
{ $cond = { op: this.valueWithTokenLocation( 'exists', $ex ),
|
|
2097
2256
|
args: [ this.surroundByParens( $qe.query, $open, $close, true ) ] }; }
|
|
2098
2257
|
|
|
|
2099
2258
|
qm=( HideAlternatives | '?' )
|
|
2100
|
-
{ $cond = { op: this.
|
|
2101
|
-
{ param: this.
|
|
2259
|
+
{ $cond = { op: this.valueWithTokenLocation( 'exists', $ex ), args: [
|
|
2260
|
+
{ param: this.valueWithTokenLocation( '?', $qm ), scope: 'param' }
|
|
2102
2261
|
] };
|
|
2103
2262
|
this.csnParseOnly( 'Dynamic parameter "?" is not supported', $qm );
|
|
2104
2263
|
}
|
|
2105
2264
|
|
|
|
2106
2265
|
ep=valuePath[ 'ref' ]
|
|
2107
2266
|
{ $ep.qp['$'+'expected'] = 'exists';
|
|
2108
|
-
$cond = { op: this.
|
|
2267
|
+
$cond = { op: this.valueWithTokenLocation( 'exists', $ex ), args: [ $ep.qp ] };
|
|
2109
2268
|
}
|
|
2110
2269
|
)
|
|
2111
2270
|
|
|
|
2112
2271
|
expr=expression // see @after
|
|
2113
2272
|
(
|
|
2114
2273
|
rel=( '=' | '<>' | '>' | '>=' | '<' | '<=' | '!=' )
|
|
2115
|
-
{ $cond = { op: this.
|
|
2274
|
+
{ $cond = { op: this.valueWithTokenLocation( $rel.text, $rel ), args: [ $expr.expr ] }; }
|
|
2116
2275
|
( asa=( ANY | SOME | ALL )
|
|
2117
|
-
{ $cond.quantifier = this.
|
|
2276
|
+
{ $cond.quantifier = this.valueWithTokenLocation( $asa.text.toLowerCase(), $asa ); }
|
|
2118
2277
|
)?
|
|
2119
2278
|
e2=expression { $cond.args.push($e2.expr); }
|
|
2120
2279
|
|
|
|
2121
2280
|
IS ( inn=NOT NULL | innu=NULL )
|
|
2122
|
-
{ $cond = { op: $inn ? this.
|
|
2281
|
+
{ $cond = { op: $inn ? this.valueWithTokenLocation( 'isNotNull', $inn ) : this.valueWithTokenLocation( 'isNull', $innu ), args: [ $expr.expr ] }; }
|
|
2123
2282
|
|
|
|
2124
2283
|
{ $cond = { args: [ $expr.expr ] }; }
|
|
2125
2284
|
NOT predicate[ $cond, true ]
|
|
@@ -2135,14 +2294,14 @@ predicate[ cond, negated ]
|
|
|
2135
2294
|
// NOT (a BETWEEN b AND c)
|
|
2136
2295
|
:
|
|
2137
2296
|
ino=IN e1=expression // including ExpressionList
|
|
2138
|
-
{ $cond.op = this.
|
|
2297
|
+
{ $cond.op = this.valueWithTokenLocation( (negated) ? 'notIn' : 'in', $ino ); $cond.args.push( $e1.expr ); }
|
|
2139
2298
|
|
|
|
2140
2299
|
bw=BETWEEN e2=expression
|
|
2141
|
-
{ $cond.op = this.
|
|
2300
|
+
{ $cond.op = this.valueWithTokenLocation( (negated) ? 'notBetween' : 'between', $bw ); $cond.args.push( $e2.expr ); }
|
|
2142
2301
|
AND e3=expression { $cond.args.push( $e3.expr ); }
|
|
2143
2302
|
|
|
|
2144
2303
|
lk=LIKE e4=expression
|
|
2145
|
-
{ $cond.op = this.
|
|
2304
|
+
{ $cond.op = this.valueWithTokenLocation( (negated) ? 'notLike' : 'like', $lk ); $cond.args.push( $e4.expr ); }
|
|
2146
2305
|
( ESCAPE e5=expression { $cond.args.push( $e5.expr ); } )?
|
|
2147
2306
|
;
|
|
2148
2307
|
|
|
@@ -2154,7 +2313,7 @@ expression returns [ expr ]
|
|
|
2154
2313
|
or='||' e2=expressionSum
|
|
2155
2314
|
{
|
|
2156
2315
|
$expr = {
|
|
2157
|
-
op: this.
|
|
2316
|
+
op: this.valueWithTokenLocation( '||', $or ), args: [$expr, $e2.expr],
|
|
2158
2317
|
location: this.combinedLocation( $expr, $e2.expr ) };
|
|
2159
2318
|
}
|
|
2160
2319
|
)*
|
|
@@ -2168,7 +2327,7 @@ expressionSum returns [ expr ]
|
|
|
2168
2327
|
op=( '+' | '-' ) e2=expressionFactor
|
|
2169
2328
|
{
|
|
2170
2329
|
$expr = {
|
|
2171
|
-
op: this.
|
|
2330
|
+
op: this.valueWithTokenLocation( $op.text, $op ), args: [$expr, $e2.expr],
|
|
2172
2331
|
location: this.combinedLocation( $expr, $e2.expr ) };
|
|
2173
2332
|
}
|
|
2174
2333
|
)*
|
|
@@ -2182,7 +2341,7 @@ expressionFactor returns [ expr ]
|
|
|
2182
2341
|
op=( '*' | '/' ) e2=expressionTerm
|
|
2183
2342
|
{
|
|
2184
2343
|
$expr = {
|
|
2185
|
-
op: this.
|
|
2344
|
+
op: this.valueWithTokenLocation( $op.text, $op ), args: [$expr, $e2.expr],
|
|
2186
2345
|
location: this.combinedLocation( $expr, $e2.expr ) };
|
|
2187
2346
|
}
|
|
2188
2347
|
)*
|
|
@@ -2202,7 +2361,7 @@ expressionTerm returns [ expr ] locals [ op, args = [] ]
|
|
|
2202
2361
|
{ $expr = $sf.ret; }
|
|
2203
2362
|
|
|
|
2204
2363
|
ca=CASE
|
|
2205
|
-
{ $expr = { op : this.
|
|
2364
|
+
{ $expr = { op : this.valueWithTokenLocation( 'case', $ca ), args: [] }; }
|
|
2206
2365
|
(
|
|
2207
2366
|
e2=expression { $expr.args.push($e2.expr); }
|
|
2208
2367
|
( ow=WHEN ew=expression THEN e3=expression
|
|
@@ -2220,7 +2379,7 @@ expressionTerm returns [ expr ] locals [ op, args = [] ]
|
|
|
2220
2379
|
|
|
|
2221
2380
|
ne=NEW nqp=valuePath[ 'ref', null] // token rewrite for NEW
|
|
2222
2381
|
// please note: there will be no compiler-supported code completion after NEW
|
|
2223
|
-
{ $expr = { op: this.
|
|
2382
|
+
{ $expr = { op: this.valueWithTokenLocation( 'new', $ne ), args: [] };
|
|
2224
2383
|
this.notSupportedYet( $ne ); }
|
|
2225
2384
|
|
|
|
2226
2385
|
vp=valuePath[ 'ref', null ] { $expr = this.valuePathAst( $vp.qp ); }
|
|
@@ -2239,7 +2398,7 @@ expressionTerm returns [ expr ] locals [ op, args = [] ]
|
|
|
2239
2398
|
)
|
|
2240
2399
|
|
|
|
2241
2400
|
qm=( HideAlternatives | '?' )
|
|
2242
|
-
{ $expr = { param: this.
|
|
2401
|
+
{ $expr = { param: this.valueWithTokenLocation( '?', $qm ), scope: 'param' };
|
|
2243
2402
|
this.csnParseOnly( 'Dynamic parameter "?" is not supported', $qm );
|
|
2244
2403
|
}
|
|
2245
2404
|
|
|
|
@@ -2257,7 +2416,7 @@ expressionTerm returns [ expr ] locals [ op, args = [] ]
|
|
|
2257
2416
|
close=')'
|
|
2258
2417
|
{
|
|
2259
2418
|
if ($expr.length > 1)
|
|
2260
|
-
$expr = { op: this.
|
|
2419
|
+
$expr = { op: this.valueWithTokenLocation( ',', $open ), args: $expr };
|
|
2261
2420
|
else if ($expr[0]) // can be `null` if condition failed to parse
|
|
2262
2421
|
$expr = this.surroundByParens( $expr[0], $open, $close );
|
|
2263
2422
|
}
|
|
@@ -2297,7 +2456,7 @@ specialFunction returns [ ret = { } ] locals[ art = {} ]
|
|
|
2297
2456
|
ca=CAST open='('
|
|
2298
2457
|
{
|
|
2299
2458
|
$ret = {
|
|
2300
|
-
op: this.
|
|
2459
|
+
op: this.valueWithTokenLocation( 'cast', $ca ),
|
|
2301
2460
|
args: [ ],
|
|
2302
2461
|
location: this.tokenLocation( $ca )
|
|
2303
2462
|
};
|
|
@@ -2345,6 +2504,7 @@ fromArguments[ pathStep ]
|
|
|
2345
2504
|
pathArguments[ pathStep, considerSpecial ]
|
|
2346
2505
|
@after{ /* #ATN 1 */ }
|
|
2347
2506
|
:
|
|
2507
|
+
{ this.excludeExpected([ 'ORDER' ]); }
|
|
2348
2508
|
paren='('
|
|
2349
2509
|
{ this.prepareGenericKeywords( $considerSpecial ); }
|
|
2350
2510
|
// ATN, LL2: Identifier can start both named arguments and the positional.
|
|
@@ -2366,16 +2526,23 @@ pathArguments[ pathStep, considerSpecial ]
|
|
|
2366
2526
|
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
2367
2527
|
funcExpression[ $pathStep, $considerSpecial ]
|
|
2368
2528
|
)*
|
|
2529
|
+
// Note: We can't move this into funcExpression, or we would increase the ATN count because of `,` amiguity.
|
|
2530
|
+
( ob=functionOrderByClause[ $pathStep.args[$pathStep.args.length - 1] ]
|
|
2531
|
+
{
|
|
2532
|
+
// Remove the last entry which was copied to $ob.expr and push $ob.expr.
|
|
2533
|
+
$pathStep.args[$pathStep.args.length - 1] = $ob.expr;
|
|
2534
|
+
}
|
|
2535
|
+
)?
|
|
2369
2536
|
|
|
|
2370
|
-
a=ALL { $pathStep.quantifier = this.
|
|
2537
|
+
a=ALL { $pathStep.quantifier = this.valueWithTokenLocation( 'all', $a ); }
|
|
2371
2538
|
e1=expression { $pathStep.args = [ $e1.expr ]; }
|
|
2372
2539
|
|
|
|
2373
|
-
d=DISTINCT { $pathStep.quantifier = this.
|
|
2540
|
+
d=DISTINCT { $pathStep.quantifier = this.valueWithTokenLocation( 'distinct', $d ); }
|
|
2374
2541
|
e1=expression { $pathStep.args = [ $e1.expr ]; }
|
|
2375
2542
|
( ',' e2=expression { $pathStep.args.push( $e2.expr ); } )*
|
|
2376
2543
|
|
|
|
2377
2544
|
star='*'
|
|
2378
|
-
{ $pathStep.args = [ { location: this.tokenLocation($star), val: '*', literal: 'token' } ]; }
|
|
2545
|
+
{ $pathStep.args = [ { location: this.tokenLocation( $star ), val: '*', literal: 'token' } ]; }
|
|
2379
2546
|
|
|
|
2380
2547
|
{ $pathStep.args = []; }
|
|
2381
2548
|
)
|
|
@@ -2449,7 +2616,7 @@ optionalWhereForFilter
|
|
|
2449
2616
|
|
|
2450
2617
|
// Simple paths and values ---------------------------------------------------
|
|
2451
2618
|
|
|
2452
|
-
annoValueBase returns[ val ] locals [
|
|
2619
|
+
annoValueBase returns[ val ] locals [ seenEllipsis = false ]
|
|
2453
2620
|
@after { this.attachLocation($val); }
|
|
2454
2621
|
:
|
|
2455
2622
|
{ $val = { literal: 'struct', location: this.startLocation() }; }
|
|
@@ -2469,30 +2636,43 @@ annoValueBase returns[ val ] locals [ hasEllipsis=0 ]
|
|
|
2469
2636
|
'['
|
|
2470
2637
|
(
|
|
2471
2638
|
(
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2639
|
+
head=arrayValue { $val.val.push( $head.val ); }
|
|
2640
|
+
|
|
|
2641
|
+
e='...' ( UP TO upTo=arrayValue )?
|
|
2642
|
+
{{
|
|
2643
|
+
const item = { literal: 'token', val: '...', location: this.tokenLocation($e) };
|
|
2644
|
+
$val.val.push( item );
|
|
2645
|
+
if ($ctx.upTo) item.upTo = $upTo.val;
|
|
2646
|
+
$seenEllipsis = !$ctx.upTo || 'upTo';
|
|
2647
|
+
}}
|
|
2479
2648
|
)
|
|
2480
2649
|
(
|
|
2481
2650
|
',' { if (this.isStraightBefore(']')) break; } // allow ',' before ']'
|
|
2482
2651
|
(
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2652
|
+
tail=arrayValue { $val.val.push( $tail.val ); }
|
|
2653
|
+
|
|
|
2654
|
+
{ $ctx.upTo = null; } // is not reset
|
|
2655
|
+
e='...' ( UP TO upTo=arrayValue )?
|
|
2656
|
+
{{
|
|
2657
|
+
const item = { literal: 'token', val: '...', location: this.tokenLocation($e) };
|
|
2658
|
+
if ($ctx.upTo) item.upTo = $upTo.val;
|
|
2659
|
+
$val.val.push( item );
|
|
2660
|
+
if ($seenEllipsis === true) // TODO: adapt msg to UP TO
|
|
2661
|
+
this.error( 'syntax-unexpected-ellipsis', $e, { code: '...' },
|
|
2662
|
+
'Expected no more than one $(CODE)' );
|
|
2663
|
+
else
|
|
2664
|
+
$seenEllipsis = !$ctx.upTo || 'upTo';
|
|
2665
|
+
}}
|
|
2492
2666
|
)
|
|
2493
2667
|
)*
|
|
2494
2668
|
)?
|
|
2495
|
-
']'
|
|
2669
|
+
cb=']'
|
|
2670
|
+
{
|
|
2671
|
+
if ($seenEllipsis === 'upTo')
|
|
2672
|
+
this.error( 'syntax-expecting-ellipsis', $cb, // at closing bracket
|
|
2673
|
+
{ code: '... up to', newcode: '...' },
|
|
2674
|
+
'Expecting an array item $(NEWCODE) after an item with $(CODE)' );
|
|
2675
|
+
}
|
|
2496
2676
|
|
|
|
2497
2677
|
v1=literalValue { $val = $v1.val; }
|
|
2498
2678
|
|
|
|
@@ -2660,6 +2840,7 @@ ident[ category ] returns[ id ]
|
|
|
2660
2840
|
| ASSOCIATION
|
|
2661
2841
|
| BETWEEN
|
|
2662
2842
|
| BOTH
|
|
2843
|
+
| COLUMNS
|
|
2663
2844
|
| COMPOSITION
|
|
2664
2845
|
| CONTEXT
|
|
2665
2846
|
| CROSS
|
|
@@ -2667,8 +2848,10 @@ ident[ category ] returns[ id ]
|
|
|
2667
2848
|
| DAY
|
|
2668
2849
|
| DEFAULT
|
|
2669
2850
|
| DEFINE
|
|
2851
|
+
| DEFINITIONS
|
|
2670
2852
|
| DESC
|
|
2671
2853
|
| ELEMENT
|
|
2854
|
+
| ELEMENTS
|
|
2672
2855
|
| ELSE
|
|
2673
2856
|
| END
|
|
2674
2857
|
| ENTITY
|
|
@@ -2725,6 +2908,7 @@ ident[ category ] returns[ id ]
|
|
|
2725
2908
|
| THEN
|
|
2726
2909
|
| TRAILING
|
|
2727
2910
|
| UNION
|
|
2911
|
+
| UP
|
|
2728
2912
|
| TO
|
|
2729
2913
|
| TYPE
|
|
2730
2914
|
| USING
|
|
@@ -2749,9 +2933,40 @@ LineComment : '//' ~[\r\n\u2028\u2029]* -> channel(HIDDEN);
|
|
|
2749
2933
|
|
|
2750
2934
|
// Values --------------------------------------------------------------------
|
|
2751
2935
|
|
|
2752
|
-
|
|
2936
|
+
// for syntactic code-completion: Combine all three string styles
|
|
2937
|
+
// Note: Use rule `string` instead as that also parses escape sequences!
|
|
2938
|
+
String : SingleLineString
|
|
2939
|
+
| MultiLineString
|
|
2940
|
+
| MutlLineStringBlock;
|
|
2941
|
+
|
|
2942
|
+
fragment SingleLineString
|
|
2753
2943
|
:
|
|
2754
|
-
|
|
2944
|
+
// \u0027 = '\''
|
|
2945
|
+
// \u2028 = LS (Line Separator)
|
|
2946
|
+
// \u2029 = PS (Paragraph Separator)
|
|
2947
|
+
( '\'' ~[\u0027\n\r\u2028\u2029]* '\'' )+ //
|
|
2948
|
+
;
|
|
2949
|
+
|
|
2950
|
+
fragment MultiLineString
|
|
2951
|
+
:
|
|
2952
|
+
('`' ( MultiLineStringContentChar | EscapeSequence )* '`' )
|
|
2953
|
+
;
|
|
2954
|
+
|
|
2955
|
+
fragment MutlLineStringBlock
|
|
2956
|
+
:
|
|
2957
|
+
('```' ( MultiLineStringContentChar | EscapeSequence )* '```')
|
|
2958
|
+
;
|
|
2959
|
+
|
|
2960
|
+
fragment EscapeSequence
|
|
2961
|
+
:
|
|
2962
|
+
// we could list each escape sequence explicitly, but we already
|
|
2963
|
+
// decode them in genericAntlrParser.js, so no need to do work twice.
|
|
2964
|
+
'\\' .
|
|
2965
|
+
;
|
|
2966
|
+
|
|
2967
|
+
fragment MultiLineStringContentChar
|
|
2968
|
+
:
|
|
2969
|
+
(~[\u0060\\]) // \u0060 = '`'
|
|
2755
2970
|
;
|
|
2756
2971
|
|
|
2757
2972
|
QuotedLiteral
|
|
@@ -2760,10 +2975,15 @@ QuotedLiteral
|
|
|
2760
2975
|
( '\'' ~[\u0027\n\r\u2028\u2029]* '\'' )+ // \u0027 = '\''
|
|
2761
2976
|
;
|
|
2762
2977
|
|
|
2978
|
+
// This literal improves error messages for unterminated literals.
|
|
2763
2979
|
UnterminatedLiteral
|
|
2764
2980
|
:
|
|
2765
2981
|
( [xX] | [dD][aA][tT][eE] | [tT][iI][mM][eE] ( [sS][tT][aA][mM][pP] )? )?
|
|
2766
2982
|
'\'' ~[\u0027\n\r\u2028\u2029]* // \u0027 = '\''
|
|
2983
|
+
|
|
|
2984
|
+
('`' ( MultiLineStringContentChar | EscapeSequence )* )
|
|
2985
|
+
|
|
|
2986
|
+
('```' ( MultiLineStringContentChar | EscapeSequence )* )
|
|
2767
2987
|
;
|
|
2768
2988
|
|
|
2769
2989
|
UnterminatedDelimitedIdentifier
|
|
@@ -2827,6 +3047,7 @@ ASPECT : [aA][sS][pP][eE][cC][tT] ;
|
|
|
2827
3047
|
ASSOCIATION : [aA][sS][sS][oO][cC][iI][aA][tT][iI][oO][nN] ;
|
|
2828
3048
|
BETWEEN : [bB][eE][tT][wW][eE][eE][nN] ;
|
|
2829
3049
|
BOTH : [bB][oO][tT][hH] ;
|
|
3050
|
+
COLUMNS : [cC][oO][lL][uU][mM][nN][sS];
|
|
2830
3051
|
COMPOSITION : [cC][oO][mM][pP][oO][sS][iI][tT][iI][oO][nN] ;
|
|
2831
3052
|
CONTEXT : [cC][oO][nN][tT][eE][xX][tT] ;
|
|
2832
3053
|
CROSS : [cC][rR][oO][sS][sS] ;
|
|
@@ -2834,8 +3055,10 @@ CURRENT : [cC][uU][rR][rR][eE][nN][tT] ;
|
|
|
2834
3055
|
DAY : [dD][aA][yY] ;
|
|
2835
3056
|
DEFAULT : [dD][eE][fF][aA][uU][lL][tT] ;
|
|
2836
3057
|
DEFINE : [dD][eE][fF][iI][nN][eE] ;
|
|
3058
|
+
DEFINITIONS : [dD][eE][fF][iI][nN][iI][tT][iI][oO][nN][sS] ;
|
|
2837
3059
|
DESC : [dD][eE][sS][cC] ;
|
|
2838
3060
|
ELEMENT : [eE][lL][eE][mM][eE][nN][tT] ;
|
|
3061
|
+
ELEMENTS : [eE][lL][eE][mM][eE][nN][tT][sS] ;
|
|
2839
3062
|
ELSE : [eE][lL][sS][eE] ;
|
|
2840
3063
|
END : [eE][nN][dD] ;
|
|
2841
3064
|
ENTITY : [eE][nN][tT][iI][tT][yY] ;
|
|
@@ -2896,6 +3119,7 @@ TO : [tT][oO] ; // or make reserved? (is in SQL-92)
|
|
|
2896
3119
|
TYPE : [tT][yY][pP][eE] ;
|
|
2897
3120
|
UNION : [uU][nN][iI][oO][nN] ;
|
|
2898
3121
|
UNBOUNDED : [uU][nN][bB][oO][uU][nN][dD][eE][dD] ;
|
|
3122
|
+
UP : [uU][pP] ;
|
|
2899
3123
|
USING : [uU][sS][iI][nN][gG] ;
|
|
2900
3124
|
VARIABLE : [vV][aA][rR][iI][aA][bB][lL][eE] ;
|
|
2901
3125
|
VIEW : [vV][iI][eE][wW] ;
|