@sap/cds-compiler 2.11.4 → 2.13.8
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 +159 -1
- package/bin/cds_update_identifiers.js +7 -7
- package/bin/cdsc.js +22 -23
- package/bin/cdsse.js +2 -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 +30 -63
- package/lib/api/options.js +5 -5
- package/lib/api/validate.js +0 -5
- package/lib/backends.js +15 -23
- package/lib/base/dictionaries.js +0 -8
- package/lib/base/error.js +26 -0
- package/lib/base/keywords.js +7 -17
- package/lib/base/location.js +9 -4
- package/lib/base/message-registry.js +52 -2
- package/lib/base/messages.js +16 -26
- 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/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/validator.js +12 -7
- package/lib/compiler/assert-consistency.js +10 -6
- package/lib/compiler/base.js +0 -1
- package/lib/compiler/builtins.js +8 -6
- 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 +33 -14
- 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 +76 -38
- package/lib/compiler/tweak-assocs.js +529 -0
- package/lib/compiler/utils.js +204 -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 +143 -71
- package/lib/language/antlrParser.js +3 -3
- package/lib/language/docCommentParser.js +3 -3
- package/lib/language/genericAntlrParser.js +144 -54
- package/lib/language/language.g4 +424 -203
- package/lib/language/multiLineStringParser.js +536 -0
- package/lib/main.d.ts +472 -61
- package/lib/main.js +38 -11
- package/lib/model/api.js +3 -1
- package/lib/model/csnRefs.js +321 -204
- package/lib/model/csnUtils.js +224 -263
- package/lib/model/enrichCsn.js +97 -40
- package/lib/model/revealInternalProperties.js +27 -6
- package/lib/model/sortViews.js +2 -1
- package/lib/modelCompare/compare.js +17 -12
- package/lib/optionProcessor.js +7 -6
- 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 +201 -115
- package/lib/render/toRename.js +7 -10
- package/lib/render/toSql.js +149 -75
- 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 +35 -12
- 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 +552 -105
- package/lib/transform/db/groupByOrderBy.js +3 -1
- package/lib/transform/db/temporal.js +236 -0
- package/lib/transform/db/transformExists.js +94 -28
- package/lib/transform/db/views.js +5 -4
- 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 +94 -801
- 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 +10 -27
- 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 +2 -1
- 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 -2340
- package/lib/compiler/resolver.js +0 -2988
- 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,12 +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
|
-
|
|
1505
|
-
|
|
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
|
|
1506
1630
|
)
|
|
1507
1631
|
|
|
|
1508
1632
|
':' // with element, e.g. `type T : E:elem enum { ... }`
|
|
@@ -1510,22 +1634,36 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
|
|
|
1510
1634
|
simplePath[ $art.type, 'ref']
|
|
1511
1635
|
{ this.docComment( $annos ); }
|
|
1512
1636
|
annotationAssignment_ll1[ $annos ]*
|
|
1513
|
-
(
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
'}'
|
|
1517
|
-
|
|
1518
|
-
|
|
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
|
|
1519
1650
|
)
|
|
1520
1651
|
|
|
|
1521
1652
|
{ this.docComment( $annos ); }
|
|
1522
1653
|
annotationAssignment_ll1[ $annos ]*
|
|
1523
|
-
(
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
'}'
|
|
1527
|
-
|
|
1528
|
-
|
|
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
|
|
1529
1667
|
)
|
|
1530
1668
|
|
|
|
1531
1669
|
// TODO: complain if used in anno def?
|
|
@@ -1542,15 +1680,17 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
|
|
|
1542
1680
|
typeStruct[ art, attachLoc = false ]
|
|
1543
1681
|
@after { if ($attachLoc) this.attachLocation($art); }
|
|
1544
1682
|
:
|
|
1545
|
-
{ $art.elements =
|
|
1546
|
-
|
|
1683
|
+
'{' { $art.elements = this.createDict(); }
|
|
1684
|
+
elementDef[ $art ]*
|
|
1685
|
+
'}' { this.setDictEndLocation( $art.elements ); }
|
|
1547
1686
|
;
|
|
1548
1687
|
|
|
1549
1688
|
typeCompoStruct[ art ]
|
|
1550
1689
|
@after { this.attachLocation($art); }
|
|
1551
1690
|
:
|
|
1552
|
-
{ $art.elements =
|
|
1553
|
-
|
|
1691
|
+
COMPOSITIONofBRACE { $art.elements = this.createDict(); }
|
|
1692
|
+
elementDef[ $art ]*
|
|
1693
|
+
'}' { this.setDictEndLocation( $art.elements ); }
|
|
1554
1694
|
;
|
|
1555
1695
|
|
|
1556
1696
|
typeArray[ art ]
|
|
@@ -1569,10 +1709,10 @@ typeArray[ art ]
|
|
|
1569
1709
|
nullability[ $art.items ]?
|
|
1570
1710
|
| typeRefOptArgs[ $art.items ]
|
|
1571
1711
|
nullability[ $art.items ]?
|
|
1572
|
-
(
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
'}'
|
|
1712
|
+
(
|
|
1713
|
+
ENUM '{' { $art.items.enum = this.createDict(); }
|
|
1714
|
+
enumSymbolDef[ $art.items ]*
|
|
1715
|
+
'}' { this.setDictEndLocation( $art.items.enum ); }
|
|
1576
1716
|
)?
|
|
1577
1717
|
)
|
|
1578
1718
|
;
|
|
@@ -1600,7 +1740,7 @@ typeAssociationBase[ art, handleTypeCompo ] // including Composition
|
|
|
1600
1740
|
typeAssociationCont[ art ]
|
|
1601
1741
|
:
|
|
1602
1742
|
(
|
|
1603
|
-
'{'
|
|
1743
|
+
'{' { $art.foreignKeys = this.createDict(); }
|
|
1604
1744
|
{ this.addDef( $art, 'foreignKeys' ); }
|
|
1605
1745
|
(
|
|
1606
1746
|
foreignKey[ $art ]
|
|
@@ -1608,7 +1748,7 @@ typeAssociationCont[ art ]
|
|
|
1608
1748
|
foreignKey[ $art ]
|
|
1609
1749
|
)*
|
|
1610
1750
|
)?
|
|
1611
|
-
'}'
|
|
1751
|
+
'}' { this.setDictEndLocation( $art.foreignKeys ); }
|
|
1612
1752
|
|
|
|
1613
1753
|
ON cond=condition
|
|
1614
1754
|
{ $art.on=$cond.cond; }
|
|
@@ -1619,7 +1759,7 @@ typeAssociationElementCont[ art, annos ] // including Composition
|
|
|
1619
1759
|
// optional NULL / NOT NULL for managed association only
|
|
1620
1760
|
:
|
|
1621
1761
|
(
|
|
1622
|
-
'{'
|
|
1762
|
+
'{' { $art.foreignKeys = this.createDict(); }
|
|
1623
1763
|
{ this.addDef( $art, 'foreignKeys' ); }
|
|
1624
1764
|
(
|
|
1625
1765
|
foreignKey[ $art ]
|
|
@@ -1627,7 +1767,7 @@ typeAssociationElementCont[ art, annos ] // including Composition
|
|
|
1627
1767
|
foreignKey[ $art ]
|
|
1628
1768
|
)*
|
|
1629
1769
|
)?
|
|
1630
|
-
'}'
|
|
1770
|
+
'}' { this.setDictEndLocation( $art.foreignKeys ); }
|
|
1631
1771
|
nullability[ $art ]?
|
|
1632
1772
|
|
|
|
1633
1773
|
ON cond=condition
|
|
@@ -1767,33 +1907,47 @@ orderByClause[ inQuery ] returns [ query ]
|
|
|
1767
1907
|
( ',' obn=orderBySpec { $query.orderBy.push( $obn.ob ); } )*
|
|
1768
1908
|
;
|
|
1769
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
|
+
|
|
1770
1920
|
overOrderByClause returns [ expr ]
|
|
1921
|
+
@after { this.attachLocation( $expr ); }
|
|
1771
1922
|
:
|
|
1772
|
-
o=ORDER b=BY { $expr = { op: this.
|
|
1923
|
+
o=ORDER b=BY { $expr = { op: this.valueWithTokenLocation( 'overOrderBy', $o, $b ) , args: [] }}
|
|
1773
1924
|
ob1=orderBySpec { $expr.args.push( $ob1.ob ); }
|
|
1774
1925
|
( ',' obn=orderBySpec { $expr.args.push( $obn.ob ); } )*
|
|
1775
1926
|
;
|
|
1776
1927
|
|
|
1777
1928
|
partitionByClause returns [ expr ]
|
|
1929
|
+
@after { this.attachLocation( $expr ); }
|
|
1778
1930
|
:
|
|
1779
|
-
p=PARTITION b=BY { $expr = { op: this.
|
|
1931
|
+
p=PARTITION b=BY { $expr = { op: this.valueWithTokenLocation( 'partitionBy', $p, $b ) , args: [] }}
|
|
1780
1932
|
e1=expression { $expr.args.push( $e1.expr ); }
|
|
1781
1933
|
( ',' en=expression { $expr.args.push( $en.expr ); } )*
|
|
1782
1934
|
;
|
|
1783
1935
|
|
|
1784
1936
|
windowFrameClause returns [ wf ]
|
|
1937
|
+
@after { this.attachLocation( $wf ); }
|
|
1785
1938
|
:
|
|
1786
|
-
r=ROWS { $wf = { op: this.
|
|
1939
|
+
r=ROWS { $wf = { op: this.valueWithTokenLocation( 'rows', $r ) , args: [] }}
|
|
1787
1940
|
wfe=windowFrameExtentSpec { $wf.args.push( $wfe.wfe ); }
|
|
1788
1941
|
;
|
|
1789
1942
|
|
|
1790
1943
|
windowFrameExtentSpec returns[ wfe ]
|
|
1944
|
+
@after { this.attachLocation( $wfe ); }
|
|
1791
1945
|
:
|
|
1792
1946
|
{ $wfe = {} }
|
|
1793
1947
|
windowFrameStartSpec [ $wfe ]
|
|
1794
1948
|
|
|
|
1795
1949
|
b=BETWEEN
|
|
1796
|
-
{ $wfe = { op: this.
|
|
1950
|
+
{ $wfe = { op: this.valueWithTokenLocation( 'frameBetween', $b ), args: [] } }
|
|
1797
1951
|
wfb1=windowFrameBoundSpec { $wfe.args.push( $wfb1.wfb ); }
|
|
1798
1952
|
AND
|
|
1799
1953
|
wfb2=windowFrameBoundSpec { $wfe.args.push( $wfb2.wfb ); }
|
|
@@ -1805,42 +1959,43 @@ windowFrameBoundSpec returns [ wfb ]
|
|
|
1805
1959
|
// #ATN: Not ll1 because `UNBOUNDED` could also be part of the windowFrameStartSpec
|
|
1806
1960
|
// `UNBOUNDED` would then be immediately followed by `PRECEDING`
|
|
1807
1961
|
u=UNBOUNDED f=FOLLOWING
|
|
1808
|
-
{ $wfb = { op: this.
|
|
1962
|
+
{ $wfb = { op: this.valueWithTokenLocation( 'unboundedFollowing', $u, $f ), args: []} }
|
|
1809
1963
|
|
|
|
1810
1964
|
// #ATN: Not ll1 because `Number` could also be part of the windowFrameStartSpec
|
|
1811
1965
|
// `Number` would then be immediately followed by `PRECEDING`
|
|
1812
1966
|
n=Number f=FOLLOWING
|
|
1813
|
-
{ $wfb = { op: this.
|
|
1967
|
+
{ $wfb = { op: this.valueWithTokenLocation( 'following', $n, $f ), args: [ this.numberLiteral( $n ) ]} }
|
|
1814
1968
|
|
|
|
1815
1969
|
{ $wfb = {} }
|
|
1816
1970
|
windowFrameStartSpec [ $wfb ]
|
|
1817
1971
|
;
|
|
1818
1972
|
|
|
1819
1973
|
windowFrameStartSpec [ wf ]
|
|
1974
|
+
@after { this.attachLocation( $wf ); }
|
|
1820
1975
|
:
|
|
1821
1976
|
u=UNBOUNDED p=PRECEDING
|
|
1822
1977
|
{
|
|
1823
|
-
$wf.op = this.
|
|
1978
|
+
$wf.op = this.valueWithTokenLocation( 'unboundedPreceding', $u, $p );
|
|
1824
1979
|
$wf.args = [];
|
|
1825
1980
|
}
|
|
1826
1981
|
|
|
|
1827
1982
|
n=Number p=PRECEDING
|
|
1828
1983
|
{
|
|
1829
|
-
$wf.op = this.
|
|
1984
|
+
$wf.op = this.valueWithTokenLocation( 'preceding', $p );
|
|
1830
1985
|
$wf.args = [ this.numberLiteral( $n ) ];
|
|
1831
1986
|
}
|
|
1832
|
-
|
|
|
1987
|
+
|
|
|
1833
1988
|
c=CURRENT r=ROW
|
|
1834
1989
|
{
|
|
1835
|
-
$wf.op = this.
|
|
1990
|
+
$wf.op = this.valueWithTokenLocation( 'currentRow', $c, $r );
|
|
1836
1991
|
$wf.args = [];
|
|
1837
1992
|
}
|
|
1838
1993
|
;
|
|
1839
1994
|
|
|
1840
1995
|
overClause returns [ over ]
|
|
1841
|
-
@after { this.attachLocation($over); }
|
|
1996
|
+
@after { this.attachLocation( $over ); }
|
|
1842
1997
|
:
|
|
1843
|
-
o=OVER { $over = { op: this.
|
|
1998
|
+
o=OVER { $over = { op: this.valueWithTokenLocation( 'over', $o ) , args: [] } }
|
|
1844
1999
|
'('
|
|
1845
2000
|
( pb=partitionByClause { $over.args.push( $pb.expr ); } )?
|
|
1846
2001
|
( ob=overOrderByClause { $over.args.push( $ob.expr ); } )?
|
|
@@ -1861,11 +2016,11 @@ limitClause[ inQuery ] returns [ query ]
|
|
|
1861
2016
|
orderBySpec returns[ ob ]
|
|
1862
2017
|
:
|
|
1863
2018
|
e=expression { $ob = $e.expr; }
|
|
1864
|
-
( asc=ASC { $ob.sort = this.
|
|
1865
|
-
| desc=DESC { $ob.sort = this.
|
|
2019
|
+
( asc=ASC { $ob.sort = this.valueWithTokenLocation( 'asc', $asc ); }
|
|
2020
|
+
| desc=DESC { $ob.sort = this.valueWithTokenLocation( 'desc', $desc ); }
|
|
1866
2021
|
)?
|
|
1867
2022
|
( nb=NULLS ne=( FIRST | LAST )
|
|
1868
|
-
{ $ob.nulls = this.
|
|
2023
|
+
{ $ob.nulls = this.valueWithTokenLocation( $ne.text.toLowerCase(), $nb, $ne ); }
|
|
1869
2024
|
)?
|
|
1870
2025
|
;
|
|
1871
2026
|
|
|
@@ -1888,22 +2043,23 @@ queryPrimary returns[ query = {} ]
|
|
|
1888
2043
|
{ $query = this.surroundByParens( $qe.query, $open, $close ); }
|
|
1889
2044
|
|
|
|
1890
2045
|
select=SELECT
|
|
1891
|
-
{ $query = { op: this.
|
|
2046
|
+
{ $query = { op: this.valueWithTokenLocation( 'SELECT', $select ), location: this.startLocation() }; }
|
|
1892
2047
|
(
|
|
1893
2048
|
FROM querySource[ $query ]
|
|
1894
2049
|
(
|
|
1895
|
-
mixin=MIXIN '{'
|
|
2050
|
+
mixin=MIXIN '{' { $query.mixin = this.createDict(); }
|
|
1896
2051
|
mixinElementDef[ $query ]*
|
|
1897
|
-
'}'
|
|
2052
|
+
'}' { this.setDictEndLocation( $query.mixin ); }
|
|
2053
|
+
INTO
|
|
1898
2054
|
)?
|
|
1899
2055
|
( ad=( ALL | DISTINCT ) // TODO: or directly after SELECT ?
|
|
1900
|
-
{ $query.quantifier = this.
|
|
2056
|
+
{ $query.quantifier = this.valueWithTokenLocation( $ad.text.toLowerCase(), $ad ); }
|
|
1901
2057
|
)?
|
|
1902
2058
|
bracedSelectItemListDef[ $query ]?
|
|
1903
2059
|
excludingClause[ $query ]?
|
|
1904
2060
|
|
|
|
1905
2061
|
( ad=( ALL | DISTINCT ) // TODO: or directly after SELECT ?
|
|
1906
|
-
{ $query.quantifier = this.
|
|
2062
|
+
{ $query.quantifier = this.valueWithTokenLocation( $ad.text.toLowerCase(), $ad ); }
|
|
1907
2063
|
)?
|
|
1908
2064
|
{ $query.columns = []; } // set it early to avoid "wildcard" errors
|
|
1909
2065
|
selectItemDef[ $query.columns ]
|
|
@@ -1957,8 +2113,8 @@ joinOp[ left ] returns[ table ] locals [ join ]
|
|
|
1957
2113
|
| t1=RIGHT t2=OUTER? c=joinCardinality? op=JOIN { $join = 'right' }
|
|
1958
2114
|
| t1=FULL t2=OUTER? c=joinCardinality? op=JOIN { $join = 'full' }
|
|
1959
2115
|
)
|
|
1960
|
-
{ $table = { op: this.
|
|
1961
|
-
join: this.
|
|
2116
|
+
{ $table = { op: this.valueWithTokenLocation( 'join', $op ),
|
|
2117
|
+
join: this.valueWithTokenLocation( $join, $t1 || $op, $t2 ),
|
|
1962
2118
|
args: ($left ? [$left] : []),
|
|
1963
2119
|
location: $left && $left.location };
|
|
1964
2120
|
if ($ctx.c) $table.cardinality = $c.joinCard; }
|
|
@@ -2065,24 +2221,24 @@ fromPath[ qp, idkind ]
|
|
|
2065
2221
|
|
|
2066
2222
|
condition returns [ cond ] locals [ args = [], orl = [] ]
|
|
2067
2223
|
@after{
|
|
2068
|
-
$cond = ($args.length
|
|
2224
|
+
$cond = ($args.length === 1)
|
|
2069
2225
|
? this.attachLocation( $args[0] )
|
|
2070
2226
|
: this.attachLocation({ op: $orl[0], args: $args });
|
|
2071
2227
|
}
|
|
2072
2228
|
:
|
|
2073
2229
|
c1=conditionAnd { $args.push($c1.cond); }
|
|
2074
|
-
( 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 ))} )*
|
|
2075
2231
|
;
|
|
2076
2232
|
|
|
2077
2233
|
conditionAnd returns [ cond ] locals [ args = [], andl = [] ]
|
|
2078
2234
|
@after{
|
|
2079
|
-
$cond = ($args.length
|
|
2235
|
+
$cond = ($args.length === 1)
|
|
2080
2236
|
? $args[0]
|
|
2081
2237
|
: this.attachLocation({ op: $andl[0], args: $args });
|
|
2082
2238
|
}
|
|
2083
2239
|
:
|
|
2084
2240
|
c1=conditionTerm { $args.push($c1.cond); }
|
|
2085
|
-
( 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 )) } )*
|
|
2086
2242
|
;
|
|
2087
2243
|
|
|
2088
2244
|
conditionTerm returns [ cond ]
|
|
@@ -2091,38 +2247,38 @@ conditionTerm returns [ cond ]
|
|
|
2091
2247
|
}
|
|
2092
2248
|
:
|
|
2093
2249
|
nt=NOT ct=conditionTerm
|
|
2094
|
-
{ $cond = { op: this.
|
|
2250
|
+
{ $cond = { op: this.valueWithTokenLocation( 'not', $nt ), args: [ $ct.cond ] }; }
|
|
2095
2251
|
|
|
|
2096
2252
|
ex=EXISTS
|
|
2097
2253
|
(
|
|
2098
2254
|
open='(' qe=queryExpression close=')'
|
|
2099
|
-
{ $cond = { op: this.
|
|
2255
|
+
{ $cond = { op: this.valueWithTokenLocation( 'exists', $ex ),
|
|
2100
2256
|
args: [ this.surroundByParens( $qe.query, $open, $close, true ) ] }; }
|
|
2101
2257
|
|
|
|
2102
2258
|
qm=( HideAlternatives | '?' )
|
|
2103
|
-
{ $cond = { op: this.
|
|
2104
|
-
{ param: this.
|
|
2259
|
+
{ $cond = { op: this.valueWithTokenLocation( 'exists', $ex ), args: [
|
|
2260
|
+
{ param: this.valueWithTokenLocation( '?', $qm ), scope: 'param' }
|
|
2105
2261
|
] };
|
|
2106
2262
|
this.csnParseOnly( 'Dynamic parameter "?" is not supported', $qm );
|
|
2107
2263
|
}
|
|
2108
2264
|
|
|
|
2109
2265
|
ep=valuePath[ 'ref' ]
|
|
2110
2266
|
{ $ep.qp['$'+'expected'] = 'exists';
|
|
2111
|
-
$cond = { op: this.
|
|
2267
|
+
$cond = { op: this.valueWithTokenLocation( 'exists', $ex ), args: [ $ep.qp ] };
|
|
2112
2268
|
}
|
|
2113
2269
|
)
|
|
2114
2270
|
|
|
|
2115
2271
|
expr=expression // see @after
|
|
2116
2272
|
(
|
|
2117
2273
|
rel=( '=' | '<>' | '>' | '>=' | '<' | '<=' | '!=' )
|
|
2118
|
-
{ $cond = { op: this.
|
|
2274
|
+
{ $cond = { op: this.valueWithTokenLocation( $rel.text, $rel ), args: [ $expr.expr ] }; }
|
|
2119
2275
|
( asa=( ANY | SOME | ALL )
|
|
2120
|
-
{ $cond.quantifier = this.
|
|
2276
|
+
{ $cond.quantifier = this.valueWithTokenLocation( $asa.text.toLowerCase(), $asa ); }
|
|
2121
2277
|
)?
|
|
2122
2278
|
e2=expression { $cond.args.push($e2.expr); }
|
|
2123
2279
|
|
|
|
2124
2280
|
IS ( inn=NOT NULL | innu=NULL )
|
|
2125
|
-
{ $cond = { op: $inn ? this.
|
|
2281
|
+
{ $cond = { op: $inn ? this.valueWithTokenLocation( 'isNotNull', $inn ) : this.valueWithTokenLocation( 'isNull', $innu ), args: [ $expr.expr ] }; }
|
|
2126
2282
|
|
|
|
2127
2283
|
{ $cond = { args: [ $expr.expr ] }; }
|
|
2128
2284
|
NOT predicate[ $cond, true ]
|
|
@@ -2138,14 +2294,14 @@ predicate[ cond, negated ]
|
|
|
2138
2294
|
// NOT (a BETWEEN b AND c)
|
|
2139
2295
|
:
|
|
2140
2296
|
ino=IN e1=expression // including ExpressionList
|
|
2141
|
-
{ $cond.op = this.
|
|
2297
|
+
{ $cond.op = this.valueWithTokenLocation( (negated) ? 'notIn' : 'in', $ino ); $cond.args.push( $e1.expr ); }
|
|
2142
2298
|
|
|
|
2143
2299
|
bw=BETWEEN e2=expression
|
|
2144
|
-
{ $cond.op = this.
|
|
2300
|
+
{ $cond.op = this.valueWithTokenLocation( (negated) ? 'notBetween' : 'between', $bw ); $cond.args.push( $e2.expr ); }
|
|
2145
2301
|
AND e3=expression { $cond.args.push( $e3.expr ); }
|
|
2146
2302
|
|
|
|
2147
2303
|
lk=LIKE e4=expression
|
|
2148
|
-
{ $cond.op = this.
|
|
2304
|
+
{ $cond.op = this.valueWithTokenLocation( (negated) ? 'notLike' : 'like', $lk ); $cond.args.push( $e4.expr ); }
|
|
2149
2305
|
( ESCAPE e5=expression { $cond.args.push( $e5.expr ); } )?
|
|
2150
2306
|
;
|
|
2151
2307
|
|
|
@@ -2157,7 +2313,7 @@ expression returns [ expr ]
|
|
|
2157
2313
|
or='||' e2=expressionSum
|
|
2158
2314
|
{
|
|
2159
2315
|
$expr = {
|
|
2160
|
-
op: this.
|
|
2316
|
+
op: this.valueWithTokenLocation( '||', $or ), args: [$expr, $e2.expr],
|
|
2161
2317
|
location: this.combinedLocation( $expr, $e2.expr ) };
|
|
2162
2318
|
}
|
|
2163
2319
|
)*
|
|
@@ -2171,7 +2327,7 @@ expressionSum returns [ expr ]
|
|
|
2171
2327
|
op=( '+' | '-' ) e2=expressionFactor
|
|
2172
2328
|
{
|
|
2173
2329
|
$expr = {
|
|
2174
|
-
op: this.
|
|
2330
|
+
op: this.valueWithTokenLocation( $op.text, $op ), args: [$expr, $e2.expr],
|
|
2175
2331
|
location: this.combinedLocation( $expr, $e2.expr ) };
|
|
2176
2332
|
}
|
|
2177
2333
|
)*
|
|
@@ -2185,7 +2341,7 @@ expressionFactor returns [ expr ]
|
|
|
2185
2341
|
op=( '*' | '/' ) e2=expressionTerm
|
|
2186
2342
|
{
|
|
2187
2343
|
$expr = {
|
|
2188
|
-
op: this.
|
|
2344
|
+
op: this.valueWithTokenLocation( $op.text, $op ), args: [$expr, $e2.expr],
|
|
2189
2345
|
location: this.combinedLocation( $expr, $e2.expr ) };
|
|
2190
2346
|
}
|
|
2191
2347
|
)*
|
|
@@ -2205,7 +2361,7 @@ expressionTerm returns [ expr ] locals [ op, args = [] ]
|
|
|
2205
2361
|
{ $expr = $sf.ret; }
|
|
2206
2362
|
|
|
|
2207
2363
|
ca=CASE
|
|
2208
|
-
{ $expr = { op : this.
|
|
2364
|
+
{ $expr = { op : this.valueWithTokenLocation( 'case', $ca ), args: [] }; }
|
|
2209
2365
|
(
|
|
2210
2366
|
e2=expression { $expr.args.push($e2.expr); }
|
|
2211
2367
|
( ow=WHEN ew=expression THEN e3=expression
|
|
@@ -2223,7 +2379,7 @@ expressionTerm returns [ expr ] locals [ op, args = [] ]
|
|
|
2223
2379
|
|
|
|
2224
2380
|
ne=NEW nqp=valuePath[ 'ref', null] // token rewrite for NEW
|
|
2225
2381
|
// please note: there will be no compiler-supported code completion after NEW
|
|
2226
|
-
{ $expr = { op: this.
|
|
2382
|
+
{ $expr = { op: this.valueWithTokenLocation( 'new', $ne ), args: [] };
|
|
2227
2383
|
this.notSupportedYet( $ne ); }
|
|
2228
2384
|
|
|
|
2229
2385
|
vp=valuePath[ 'ref', null ] { $expr = this.valuePathAst( $vp.qp ); }
|
|
@@ -2242,7 +2398,7 @@ expressionTerm returns [ expr ] locals [ op, args = [] ]
|
|
|
2242
2398
|
)
|
|
2243
2399
|
|
|
|
2244
2400
|
qm=( HideAlternatives | '?' )
|
|
2245
|
-
{ $expr = { param: this.
|
|
2401
|
+
{ $expr = { param: this.valueWithTokenLocation( '?', $qm ), scope: 'param' };
|
|
2246
2402
|
this.csnParseOnly( 'Dynamic parameter "?" is not supported', $qm );
|
|
2247
2403
|
}
|
|
2248
2404
|
|
|
|
@@ -2260,7 +2416,7 @@ expressionTerm returns [ expr ] locals [ op, args = [] ]
|
|
|
2260
2416
|
close=')'
|
|
2261
2417
|
{
|
|
2262
2418
|
if ($expr.length > 1)
|
|
2263
|
-
$expr = { op: this.
|
|
2419
|
+
$expr = { op: this.valueWithTokenLocation( ',', $open ), args: $expr };
|
|
2264
2420
|
else if ($expr[0]) // can be `null` if condition failed to parse
|
|
2265
2421
|
$expr = this.surroundByParens( $expr[0], $open, $close );
|
|
2266
2422
|
}
|
|
@@ -2300,7 +2456,7 @@ specialFunction returns [ ret = { } ] locals[ art = {} ]
|
|
|
2300
2456
|
ca=CAST open='('
|
|
2301
2457
|
{
|
|
2302
2458
|
$ret = {
|
|
2303
|
-
op: this.
|
|
2459
|
+
op: this.valueWithTokenLocation( 'cast', $ca ),
|
|
2304
2460
|
args: [ ],
|
|
2305
2461
|
location: this.tokenLocation( $ca )
|
|
2306
2462
|
};
|
|
@@ -2348,6 +2504,7 @@ fromArguments[ pathStep ]
|
|
|
2348
2504
|
pathArguments[ pathStep, considerSpecial ]
|
|
2349
2505
|
@after{ /* #ATN 1 */ }
|
|
2350
2506
|
:
|
|
2507
|
+
{ this.excludeExpected([ 'ORDER' ]); }
|
|
2351
2508
|
paren='('
|
|
2352
2509
|
{ this.prepareGenericKeywords( $considerSpecial ); }
|
|
2353
2510
|
// ATN, LL2: Identifier can start both named arguments and the positional.
|
|
@@ -2369,16 +2526,23 @@ pathArguments[ pathStep, considerSpecial ]
|
|
|
2369
2526
|
( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
|
|
2370
2527
|
funcExpression[ $pathStep, $considerSpecial ]
|
|
2371
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
|
+
)?
|
|
2372
2536
|
|
|
|
2373
|
-
a=ALL { $pathStep.quantifier = this.
|
|
2537
|
+
a=ALL { $pathStep.quantifier = this.valueWithTokenLocation( 'all', $a ); }
|
|
2374
2538
|
e1=expression { $pathStep.args = [ $e1.expr ]; }
|
|
2375
2539
|
|
|
|
2376
|
-
d=DISTINCT { $pathStep.quantifier = this.
|
|
2540
|
+
d=DISTINCT { $pathStep.quantifier = this.valueWithTokenLocation( 'distinct', $d ); }
|
|
2377
2541
|
e1=expression { $pathStep.args = [ $e1.expr ]; }
|
|
2378
2542
|
( ',' e2=expression { $pathStep.args.push( $e2.expr ); } )*
|
|
2379
2543
|
|
|
|
2380
2544
|
star='*'
|
|
2381
|
-
{ $pathStep.args = [ { location: this.tokenLocation($star), val: '*', literal: 'token' } ]; }
|
|
2545
|
+
{ $pathStep.args = [ { location: this.tokenLocation( $star ), val: '*', literal: 'token' } ]; }
|
|
2382
2546
|
|
|
|
2383
2547
|
{ $pathStep.args = []; }
|
|
2384
2548
|
)
|
|
@@ -2452,7 +2616,7 @@ optionalWhereForFilter
|
|
|
2452
2616
|
|
|
2453
2617
|
// Simple paths and values ---------------------------------------------------
|
|
2454
2618
|
|
|
2455
|
-
annoValueBase returns[ val ] locals [
|
|
2619
|
+
annoValueBase returns[ val ] locals [ seenEllipsis = false ]
|
|
2456
2620
|
@after { this.attachLocation($val); }
|
|
2457
2621
|
:
|
|
2458
2622
|
{ $val = { literal: 'struct', location: this.startLocation() }; }
|
|
@@ -2472,30 +2636,43 @@ annoValueBase returns[ val ] locals [ hasEllipsis=0 ]
|
|
|
2472
2636
|
'['
|
|
2473
2637
|
(
|
|
2474
2638
|
(
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
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
|
+
}}
|
|
2482
2648
|
)
|
|
2483
2649
|
(
|
|
2484
2650
|
',' { if (this.isStraightBefore(']')) break; } // allow ',' before ']'
|
|
2485
2651
|
(
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
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
|
+
}}
|
|
2495
2666
|
)
|
|
2496
2667
|
)*
|
|
2497
2668
|
)?
|
|
2498
|
-
']'
|
|
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
|
+
}
|
|
2499
2676
|
|
|
|
2500
2677
|
v1=literalValue { $val = $v1.val; }
|
|
2501
2678
|
|
|
|
@@ -2663,6 +2840,7 @@ ident[ category ] returns[ id ]
|
|
|
2663
2840
|
| ASSOCIATION
|
|
2664
2841
|
| BETWEEN
|
|
2665
2842
|
| BOTH
|
|
2843
|
+
| COLUMNS
|
|
2666
2844
|
| COMPOSITION
|
|
2667
2845
|
| CONTEXT
|
|
2668
2846
|
| CROSS
|
|
@@ -2670,8 +2848,10 @@ ident[ category ] returns[ id ]
|
|
|
2670
2848
|
| DAY
|
|
2671
2849
|
| DEFAULT
|
|
2672
2850
|
| DEFINE
|
|
2851
|
+
| DEFINITIONS
|
|
2673
2852
|
| DESC
|
|
2674
2853
|
| ELEMENT
|
|
2854
|
+
| ELEMENTS
|
|
2675
2855
|
| ELSE
|
|
2676
2856
|
| END
|
|
2677
2857
|
| ENTITY
|
|
@@ -2728,6 +2908,7 @@ ident[ category ] returns[ id ]
|
|
|
2728
2908
|
| THEN
|
|
2729
2909
|
| TRAILING
|
|
2730
2910
|
| UNION
|
|
2911
|
+
| UP
|
|
2731
2912
|
| TO
|
|
2732
2913
|
| TYPE
|
|
2733
2914
|
| USING
|
|
@@ -2752,9 +2933,40 @@ LineComment : '//' ~[\r\n\u2028\u2029]* -> channel(HIDDEN);
|
|
|
2752
2933
|
|
|
2753
2934
|
// Values --------------------------------------------------------------------
|
|
2754
2935
|
|
|
2755
|
-
|
|
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
|
|
2756
2943
|
:
|
|
2757
|
-
|
|
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 = '`'
|
|
2758
2970
|
;
|
|
2759
2971
|
|
|
2760
2972
|
QuotedLiteral
|
|
@@ -2763,10 +2975,15 @@ QuotedLiteral
|
|
|
2763
2975
|
( '\'' ~[\u0027\n\r\u2028\u2029]* '\'' )+ // \u0027 = '\''
|
|
2764
2976
|
;
|
|
2765
2977
|
|
|
2978
|
+
// This literal improves error messages for unterminated literals.
|
|
2766
2979
|
UnterminatedLiteral
|
|
2767
2980
|
:
|
|
2768
2981
|
( [xX] | [dD][aA][tT][eE] | [tT][iI][mM][eE] ( [sS][tT][aA][mM][pP] )? )?
|
|
2769
2982
|
'\'' ~[\u0027\n\r\u2028\u2029]* // \u0027 = '\''
|
|
2983
|
+
|
|
|
2984
|
+
('`' ( MultiLineStringContentChar | EscapeSequence )* )
|
|
2985
|
+
|
|
|
2986
|
+
('```' ( MultiLineStringContentChar | EscapeSequence )* )
|
|
2770
2987
|
;
|
|
2771
2988
|
|
|
2772
2989
|
UnterminatedDelimitedIdentifier
|
|
@@ -2830,6 +3047,7 @@ ASPECT : [aA][sS][pP][eE][cC][tT] ;
|
|
|
2830
3047
|
ASSOCIATION : [aA][sS][sS][oO][cC][iI][aA][tT][iI][oO][nN] ;
|
|
2831
3048
|
BETWEEN : [bB][eE][tT][wW][eE][eE][nN] ;
|
|
2832
3049
|
BOTH : [bB][oO][tT][hH] ;
|
|
3050
|
+
COLUMNS : [cC][oO][lL][uU][mM][nN][sS];
|
|
2833
3051
|
COMPOSITION : [cC][oO][mM][pP][oO][sS][iI][tT][iI][oO][nN] ;
|
|
2834
3052
|
CONTEXT : [cC][oO][nN][tT][eE][xX][tT] ;
|
|
2835
3053
|
CROSS : [cC][rR][oO][sS][sS] ;
|
|
@@ -2837,8 +3055,10 @@ CURRENT : [cC][uU][rR][rR][eE][nN][tT] ;
|
|
|
2837
3055
|
DAY : [dD][aA][yY] ;
|
|
2838
3056
|
DEFAULT : [dD][eE][fF][aA][uU][lL][tT] ;
|
|
2839
3057
|
DEFINE : [dD][eE][fF][iI][nN][eE] ;
|
|
3058
|
+
DEFINITIONS : [dD][eE][fF][iI][nN][iI][tT][iI][oO][nN][sS] ;
|
|
2840
3059
|
DESC : [dD][eE][sS][cC] ;
|
|
2841
3060
|
ELEMENT : [eE][lL][eE][mM][eE][nN][tT] ;
|
|
3061
|
+
ELEMENTS : [eE][lL][eE][mM][eE][nN][tT][sS] ;
|
|
2842
3062
|
ELSE : [eE][lL][sS][eE] ;
|
|
2843
3063
|
END : [eE][nN][dD] ;
|
|
2844
3064
|
ENTITY : [eE][nN][tT][iI][tT][yY] ;
|
|
@@ -2899,6 +3119,7 @@ TO : [tT][oO] ; // or make reserved? (is in SQL-92)
|
|
|
2899
3119
|
TYPE : [tT][yY][pP][eE] ;
|
|
2900
3120
|
UNION : [uU][nN][iI][oO][nN] ;
|
|
2901
3121
|
UNBOUNDED : [uU][nN][bB][oO][uU][nN][dD][eE][dD] ;
|
|
3122
|
+
UP : [uU][pP] ;
|
|
2902
3123
|
USING : [uU][sS][iI][nN][gG] ;
|
|
2903
3124
|
VARIABLE : [vV][aA][rR][iI][aA][bB][lL][eE] ;
|
|
2904
3125
|
VIEW : [vV][iI][eE][wW] ;
|