@sap/cds-compiler 2.12.0 → 2.15.2

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.
Files changed (128) hide show
  1. package/CHANGELOG.md +221 -15
  2. package/bin/cdsc.js +125 -50
  3. package/bin/cdsse.js +2 -2
  4. package/doc/CHANGELOG_BETA.md +13 -6
  5. package/doc/CHANGELOG_DEPRECATED.md +22 -6
  6. package/doc/NameResolution.md +21 -16
  7. package/lib/api/main.js +47 -84
  8. package/lib/api/options.js +5 -6
  9. package/lib/api/validate.js +6 -11
  10. package/lib/backends.js +15 -23
  11. package/lib/base/dictionaries.js +0 -8
  12. package/lib/base/error.js +26 -0
  13. package/lib/base/keywords.js +7 -17
  14. package/lib/base/location.js +9 -4
  15. package/lib/base/message-registry.js +114 -18
  16. package/lib/base/messages.js +101 -90
  17. package/lib/base/model.js +2 -63
  18. package/lib/base/optionProcessorHelper.js +177 -123
  19. package/lib/checks/annotationsOData.js +12 -33
  20. package/lib/checks/arrayOfs.js +1 -34
  21. package/lib/checks/cdsPersistence.js +2 -1
  22. package/lib/checks/enricher.js +17 -1
  23. package/lib/checks/invalidTarget.js +3 -1
  24. package/lib/checks/managedWithoutKeys.js +3 -1
  25. package/lib/checks/selectItems.js +4 -4
  26. package/lib/checks/sql-snippets.js +27 -26
  27. package/lib/checks/types.js +1 -1
  28. package/lib/checks/validator.js +6 -11
  29. package/lib/compiler/assert-consistency.js +6 -3
  30. package/lib/compiler/base.js +1 -0
  31. package/lib/compiler/builtins.js +19 -6
  32. package/lib/compiler/checks.js +23 -60
  33. package/lib/compiler/cycle-detector.js +1 -1
  34. package/lib/compiler/define.js +1151 -0
  35. package/lib/compiler/extend.js +1000 -0
  36. package/lib/compiler/finalize-parse-cdl.js +237 -0
  37. package/lib/compiler/index.js +107 -39
  38. package/lib/compiler/kick-start.js +190 -0
  39. package/lib/compiler/moduleLayers.js +4 -4
  40. package/lib/compiler/populate.js +1227 -0
  41. package/lib/compiler/propagator.js +114 -46
  42. package/lib/compiler/resolve.js +1521 -0
  43. package/lib/compiler/shared.js +126 -65
  44. package/lib/compiler/tweak-assocs.js +535 -0
  45. package/lib/compiler/utils.js +197 -33
  46. package/lib/edm/.eslintrc.json +5 -0
  47. package/lib/edm/annotations/genericTranslation.js +38 -24
  48. package/lib/edm/annotations/preprocessAnnotations.js +2 -2
  49. package/lib/edm/csn2edm.js +219 -100
  50. package/lib/edm/edm.js +302 -230
  51. package/lib/edm/edmPreprocessor.js +554 -419
  52. package/lib/edm/edmUtils.js +138 -44
  53. package/lib/gen/Dictionary.json +100 -19
  54. package/lib/gen/language.checksum +1 -1
  55. package/lib/gen/language.interp +11 -1
  56. package/lib/gen/language.tokens +86 -83
  57. package/lib/gen/languageLexer.interp +10 -1
  58. package/lib/gen/languageLexer.js +860 -833
  59. package/lib/gen/languageLexer.tokens +78 -75
  60. package/lib/gen/languageParser.js +5765 -4480
  61. package/lib/json/csnVersion.js +10 -11
  62. package/lib/json/from-csn.js +15 -3
  63. package/lib/json/to-csn.js +126 -68
  64. package/lib/language/docCommentParser.js +4 -4
  65. package/lib/language/genericAntlrParser.js +123 -5
  66. package/lib/language/language.g4 +355 -156
  67. package/lib/language/multiLineStringParser.js +5 -5
  68. package/lib/main.d.ts +486 -59
  69. package/lib/main.js +41 -9
  70. package/lib/model/api.js +3 -1
  71. package/lib/model/csnRefs.js +252 -156
  72. package/lib/model/csnUtils.js +384 -297
  73. package/lib/model/enrichCsn.js +71 -29
  74. package/lib/model/revealInternalProperties.js +29 -8
  75. package/lib/model/sortViews.js +2 -1
  76. package/lib/modelCompare/compare.js +23 -18
  77. package/lib/optionProcessor.js +63 -26
  78. package/lib/render/manageConstraints.js +35 -32
  79. package/lib/render/toCdl.js +897 -947
  80. package/lib/render/toHdbcds.js +205 -257
  81. package/lib/render/toSql.js +264 -225
  82. package/lib/render/utils/common.js +136 -25
  83. package/lib/render/utils/sql.js +4 -3
  84. package/lib/render/utils/stringEscapes.js +111 -0
  85. package/lib/sql-identifier.js +1 -1
  86. package/lib/transform/.eslintrc.json +5 -0
  87. package/lib/transform/db/.eslintrc.json +3 -1
  88. package/lib/transform/db/applyTransformations.js +35 -12
  89. package/lib/transform/db/assertUnique.js +1 -1
  90. package/lib/transform/db/associations.js +104 -306
  91. package/lib/transform/db/cdsPersistence.js +2 -2
  92. package/lib/transform/db/constraints.js +58 -53
  93. package/lib/transform/db/expansion.js +60 -33
  94. package/lib/transform/db/flattening.js +582 -104
  95. package/lib/transform/db/groupByOrderBy.js +3 -1
  96. package/lib/transform/db/transformExists.js +66 -13
  97. package/lib/transform/db/views.js +11 -7
  98. package/lib/transform/draft/.eslintrc.json +38 -0
  99. package/lib/transform/{db/draft.js → draft/db.js} +6 -5
  100. package/lib/transform/draft/odata.js +227 -0
  101. package/lib/transform/forHanaNew.js +109 -208
  102. package/lib/transform/forOdataNew.js +59 -212
  103. package/lib/transform/localized.js +46 -26
  104. package/lib/transform/odata/toFinalBaseType.js +85 -11
  105. package/lib/transform/odata/typesExposure.js +147 -199
  106. package/lib/transform/odata/utils.js +2 -2
  107. package/lib/transform/transformUtilsNew.js +44 -33
  108. package/lib/transform/translateAssocsToJoins.js +3 -20
  109. package/lib/transform/universalCsn/.eslintrc.json +36 -0
  110. package/lib/transform/universalCsn/coreComputed.js +172 -0
  111. package/lib/transform/universalCsn/universalCsnEnricher.js +737 -0
  112. package/lib/transform/universalCsn/utils.js +63 -0
  113. package/lib/utils/moduleResolve.js +13 -6
  114. package/lib/utils/objectUtils.js +30 -0
  115. package/package.json +1 -1
  116. package/share/messages/README.md +26 -0
  117. package/share/messages/message-explanations.json +2 -1
  118. package/share/messages/syntax-expected-integer.md +37 -0
  119. package/lib/compiler/definer.js +0 -2361
  120. package/lib/compiler/resolver.js +0 -3079
  121. package/lib/transform/odata/attachPath.js +0 -96
  122. package/lib/transform/odata/expandStructKeysInAssociations.js +0 -59
  123. package/lib/transform/odata/generateForeignKeyElements.js +0 -261
  124. package/lib/transform/odata/referenceFlattener.js +0 -290
  125. package/lib/transform/odata/sortByAssociationDependency.js +0 -105
  126. package/lib/transform/odata/structuralPath.js +0 -72
  127. package/lib/transform/odata/structureFlattener.js +0 -171
  128. package/lib/transform/universalCsnEnricher.js +0 -237
