expressir 2.1.30 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/docs.yml +99 -0
  3. data/.github/workflows/links.yml +100 -0
  4. data/.github/workflows/rake.yml +4 -0
  5. data/.github/workflows/release.yml +11 -0
  6. data/.github/workflows/validate_schemas.yml +1 -1
  7. data/.gitignore +3 -0
  8. data/.rubocop.yml +1 -1
  9. data/.rubocop_todo.yml +267 -53
  10. data/Gemfile +2 -1
  11. data/README.adoc +993 -55
  12. data/docs/Gemfile +12 -0
  13. data/docs/_config.yml +141 -0
  14. data/docs/_guides/changes/changes-format.adoc +778 -0
  15. data/docs/_guides/changes/importing-eengine.adoc +898 -0
  16. data/docs/_guides/changes/index.adoc +396 -0
  17. data/docs/_guides/changes/programmatic-usage.adoc +1038 -0
  18. data/docs/_guides/changes/validating-changes.adoc +681 -0
  19. data/docs/_guides/cli/benchmark-performance.adoc +834 -0
  20. data/docs/_guides/cli/coverage-analysis.adoc +921 -0
  21. data/docs/_guides/cli/format-schemas.adoc +547 -0
  22. data/docs/_guides/cli/index.adoc +8 -0
  23. data/docs/_guides/cli/managing-changes.adoc +927 -0
  24. data/docs/_guides/cli/validate-ascii.adoc +645 -0
  25. data/docs/_guides/cli/validate-schemas.adoc +534 -0
  26. data/docs/_guides/formatter/formatter-architecture.adoc +401 -0
  27. data/docs/_guides/index.adoc +165 -0
  28. data/docs/_guides/ler/creating-packages.adoc +664 -0
  29. data/docs/_guides/ler/index.adoc +305 -0
  30. data/docs/_guides/ler/loading-packages.adoc +707 -0
  31. data/docs/_guides/ler/package-formats.adoc +748 -0
  32. data/docs/_guides/ler/querying-packages.adoc +826 -0
  33. data/docs/_guides/ler/validating-packages.adoc +750 -0
  34. data/docs/_guides/liquid/basic-templates.adoc +813 -0
  35. data/docs/_guides/liquid/documentation-generation.adoc +1042 -0
  36. data/docs/_guides/liquid/drops-reference.adoc +829 -0
  37. data/docs/_guides/liquid/filters-and-tags.adoc +912 -0
  38. data/docs/_guides/liquid/index.adoc +468 -0
  39. data/docs/_guides/manifests/creating-manifests.adoc +483 -0
  40. data/docs/_guides/manifests/index.adoc +307 -0
  41. data/docs/_guides/manifests/resolving-manifests.adoc +557 -0
  42. data/docs/_guides/manifests/validating-manifests.adoc +713 -0
  43. data/docs/_guides/ruby-api/formatting-schemas.adoc +605 -0
  44. data/docs/_guides/ruby-api/index.adoc +257 -0
  45. data/docs/_guides/ruby-api/parsing-files.adoc +421 -0
  46. data/docs/_guides/ruby-api/search-engine.adoc +609 -0
  47. data/docs/_guides/ruby-api/working-with-repository.adoc +577 -0
  48. data/docs/_pages/data-model.adoc +665 -0
  49. data/docs/_pages/express-language.adoc +506 -0
  50. data/docs/_pages/getting-started.adoc +414 -0
  51. data/docs/_pages/index.adoc +116 -0
  52. data/docs/_pages/introduction.adoc +256 -0
  53. data/docs/_pages/ler-packages.adoc +837 -0
  54. data/docs/_pages/parsers.adoc +709 -0
  55. data/docs/_pages/schema-manifests.adoc +431 -0
  56. data/docs/_references/index.adoc +228 -0
  57. data/docs/_tutorials/creating-ler-package.adoc +735 -0
  58. data/docs/_tutorials/documentation-coverage.adoc +795 -0
  59. data/docs/_tutorials/index.adoc +221 -0
  60. data/docs/_tutorials/liquid-templates.adoc +806 -0
  61. data/docs/_tutorials/parsing-your-first-schema.adoc +522 -0
  62. data/docs/_tutorials/querying-schemas.adoc +751 -0
  63. data/docs/_tutorials/working-with-multiple-schemas.adoc +676 -0
  64. data/docs/index.adoc +242 -0
  65. data/docs/lychee.toml +87 -0
  66. data/examples/demo_ler_usage.sh +86 -0
  67. data/examples/ler/README.md +111 -0
  68. data/examples/ler/simple_example.ler +0 -0
  69. data/examples/ler/simple_schema.exp +33 -0
  70. data/examples/ler_build.rb +75 -0
  71. data/examples/ler_cli.rb +79 -0
  72. data/examples/ler_demo_complete.rb +276 -0
  73. data/examples/ler_query.rb +91 -0
  74. data/examples/ler_query_examples.rb +305 -0
  75. data/examples/ler_stats.rb +81 -0
  76. data/examples/phase3_demo.rb +159 -0
  77. data/examples/query_demo_simple.rb +131 -0
  78. data/expressir.gemspec +4 -2
  79. data/lib/expressir/benchmark.rb +6 -6
  80. data/lib/expressir/cli.rb +21 -4
  81. data/lib/expressir/commands/format.rb +28 -0
  82. data/lib/expressir/commands/manifest.rb +427 -0
  83. data/lib/expressir/commands/package.rb +1274 -0
  84. data/lib/expressir/commands/validate.rb +70 -37
  85. data/lib/expressir/commands/validate_ascii.rb +607 -0
  86. data/lib/expressir/commands/validate_load.rb +88 -0
  87. data/lib/expressir/coverage.rb +15 -11
  88. data/lib/expressir/express/builder.rb +350 -0
  89. data/lib/expressir/express/builders/attribute_decl_builder.rb +38 -0
  90. data/lib/expressir/express/builders/built_in_builder.rb +88 -0
  91. data/lib/expressir/express/builders/constant_builder.rb +115 -0
  92. data/lib/expressir/express/builders/declaration_builder.rb +24 -0
  93. data/lib/expressir/express/builders/derive_clause_builder.rb +16 -0
  94. data/lib/expressir/express/builders/derived_attr_builder.rb +28 -0
  95. data/lib/expressir/express/builders/domain_rule_builder.rb +21 -0
  96. data/lib/expressir/express/builders/entity_decl_builder.rb +108 -0
  97. data/lib/expressir/express/builders/explicit_attr_builder.rb +52 -0
  98. data/lib/expressir/express/builders/expression_builder.rb +453 -0
  99. data/lib/expressir/express/builders/function_decl_builder.rb +84 -0
  100. data/lib/expressir/express/builders/helpers.rb +148 -0
  101. data/lib/expressir/express/builders/interface_builder.rb +171 -0
  102. data/lib/expressir/express/builders/inverse_attr_builder.rb +45 -0
  103. data/lib/expressir/express/builders/inverse_attr_type_builder.rb +36 -0
  104. data/lib/expressir/express/builders/inverse_clause_builder.rb +16 -0
  105. data/lib/expressir/express/builders/literal_builder.rb +107 -0
  106. data/lib/expressir/express/builders/procedure_decl_builder.rb +80 -0
  107. data/lib/expressir/express/builders/qualifier_builder.rb +128 -0
  108. data/lib/expressir/express/builders/reference_builder.rb +27 -0
  109. data/lib/expressir/express/builders/rule_decl_builder.rb +95 -0
  110. data/lib/expressir/express/builders/schema_body_decl_builder.rb +22 -0
  111. data/lib/expressir/express/builders/schema_decl_builder.rb +62 -0
  112. data/lib/expressir/express/builders/schema_version_builder.rb +40 -0
  113. data/lib/expressir/express/builders/simple_id_builder.rb +26 -0
  114. data/lib/expressir/express/builders/statement_builder.rb +250 -0
  115. data/lib/expressir/express/builders/subtype_constraint_builder.rb +188 -0
  116. data/lib/expressir/express/builders/syntax_builder.rb +19 -0
  117. data/lib/expressir/express/builders/token_builder.rb +15 -0
  118. data/lib/expressir/express/builders/type_builder.rb +264 -0
  119. data/lib/expressir/express/builders/type_decl_builder.rb +32 -0
  120. data/lib/expressir/express/builders/unique_clause_builder.rb +22 -0
  121. data/lib/expressir/express/builders/unique_rule_builder.rb +36 -0
  122. data/lib/expressir/express/builders/where_clause_builder.rb +22 -0
  123. data/lib/expressir/express/builders.rb +43 -0
  124. data/lib/expressir/express/error.rb +18 -2
  125. data/lib/expressir/express/formatter.rb +23 -1509
  126. data/lib/expressir/express/formatters/data_types_formatter.rb +317 -0
  127. data/lib/expressir/express/formatters/declarations_formatter.rb +689 -0
  128. data/lib/expressir/express/formatters/expressions_formatter.rb +160 -0
  129. data/lib/expressir/express/formatters/literals_formatter.rb +46 -0
  130. data/lib/expressir/express/formatters/references_formatter.rb +42 -0
  131. data/lib/expressir/express/formatters/remark_formatter.rb +296 -0
  132. data/lib/expressir/express/formatters/remark_item_formatter.rb +25 -0
  133. data/lib/expressir/express/formatters/statements_formatter.rb +224 -0
  134. data/lib/expressir/express/formatters/supertype_expressions_formatter.rb +48 -0
  135. data/lib/expressir/express/parser.rb +155 -7
  136. data/lib/expressir/express/pretty_formatter.rb +624 -0
  137. data/lib/expressir/express/remark_attacher.rb +1155 -0
  138. data/lib/expressir/express/resolve_references_model_visitor.rb +1 -0
  139. data/lib/expressir/express/streaming_builder.rb +467 -0
  140. data/lib/expressir/express/transformer/remark_handling.rb +196 -0
  141. data/lib/expressir/manifest/resolver.rb +213 -0
  142. data/lib/expressir/manifest/validator.rb +195 -0
  143. data/lib/expressir/model/declarations/entity.rb +6 -0
  144. data/lib/expressir/model/dependency_resolver.rb +270 -0
  145. data/lib/expressir/model/identifier.rb +1 -1
  146. data/lib/expressir/model/indexes/entity_index.rb +103 -0
  147. data/lib/expressir/model/indexes/reference_index.rb +148 -0
  148. data/lib/expressir/model/indexes/type_index.rb +149 -0
  149. data/lib/expressir/model/interface_validator.rb +384 -0
  150. data/lib/expressir/model/model_element.rb +30 -2
  151. data/lib/expressir/model/remark_info.rb +51 -0
  152. data/lib/expressir/model/repository.rb +400 -5
  153. data/lib/expressir/model/repository_validator.rb +295 -0
  154. data/lib/expressir/model/search_engine.rb +574 -0
  155. data/lib/expressir/model.rb +4 -94
  156. data/lib/expressir/package/builder.rb +200 -0
  157. data/lib/expressir/package/metadata.rb +81 -0
  158. data/lib/expressir/package/reader.rb +165 -0
  159. data/lib/expressir/schema_manifest.rb +11 -1
  160. data/lib/expressir/version.rb +1 -1
  161. data/lib/expressir.rb +20 -3
  162. metadata +168 -9
  163. data/docs/benchmarking.adoc +0 -107
  164. data/docs/liquid_drops.adoc +0 -1547
  165. data/lib/expressir/express/visitor.rb +0 -2815
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Express
5
+ module Builders
6
+ # Builds derived_attr nodes.
7
+ class DerivedAttrBuilder
8
+ def call(ast_data)
9
+ attr_decl_data = ast_data[:attribute_decl]
10
+ attr = if attr_decl_data.is_a?(Hash)
11
+ Builder.build({ attribute_decl: attr_decl_data })
12
+ end
13
+ type = Builder.build_optional(ast_data[:parameter_type])
14
+ expression = Builder.build_optional(ast_data[:expression])
15
+
16
+ Expressir::Model::Declarations::DerivedAttribute.new(
17
+ id: attr&.id,
18
+ supertype_attribute: attr&.supertype_attribute,
19
+ type: type,
20
+ expression: expression,
21
+ )
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ Builder.register(:derived_attr, Expressir::Express::Builders::DerivedAttrBuilder.new)
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Express
5
+ module Builders
6
+ # Builds domain_rule nodes.
7
+ class DomainRuleBuilder
8
+ def call(ast_data)
9
+ inner_data = ast_data[:domain_rule] || ast_data
10
+
11
+ id = Builder.build_optional(inner_data[:rule_label_id])
12
+ expression = Builder.build_optional(inner_data[:expression])
13
+ Expressir::Model::Declarations::WhereRule.new(id: id,
14
+ expression: expression)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ Builder.register(:domain_rule, Expressir::Express::Builders::DomainRuleBuilder.new)
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "helpers"
4
+
5
+ module Expressir
6
+ module Express
7
+ module Builders
8
+ # Builds entity_decl nodes into Entity objects.
9
+ class EntityDeclBuilder
10
+ include Helpers
11
+
12
+ def call(ast_data)
13
+ entity_head = ast_data[:entity_head]
14
+ entity_body = ast_data[:entity_body]
15
+
16
+ return nil unless entity_head
17
+
18
+ id = Builder.build_optional(entity_head[:entity_id])
19
+ subsuper = entity_head[:subsuper]
20
+
21
+ abstract = false
22
+ supertype_expression = nil
23
+ subtype_of = []
24
+
25
+ if subsuper.is_a?(Hash)
26
+ supertype_constraint = subsuper[:supertype_constraint]
27
+ subtype_declaration = subsuper[:subtype_declaration]
28
+
29
+ if supertype_constraint.is_a?(Hash)
30
+ abstract_entity = supertype_constraint[:abstract_entity_declaration]
31
+ abstract_supertype = supertype_constraint[:abstract_supertype_declaration]
32
+ supertype_rule = supertype_constraint[:supertype_rule]
33
+
34
+ abstract = !abstract_entity.nil? || !abstract_supertype.nil?
35
+
36
+ if supertype_rule.is_a?(Hash)
37
+ supertype_expression = Builder.build({ supertype_rule: supertype_rule })
38
+ elsif abstract_supertype.is_a?(Hash) && abstract_supertype[:subtype_constraint]
39
+ subtype_constraint = abstract_supertype[:subtype_constraint]
40
+ if subtype_constraint[:supertype_expression]
41
+ supertype_expression = Builder.build({ supertype_expression: subtype_constraint[:supertype_expression] })
42
+ elsif subtype_constraint[:list_of_entity_ref]
43
+ entity_refs = Builder.build_children([subtype_constraint[:list_of_entity_ref][:entity_ref]].flatten.compact)
44
+ supertype_expression = entity_refs.first if entity_refs.length == 1
45
+ end
46
+ end
47
+ end
48
+
49
+ if subtype_declaration.is_a?(Hash)
50
+ list_ref = subtype_declaration[:list_of_entity_ref]
51
+ if list_ref.is_a?(Hash)
52
+ entity_ref_data = list_ref[:entity_ref]
53
+ if entity_ref_data
54
+ subtype_of = Builder.build_children([{ entity_ref: entity_ref_data }].flatten.compact)
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ attributes = []
61
+ unique_rules = []
62
+ where_rules = []
63
+
64
+ if entity_body.is_a?(Hash)
65
+ if entity_body[:explicit_attr]
66
+ explicit_attrs = Builder.build_children(entity_body[:explicit_attr])
67
+ attributes.concat(explicit_attrs.flatten.compact)
68
+ end
69
+
70
+ if entity_body[:derive_clause]
71
+ derived = Builder.build({ derive_clause: entity_body[:derive_clause] })
72
+ attributes.concat([derived].flatten.compact) if derived
73
+ end
74
+
75
+ if entity_body[:inverse_clause]
76
+ inverse = Builder.build({ inverse_clause: entity_body[:inverse_clause] })
77
+ attributes.concat([inverse].flatten.compact) if inverse
78
+ end
79
+
80
+ if entity_body[:unique_clause]
81
+ unique_rules = Builder.build({ unique_clause: entity_body[:unique_clause] })
82
+ end
83
+ unique_rules ||= []
84
+
85
+ if entity_body[:where_clause]
86
+ where_rules = Builder.build({ where_clause: entity_body[:where_clause] })
87
+ end
88
+ where_rules ||= []
89
+ end
90
+
91
+ entity_params = {
92
+ id: id,
93
+ supertype_expression: supertype_expression,
94
+ subtype_of: subtype_of,
95
+ attributes: attributes,
96
+ unique_rules: [unique_rules].flatten.compact,
97
+ where_rules: [where_rules].flatten.compact,
98
+ }
99
+ entity_params[:abstract] = true if abstract
100
+
101
+ Expressir::Model::Declarations::Entity.new(**entity_params)
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+
108
+ Builder.register(:entity_decl, Expressir::Express::Builders::EntityDeclBuilder.new)
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "helpers"
4
+
5
+ module Expressir
6
+ module Express
7
+ module Builders
8
+ # Builds explicit_attr nodes.
9
+ class ExplicitAttrBuilder
10
+ include Helpers
11
+
12
+ def call(ast_data)
13
+ list_data = ast_data[:list_of_attribute_decl]
14
+ attr_decl_data = if list_data.is_a?(Hash)
15
+ list_data[:attribute_decl]
16
+ elsif list_data.is_a?(Array)
17
+ list_data.filter_map do |item|
18
+ item[:attribute_decl] if item.is_a?(Hash)
19
+ end
20
+ else
21
+ ast_data[:attribute_decl]
22
+ end
23
+ attr_decls = [attr_decl_data].flatten.compact
24
+ optional = !ast_data[:t_optional].nil?
25
+ type = Builder.build_optional(ast_data[:parameter_type])
26
+
27
+ attrs = attr_decls.map do |attr_data|
28
+ Builder.build({ attribute_decl: attr_data })
29
+ end
30
+
31
+ attrs.map do |attr|
32
+ next attr unless attr.is_a?(Expressir::Model::Declarations::Attribute)
33
+
34
+ attr_params = {
35
+ id: attr.id,
36
+ kind: Expressir::Model::Declarations::Attribute::EXPLICIT,
37
+ supertype_attribute: attr.supertype_attribute,
38
+ type: type,
39
+ }
40
+ attr_params[:optional] = true if optional
41
+ # Preserve source information from the intermediate object
42
+ attr_params[:source] = attr.source if attr.source
43
+ attr_params[:source_offset] = attr.source_offset if attr.source_offset
44
+ Expressir::Model::Declarations::Attribute.new(**attr_params)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ Builder.register(:explicit_attr, Expressir::Express::Builders::ExplicitAttrBuilder.new)
@@ -0,0 +1,453 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "helpers"
4
+
5
+ module Expressir
6
+ module Express
7
+ module Builders
8
+ # Builds expression nodes (binary, unary, query, interval, etc.).
9
+ class ExpressionBuilder
10
+ include Helpers
11
+
12
+ # Expression
13
+ def build_expression(ast_data)
14
+ left = if ast_data[:simple_expression]
15
+ Builder.build_simple_expression(ast_data[:simple_expression])
16
+ elsif ast_data[:logical_expression]
17
+ Builder.build_simple_expression(ast_data[:logical_expression][:simple_expression])
18
+ end
19
+
20
+ if ast_data[:rel_op_extended] && ast_data[:rhs]
21
+ op = build_rel_op_extended(ast_data[:rel_op_extended])
22
+ right = Builder.build(ast_data[:rhs])
23
+ Expressir::Model::Expressions::BinaryExpression.new(
24
+ operator: op,
25
+ operand1: left,
26
+ operand2: right,
27
+ )
28
+ else
29
+ left
30
+ end
31
+ end
32
+
33
+ def build_logical_expression(ast_data)
34
+ Builder.build_simple_expression(ast_data[:simple_expression])
35
+ end
36
+
37
+ def build_numeric_expression(ast_data)
38
+ Builder.build_simple_expression(ast_data[:simple_expression])
39
+ end
40
+
41
+ # Simple expression (addition/subtraction chain)
42
+ def build_simple_expression(ast_data)
43
+ return nil unless ast_data[:term]
44
+
45
+ term = Builder.build_term(ast_data[:term])
46
+ rhs = ast_data[:rhs] || []
47
+
48
+ return term if rhs.empty?
49
+
50
+ operands = [term]
51
+ operators = []
52
+
53
+ rhs.each do |r|
54
+ item = r[:item] || r
55
+ op_data = item[:operator]
56
+ operators << extract_operator(op_data[:add_like_op]) if op_data
57
+ if item[:term]
58
+ operands << Builder.build_term(item[:term])
59
+ end
60
+ end
61
+
62
+ build_binary_expression(operands, operators)
63
+ end
64
+
65
+ # Term (multiplication/division chain)
66
+ def build_term(ast_data)
67
+ return nil unless ast_data[:factor]
68
+
69
+ factor = Builder.build_factor(ast_data[:factor])
70
+ rhs = ast_data[:rhs] || []
71
+
72
+ return factor if rhs.empty?
73
+
74
+ operands = [factor]
75
+ operators = []
76
+
77
+ rhs.each do |r|
78
+ item = r[:item] || r
79
+ op_data = item[:multiplication_like_op] || item[:mul_like_op]
80
+ operators << extract_operator(op_data) if op_data
81
+ operands << Builder.build_factor(item[:factor]) if item[:factor]
82
+ end
83
+
84
+ build_binary_expression(operands, operators)
85
+ end
86
+
87
+ def build_factor(ast_data)
88
+ return nil unless ast_data[:simple_factor]
89
+
90
+ Builder.build_simple_factor(ast_data[:simple_factor])
91
+ end
92
+
93
+ def build_simple_factor(ast_data)
94
+ return nil unless ast_data
95
+
96
+ if ast_data[:primary]
97
+ Builder.build_primary(ast_data[:primary])
98
+ elsif ast_data[:simple_factor_expression]
99
+ Builder.build_node(:simple_factor_expression,
100
+ ast_data[:simple_factor_expression])
101
+ elsif ast_data[:simple_factor_unary_expression]
102
+ Builder.build_node(:simple_factor_unary_expression,
103
+ ast_data[:simple_factor_unary_expression])
104
+ elsif ast_data[:constant_factor]
105
+ Builder.build_node(:constant_factor, ast_data[:constant_factor])
106
+ elsif ast_data[:expression]
107
+ Builder.build_expression(ast_data[:expression])
108
+ elsif ast_data[:aggregate_initializer]
109
+ Builder.build_node(:aggregate_initializer,
110
+ ast_data[:aggregate_initializer])
111
+ elsif ast_data[:query_expression]
112
+ Builder.build_node(:query_expression, ast_data[:query_expression])
113
+ elsif ast_data[:entity_constructor]
114
+ Builder.build_node(:entity_constructor,
115
+ ast_data[:entity_constructor])
116
+ elsif ast_data[:interval]
117
+ Builder.build_node(:interval, ast_data[:interval])
118
+ elsif ast_data[:string_literal]
119
+ Builder.build_node(:string_literal, ast_data[:string_literal])
120
+ elsif ast_data[:enumeration_reference]
121
+ Builder.build_node(:enumeration_reference,
122
+ ast_data[:enumeration_reference])
123
+ end
124
+ end
125
+
126
+ def build_simple_factor_expression(ast_data)
127
+ if ast_data[:primary]
128
+ Builder.build_primary(ast_data[:primary])
129
+ elsif ast_data[:expression]
130
+ Builder.build_expression(ast_data[:expression])
131
+ end
132
+ end
133
+
134
+ def build_simple_factor_unary_expression(ast_data)
135
+ op = extract_unary_op(ast_data[:unary_op])
136
+ operand = if ast_data[:simple_factor]
137
+ Builder.build_simple_factor(ast_data[:simple_factor])
138
+ elsif ast_data[:simple_factor_expression]
139
+ Builder.build_node(:simple_factor_expression,
140
+ ast_data[:simple_factor_expression])
141
+ elsif ast_data[:primary]
142
+ Builder.build_primary(ast_data[:primary])
143
+ end
144
+
145
+ if op
146
+ Expressir::Model::Expressions::UnaryExpression.new(
147
+ operator: op,
148
+ operand: operand,
149
+ )
150
+ else
151
+ operand
152
+ end
153
+ end
154
+
155
+ def build_constant_factor(ast_data)
156
+ if ast_data[:built_in_constant]
157
+ Builder.build_node(:built_in_constant, ast_data[:built_in_constant])
158
+ elsif ast_data[:constant_ref]
159
+ Builder.build_node(:constant_ref, ast_data[:constant_ref])
160
+ end
161
+ end
162
+
163
+ def build_primary(ast_data)
164
+ if ast_data[:literal]
165
+ Builder.build_node(:literal, ast_data[:literal])
166
+ elsif ast_data[:qualifiable_factor]
167
+ build_qualifiable_factor(ast_data[:qualifiable_factor],
168
+ ast_data[:qualifier])
169
+ elsif ast_data[:population]
170
+ build_population(ast_data[:population], ast_data[:qualifier])
171
+ elsif ast_data[:expression]
172
+ Builder.build_expression(ast_data[:expression])
173
+ end
174
+ end
175
+
176
+ def build_qualifiable_factor(ast_data, qualifiers = nil)
177
+ ref = nil
178
+ if ast_data[:constant_factor]
179
+ ref = Builder.build_node(:constant_factor,
180
+ ast_data[:constant_factor])
181
+ elsif ast_data[:function_call]
182
+ ref = Builder.build_node(:function_call, ast_data[:function_call])
183
+ else
184
+ %i[constant_ref function_ref general_ref parameter_ref type_label_ref
185
+ variable_ref attribute_ref entity_ref type_ref enumeration_ref].each do |key|
186
+ if ast_data[key]
187
+ ref = Builder.build_node(key, ast_data[key])
188
+ break
189
+ end
190
+ end
191
+ end
192
+
193
+ return ref unless qualifiers
194
+
195
+ [qualifiers].flatten.compact.each do |qual|
196
+ qual_result = Builder.build_node(:qualifier, qual)
197
+ ref = apply_qualifier(ref, qual_result)
198
+ end
199
+ ref
200
+ end
201
+
202
+ def build_population(ast_data, qualifiers = nil)
203
+ ref = Builder.build_node(:entity_ref, ast_data[:entity_ref])
204
+ return ref unless qualifiers
205
+
206
+ [qualifiers].flatten.compact.each do |qual|
207
+ qual_result = Builder.build_node(:qualifier, qual)
208
+ ref = apply_qualifier(ref, qual_result)
209
+ end
210
+ ref
211
+ end
212
+
213
+ def build_qualifier(ast_data)
214
+ if ast_data[:attribute_qualifier]
215
+ Builder.build_node(:attribute_qualifier,
216
+ ast_data[:attribute_qualifier])
217
+ elsif ast_data[:group_qualifier]
218
+ Builder.build_node(:group_qualifier, ast_data[:group_qualifier])
219
+ elsif ast_data[:index_qualifier]
220
+ Builder.build_node(:index_qualifier, ast_data[:index_qualifier])
221
+ end
222
+ end
223
+
224
+ def build_rel_op_extended(ast_data)
225
+ extract_rel_op(ast_data[:rel_op] || ast_data)
226
+ end
227
+
228
+ def build_binary_expression(operands, operators)
229
+ return operands.first if operands.length == 1
230
+ return nil if operands.empty? || operators.empty?
231
+
232
+ result = Expressir::Model::Expressions::BinaryExpression.new(
233
+ operator: operators.first,
234
+ operand1: operands.first,
235
+ operand2: operands[1],
236
+ )
237
+
238
+ (2...operands.length).each do |i|
239
+ result = Expressir::Model::Expressions::BinaryExpression.new(
240
+ operator: operators[i - 1],
241
+ operand1: result,
242
+ operand2: operands[i],
243
+ )
244
+ end
245
+ result
246
+ end
247
+
248
+ # Function call
249
+ def build_function_call(ast_data)
250
+ func_ref = if ast_data[:built_in_function]
251
+ Builder.build_node(:built_in_function,
252
+ ast_data[:built_in_function])
253
+ elsif ast_data[:function_ref]
254
+ Builder.build_node(:function_ref,
255
+ ast_data[:function_ref])
256
+ end
257
+
258
+ params = if ast_data[:actual_parameter_list]
259
+ Builder.build_node(:actual_parameter_list,
260
+ ast_data[:actual_parameter_list])
261
+ else
262
+ []
263
+ end
264
+
265
+ if params.empty?
266
+ func_ref
267
+ else
268
+ Expressir::Model::Expressions::FunctionCall.new(
269
+ function: func_ref,
270
+ parameters: [params].flatten.compact,
271
+ )
272
+ end
273
+ end
274
+
275
+ def build_actual_parameter_list(ast_data)
276
+ list_data = ast_data[:list_of_parameter] || ast_data[:parameter]
277
+
278
+ case list_data
279
+ when Hash
280
+ Builder.build_children(list_data[:parameter])
281
+ when Array
282
+ list_data.flat_map do |item|
283
+ if item.is_a?(Hash) && item[:parameter]
284
+ Builder.build_children(item[:parameter])
285
+ else
286
+ []
287
+ end
288
+ end
289
+ else
290
+ []
291
+ end
292
+ end
293
+
294
+ def build_parameter(ast_data)
295
+ Builder.build_optional(ast_data[:expression])
296
+ end
297
+
298
+ # Entity constructor
299
+ def build_entity_constructor(ast_data)
300
+ entity_ref = Builder.build_optional(ast_data[:entity_ref])
301
+ params = if ast_data[:actual_parameter_list]
302
+ Builder.build_node(:actual_parameter_list,
303
+ ast_data[:actual_parameter_list])
304
+ else
305
+ []
306
+ end
307
+
308
+ Expressir::Model::Expressions::FunctionCall.new(
309
+ function: entity_ref,
310
+ parameters: [params].flatten.compact,
311
+ )
312
+ end
313
+
314
+ # Query expression
315
+ def build_query_expression(ast_data)
316
+ var_id = Builder.build_optional(ast_data[:variable_id])
317
+ aggregate_source = Builder.build_optional(ast_data[:aggregate_source])
318
+ logical_expr = Builder.build_optional(ast_data[:logical_expression])
319
+
320
+ Expressir::Model::Expressions::QueryExpression.new(
321
+ id: var_id,
322
+ aggregate_source: aggregate_source,
323
+ expression: logical_expr,
324
+ )
325
+ end
326
+
327
+ def build_aggregate_source(ast_data)
328
+ Builder.build_optional(ast_data[:simple_expression])
329
+ end
330
+
331
+ # Aggregate initializer
332
+ def build_aggregate_initializer(ast_data)
333
+ list_data = ast_data[:list_of_element] || ast_data
334
+ elements = if list_data.is_a?(Array)
335
+ list_data
336
+ else
337
+ list_data[:element]
338
+ end
339
+
340
+ items = elements ? Builder.build_children(elements) : []
341
+ Expressir::Model::Expressions::AggregateInitializer.new(items: items.compact)
342
+ end
343
+
344
+ def build_element(ast_data)
345
+ expression = Builder.build_optional(ast_data[:expression])
346
+ repetition = Builder.build_optional(ast_data[:repetition])
347
+
348
+ if repetition
349
+ Expressir::Model::Expressions::AggregateInitializerItem.new(
350
+ expression: expression,
351
+ repetition: repetition,
352
+ )
353
+ else
354
+ expression
355
+ end
356
+ end
357
+
358
+ def build_repetition(ast_data)
359
+ Builder.build_optional(ast_data[:numeric_expression])
360
+ end
361
+
362
+ # Interval
363
+ def build_interval(ast_data)
364
+ low = Builder.build_optional(ast_data[:interval_low])
365
+ item = Builder.build_optional(ast_data[:interval_item])
366
+ high = Builder.build_optional(ast_data[:interval_high])
367
+
368
+ op1 = extract_interval_op(ast_data[:interval_op])
369
+ op2_data = ast_data[:interval_op2]
370
+ op2 = if op2_data.is_a?(Hash) && op2_data[:interval_op]
371
+ extract_interval_op(op2_data[:interval_op])
372
+ else
373
+ extract_interval_op(op2_data)
374
+ end
375
+
376
+ Expressir::Model::Expressions::Interval.new(
377
+ low: low,
378
+ operator1: op1,
379
+ item: item,
380
+ operator2: op2,
381
+ high: high,
382
+ )
383
+ end
384
+
385
+ def build_interval_low(ast_data)
386
+ Builder.build_optional(ast_data[:simple_expression])
387
+ end
388
+
389
+ def build_interval_high(ast_data)
390
+ Builder.build_optional(ast_data[:simple_expression])
391
+ end
392
+
393
+ def build_interval_item(ast_data)
394
+ Builder.build_optional(ast_data[:simple_expression])
395
+ end
396
+ end
397
+ end
398
+ end
399
+ end
400
+
401
+ builder = Expressir::Express::Builders::ExpressionBuilder.new
402
+
403
+ Builder.register(:expression) { |d| builder.build_expression(d) }
404
+ Builder.register(:logical_expression) do |d|
405
+ builder.build_logical_expression(d)
406
+ end
407
+ Builder.register(:numeric_expression) do |d|
408
+ builder.build_numeric_expression(d)
409
+ end
410
+ Builder.register(:simple_expression) { |d| builder.build_simple_expression(d) }
411
+ Builder.register(:term) { |d| builder.build_term(d) }
412
+ Builder.register(:factor) { |d| builder.build_factor(d) }
413
+ Builder.register(:simple_factor) { |d| builder.build_simple_factor(d) }
414
+ Builder.register(:simple_factor_expression) do |d|
415
+ builder.build_simple_factor_expression(d)
416
+ end
417
+ Builder.register(:simple_factor_unary_expression) do |d|
418
+ builder.build_simple_factor_unary_expression(d)
419
+ end
420
+ Builder.register(:constant_factor) { |d| builder.build_constant_factor(d) }
421
+ Builder.register(:primary) { |d| builder.build_primary(d) }
422
+ Builder.register(:qualifiable_factor) do |d|
423
+ builder.build_qualifiable_factor(d, nil)
424
+ end
425
+ Builder.register(:population) { |d| builder.build_population(d, nil) }
426
+ Builder.register(:qualifier) { |d| builder.build_qualifier(d) }
427
+ Builder.register(:rel_op_extended) { |d| builder.build_rel_op_extended(d) }
428
+ Builder.register(:function_call) { |d| builder.build_function_call(d) }
429
+ Builder.register(:actual_parameter_list) do |d|
430
+ builder.build_actual_parameter_list(d)
431
+ end
432
+ Builder.register(:parameter) { |d| builder.build_parameter(d) }
433
+ Builder.register(:entity_constructor) do |d|
434
+ builder.build_entity_constructor(d)
435
+ end
436
+ Builder.register(:query_expression) { |d| builder.build_query_expression(d) }
437
+ Builder.register(:aggregate_source) { |d| builder.build_aggregate_source(d) }
438
+ Builder.register(:aggregate_initializer) do |d|
439
+ builder.build_aggregate_initializer(d)
440
+ end
441
+ Builder.register(:element) { |d| builder.build_element(d) }
442
+ Builder.register(:repetition) { |d| builder.build_repetition(d) }
443
+ Builder.register(:interval) { |d| builder.build_interval(d) }
444
+ Builder.register(:interval_low) { |d| builder.build_interval_low(d) }
445
+ Builder.register(:interval_high) { |d| builder.build_interval_high(d) }
446
+ Builder.register(:interval_item) { |d| builder.build_interval_item(d) }
447
+ Builder.register(:interval_op) { |d| builder.send(:extract_interval_op, d) }
448
+
449
+ # Operators
450
+ Builder.register(:add_like_op) { |d| builder.send(:extract_operator, d) }
451
+ Builder.register(:mul_like_op) { |d| builder.send(:extract_operator, d) }
452
+ Builder.register(:unary_op) { |d| builder.send(:extract_unary_op, d) }
453
+ Builder.register(:rel_op) { |d| builder.send(:extract_rel_op, d) }