expressir 2.1.31 → 2.2.1
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.
- checksums.yaml +4 -4
- data/.github/workflows/docs.yml +3 -2
- data/.github/workflows/release.yml +6 -0
- data/.rubocop_todo.yml +106 -92
- data/Gemfile +1 -1
- data/README.adoc +372 -1
- data/docs/_guides/formatter/formatter-architecture.adoc +401 -0
- data/docs/_guides/ruby-api/parsing-files.adoc +1 -1
- data/docs/_pages/parsers.adoc +31 -5
- data/docs/lychee.toml +3 -0
- data/expressir.gemspec +3 -2
- data/lib/expressir/benchmark.rb +6 -6
- data/lib/expressir/cli.rb +9 -0
- data/lib/expressir/commands/base.rb +2 -9
- data/lib/expressir/commands/format.rb +30 -0
- data/lib/expressir/commands/package.rb +92 -87
- data/lib/expressir/commands/validate_ascii.rb +2 -4
- data/lib/expressir/commands/validate_load.rb +8 -5
- data/lib/expressir/coverage.rb +15 -11
- data/lib/expressir/errors.rb +115 -0
- data/lib/expressir/express/builder.rb +350 -0
- data/lib/expressir/express/builders/attribute_decl_builder.rb +38 -0
- data/lib/expressir/express/builders/built_in_builder.rb +88 -0
- data/lib/expressir/express/builders/constant_builder.rb +115 -0
- data/lib/expressir/express/builders/declaration_builder.rb +24 -0
- data/lib/expressir/express/builders/derive_clause_builder.rb +16 -0
- data/lib/expressir/express/builders/derived_attr_builder.rb +28 -0
- data/lib/expressir/express/builders/domain_rule_builder.rb +21 -0
- data/lib/expressir/express/builders/entity_decl_builder.rb +108 -0
- data/lib/expressir/express/builders/explicit_attr_builder.rb +52 -0
- data/lib/expressir/express/builders/expression_builder.rb +453 -0
- data/lib/expressir/express/builders/function_decl_builder.rb +84 -0
- data/lib/expressir/express/builders/helpers.rb +148 -0
- data/lib/expressir/express/builders/interface_builder.rb +171 -0
- data/lib/expressir/express/builders/inverse_attr_builder.rb +45 -0
- data/lib/expressir/express/builders/inverse_attr_type_builder.rb +36 -0
- data/lib/expressir/express/builders/inverse_clause_builder.rb +16 -0
- data/lib/expressir/express/builders/literal_builder.rb +107 -0
- data/lib/expressir/express/builders/procedure_decl_builder.rb +80 -0
- data/lib/expressir/express/builders/qualifier_builder.rb +128 -0
- data/lib/expressir/express/builders/reference_builder.rb +27 -0
- data/lib/expressir/express/builders/rule_decl_builder.rb +95 -0
- data/lib/expressir/express/builders/schema_body_decl_builder.rb +22 -0
- data/lib/expressir/express/builders/schema_decl_builder.rb +62 -0
- data/lib/expressir/express/builders/schema_version_builder.rb +40 -0
- data/lib/expressir/express/builders/simple_id_builder.rb +26 -0
- data/lib/expressir/express/builders/statement_builder.rb +250 -0
- data/lib/expressir/express/builders/subtype_constraint_builder.rb +188 -0
- data/lib/expressir/express/builders/syntax_builder.rb +19 -0
- data/lib/expressir/express/builders/token_builder.rb +15 -0
- data/lib/expressir/express/builders/type_builder.rb +264 -0
- data/lib/expressir/express/builders/type_decl_builder.rb +32 -0
- data/lib/expressir/express/builders/unique_clause_builder.rb +22 -0
- data/lib/expressir/express/builders/unique_rule_builder.rb +36 -0
- data/lib/expressir/express/builders/where_clause_builder.rb +22 -0
- data/lib/expressir/express/builders.rb +43 -0
- data/lib/expressir/express/error.rb +18 -2
- data/lib/expressir/express/formatter.rb +18 -1508
- data/lib/expressir/express/formatters/data_types_formatter.rb +317 -0
- data/lib/expressir/express/formatters/declarations_formatter.rb +689 -0
- data/lib/expressir/express/formatters/expressions_formatter.rb +160 -0
- data/lib/expressir/express/formatters/literals_formatter.rb +46 -0
- data/lib/expressir/express/formatters/references_formatter.rb +42 -0
- data/lib/expressir/express/formatters/remark_formatter.rb +296 -0
- data/lib/expressir/express/formatters/statements_formatter.rb +224 -0
- data/lib/expressir/express/formatters/supertype_expressions_formatter.rb +48 -0
- data/lib/expressir/express/parser.rb +129 -14
- data/lib/expressir/express/pretty_formatter.rb +624 -0
- data/lib/expressir/express/remark_attacher.rb +1155 -0
- data/lib/expressir/express/resolve_references_model_visitor.rb +1 -0
- data/lib/expressir/express/streaming_builder.rb +467 -0
- data/lib/expressir/express/transformer/remark_handling.rb +196 -0
- data/lib/expressir/model/identifier.rb +1 -1
- data/lib/expressir/model/model_element.rb +30 -2
- data/lib/expressir/model/remark_info.rb +51 -0
- data/lib/expressir/model/search_engine.rb +58 -9
- data/lib/expressir/version.rb +1 -1
- data/lib/expressir.rb +6 -4
- metadata +71 -7
- data/lib/expressir/express/visitor.rb +0 -2815
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "helpers"
|
|
4
|
+
|
|
5
|
+
module Expressir
|
|
6
|
+
module Express
|
|
7
|
+
module Builders
|
|
8
|
+
# Builds qualifier nodes (attribute, group, index qualifiers).
|
|
9
|
+
class QualifierBuilder
|
|
10
|
+
include Helpers
|
|
11
|
+
|
|
12
|
+
def build_redeclared_attribute(ast_data)
|
|
13
|
+
qualified_attr = ast_data[:qualified_attribute]
|
|
14
|
+
if qualified_attr.is_a?(Hash)
|
|
15
|
+
Builder.build({ qualified_attribute: qualified_attr })
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def build_referenced_attribute(ast_data)
|
|
20
|
+
if ast_data[:attribute_ref]
|
|
21
|
+
Builder.build({ attribute_ref: ast_data[:attribute_ref] })
|
|
22
|
+
elsif ast_data[:qualified_attribute]
|
|
23
|
+
Builder.build({ qualified_attribute: ast_data[:qualified_attribute] })
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def build_qualified_attribute(ast_data)
|
|
28
|
+
# t_self is part of qualified_attribute grammar
|
|
29
|
+
self_ref = if ast_data[:t_self]
|
|
30
|
+
Expressir::Model::References::SimpleReference.new(id: "SELF")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# group_qualifier contains the entity reference
|
|
34
|
+
entity_ref = if ast_data[:group_qualifier]
|
|
35
|
+
Builder.build({ entity_ref: ast_data[:group_qualifier][:entity_ref] })
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Create GroupReference with ref (SELF) and entity
|
|
39
|
+
group_qual = if self_ref || entity_ref
|
|
40
|
+
Expressir::Model::References::GroupReference.new(
|
|
41
|
+
ref: self_ref, entity: entity_ref,
|
|
42
|
+
)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
attr_qual = if ast_data[:attribute_qualifier]
|
|
46
|
+
Builder.build({ attribute_qualifier: ast_data[:attribute_qualifier] })
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
if group_qual && attr_qual
|
|
50
|
+
Expressir::Model::References::AttributeReference.new(
|
|
51
|
+
ref: group_qual, attribute: attr_qual,
|
|
52
|
+
)
|
|
53
|
+
else
|
|
54
|
+
attr_qual || group_qual
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def build_group_qualifier(ast_data)
|
|
59
|
+
entity = if ast_data[:entity_ref]
|
|
60
|
+
Builder.build({ entity_ref: ast_data[:entity_ref] })
|
|
61
|
+
end
|
|
62
|
+
Expressir::Model::References::GroupReference.new(entity: entity)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def build_attribute_qualifier(ast_data)
|
|
66
|
+
Builder.build({ attribute_ref: ast_data[:attribute_ref] })
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def build_index_qualifier(ast_data)
|
|
70
|
+
index1 = Builder.build_optional(ast_data[:index1])
|
|
71
|
+
index2 = Builder.build_optional(ast_data[:index2])
|
|
72
|
+
{ index1: index1, index2: index2 }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def build_index1(ast_data)
|
|
76
|
+
Builder.build_optional(ast_data[:numeric_expression])
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def build_index2(ast_data)
|
|
80
|
+
Builder.build_optional(ast_data[:numeric_expression])
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def build_index(ast_data)
|
|
84
|
+
Builder.build_optional(ast_data[:numeric_expression])
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def build_enumeration_reference(ast_data)
|
|
88
|
+
type_ref = Builder.build_optional(ast_data[:type_ref])
|
|
89
|
+
enum_ref = if ast_data[:enumeration_ref]
|
|
90
|
+
Builder.build({ enumeration_ref: ast_data[:enumeration_ref] })
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
if type_ref && enum_ref
|
|
94
|
+
Expressir::Model::References::AttributeReference.new(
|
|
95
|
+
ref: type_ref,
|
|
96
|
+
attribute: enum_ref,
|
|
97
|
+
)
|
|
98
|
+
elsif enum_ref
|
|
99
|
+
enum_ref
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
builder = Expressir::Express::Builders::QualifierBuilder.new
|
|
108
|
+
|
|
109
|
+
Builder.register(:redeclared_attribute) do |d|
|
|
110
|
+
builder.build_redeclared_attribute(d)
|
|
111
|
+
end
|
|
112
|
+
Builder.register(:referenced_attribute) do |d|
|
|
113
|
+
builder.build_referenced_attribute(d)
|
|
114
|
+
end
|
|
115
|
+
Builder.register(:qualified_attribute) do |d|
|
|
116
|
+
builder.build_qualified_attribute(d)
|
|
117
|
+
end
|
|
118
|
+
Builder.register(:group_qualifier) { |d| builder.build_group_qualifier(d) }
|
|
119
|
+
Builder.register(:attribute_qualifier) do |d|
|
|
120
|
+
builder.build_attribute_qualifier(d)
|
|
121
|
+
end
|
|
122
|
+
Builder.register(:index_qualifier) { |d| builder.build_index_qualifier(d) }
|
|
123
|
+
Builder.register(:index1) { |d| builder.build_index1(d) }
|
|
124
|
+
Builder.register(:index2) { |d| builder.build_index2(d) }
|
|
125
|
+
Builder.register(:index) { |d| builder.build_index(d) }
|
|
126
|
+
Builder.register(:enumeration_reference) do |d|
|
|
127
|
+
builder.build_enumeration_reference(d)
|
|
128
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "helpers"
|
|
4
|
+
|
|
5
|
+
module Expressir
|
|
6
|
+
module Express
|
|
7
|
+
module Builders
|
|
8
|
+
# Builds reference nodes (attribute_ref, entity_ref, etc.).
|
|
9
|
+
# Returns SimpleReference for all reference types.
|
|
10
|
+
class ReferenceBuilder
|
|
11
|
+
include Helpers
|
|
12
|
+
|
|
13
|
+
def call(ast_data)
|
|
14
|
+
id = extract_id_ref(ast_data)
|
|
15
|
+
Expressir::Model::References::SimpleReference.new(id: id)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Register for all reference types
|
|
23
|
+
%i[attribute_ref constant_ref entity_ref enumeration_ref function_ref
|
|
24
|
+
parameter_ref procedure_ref rule_ref rule_label_ref schema_ref
|
|
25
|
+
subtype_constraint_ref type_label_ref type_ref variable_ref].each do |ref_type|
|
|
26
|
+
Builder.register(ref_type, Expressir::Express::Builders::ReferenceBuilder.new)
|
|
27
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "helpers"
|
|
4
|
+
|
|
5
|
+
module Expressir
|
|
6
|
+
module Express
|
|
7
|
+
module Builders
|
|
8
|
+
# Builds rule declaration nodes.
|
|
9
|
+
class RuleDeclBuilder
|
|
10
|
+
include Helpers
|
|
11
|
+
|
|
12
|
+
def call(ast_data)
|
|
13
|
+
head = ast_data[:rule_head]
|
|
14
|
+
algorithm_head = ast_data[:algorithm_head]
|
|
15
|
+
stmts = ast_data[:stmt]
|
|
16
|
+
where_clause = ast_data[:where_clause]
|
|
17
|
+
|
|
18
|
+
id = Builder.build_optional(head[:rule_id]) if head
|
|
19
|
+
applies_to = build_applies_to(head)
|
|
20
|
+
|
|
21
|
+
declarations = []
|
|
22
|
+
if algorithm_head.is_a?(Hash)
|
|
23
|
+
declarations = Builder.build_children(algorithm_head[:declaration])
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
types = declarations.select { |x| x.is_a?(Expressir::Model::Declarations::Type) }
|
|
27
|
+
entities = declarations.select { |x| x.is_a?(Expressir::Model::Declarations::Entity) }
|
|
28
|
+
subtype_constraints = declarations.select { |x| x.is_a?(Expressir::Model::Declarations::SubtypeConstraint) }
|
|
29
|
+
functions = declarations.select { |x| x.is_a?(Expressir::Model::Declarations::Function) }
|
|
30
|
+
procedures = declarations.select { |x| x.is_a?(Expressir::Model::Declarations::Procedure) }
|
|
31
|
+
constants = build_constant_decl(algorithm_head[:constant_decl]) if algorithm_head.is_a?(Hash) && algorithm_head[:constant_decl]
|
|
32
|
+
variables = build_local_decl(algorithm_head[:local_decl]) if algorithm_head.is_a?(Hash) && algorithm_head[:local_decl]
|
|
33
|
+
statements = Builder.build_children(stmts)
|
|
34
|
+
where_rules = where_clause ? Builder.build({ where_clause: where_clause }) : []
|
|
35
|
+
|
|
36
|
+
Expressir::Model::Declarations::Rule.new(
|
|
37
|
+
id: id,
|
|
38
|
+
applies_to: [applies_to].flatten.compact,
|
|
39
|
+
types: types,
|
|
40
|
+
entities: entities,
|
|
41
|
+
subtype_constraints: subtype_constraints,
|
|
42
|
+
functions: functions,
|
|
43
|
+
procedures: procedures,
|
|
44
|
+
constants: [constants].flatten.compact,
|
|
45
|
+
variables: [variables].flatten.compact,
|
|
46
|
+
statements: statements.compact,
|
|
47
|
+
where_rules: [where_rules].flatten.compact,
|
|
48
|
+
)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def build_applies_to(head)
|
|
54
|
+
return [] unless head && head[:list_of_entity_ref]
|
|
55
|
+
|
|
56
|
+
entity_refs = head[:list_of_entity_ref]
|
|
57
|
+
refs = []
|
|
58
|
+
|
|
59
|
+
# entity_refs can be:
|
|
60
|
+
# - A Hash with entity_ref key (single entity)
|
|
61
|
+
# - An Array of Hashes (multiple entities)
|
|
62
|
+
if entity_refs.is_a?(Array)
|
|
63
|
+
entity_refs.each do |item|
|
|
64
|
+
if item[:entity_ref]
|
|
65
|
+
refs << Builder.build({ entity_ref: item[:entity_ref] })
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
elsif entity_refs.is_a?(Hash)
|
|
69
|
+
if entity_refs[:entity_ref]
|
|
70
|
+
refs << Builder.build({ entity_ref: entity_refs[:entity_ref] })
|
|
71
|
+
end
|
|
72
|
+
if entity_refs[:item]
|
|
73
|
+
[entity_refs[:item]].flatten.each do |item|
|
|
74
|
+
if item[:entity_ref]
|
|
75
|
+
refs << Builder.build({ entity_ref: item[:entity_ref] })
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
refs.compact
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def build_constant_decl(data)
|
|
84
|
+
Builder.build_children(data[:constant_body])
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def build_local_decl(data)
|
|
88
|
+
Builder.build_children(data[:local_variable]).flatten.compact
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
Builder.register(:rule_decl, Expressir::Express::Builders::RuleDeclBuilder.new)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "helpers"
|
|
4
|
+
|
|
5
|
+
module Expressir
|
|
6
|
+
module Express
|
|
7
|
+
module Builders
|
|
8
|
+
# Builds schema_body_declaration nodes - dispatches to declaration or rule.
|
|
9
|
+
class SchemaBodyDeclBuilder
|
|
10
|
+
def call(ast_data)
|
|
11
|
+
if ast_data[:declaration]
|
|
12
|
+
Builder.build({ declaration: ast_data[:declaration] })
|
|
13
|
+
elsif ast_data[:rule_decl]
|
|
14
|
+
Builder.build({ rule_decl: ast_data[:rule_decl] })
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
Builder.register(:schema_body_declaration, Expressir::Express::Builders::SchemaBodyDeclBuilder.new)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "helpers"
|
|
4
|
+
|
|
5
|
+
module Expressir
|
|
6
|
+
module Express
|
|
7
|
+
module Builders
|
|
8
|
+
# Builds schema_decl nodes into Schema objects.
|
|
9
|
+
class SchemaDeclBuilder
|
|
10
|
+
include Helpers
|
|
11
|
+
|
|
12
|
+
def call(ast_data)
|
|
13
|
+
id = Builder.build_optional(ast_data[:schema_id])
|
|
14
|
+
version = if ast_data[:schema_version_id]
|
|
15
|
+
Builder.build({ schema_version_id: ast_data[:schema_version_id] })
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
interfaces = []
|
|
19
|
+
constants = []
|
|
20
|
+
declarations = []
|
|
21
|
+
|
|
22
|
+
if ast_data[:schema_body]
|
|
23
|
+
interfaces = Builder.build_children(ast_data[:schema_body][:interface_specification])
|
|
24
|
+
constants = build_constants(ast_data[:schema_body][:constant_decl])
|
|
25
|
+
body_decls = ast_data[:schema_body][:schema_body_declaration]
|
|
26
|
+
declarations = Builder.build_children(body_decls) if body_decls
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
types = declarations.select { |x| x.is_a?(Expressir::Model::Declarations::Type) }
|
|
30
|
+
entities = declarations.select { |x| x.is_a?(Expressir::Model::Declarations::Entity) }
|
|
31
|
+
subtype_constraints = declarations.select { |x| x.is_a?(Expressir::Model::Declarations::SubtypeConstraint) }
|
|
32
|
+
functions = declarations.select { |x| x.is_a?(Expressir::Model::Declarations::Function) }
|
|
33
|
+
rules = declarations.select { |x| x.is_a?(Expressir::Model::Declarations::Rule) }
|
|
34
|
+
procedures = declarations.select { |x| x.is_a?(Expressir::Model::Declarations::Procedure) }
|
|
35
|
+
|
|
36
|
+
Expressir::Model::Declarations::Schema.new(
|
|
37
|
+
id: id,
|
|
38
|
+
version: version,
|
|
39
|
+
interfaces: interfaces.compact,
|
|
40
|
+
constants: [constants].flatten.compact,
|
|
41
|
+
types: types,
|
|
42
|
+
entities: entities,
|
|
43
|
+
subtype_constraints: subtype_constraints,
|
|
44
|
+
functions: functions,
|
|
45
|
+
rules: rules,
|
|
46
|
+
procedures: procedures,
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def build_constants(data)
|
|
53
|
+
return [] unless data
|
|
54
|
+
|
|
55
|
+
Builder.build_children(data[:constant_body])
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
Builder.register(:schema_decl, Expressir::Express::Builders::SchemaDeclBuilder.new)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "helpers"
|
|
4
|
+
|
|
5
|
+
module Expressir
|
|
6
|
+
module Express
|
|
7
|
+
module Builders
|
|
8
|
+
# Builds schema_version_id nodes into SchemaVersion objects.
|
|
9
|
+
class SchemaVersionBuilder
|
|
10
|
+
include Helpers
|
|
11
|
+
|
|
12
|
+
def call(ast_data)
|
|
13
|
+
string_val = Builder.build_optional(ast_data[:string_literal])
|
|
14
|
+
value = string_val.is_a?(Expressir::Model::Literals::String) ? string_val.value : string_val.to_s
|
|
15
|
+
|
|
16
|
+
items = nil
|
|
17
|
+
if value.start_with?("{") && value.end_with?("}")
|
|
18
|
+
parts = value[1..-2].split
|
|
19
|
+
items = parts.map do |part|
|
|
20
|
+
if (match = part.match(/^(.+)\((\d+)\)$/))
|
|
21
|
+
Expressir::Model::Declarations::SchemaVersionItem.new(
|
|
22
|
+
name: match[1], value: match[2],
|
|
23
|
+
)
|
|
24
|
+
elsif /^\d+$/.match?(part)
|
|
25
|
+
Expressir::Model::Declarations::SchemaVersionItem.new(value: part)
|
|
26
|
+
else
|
|
27
|
+
Expressir::Model::Declarations::SchemaVersionItem.new(name: part)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
Expressir::Model::Declarations::SchemaVersion.new(value: value,
|
|
33
|
+
items: items)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
Builder.register(:schema_version_id, Expressir::Express::Builders::SchemaVersionBuilder.new)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "helpers"
|
|
4
|
+
|
|
5
|
+
module Expressir
|
|
6
|
+
module Express
|
|
7
|
+
module Builders
|
|
8
|
+
# Builds simple ID nodes (simple_id, schema_id, entity_id, etc.)
|
|
9
|
+
# These return a string, not a Model object.
|
|
10
|
+
class SimpleIdBuilder
|
|
11
|
+
include Helpers
|
|
12
|
+
|
|
13
|
+
def call(ast_data)
|
|
14
|
+
extract_text(ast_data[:str]) || extract_text(ast_data[:simple_id]&.dig(:str))
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Register for all ID types
|
|
22
|
+
%i[simple_id schema_id entity_id type_id function_id procedure_id
|
|
23
|
+
rule_id rule_label_id constant_id parameter_id variable_id
|
|
24
|
+
enumeration_id subtype_constraint_id type_label_id attribute_id].each do |id_type|
|
|
25
|
+
Builder.register(id_type, Expressir::Express::Builders::SimpleIdBuilder.new)
|
|
26
|
+
end
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "helpers"
|
|
4
|
+
|
|
5
|
+
module Expressir
|
|
6
|
+
module Express
|
|
7
|
+
module Builders
|
|
8
|
+
# Builds statement nodes (assignment, if, case, repeat, etc.).
|
|
9
|
+
class StatementBuilder
|
|
10
|
+
include Helpers
|
|
11
|
+
|
|
12
|
+
# stmt - choice dispatcher
|
|
13
|
+
def build_stmt(ast_data)
|
|
14
|
+
if ast_data[:assignment_stmt]
|
|
15
|
+
Builder.build({ assignment_stmt: ast_data[:assignment_stmt] })
|
|
16
|
+
elsif ast_data[:alias_stmt]
|
|
17
|
+
Builder.build({ alias_stmt: ast_data[:alias_stmt] })
|
|
18
|
+
elsif ast_data[:if_stmt]
|
|
19
|
+
Builder.build({ if_stmt: ast_data[:if_stmt] })
|
|
20
|
+
elsif ast_data[:case_stmt]
|
|
21
|
+
Builder.build({ case_stmt: ast_data[:case_stmt] })
|
|
22
|
+
elsif ast_data[:compound_stmt]
|
|
23
|
+
Builder.build({ compound_stmt: ast_data[:compound_stmt] })
|
|
24
|
+
elsif ast_data[:repeat_stmt]
|
|
25
|
+
Builder.build({ repeat_stmt: ast_data[:repeat_stmt] })
|
|
26
|
+
elsif ast_data[:return_stmt]
|
|
27
|
+
Builder.build({ return_stmt: ast_data[:return_stmt] })
|
|
28
|
+
elsif ast_data[:escape_stmt]
|
|
29
|
+
Builder.build({ escape_stmt: ast_data[:escape_stmt] })
|
|
30
|
+
elsif ast_data[:skip_stmt]
|
|
31
|
+
Builder.build({ skip_stmt: ast_data[:skip_stmt] })
|
|
32
|
+
elsif ast_data[:null_stmt]
|
|
33
|
+
Builder.build({ null_stmt: ast_data[:null_stmt] })
|
|
34
|
+
elsif ast_data[:procedure_call_stmt]
|
|
35
|
+
Builder.build({ procedure_call_stmt: ast_data[:procedure_call_stmt] })
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def build_assignment_stmt(ast_data)
|
|
40
|
+
ref = Builder.build_optional(ast_data[:general_ref])
|
|
41
|
+
expression = Builder.build_optional(ast_data[:expression])
|
|
42
|
+
|
|
43
|
+
if ast_data[:qualifier]
|
|
44
|
+
[ast_data[:qualifier]].flatten.compact.each do |qual|
|
|
45
|
+
qual_result = Builder.build({ qualifier: qual })
|
|
46
|
+
ref = apply_qualifier(ref, qual_result)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
Expressir::Model::Statements::Assignment.new(ref: ref,
|
|
51
|
+
expression: expression)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def build_alias_stmt(ast_data)
|
|
55
|
+
var_id = Builder.build_optional(ast_data[:variable_id])
|
|
56
|
+
expression = Builder.build_optional(ast_data[:general_ref])
|
|
57
|
+
statements = Builder.build_children(ast_data[:stmt])
|
|
58
|
+
|
|
59
|
+
if ast_data[:qualifier] && expression
|
|
60
|
+
[ast_data[:qualifier]].flatten.compact.each do |qual|
|
|
61
|
+
qual_result = Builder.build({ qualifier: qual })
|
|
62
|
+
expression = apply_qualifier(expression, qual_result)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
Expressir::Model::Statements::Alias.new(
|
|
67
|
+
id: var_id,
|
|
68
|
+
expression: expression,
|
|
69
|
+
statements: statements.compact,
|
|
70
|
+
)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def build_if_stmt(ast_data)
|
|
74
|
+
expression = Builder.build_optional(ast_data[:logical_expression])
|
|
75
|
+
then_stmts = Builder.build_children(ast_data[:if_stmt_statements]&.dig(:stmt))
|
|
76
|
+
else_stmts = Builder.build_children(ast_data[:if_stmt_else_statements]&.dig(:stmt))
|
|
77
|
+
|
|
78
|
+
Expressir::Model::Statements::If.new(
|
|
79
|
+
expression: expression,
|
|
80
|
+
statements: then_stmts.compact,
|
|
81
|
+
else_statements: else_stmts.compact,
|
|
82
|
+
)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def build_case_stmt(ast_data)
|
|
86
|
+
selector = Builder.build_optional(ast_data[:selector])
|
|
87
|
+
actions = Builder.build_children(ast_data[:case_action])
|
|
88
|
+
otherwise = Builder.build_children(ast_data[:otherwise]&.dig(:stmt))
|
|
89
|
+
|
|
90
|
+
Expressir::Model::Statements::Case.new(
|
|
91
|
+
expression: selector,
|
|
92
|
+
actions: actions.compact,
|
|
93
|
+
otherwise: otherwise.compact,
|
|
94
|
+
)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def build_selector(ast_data)
|
|
98
|
+
Builder.build_optional(ast_data[:expression])
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def build_case_action(ast_data)
|
|
102
|
+
labels = Builder.build_children(ast_data[:case_label])
|
|
103
|
+
statements = Builder.build_children(ast_data[:stmt])
|
|
104
|
+
|
|
105
|
+
Expressir::Model::Statements::CaseAction.new(
|
|
106
|
+
labels: labels.compact,
|
|
107
|
+
statements: statements.compact,
|
|
108
|
+
)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def build_case_label(ast_data)
|
|
112
|
+
Builder.build_optional(ast_data[:expression])
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def build_compound_stmt(ast_data)
|
|
116
|
+
statements = Builder.build_children(ast_data[:stmt])
|
|
117
|
+
Expressir::Model::Statements::Compound.new(statements: statements.compact)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def build_repeat_stmt(ast_data)
|
|
121
|
+
control = ast_data[:repeat_control]
|
|
122
|
+
statements = Builder.build_children(ast_data[:stmt])
|
|
123
|
+
|
|
124
|
+
var_id = nil
|
|
125
|
+
bound1 = nil
|
|
126
|
+
bound2 = nil
|
|
127
|
+
increment = nil
|
|
128
|
+
|
|
129
|
+
increment_control = control[:increment_control] if control.is_a?(Hash)
|
|
130
|
+
if increment_control.is_a?(Hash)
|
|
131
|
+
var_id = Builder.build_optional(increment_control[:variable_id])
|
|
132
|
+
bound1 = Builder.build_optional(increment_control[:bound1])
|
|
133
|
+
bound2 = Builder.build_optional(increment_control[:bound2])
|
|
134
|
+
increment = Builder.build_optional(increment_control[:increment])
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
while_ctrl = control.is_a?(Hash) ? control[:while_control] : nil
|
|
138
|
+
until_ctrl = control.is_a?(Hash) ? control[:until_control] : nil
|
|
139
|
+
|
|
140
|
+
while_expression = if while_ctrl.is_a?(Hash)
|
|
141
|
+
Builder.build_optional(while_ctrl[:logical_expression])
|
|
142
|
+
end
|
|
143
|
+
until_expression = if until_ctrl.is_a?(Hash)
|
|
144
|
+
Builder.build_optional(until_ctrl[:logical_expression])
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
Expressir::Model::Statements::Repeat.new(
|
|
148
|
+
id: var_id,
|
|
149
|
+
bound1: bound1,
|
|
150
|
+
bound2: bound2,
|
|
151
|
+
increment: increment,
|
|
152
|
+
while_expression: while_expression,
|
|
153
|
+
until_expression: until_expression,
|
|
154
|
+
statements: statements.compact,
|
|
155
|
+
)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def build_increment_control(_ast_data)
|
|
159
|
+
nil
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def build_increment(ast_data)
|
|
163
|
+
Builder.build_optional(ast_data[:numeric_expression])
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def build_while_control(ast_data)
|
|
167
|
+
Builder.build_optional(ast_data[:logical_expression])
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def build_until_control(ast_data)
|
|
171
|
+
Builder.build_optional(ast_data[:logical_expression])
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def build_return_stmt(ast_data)
|
|
175
|
+
expression = Builder.build_optional(ast_data[:expression])
|
|
176
|
+
Expressir::Model::Statements::Return.new(expression: expression)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def build_escape_stmt(_ast_data)
|
|
180
|
+
Expressir::Model::Statements::Escape.new
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def build_skip_stmt(_ast_data)
|
|
184
|
+
Expressir::Model::Statements::Skip.new
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def build_null_stmt(_ast_data)
|
|
188
|
+
Expressir::Model::Statements::Null.new
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def build_procedure_call_stmt(ast_data)
|
|
192
|
+
proc_ref = if ast_data[:procedure_ref]
|
|
193
|
+
Builder.build({ procedure_ref: ast_data[:procedure_ref] })
|
|
194
|
+
elsif ast_data[:built_in_procedure]
|
|
195
|
+
Builder.build({ built_in_procedure: ast_data[:built_in_procedure] })
|
|
196
|
+
end
|
|
197
|
+
params = if ast_data[:actual_parameter_list]
|
|
198
|
+
Builder.build({ actual_parameter_list: ast_data[:actual_parameter_list] })
|
|
199
|
+
else
|
|
200
|
+
[]
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
Expressir::Model::Statements::ProcedureCall.new(
|
|
204
|
+
procedure: proc_ref,
|
|
205
|
+
parameters: [params].flatten.compact,
|
|
206
|
+
)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def build_type_label(ast_data)
|
|
210
|
+
if ast_data[:type_label_id]
|
|
211
|
+
Builder.build({ type_label_id: ast_data[:type_label_id] })
|
|
212
|
+
elsif ast_data[:type_label_ref]
|
|
213
|
+
Builder.build({ type_label_ref: ast_data[:type_label_ref] })
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def build_type_label_ref(ast_data)
|
|
218
|
+
id = extract_text(ast_data[:str] || ast_data[:type_label_id]&.dig(:str))
|
|
219
|
+
Expressir::Model::References::SimpleReference.new(id: id)
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
builder = Expressir::Express::Builders::StatementBuilder.new
|
|
227
|
+
|
|
228
|
+
Builder.register(:stmt) { |d| builder.build_stmt(d) }
|
|
229
|
+
Builder.register(:assignment_stmt) { |d| builder.build_assignment_stmt(d) }
|
|
230
|
+
Builder.register(:alias_stmt) { |d| builder.build_alias_stmt(d) }
|
|
231
|
+
Builder.register(:if_stmt) { |d| builder.build_if_stmt(d) }
|
|
232
|
+
Builder.register(:case_stmt) { |d| builder.build_case_stmt(d) }
|
|
233
|
+
Builder.register(:selector) { |d| builder.build_selector(d) }
|
|
234
|
+
Builder.register(:case_action) { |d| builder.build_case_action(d) }
|
|
235
|
+
Builder.register(:case_label) { |d| builder.build_case_label(d) }
|
|
236
|
+
Builder.register(:compound_stmt) { |d| builder.build_compound_stmt(d) }
|
|
237
|
+
Builder.register(:repeat_stmt) { |d| builder.build_repeat_stmt(d) }
|
|
238
|
+
Builder.register(:increment_control) { |d| builder.build_increment_control(d) }
|
|
239
|
+
Builder.register(:increment) { |d| builder.build_increment(d) }
|
|
240
|
+
Builder.register(:while_control) { |d| builder.build_while_control(d) }
|
|
241
|
+
Builder.register(:until_control) { |d| builder.build_until_control(d) }
|
|
242
|
+
Builder.register(:return_stmt) { |d| builder.build_return_stmt(d) }
|
|
243
|
+
Builder.register(:escape_stmt) { |d| builder.build_escape_stmt(d) }
|
|
244
|
+
Builder.register(:skip_stmt) { |d| builder.build_skip_stmt(d) }
|
|
245
|
+
Builder.register(:null_stmt) { |d| builder.build_null_stmt(d) }
|
|
246
|
+
Builder.register(:procedure_call_stmt) do |d|
|
|
247
|
+
builder.build_procedure_call_stmt(d)
|
|
248
|
+
end
|
|
249
|
+
Builder.register(:type_label) { |d| builder.build_type_label(d) }
|
|
250
|
+
Builder.register(:type_label_ref) { |d| builder.build_type_label_ref(d) }
|