@@ -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
- // TODO: what about extendAction
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
- '{' artifactDef[ $art, defOnly, true ]* '}'
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', true ]*
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 = Object.create(null); } // better for include and annotate
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
- ( ACTIONS '{' actionFunctionDef[ $art ]* '}' )?
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
- ( ACTIONS '{' actionFunctionDef[ $art ]* '}' optionalSemi
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
- ( ACTIONS '{' actionFunctionDef[ $art ]* '}' )?
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
  )
@@ -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
- ( ACTIONS '{' actionFunctionDef[ $art ]* '}' )?
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 '{' actionFunctionDef[ $art ]* '}'
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
- ( ACTIONS '{' actionFunctionDef[ $art ]* '}' )?
617
+ (
618
+ ACTIONS '{' { $art.actions = this.createDict(); }
619
+ actionFunctionDef[ $art ]*
620
+ '}' { this.setDictEndLocation( $art.actions ); }
621
+ )?
598
622
  optionalSemi
599
623
  |
600
- ACTIONS '{' actionFunctionDef[ $art ]* '}'
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
- ( ACTIONS '{' actionFunctionDef[ $art ]* '}' )?
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 { this.attachLocation($art); }
790
+ extendArtifact[ outer, loc, annos ] locals[ art, name = {}, elemName = {} ]
791
+ @after{ /* #ATN 1 */ this.attachLocation($art); }
763
792
  :
764
793
  simplePath[ $name, 'Extend' ]
765
- { $art = this.addItem( $outer, 'extensions', 'extend', $annos,
766
- { name: $name }, $loc ); }
767
- extendWithOptElements[ $art, $annos ]
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
- { $art = this.addItem( $outer, 'extensions', 'annotate', $annos, { name: $name }, $loc ); }
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 '{' { $art['$'+'syntax'] = '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 '{' { $art['$'+'syntax'] = '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)
@@ -995,7 +1111,7 @@ elementDefInner[ outer, loc, annos, allowEq ] returns[ art ]
995
1111
  :
996
1112
  // TODO: it would be excellent to remove ELEMENT...
997
1113
  // or have a special ident rule without the ELEMENT
998
- // Reason: it would be good for error recover to start a major block without LL1 ambiguity
1114
+ // Reason: it would be good for error recovery to start a major block without LL1 ambiguity
999
1115
  // VIRTUAL is keyword, except if before the following tokens texts:
1000
1116
  { this.setLocalToken( 'VIRTUAL', 'VIRTUAL', /^[:{@=}]$/ ); }
1001
1117
  virtual=VIRTUAL? key=KEY?
@@ -1047,7 +1163,7 @@ elementDefInner[ outer, loc, annos, allowEq ] returns[ art ]
1047
1163
  )
