@sap/cds-compiler 2.12.0 → 2.13.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/CHANGELOG.md +110 -15
  2. package/bin/cdsc.js +13 -13
  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 +28 -63
  8. package/lib/api/options.js +3 -3
  9. package/lib/api/validate.js +0 -5
  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 +25 -4
  16. package/lib/base/messages.js +16 -26
  17. package/lib/base/model.js +2 -63
  18. package/lib/base/optionProcessorHelper.js +158 -123
  19. package/lib/checks/annotationsOData.js +1 -1
  20. package/lib/checks/cdsPersistence.js +2 -1
  21. package/lib/checks/enricher.js +17 -1
  22. package/lib/checks/invalidTarget.js +3 -1
  23. package/lib/checks/managedWithoutKeys.js +3 -1
  24. package/lib/checks/selectItems.js +4 -4
  25. package/lib/checks/sql-snippets.js +27 -26
  26. package/lib/checks/types.js +1 -1
  27. package/lib/checks/validator.js +4 -7
  28. package/lib/compiler/assert-consistency.js +5 -3
  29. package/lib/compiler/builtins.js +8 -6
  30. package/lib/compiler/checks.js +14 -3
  31. package/lib/compiler/cycle-detector.js +1 -1
  32. package/lib/compiler/define.js +1103 -0
  33. package/lib/compiler/extend.js +983 -0
  34. package/lib/compiler/finalize-parse-cdl.js +231 -0
  35. package/lib/compiler/index.js +32 -13
  36. package/lib/compiler/kick-start.js +190 -0
  37. package/lib/compiler/moduleLayers.js +4 -4
  38. package/lib/compiler/populate.js +1226 -0
  39. package/lib/compiler/propagator.js +111 -46
  40. package/lib/compiler/resolve.js +1433 -0
  41. package/lib/compiler/shared.js +64 -37
  42. package/lib/compiler/tweak-assocs.js +529 -0
  43. package/lib/compiler/utils.js +197 -33
  44. package/lib/edm/.eslintrc.json +5 -0
  45. package/lib/edm/annotations/genericTranslation.js +5 -9
  46. package/lib/edm/annotations/preprocessAnnotations.js +2 -2
  47. package/lib/edm/csn2edm.js +9 -8
  48. package/lib/edm/edm.js +11 -12
  49. package/lib/edm/edmPreprocessor.js +137 -73
  50. package/lib/edm/edmUtils.js +116 -22
  51. package/lib/gen/Dictionary.json +10 -3
  52. package/lib/gen/language.checksum +1 -1
  53. package/lib/gen/language.interp +9 -1
  54. package/lib/gen/language.tokens +86 -83
  55. package/lib/gen/languageLexer.interp +10 -1
  56. package/lib/gen/languageLexer.js +860 -833
  57. package/lib/gen/languageLexer.tokens +78 -75
  58. package/lib/gen/languageParser.js +5282 -4265
  59. package/lib/json/from-csn.js +12 -1
  60. package/lib/json/to-csn.js +126 -66
  61. package/lib/language/docCommentParser.js +2 -2
  62. package/lib/language/genericAntlrParser.js +76 -3
  63. package/lib/language/language.g4 +297 -130
  64. package/lib/language/multiLineStringParser.js +5 -5
  65. package/lib/main.d.ts +468 -59
  66. package/lib/main.js +35 -9
  67. package/lib/model/api.js +3 -1
  68. package/lib/model/csnRefs.js +225 -156
  69. package/lib/model/csnUtils.js +192 -223
  70. package/lib/model/enrichCsn.js +70 -29
  71. package/lib/model/revealInternalProperties.js +27 -6
  72. package/lib/model/sortViews.js +2 -1
  73. package/lib/modelCompare/compare.js +17 -12
  74. package/lib/optionProcessor.js +5 -4
  75. package/lib/render/manageConstraints.js +35 -32
  76. package/lib/render/toCdl.js +73 -288
  77. package/lib/render/toHdbcds.js +25 -23
  78. package/lib/render/toSql.js +98 -41
  79. package/lib/render/utils/common.js +5 -10
  80. package/lib/render/utils/sql.js +4 -3
  81. package/lib/render/utils/stringEscapes.js +111 -0
  82. package/lib/sql-identifier.js +1 -1
  83. package/lib/transform/.eslintrc.json +5 -0
  84. package/lib/transform/db/.eslintrc.json +2 -0
  85. package/lib/transform/db/applyTransformations.js +35 -12
  86. package/lib/transform/db/assertUnique.js +1 -1
  87. package/lib/transform/db/associations.js +103 -305
  88. package/lib/transform/db/cdsPersistence.js +2 -2
  89. package/lib/transform/db/constraints.js +55 -52
  90. package/lib/transform/db/expansion.js +46 -24
  91. package/lib/transform/db/flattening.js +553 -102
  92. package/lib/transform/db/groupByOrderBy.js +3 -1
  93. package/lib/transform/db/transformExists.js +59 -6
  94. package/lib/transform/db/views.js +5 -4
  95. package/lib/transform/draft/.eslintrc.json +38 -0
  96. package/lib/transform/{db/draft.js → draft/db.js} +6 -5
  97. package/lib/transform/draft/odata.js +227 -0
  98. package/lib/transform/forHanaNew.js +67 -183
  99. package/lib/transform/forOdataNew.js +17 -171
  100. package/lib/transform/localized.js +34 -19
  101. package/lib/transform/odata/generateForeignKeyElements.js +1 -1
  102. package/lib/transform/odata/referenceFlattener.js +95 -89
  103. package/lib/transform/odata/structureFlattener.js +1 -1
  104. package/lib/transform/odata/toFinalBaseType.js +86 -12
  105. package/lib/transform/odata/typesExposure.js +5 -5
  106. package/lib/transform/odata/utils.js +2 -2
  107. package/lib/transform/transformUtilsNew.js +36 -22
  108. package/lib/transform/translateAssocsToJoins.js +2 -19
  109. package/lib/transform/universalCsn/.eslintrc.json +36 -0
  110. package/lib/transform/universalCsn/coreComputed.js +170 -0
  111. package/lib/transform/universalCsn/universalCsnEnricher.js +715 -0
  112. package/lib/transform/universalCsn/utils.js +63 -0
  113. package/lib/utils/objectUtils.js +30 -0
  114. package/package.json +1 -1
  115. package/share/messages/README.md +26 -0
  116. package/lib/compiler/definer.js +0 -2361
  117. package/lib/compiler/resolver.js +0 -3079
  118. 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
  )?