1048
1164
  |
1049
1165
  (
1050
- array=ARRAY of=OF
1166
+ array=ARRAY of=OF
1051
1167
  { $art.items = { location: this.tokenLocation( $array, $of ) }; }
1052
1168
  | many=MANY
1053
1169
  { $art.items = { location: this.tokenLocation( $many ) };}
@@ -1065,10 +1181,9 @@ elementDefInner[ outer, loc, annos, allowEq ] returns[ art ]
1065
1181
  { this.docComment( $annos ); }
1066
1182
  annotationAssignment_ll1[ $annos ]*
1067
1183
  (
1068
- ENUM '{'
1069
- { $art.items.enum = Object.create(null); }
1070
- enumSymbolDef[ $art.items ]*
1071
- '}'
1184
+ ENUM '{' { $art.items.enum = this.createDict(); }
1185
+ enumSymbolDef[ $art.items ]*
1186
+ '}' { this.setDictEndLocation( $art.items.enum ); }
1072
1187
  misplacedAnnotations[ $annos, 'syntax-anno-after-enum' ]?
1073
1188
  )?
1074
1189
  )
@@ -1092,13 +1207,14 @@ elementDefInner[ outer, loc, annos, allowEq ] returns[ art ]
1092
1207
  typeRefOptArgs[ $art ]
1093
1208
  { this.docComment( $annos ); }
1094
1209
  annotationAssignment_ll1[ $annos ]*
1095
- ( ENUM '{'
1096
- { $art.enum = Object.create(null); }
1097
- enumSymbolDef[ $art ]*
1098
- '}'
1210
+ (
1211
+ ENUM '{' { $art.enum = this.createDict(); }
1212
+ enumSymbolDef[ $art ]*
1213
+ '}' { this.setDictEndLocation( $art.enum ); }
1099
1214
  elementProperties[ $art ]?
1100
1215
  misplacedAnnotations[ $annos, 'syntax-anno-after-enum' ]?
1101
- | elementProperties[ $art ]
1216
+ |
1217
+ elementProperties[ $art ]
1102
1218
  { this.docComment( $annos ); }
1103
1219
  annotationAssignment_ll1[ $annos ]*
1104
1220
  )?
@@ -1163,7 +1279,7 @@ selectItemDef[ outer ] locals[ annos = [] ]
1163
1279
  ;
1164
1280
 
1165
1281
  selectItemDefBody[ outer, annos ] returns[ art = {} ]
1166
- @after{ /* #ATN 1 */ this.attachLocation($art); }
1282
+ @after{ /* #ATN 2 */ this.attachLocation($art); }
1167
1283
  :
1168
1284
  (
1169
1285
  e=expression
@@ -1219,6 +1335,12 @@ selectItemDefBody[ outer, annos ] returns[ art = {} ]
1219
1335
  | typeRefOptArgs[ $art ] // TODO: annos here?
1220
1336
  { this.docComment( $annos ); }
1221
1337
  annotationAssignment_ll1[ $annos ]*
1338
+ |
1339
+ typeAssociationBase[ $art, false ]
1340
+ // #ATN: path could start with MANY or ONE - make sure a token follows in same rule!
1341
+ ( typeToMany[ $art ] | typeToOne[ $art ] | simplePath[ $art.target, 'artref' ] )
1342
+ typeAssociationCont[ $art ]?
1343
+ { this.associationInSelectItem( $art ); }
1222
1344
  )
1223
1345
  )?
1224
1346
  ;
@@ -1249,7 +1371,7 @@ selectItemInlineDef[ outer ] locals[ annos = [] ]
1249
1371
 
1250
1372
  parameterListDef[ art ]
1251
1373
  :
1252
- '('
1374
+ '(' { $art.params = this.createDict(); }
1253
1375
  // also empty param list (we might do some hacking later to allow reserved words)
1254
1376
  // see annotationAssignment_paren
1255
1377
  (
@@ -1258,7 +1380,7 @@ parameterListDef[ art ]
1258
1380
  parameterDef[ $art ]
1259
1381
  )*
1260
1382
  )?
1261
- ')'
1383
+ ')' { this.setDictEndLocation( $art.params ); }
1262
1384
  ;
1263
1385
 
1264
1386
  parameterDef[ outer ] locals[ art, annos = [] ]
@@ -1271,14 +1393,14 @@ parameterDef[ outer ] locals[ art, annos = [] ]
1271
1393
  this.docComment( $annos ); }
1272
1394
  annotationAssignment_fix[ $annos ]*
1273
1395
  typeSpec[ $art ]
1274
- ( DEFAULT expr=expression { $art.default = $expr.expr; } )?
1396
+ defaultValue[ $art ]?
1275
1397
  { this.docComment( $annos ); }
1276
1398
  annotationAssignment_ll1[ $annos ]*
1277
1399
  ;
1278
1400
 
1279
1401
  entityParameters[ art ]
1280
1402
  :
1281
- '('
1403
+ '(' { $art.params = this.createDict(); }
1282
1404
  // also empty param list (we might do some hacking later to allow reserved words)
1283
1405
  // see annotationAssignment_paren
1284
1406
  (
@@ -1287,7 +1409,7 @@ entityParameters[ art ]
1287
1409
  entityParameterDef[ $art ]
1288
1410
  )*
1289
1411
  )?
1290
- ')'
1412
+ ')' { this.setDictEndLocation( $art.params ); }
1291
1413
  ;
1292
1414
 
1293
1415
  entityParameterDef[ outer ] locals[ art, annos = [] ]
@@ -1300,7 +1422,7 @@ entityParameterDef[ outer ] locals[ art, annos = [] ]
1300
1422
  this.docComment( $annos ); }
1301
1423
  annotationAssignment_fix[ $annos ]*
1302
1424
  typeSpec[ $art ]
1303
- ( DEFAULT expr=expression { $art.default = $expr.expr; } )?
1425
+ defaultValue[ $art ]?
1304
1426
  { this.docComment( $annos ); }
1305
1427
  annotationAssignment_ll1[ $annos ]*
1306
1428
  ;
@@ -1316,17 +1438,11 @@ nullability[ art ]
1316
1438
 
1317
1439
  elementProperties[ elem ]
1318
1440
  :
1319
- nullability[$elem]
1320
- (
1321
- DEFAULT expr=expression
1322
- { $elem.default = $expr.expr; }
1323
- )?
1441
+ nullability[ $elem ]
1442
+ defaultValue[ $elem ]?
1324
1443
  |
1325
- (
1326
- DEFAULT expr=expression
1327
- { $elem.default = $expr.expr; }
1328
- )
1329
- nullability[$elem]?
1444
+ defaultValue[ $elem ]
1445
+ nullability[ $elem ]?
1330
1446
  |
1331
1447
  eq='='
1332
1448
  { this.notSupportedYet( 'Calculated fields are not supported yet', $eq ); }
@@ -1377,10 +1493,10 @@ typeSpec[ art ] // for params
1377
1493
  // TODO: no LOCALIZED ?
1378
1494
  | typeRefOptArgs[ $art ]
1379
1495
  nullability[ $art ]?
1380
- ( ENUM '{'
1381
- { $art.enum = Object.create(null); }
1382
- enumSymbolDef[ $art ]*
1383
- '}'
1496
+ (
1497
+ ENUM '{' { $art.enum = this.createDict(); }
1498
+ enumSymbolDef[ $art ]*
1499
+ '}' { this.setDictEndLocation( $art.enum ); }
1384
1500
  )?
1385
1501
  )
1386
1502
  ;
@@ -1390,7 +1506,7 @@ returnTypeSpec[ art, annos ]
1390
1506
  :
1391
1507
  ret=RETURNS { $art.returns = { location: this.tokenLocation( $ret ), kind: 'param' }; }
1392
1508
  // #ATN: typeSimple can start with ARRAY or TYPE