@@ -1249,7 +1365,7 @@ selectItemInlineDef[ outer ] locals[ annos = [] ]
1249
1365
 
1250
1366
  parameterListDef[ art ]
1251
1367
  :
1252
- '('
1368
+ '(' { $art.params = this.createDict(); }
1253
1369
  // also empty param list (we might do some hacking later to allow reserved words)
1254
1370
  // see annotationAssignment_paren
1255
1371
  (
@@ -1258,7 +1374,7 @@ parameterListDef[ art ]
1258
1374
  parameterDef[ $art ]
1259
1375
  )*
1260
1376
  )?
1261
- ')'
1377
+ ')' { this.setDictEndLocation( $art.params ); }
1262
1378
  ;
1263
1379
 
1264
1380
  parameterDef[ outer ] locals[ art, annos = [] ]
@@ -1271,14 +1387,14 @@ parameterDef[ outer ] locals[ art, annos = [] ]
1271
1387
  this.docComment( $annos ); }
1272
1388
  annotationAssignment_fix[ $annos ]*
1273
1389
  typeSpec[ $art ]
1274
- ( DEFAULT expr=expression { $art.default = $expr.expr; } )?
1390
+ defaultValue[ $art ]?
1275
1391
  { this.docComment( $annos ); }
1276
1392
  annotationAssignment_ll1[ $annos ]*
1277
1393
  ;
1278
1394
 
1279
1395
  entityParameters[ art ]
1280
1396
  :
1281
- '('
1397
+ '(' { $art.params = this.createDict(); }
1282
1398
  // also empty param list (we might do some hacking later to allow reserved words)
1283
1399
  // see annotationAssignment_paren
1284
1400
  (
@@ -1287,7 +1403,7 @@ entityParameters[ art ]
1287
1403
  entityParameterDef[ $art ]
1288
1404
  )*
1289
1405
  )?
1290
- ')'
1406
+ ')' { this.setDictEndLocation( $art.params ); }
1291
1407
  ;
1292
1408
 
1293
1409
  entityParameterDef[ outer ] locals[ art, annos = [] ]
@@ -1300,7 +1416,7 @@ entityParameterDef[ outer ] locals[ art, annos = [] ]
1300
1416
  this.docComment( $annos ); }
1301
1417
  annotationAssignment_fix[ $annos ]*
1302
1418
  typeSpec[ $art ]
1303
- ( DEFAULT expr=expression { $art.default = $expr.expr; } )?
1419
+ defaultValue[ $art ]?
1304
1420
  { this.docComment( $annos ); }
1305
1421
  annotationAssignment_ll1[ $annos ]*
1306
1422
  ;
@@ -1316,17 +1432,11 @@ nullability[ art ]
1316
1432
 
1317
1433
  elementProperties[ elem ]
1318
1434
  :
1319
- nullability[$elem]
1320
- (
1321
- DEFAULT expr=expression
1322
- { $elem.default = $expr.expr; }
1323
- )?
1435
+ nullability[ $elem ]
1436
+ defaultValue[ $elem ]?
1324
1437
  |
1325
- (
1326
- DEFAULT expr=expression
1327
- { $elem.default = $expr.expr; }
1328
- )
1329
- nullability[$elem]?
1438
+ defaultValue[ $elem ]
1439
+ nullability[ $elem ]?
1330
1440
  |
1331
1441
  eq='='
1332
1442
  { this.notSupportedYet( 'Calculated fields are not supported yet', $eq ); }
@@ -1377,10 +1487,10 @@ typeSpec[ art ] // for params
1377
1487
  // TODO: no LOCALIZED ?
1378
1488
  | typeRefOptArgs[ $art ]
1379
1489
  nullability[ $art ]?
1380
- ( ENUM '{'
1381
- { $art.enum = Object.create(null); }
1382
- enumSymbolDef[ $art ]*
1383
- '}'
1490
+ (
1491
+ ENUM '{' { $art.enum = this.createDict(); }
1492
+ enumSymbolDef[ $art ]*
1493
+ '}' { this.setDictEndLocation( $art.enum ); }
1384
1494
  )?
1385
1495
  )
1386
1496
  ;
@@ -1390,7 +1500,7 @@ returnTypeSpec[ art, annos ]
1390
1500
  :
1391
1501
  ret=RETURNS { $art.returns = { location: this.tokenLocation( $ret ), kind: 'param' }; }
1392
1502
  // #ATN: typeSimple can start with ARRAY or TYPE
1393
- ( typeStruct[ $art.returns ]
1503
+ ( typeStruct[ $art.returns ]
1394
1504
  nullability[ $art.returns ]?
1395
1505
  | typeArray[ $art.returns ] // nullability is set in typeArray
1396
1506
  | typeTypeOf[ $art.returns ]
@@ -1398,11 +1508,12 @@ returnTypeSpec[ art, annos ]
1398
1508
  // TODO: no LOCALIZED ?
1399
1509
  | typeRefOptArgs[ $art.returns ]
1400
1510
  nullability[ $art.returns ]?
1401
- ( ENUM '{'
1402
- { $art.returns.enum = Object.create(null); }
1403
- enumSymbolDef[ $art.returns ]*
1404
- '}'
1405
- | misplacedAnnotations[ $annos, 'syntax-anno-after-params' ]
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' ]
1406
1517
  )?
1407
1518
  )
1408
1519
 
@@ -1443,7 +1554,7 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
1443
1554
  { $art.items = { location: this.tokenLocation( $many ) };}
1444
1555
  )
1445
1556
  // #ATN: typeRefOptArgs can start with TYPE