1393
- ( typeStruct[ $art.returns ]
1509
+ ( typeStruct[ $art.returns ]
1394
1510
  nullability[ $art.returns ]?
1395
1511
  | typeArray[ $art.returns ] // nullability is set in typeArray
1396
1512
  | typeTypeOf[ $art.returns ]
@@ -1398,11 +1514,12 @@ returnTypeSpec[ art, annos ]
1398
1514
  // TODO: no LOCALIZED ?
1399
1515
  | typeRefOptArgs[ $art.returns ]
1400
1516
  nullability[ $art.returns ]?
1401
- ( ENUM '{'
1402
- { $art.returns.enum = Object.create(null); }
1403
- enumSymbolDef[ $art.returns ]*
1404
- '}'
1405
- | misplacedAnnotations[ $annos, 'syntax-anno-after-params' ]
1517
+ (
1518
+ ENUM '{' { $art.returns.enum = this.createDict(); }
1519
+ enumSymbolDef[ $art.returns ]*
1520
+ '}' { this.setDictEndLocation( $art.returns.enum ); }
1521
+ |
1522
+ misplacedAnnotations[ $annos, 'syntax-anno-after-params' ]
1406
1523
  )?
1407
1524
  )
1408
1525
 
@@ -1443,7 +1560,7 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
1443
1560
  { $art.items = { location: this.tokenLocation( $many ) };}
1444
1561
  )
1445
1562
  // #ATN: typeRefOptArgs can start with TYPE
1446
- ( typeStruct[ $art.items ]
1563
+ ( typeStruct[ $art.items ]
1447
1564
  nullability[ $art.items ]?
1448
1565
  optionalSemi
1449
1566
  | typeTypeOf[ $art.items ]
@@ -1455,21 +1572,24 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
1455
1572
  nullability[ $art.items ]?
1456
1573
  { this.docComment( $annos ); }
1457
1574
  annotationAssignment_ll1[ $annos ]*
1458
- ( ENUM '{'
1459
- { $art.items.enum = Object.create(null); }
1460
- enumSymbolDef[ $art.items ]*
1461
- '}'
1462
- optionalSemi
1463
- | requiredSemi
1575
+ (
1576
+ ENUM '{' { $art.items.enum = this.createDict(); }
1577
+ enumSymbolDef[ $art.items ]*
1578
+ '}' { this.setDictEndLocation( $art.items.enum ); }
1579
+ optionalSemi
1580
+ |
1581
+ requiredSemi
1464
1582
  )
1465
1583
  )
1466
1584
  |
1467
1585
  typeTypeOf[ $art ]
1586
+ defaultValue[ $art ]?
1468
1587
  { this.docComment( $annos ); }
1469
1588
  annotationAssignment_ll1[ $annos ]* requiredSemi
1470
1589
  |
1471
1590
  l=LOCALIZED { $art.localized = this.valueWithTokenLocation( true, $l ); }
1472
1591
  typeRefOptArgs[ $art ]
1592
+ defaultValue[ $art ]?
1473
1593
  { this.docComment( $annos ); }
1474
1594
  annotationAssignment_ll1[ $annos ]*
1475
1595
  requiredSemi
@@ -1478,34 +1598,22 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
1478
1598
  { $art.type = {}; }
1479
1599
  simplePath[ $art.type, 'artref' ]
1480
1600
  (
1481
- '(' // with type args, e.g. `type T : String(100) enum { ... }`
1482
- head=Number
1483
- { $art['$'+'typeArgs'] = [ this.numberLiteral( $head ) ]; }
1484
- ( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
1601
+ typeRefArgs[ $art ]
1602
+ { this.docComment( $annos ); }
1603
+ annotationAssignment_ll1[ $annos ]*
1604
+ (
1605
+ ENUM '{' { $art.enum = this.createDict(); }
1606
+ enumSymbolDef[ $art ]*
1607
+ '}' { this.setDictEndLocation( $art.enum ); }
1485
1608
  (
1486
- v=VARIABLE
1487
- { $art['$'+'typeArgs'].push(
1488
- { literal: 'string', val: 'variable', location: this.tokenLocation($v) } );
1489
- }
1490
- |
1491
- f=FLOATING
1492
- { $art['$'+'typeArgs'].push(
1493
- { literal: 'string', val: 'floating', location: this.tokenLocation($f) } );
1494
- }
1609
+ optionalSemi
1495
1610
  |
1496
- tail=Number
1497
- { $art['$'+'typeArgs'].push( this.numberLiteral( $tail ) ); }
1611
+ defaultValue[ $art ]
1612
+ requiredSemi
1498
1613
  )
1499
- )*
1500
- ')'
1501
- { this.docComment( $annos ); }
1502
- annotationAssignment_ll1[ $annos ]*
1503
- ( ENUM '{'
1504
- { $art.enum = Object.create(null); }
1505
- enumSymbolDef[ $art ]*
1506
- '}'
1507
- optionalSemi
1508
- | requiredSemi
1614
+ |
1615
+ defaultValue[ $art ]?
1616
+ requiredSemi
1509
1617
  )
1510
1618
  |
1511
1619
  ':' // with element, e.g. `type T : E:elem enum { ... }`
@@ -1513,22 +1621,36 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
1513
1621
  simplePath[ $art.type, 'ref']
1514
1622
  { this.docComment( $annos ); }
1515
1623
  annotationAssignment_ll1[ $annos ]*
1516
- ( ENUM '{'
1517
- { $art.enum = Object.create(null); }
1518
- enumSymbolDef[ $art ]*
1519
- '}'
1520
- optionalSemi
1521
- | requiredSemi
1624
+ (
1625
+ ENUM '{' { $art.enum = this.createDict(); }
1626
+ enumSymbolDef[ $art ]*
1627
+ '}' { this.setDictEndLocation( $art.enum ); }
1628
+ (
1629
+ optionalSemi
1630
+ |
1631
+ defaultValue[ $art ]
1632
+ requiredSemi
1633
+ )
1634
+ |
1635
+ defaultValue[ $art ]?
1636
+ requiredSemi
1522
1637
  )
1523
1638
  |
1524
1639
  { this.docComment( $annos ); }
1525
1640
  annotationAssignment_ll1[ $annos ]*
1526
- ( ENUM '{'
1527
- { $art.enum = Object.create(null); }
1528
- enumSymbolDef[ $art ]*
1529
- '}'
1530
- optionalSemi
1531
- | requiredSemi
1641
+ (
1642
+ ENUM '{' { $art.enum = this.createDict(); }
1643
+ enumSymbolDef[ $art ]*
1644
+ '}' { this.setDictEndLocation( $art.enum ); }
1645
+ (
1646
+ optionalSemi
1647
+ |
1648
+ defaultValue[ $art ]
1649
+ requiredSemi
1650
+ )
1651
+ |
1652
+ defaultValue[ $art ]?
1653
+ requiredSemi
1532
1654
  )
1533
1655
  |
1534
1656
  // TODO: complain if used in anno def?
@@ -1545,15 +1667,17 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
1545
1667
  typeStruct[ art, attachLoc = false ]
1546
1668
  @after { if ($attachLoc) this.attachLocation($art); }
1547
1669
  :
1548
- { $art.elements = Object.create(null); } // we allow empty structures
1549
- '{' elementDef[ $art ]* '}'
1670
+ '{' { $art.elements = this.createDict(); }
1671
+ elementDef[ $art ]*
1672
+ '}' { this.setDictEndLocation( $art.elements ); }
1550
1673
  ;
1551
1674
 
1552
1675
  typeCompoStruct[ art ]
1553
1676
  @after { this.attachLocation($art); }
1554
1677
  :
1555
- { $art.elements = Object.create(null); } // we allow empty structures
1556
- COMPOSITIONofBRACE elementDef[ $art ]* '}'
1678
+ COMPOSITIONofBRACE { $art.elements = this.createDict(); }
1679
+ elementDef[ $art ]*
1680
+ '}' { this.setDictEndLocation( $art.elements ); }
1557
1681
  ;
1558
1682
 
1559
1683
  typeArray[ art ]
@@ -1572,10 +1696,10 @@ typeArray[ art ]
1572
1696
  nullability[ $art.items ]?
1573
1697
  | typeRefOptArgs[ $art.items ]
1574
1698
  nullability[ $art.items ]?
1575
- ( ENUM '{'
1576
- { $art.items.enum = Object.create(null); }
1577
- enumSymbolDef[ $art.items ]*
1578
- '}'
1699
+ (
1700
+ ENUM '{' { $art.items.enum = this.createDict(); }
1701
+ enumSymbolDef[ $art.items ]*
1702
+ '}' { this.setDictEndLocation( $art.items.enum ); }
1579
1703
  )?
1580
1704
  )
1581
1705
  ;
@@ -1603,7 +1727,7 @@ typeAssociationBase[ art, handleTypeCompo ] // including Composition
1603
1727
  typeAssociationCont[ art ]
1604
1728
  :
1605
1729
  (
1606
- '{'
1730
+ '{' { $art.foreignKeys = this.createDict(); }
1607
1731
  { this.addDef( $art, 'foreignKeys' ); }
1608
1732
  (
1609
1733
  foreignKey[ $art ]
@@ -1611,7 +1735,7 @@ typeAssociationCont[ art ]
1611
1735
  foreignKey[ $art ]
1612
1736
  )*
1613
1737
  )?
1614
- '}'
1738
+ '}' { this.setDictEndLocation( $art.foreignKeys ); }
1615
1739
  |
1616
1740
  ON cond=condition
1617
1741
  { $art.on=$cond.cond; }
@@ -1622,7 +1746,7 @@ typeAssociationElementCont[ art, annos ] // including Composition
1622
1746
  // optional NULL / NOT NULL for managed association only
1623
1747
  :
1624
1748
  (
1625
- '{'
1749
+ '{' { $art.foreignKeys = this.createDict(); }
1626
1750
  { this.addDef( $art, 'foreignKeys' ); }
1627
1751
  (
1628
1752
  foreignKey[ $art ]
@@ -1630,7 +1754,7 @@ typeAssociationElementCont[ art, annos ] // including Composition
1630
1754
  foreignKey[ $art ]
1631
1755
  )*
1632
1756
  )?
1633
- '}'
1757
+ '}' { this.setDictEndLocation( $art.foreignKeys ); }
1634
1758
  nullability[ $art ]?
1635
1759
  |
1636
1760
  ON cond=condition
@@ -1718,7 +1842,19 @@ typeRefOptArgs[ art ]
1718
1842
  :
1719
1843
  simplePath[ $art.type, 'artref' ]
1720
1844
  (
1721
- '('
1845
+ typeRefArgs[ $art ]
1846
+ |
1847
+ ':'
1848
+ { $art.type.scope = $art.type.path.length; }
1849
+ simplePath[ $art.type, 'ref']
1850
+ )?
1851
+ ;
1852
+
1853
+ typeRefArgs[ art ]
1854
+ :
1855
+ paren='('
1856
+ (
1857
+ // unnamed arguments
1722
1858
  head=Number
1723
1859
  { $art['$'+'typeArgs'] = [ this.numberLiteral( $head ) ]; }
1724
1860
  ( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
@@ -1737,14 +1873,45 @@ typeRefOptArgs[ art ]
1737
1873
  { $art['$'+'typeArgs'].push( this.numberLiteral( $tail ) ); }
1738
1874
  )
1739
1875
  )*
1740
- ')'
1741
1876
  |
1742
- ':'
1743
- { $art.type.scope = $art.type.path.length; }
1744
- simplePath[ $art.type, 'ref']
1745
- )?
1877
+ // named arguments
1878
+ typeNamedArg[ $art ]
1879
+ ( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
1880
+ typeNamedArg[ $art ]
1881
+ )*
1882
+ )
1883
+ ')'
1746
1884
  ;
1747
1885
 
1886
+ typeNamedArg[ art ] locals[ arg = '' ]
1887
+ :
1888
+ name=ident['paramname']
1889
+ ':'
1890
+ { if (this.checkTypeFacet( $art, $name.id ))
1891
+ $arg = $name.id.id;
1892
+ }
1893
+ (
1894
+ val=Number
1895
+ { if ($arg && $art && $name.id) {
1896
+ $art[$arg] = this.numberLiteral( $val );
1897
+ }
1898
+ }
1899
+ |
1900
+ v=VARIABLE
1901
+ { if ($arg && $art && $name.id) {
1902
+ $art[$arg] = { literal: 'string', val: 'variable', location: this.tokenLocation($v) };
1903
+ }
1904
+ }
1905
+ |
1906
+ f=FLOATING
1907
+ { if ($arg && $art && $name.id) {
1908
+ $art[$arg] = { literal: 'string', val: 'floating', location: this.tokenLocation($f) };
1909
+ }
1910
+ }
1911
+ )
1912
+ ;
1913
+
1914
+
1748
1915
  // Queries -------------------------------------------------------------------
1749
1916
 
1750
1917
  queryExpression returns[ query ] // QLSubqueryComplex, SubqueryComplex
@@ -1770,14 +1937,26 @@ orderByClause[ inQuery ] returns [ query ]
1770
1937
  ( ',' obn=orderBySpec { $query.orderBy.push( $obn.ob ); } )*
1771
1938
  ;
1772
1939
 
1940
+ // Generic function ORDER BY clause, e.g. `first_value(id order by name)`
1941
+ // lhsExpr is the left expression of the ORDER BY clause.
1942
+ functionOrderByClause[ lhsExpr ] returns [ expr ]
1943
+ @after { this.attachLocation( $expr ); }
1944
+ :
1945
+ o=ORDER b=BY { $expr = { op: this.valueWithTokenLocation( 'orderBy', $o, $b ) , args: [ $lhsExpr ] }}
1946
+ ob1=orderBySpec { $expr.args.push( $ob1.ob ); }
1947
+ ( ',' obn=orderBySpec { $expr.args.push( $obn.ob ); } )*
1948
+ ;
1949
+
1773
1950
  overOrderByClause returns [ expr ]
1951
+ @after { this.attachLocation( $expr ); }
1774
1952
  :
1775
- o=ORDER b=BY { $expr = { op: this.valueWithTokenLocation( 'orderBy', $o, $b ) , args: [] }}
1953
+ o=ORDER b=BY { $expr = { op: this.valueWithTokenLocation( 'overOrderBy', $o, $b ) , args: [] }}
1776
1954
  ob1=orderBySpec { $expr.args.push( $ob1.ob ); }
1777
1955
  ( ',' obn=orderBySpec { $expr.args.push( $obn.ob ); } )*
1778
1956
  ;
1779
1957
 
1780
1958
  partitionByClause returns [ expr ]
1959
+ @after { this.attachLocation( $expr ); }
1781
1960
  :
1782
1961
  p=PARTITION b=BY { $expr = { op: this.valueWithTokenLocation( 'partitionBy', $p, $b ) , args: [] }}
1783
1962
  e1=expression { $expr.args.push( $e1.expr ); }
@@ -1785,12 +1964,14 @@ partitionByClause returns [ expr ]
1785
1964
  ;
1786
1965
 
1787
1966
  windowFrameClause returns [ wf ]
1967
+ @after { this.attachLocation( $wf ); }
1788
1968
  :
1789
1969
  r=ROWS { $wf = { op: this.valueWithTokenLocation( 'rows', $r ) , args: [] }}
1790
1970
  wfe=windowFrameExtentSpec { $wf.args.push( $wfe.wfe ); }
1791
1971
  ;
1792
1972
 
1793
1973
  windowFrameExtentSpec returns[ wfe ]
1974
+ @after { this.attachLocation( $wfe ); }
1794
1975
  :
1795
1976
  { $wfe = {} }
1796
1977
  windowFrameStartSpec [ $wfe ]
@@ -1820,6 +2001,7 @@ windowFrameBoundSpec returns [ wfb ]
1820
2001
  ;
1821
2002
 
1822
2003
  windowFrameStartSpec [ wf ]
2004
+ @after { this.attachLocation( $wf ); }
1823
2005
  :
1824
2006
  u=UNBOUNDED p=PRECEDING
1825
2007
  {
@@ -1832,7 +2014,7 @@ windowFrameStartSpec [ wf ]
1832
2014
  $wf.op = this.valueWithTokenLocation( 'preceding', $p );
1833
2015
  $wf.args = [ this.numberLiteral( $n ) ];
1834
2016
  }
1835
- |
2017
+ |
1836
2018
  c=CURRENT r=ROW
1837
2019
  {
1838
2020
  $wf.op = this.valueWithTokenLocation( 'currentRow', $c, $r );
@@ -1841,7 +2023,7 @@ windowFrameStartSpec [ wf ]
1841
2023
  ;
1842
2024
 
1843
2025
  overClause returns [ over ]
1844
- @after { this.attachLocation($over); }
2026
+ @after { this.attachLocation( $over ); }
1845
2027
  :
1846
2028
  o=OVER { $over = { op: this.valueWithTokenLocation( 'over', $o ) , args: [] } }
1847
2029
  '('
@@ -1895,9 +2077,10 @@ queryPrimary returns[ query = {} ]
1895
2077
  (
1896
2078
  FROM querySource[ $query ]
1897
2079
  (
1898
- mixin=MIXIN '{'
2080
+ mixin=MIXIN '{' { $query.mixin = this.createDict(); }
1899
2081
  mixinElementDef[ $query ]*
1900
- '}' INTO
2082
+ '}' { this.setDictEndLocation( $query.mixin ); }
2083
+ INTO
1901
2084
  )?
1902
2085
  ( ad=( ALL | DISTINCT ) // TODO: or directly after SELECT ?
1903
2086
  { $query.quantifier = this.valueWithTokenLocation( $ad.text.toLowerCase(), $ad ); }
@@ -2088,6 +2271,7 @@ conditionAnd returns [ cond ] locals [ args = [], andl = [] ]
2088
2271
  ( and=AND c2=conditionTerm { $args.push($c2.cond); $andl.push(this.valueWithTokenLocation( 'and', $and )) } )*
2089
2272
  ;
2090
2273
 
2274
+ // Note: New operators need to be added to functionExpressionOperatorsRequireParentheses[] in toCdl.js.
2091
2275
  conditionTerm returns [ cond ]
2092
2276
  @after{
2093
2277
  if ($cond) { this.attachLocation($cond); } else { $cond = $expr.expr; }
@@ -2135,6 +2319,7 @@ conditionTerm returns [ cond ]
2135
2319
  )? // optional: for conditions in parentheses
2136
2320
  ;
2137
2321
 
2322
+ // Note: New operators need to be added to functionExpressionOperatorsRequireParentheses[] in toCdl.js.
2138
2323
  predicate[ cond, negated ]
2139
2324
  // As an alternative, we could have a `negated` properties for the operations
2140
2325
  // `isNull`(!), `in`, `between` and `like` (or produce the same AST as for
@@ -2351,6 +2536,7 @@ fromArguments[ pathStep ]
2351
2536
  pathArguments[ pathStep, considerSpecial ]
2352
2537
  @after{ /* #ATN 1 */ }
2353
2538
  :
2539
+ { this.excludeExpected([ 'ORDER' ]); }
2354
2540
  paren='('
2355
2541
  { this.prepareGenericKeywords( $considerSpecial ); }
2356
2542
  // ATN, LL2: Identifier can start both named arguments and the positional.
@@ -2372,6 +2558,13 @@ pathArguments[ pathStep, considerSpecial ]
2372
2558
  ( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
2373
2559
  funcExpression[ $pathStep, $considerSpecial ]
2374
2560
  )*
2561
+ // Note: We can't move this into funcExpression, or we would increase the ATN count because of `,` amiguity.
2562
+ ( ob=functionOrderByClause[ $pathStep.args[$pathStep.args.length - 1] ]
2563
+ {
2564
+ // Remove the last entry which was copied to $ob.expr and push $ob.expr.
2565
+ $pathStep.args[$pathStep.args.length - 1] = $ob.expr;
2566
+ }
2567
+ )?
2375
2568
  |
2376
2569
  a=ALL { $pathStep.quantifier = this.valueWithTokenLocation( 'all', $a ); }
2377
2570
  e1=expression { $pathStep.args = [ $e1.expr ]; }
@@ -2679,6 +2872,7 @@ ident[ category ] returns[ id ]
2679
2872
  | ASSOCIATION
2680
2873
  | BETWEEN
2681
2874
  | BOTH
2875
+ | COLUMNS
2682
2876
  | COMPOSITION
2683
2877
  | CONTEXT
2684
2878
  | CROSS
@@ -2686,8 +2880,10 @@ ident[ category ] returns[ id ]
2686
2880
  | DAY
2687
2881
  | DEFAULT
2688
2882
  | DEFINE
2883
+ | DEFINITIONS
2689
2884
  | DESC
2690
2885
  | ELEMENT
2886
+ | ELEMENTS
2691
2887
  | ELSE
2692
2888
  | END
2693
2889
  | ENTITY
@@ -2883,6 +3079,7 @@ ASPECT : [aA][sS][pP][eE][cC][tT] ;
2883
3079
  ASSOCIATION : [aA][sS][sS][oO][cC][iI][aA][tT][iI][oO][nN] ;
2884
3080
  BETWEEN : [bB][eE][tT][wW][eE][eE][nN] ;
2885
3081
  BOTH : [bB][oO][tT][hH] ;
3082
+ COLUMNS : [cC][oO][lL][uU][mM][nN][sS];
2886
3083
  COMPOSITION : [cC][oO][mM][pP][oO][sS][iI][tT][iI][oO][nN] ;
2887
3084
  CONTEXT : [cC][oO][nN][tT][eE][xX][tT] ;
2888
3085
  CROSS : [cC][rR][oO][sS][sS] ;
@@ -2890,8 +3087,10 @@ CURRENT : [cC][uU][rR][rR][eE][nN][tT] ;
2890
3087
  DAY : [dD][aA][yY] ;
2891
3088
  DEFAULT : [dD][eE][fF][aA][uU][lL][tT] ;
2892
3089
  DEFINE : [dD][eE][fF][iI][nN][eE] ;
3090
+ DEFINITIONS : [dD][eE][fF][iI][nN][iI][tT][iI][oO][nN][sS] ;
2893
3091
  DESC : [dD][eE][sS][cC] ;
2894
3092
  ELEMENT : [eE][lL][eE][mM][eE][nN][tT] ;
3093
+ ELEMENTS : [eE][lL][eE][mM][eE][nN][tT][sS] ;
2895
3094
  ELSE : [eE][lL][sS][eE] ;
2896
3095
  END : [eE][nN][dD] ;
2897
3096
  ENTITY : [eE][nN][tT][iI][tT][yY] ;