1446
- ( typeStruct[ $art.items ]
1557
+ ( typeStruct[ $art.items ]
1447
1558
  nullability[ $art.items ]?
1448
1559
  optionalSemi
1449
1560
  | typeTypeOf[ $art.items ]
@@ -1455,21 +1566,24 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
1455
1566
  nullability[ $art.items ]?
1456
1567
  { this.docComment( $annos ); }
1457
1568
  annotationAssignment_ll1[ $annos ]*
1458
- ( ENUM '{'
1459
- { $art.items.enum = Object.create(null); }
1460
- enumSymbolDef[ $art.items ]*
1461
- '}'
1462
- optionalSemi
1463
- | requiredSemi
1569
+ (
1570
+ ENUM '{' { $art.items.enum = this.createDict(); }
1571
+ enumSymbolDef[ $art.items ]*
1572
+ '}' { this.setDictEndLocation( $art.items.enum ); }
1573
+ optionalSemi
1574
+ |
1575
+ requiredSemi
1464
1576
  )
1465
1577
  )
1466
1578
  |
1467
1579
  typeTypeOf[ $art ]
1580
+ defaultValue[ $art ]?
1468
1581
  { this.docComment( $annos ); }
1469
1582
  annotationAssignment_ll1[ $annos ]* requiredSemi
1470
1583
  |
1471
1584
  l=LOCALIZED { $art.localized = this.valueWithTokenLocation( true, $l ); }
1472
1585
  typeRefOptArgs[ $art ]
1586
+ defaultValue[ $art ]?
1473
1587
  { this.docComment( $annos ); }
1474
1588
  annotationAssignment_ll1[ $annos ]*
1475
1589
  requiredSemi
@@ -1500,12 +1614,19 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
1500
1614
  ')'
1501
1615
  { this.docComment( $annos ); }
1502
1616
  annotationAssignment_ll1[ $annos ]*
1503
- ( ENUM '{'
1504
- { $art.enum = Object.create(null); }
1505
- enumSymbolDef[ $art ]*
1506
- '}'
1507
- optionalSemi
1508
- | requiredSemi
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
1509
1630
  )
1510
1631
  |
1511
1632
  ':' // with element, e.g. `type T : E:elem enum { ... }`
@@ -1513,22 +1634,36 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
1513
1634
  simplePath[ $art.type, 'ref']
1514
1635
  { this.docComment( $annos ); }
1515
1636
  annotationAssignment_ll1[ $annos ]*
1516
- ( ENUM '{'
1517
- { $art.enum = Object.create(null); }
1518
- enumSymbolDef[ $art ]*
1519
- '}'
1520
- optionalSemi
1521
- | requiredSemi
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
1522
1650
  )
1523
1651
  |
1524
1652
  { this.docComment( $annos ); }
1525
1653
  annotationAssignment_ll1[ $annos ]*
1526
- ( ENUM '{'
1527
- { $art.enum = Object.create(null); }
1528
- enumSymbolDef[ $art ]*
1529
- '}'
1530
- optionalSemi
1531
- | requiredSemi
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
1532
1667
  )
1533
1668
  |
1534
1669
  // TODO: complain if used in anno def?
@@ -1545,15 +1680,17 @@ typeSpecSemi[ art, annos ] // with 'includes', for type and annotation defs
1545
1680
  typeStruct[ art, attachLoc = false ]
1546
1681
  @after { if ($attachLoc) this.attachLocation($art); }
1547
1682
  :
1548
- { $art.elements = Object.create(null); } // we allow empty structures
1549
- '{' elementDef[ $art ]* '}'
1683
+ '{' { $art.elements = this.createDict(); }
1684
+ elementDef[ $art ]*
1685
+ '}' { this.setDictEndLocation( $art.elements ); }
1550
1686
  ;
1551
1687
 
1552
1688
  typeCompoStruct[ art ]
1553
1689
  @after { this.attachLocation($art); }
1554
1690
  :
1555
- { $art.elements = Object.create(null); } // we allow empty structures
1556
- COMPOSITIONofBRACE elementDef[ $art ]* '}'
1691
+ COMPOSITIONofBRACE { $art.elements = this.createDict(); }
1692
+ elementDef[ $art ]*
1693
+ '}' { this.setDictEndLocation( $art.elements ); }
1557
1694
  ;
1558
1695
 
1559
1696
  typeArray[ art ]
@@ -1572,10 +1709,10 @@ typeArray[ art ]
1572
1709
  nullability[ $art.items ]?
1573
1710
  | typeRefOptArgs[ $art.items ]
1574
1711
  nullability[ $art.items ]?
1575
- ( ENUM '{'
1576
- { $art.items.enum = Object.create(null); }
1577
- enumSymbolDef[ $art.items ]*
1578
- '}'
1712
+ (
1713
+ ENUM '{' { $art.items.enum = this.createDict(); }
1714
+ enumSymbolDef[ $art.items ]*
1715
+ '}' { this.setDictEndLocation( $art.items.enum ); }
1579
1716
  )?
1580
1717
  )
1581
1718
  ;
@@ -1603,7 +1740,7 @@ typeAssociationBase[ art, handleTypeCompo ] // including Composition
1603
1740
  typeAssociationCont[ art ]
1604
1741
  :
1605
1742
  (
1606
- '{'
1743
+ '{' { $art.foreignKeys = this.createDict(); }
1607
1744
  { this.addDef( $art, 'foreignKeys' ); }
1608
1745
  (
1609
1746
  foreignKey[ $art ]
@@ -1611,7 +1748,7 @@ typeAssociationCont[ art ]
1611
1748
  foreignKey[ $art ]
1612
1749
  )*
1613
1750
  )?
1614
- '}'
1751
+ '}' { this.setDictEndLocation( $art.foreignKeys ); }
1615
1752
  |
1616
1753
  ON cond=condition
1617
1754
  { $art.on=$cond.cond; }
@@ -1622,7 +1759,7 @@ typeAssociationElementCont[ art, annos ] // including Composition
1622
1759
  // optional NULL / NOT NULL for managed association only
1623
1760
  :
1624
1761
  (
1625
- '{'
1762
+ '{' { $art.foreignKeys = this.createDict(); }
1626
1763
  { this.addDef( $art, 'foreignKeys' ); }
1627
1764
  (
1628
1765
  foreignKey[ $art ]
@@ -1630,7 +1767,7 @@ typeAssociationElementCont[ art, annos ] // including Composition
1630
1767
  foreignKey[ $art ]
1631
1768
  )*
1632
1769
  )?
1633
- '}'
1770
+ '}' { this.setDictEndLocation( $art.foreignKeys ); }
1634
1771
  nullability[ $art ]?
1635
1772
  |
1636
1773
  ON cond=condition
@@ -1770,14 +1907,26 @@ orderByClause[ inQuery ] returns [ query ]
1770
1907
  ( ',' obn=orderBySpec { $query.orderBy.push( $obn.ob ); } )*
1771
1908
  ;
1772
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
+
1773
1920
  overOrderByClause returns [ expr ]
1921
+ @after { this.attachLocation( $expr ); }
1774
1922
  :
1775
- o=ORDER b=BY { $expr = { op: this.valueWithTokenLocation( 'orderBy', $o, $b ) , args: [] }}
1923
+ o=ORDER b=BY { $expr = { op: this.valueWithTokenLocation( 'overOrderBy', $o, $b ) , args: [] }}
1776
1924
  ob1=orderBySpec { $expr.args.push( $ob1.ob ); }
1777
1925
  ( ',' obn=orderBySpec { $expr.args.push( $obn.ob ); } )*
1778
1926
  ;
1779
1927
 
1780
1928
  partitionByClause returns [ expr ]
1929
+ @after { this.attachLocation( $expr ); }
1781
1930
  :
1782
1931
  p=PARTITION b=BY { $expr = { op: this.valueWithTokenLocation( 'partitionBy', $p, $b ) , args: [] }}
1783
1932
  e1=expression { $expr.args.push( $e1.expr ); }
@@ -1785,12 +1934,14 @@ partitionByClause returns [ expr ]
1785
1934
  ;
1786
1935
 
1787
1936
  windowFrameClause returns [ wf ]
1937
+ @after { this.attachLocation( $wf ); }
1788
1938
  :
1789
1939
  r=ROWS { $wf = { op: this.valueWithTokenLocation( 'rows', $r ) , args: [] }}
1790
1940
  wfe=windowFrameExtentSpec { $wf.args.push( $wfe.wfe ); }
1791
1941
  ;
1792
1942
 
1793
1943
  windowFrameExtentSpec returns[ wfe ]
1944
+ @after { this.attachLocation( $wfe ); }
1794
1945
  :
1795
1946
  { $wfe = {} }
1796
1947
  windowFrameStartSpec [ $wfe ]
@@ -1820,6 +1971,7 @@ windowFrameBoundSpec returns [ wfb ]
1820
1971
  ;
1821
1972
 
1822
1973
  windowFrameStartSpec [ wf ]
1974
+ @after { this.attachLocation( $wf ); }
1823
1975
  :
1824
1976
  u=UNBOUNDED p=PRECEDING
1825
1977
  {
@@ -1832,7 +1984,7 @@ windowFrameStartSpec [ wf ]
1832
1984
  $wf.op = this.valueWithTokenLocation( 'preceding', $p );
1833
1985
  $wf.args = [ this.numberLiteral( $n ) ];
1834
1986
  }
1835
- |
1987
+ |
1836
1988
  c=CURRENT r=ROW
1837
1989
  {
1838
1990
  $wf.op = this.valueWithTokenLocation( 'currentRow', $c, $r );
@@ -1841,7 +1993,7 @@ windowFrameStartSpec [ wf ]
1841
1993
  ;
1842
1994
 
1843
1995
  overClause returns [ over ]
1844
- @after { this.attachLocation($over); }
1996
+ @after { this.attachLocation( $over ); }
1845
1997
  :
1846
1998
  o=OVER { $over = { op: this.valueWithTokenLocation( 'over', $o ) , args: [] } }
1847
1999
  '('
@@ -1895,9 +2047,10 @@ queryPrimary returns[ query = {} ]
1895
2047
  (
1896
2048
  FROM querySource[ $query ]
1897
2049
  (
1898
- mixin=MIXIN '{'
2050
+ mixin=MIXIN '{' { $query.mixin = this.createDict(); }
1899
2051
  mixinElementDef[ $query ]*
1900
- '}' INTO
2052
+ '}' { this.setDictEndLocation( $query.mixin ); }
2053
+ INTO
1901
2054
  )?
1902
2055
  ( ad=( ALL | DISTINCT ) // TODO: or directly after SELECT ?
1903
2056
  { $query.quantifier = this.valueWithTokenLocation( $ad.text.toLowerCase(), $ad ); }
@@ -2351,6 +2504,7 @@ fromArguments[ pathStep ]
2351
2504
  pathArguments[ pathStep, considerSpecial ]
2352
2505
  @after{ /* #ATN 1 */ }
2353
2506
  :
2507
+ { this.excludeExpected([ 'ORDER' ]); }
2354
2508
  paren='('
2355
2509
  { this.prepareGenericKeywords( $considerSpecial ); }
2356
2510
  // ATN, LL2: Identifier can start both named arguments and the positional.
@@ -2372,6 +2526,13 @@ pathArguments[ pathStep, considerSpecial ]
2372
2526
  ( ',' { if (this.isStraightBefore(')')) break; } // allow ',' before ')'
2373
2527
  funcExpression[ $pathStep, $considerSpecial ]
2374
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
+ )?
2375
2536
  |
2376
2537
  a=ALL { $pathStep.quantifier = this.valueWithTokenLocation( 'all', $a ); }
2377
2538
  e1=expression { $pathStep.args = [ $e1.expr ]; }
@@ -2679,6 +2840,7 @@ ident[ category ] returns[ id ]
2679
2840
  | ASSOCIATION
2680
2841
  | BETWEEN
2681
2842
  | BOTH
2843
+ | COLUMNS
2682
2844
  | COMPOSITION
2683
2845
  | CONTEXT
2684
2846
  | CROSS
@@ -2686,8 +2848,10 @@ ident[ category ] returns[ id ]
2686
2848
  | DAY
2687
2849
  | DEFAULT
2688
2850
  | DEFINE
2851
+ | DEFINITIONS
2689
2852
  | DESC
2690
2853
  | ELEMENT
2854
+ | ELEMENTS
2691
2855
  | ELSE
2692
2856
  | END
2693
2857
  | ENTITY
@@ -2883,6 +3047,7 @@ ASPECT : [aA][sS][pP][eE][cC][tT] ;
2883
3047
  ASSOCIATION : [aA][sS][sS][oO][cC][iI][aA][tT][iI][oO][nN] ;
2884
3048
  BETWEEN : [bB][eE][tT][wW][eE][eE][nN] ;
2885
3049
  BOTH : [bB][oO][tT][hH] ;
3050
+ COLUMNS : [cC][oO][lL][uU][mM][nN][sS];
2886
3051
  COMPOSITION : [cC][oO][mM][pP][oO][sS][iI][tT][iI][oO][nN] ;
2887
3052
  CONTEXT : [cC][oO][nN][tT][eE][xX][tT] ;
2888
3053
  CROSS : [cC][rR][oO][sS][sS] ;
@@ -2890,8 +3055,10 @@ CURRENT : [cC][uU][rR][rR][eE][nN][tT] ;
2890
3055
  DAY : [dD][aA][yY] ;
2891
3056
  DEFAULT : [dD][eE][fF][aA][uU][lL][tT] ;
2892
3057
  DEFINE : [dD][eE][fF][iI][nN][eE] ;
3058
+ DEFINITIONS : [dD][eE][fF][iI][nN][iI][tT][iI][oO][nN][sS] ;
2893
3059
  DESC : [dD][eE][sS][cC] ;
2894
3060
  ELEMENT : [eE][lL][eE][mM][eE][nN][tT] ;
3061
+ ELEMENTS : [eE][lL][eE][mM][eE][nN][tT][sS] ;
2895
3062
  ELSE : [eE][lL][sS][eE] ;
2896
3063
  END : [eE][nN][dD] ;
2897
3064
  ENTITY : [eE][nN][tT][iI][tT][yY] ;