expressir 0.2.5 → 0.2.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/.cross_rubies +30 -0
  3. data/.github/workflows/rake.yml +14 -15
  4. data/.github/workflows/release.yml +24 -16
  5. data/.gitignore +3 -1
  6. data/Gemfile +0 -2
  7. data/Rakefile +2 -8
  8. data/expressir.gemspec +7 -4
  9. data/ext/express-parser/express_parser.cpp +12 -10
  10. data/ext/express-parser/extconf.rb +48 -25
  11. data/lib/expressir/express_exp/formatter.rb +74 -23
  12. data/lib/expressir/express_exp/parser.rb +20 -2
  13. data/lib/expressir/express_exp/visitor.rb +201 -96
  14. data/lib/expressir/model.rb +3 -0
  15. data/lib/expressir/model/attribute.rb +3 -1
  16. data/lib/expressir/model/constant.rb +3 -1
  17. data/lib/expressir/model/entity.rb +12 -19
  18. data/lib/expressir/model/enumeration_item.rb +3 -1
  19. data/lib/expressir/model/expressions/aggregate_initializer.rb +2 -2
  20. data/lib/expressir/model/expressions/aggregate_item.rb +1 -1
  21. data/lib/expressir/model/expressions/attribute_reference.rb +1 -1
  22. data/lib/expressir/model/expressions/binary_expression.rb +1 -1
  23. data/lib/expressir/model/expressions/call.rb +2 -2
  24. data/lib/expressir/model/expressions/entity_constructor.rb +2 -2
  25. data/lib/expressir/model/expressions/group_reference.rb +1 -1
  26. data/lib/expressir/model/expressions/index_reference.rb +1 -1
  27. data/lib/expressir/model/expressions/interval.rb +1 -1
  28. data/lib/expressir/model/expressions/query_expression.rb +5 -3
  29. data/lib/expressir/model/expressions/simple_reference.rb +1 -1
  30. data/lib/expressir/model/expressions/unary_expression.rb +1 -1
  31. data/lib/expressir/model/function.rb +32 -38
  32. data/lib/expressir/model/identifier.rb +1 -0
  33. data/lib/expressir/model/informal_proposition.rb +13 -0
  34. data/lib/expressir/model/interface.rb +2 -2
  35. data/lib/expressir/model/literals/binary.rb +1 -1
  36. data/lib/expressir/model/literals/integer.rb +1 -1
  37. data/lib/expressir/model/literals/logical.rb +1 -1
  38. data/lib/expressir/model/literals/real.rb +1 -1
  39. data/lib/expressir/model/literals/string.rb +1 -1
  40. data/lib/expressir/model/model_element.rb +67 -0
  41. data/lib/expressir/model/parameter.rb +3 -1
  42. data/lib/expressir/model/procedure.rb +33 -39
  43. data/lib/expressir/model/renamed_ref.rb +1 -1
  44. data/lib/expressir/model/repository.rb +3 -3
  45. data/lib/expressir/model/rule.rb +35 -38
  46. data/lib/expressir/model/schema.rb +35 -46
  47. data/lib/expressir/model/scope.rb +49 -3
  48. data/lib/expressir/model/statements/alias.rb +4 -2
  49. data/lib/expressir/model/statements/assignment.rb +1 -1
  50. data/lib/expressir/model/statements/call.rb +2 -2
  51. data/lib/expressir/model/statements/case.rb +2 -2
  52. data/lib/expressir/model/statements/case_action.rb +2 -2
  53. data/lib/expressir/model/statements/compound.rb +2 -2
  54. data/lib/expressir/model/statements/escape.rb +1 -1
  55. data/lib/expressir/model/statements/if.rb +3 -3
  56. data/lib/expressir/model/statements/null.rb +1 -1
  57. data/lib/expressir/model/statements/repeat.rb +4 -2
  58. data/lib/expressir/model/statements/return.rb +1 -1
  59. data/lib/expressir/model/statements/skip.rb +1 -1
  60. data/lib/expressir/model/subtype_constraint.rb +3 -1
  61. data/lib/expressir/model/type.rb +13 -3
  62. data/lib/expressir/model/types/aggregate.rb +3 -1
  63. data/lib/expressir/model/types/array.rb +1 -1
  64. data/lib/expressir/model/types/bag.rb +1 -1
  65. data/lib/expressir/model/types/binary.rb +1 -1
  66. data/lib/expressir/model/types/boolean.rb +1 -1
  67. data/lib/expressir/model/types/enumeration.rb +3 -3
  68. data/lib/expressir/model/types/generic.rb +3 -1
  69. data/lib/expressir/model/types/generic_entity.rb +3 -1
  70. data/lib/expressir/model/types/integer.rb +1 -1
  71. data/lib/expressir/model/types/list.rb +1 -1
  72. data/lib/expressir/model/types/logical.rb +1 -1
  73. data/lib/expressir/model/types/number.rb +1 -1
  74. data/lib/expressir/model/types/real.rb +1 -1
  75. data/lib/expressir/model/types/select.rb +3 -3
  76. data/lib/expressir/model/types/set.rb +1 -1
  77. data/lib/expressir/model/types/string.rb +1 -1
  78. data/lib/expressir/model/unique.rb +4 -2
  79. data/lib/expressir/model/variable.rb +3 -1
  80. data/lib/expressir/model/where.rb +3 -1
  81. data/lib/expressir/version.rb +1 -1
  82. data/original/examples/syntax/remark.exp +64 -20
  83. data/original/examples/syntax/remark_formatted.exp +63 -24
  84. data/original/examples/syntax/simple.exp +3 -0
  85. data/original/examples/syntax/source.exp +16 -0
  86. data/original/examples/syntax/syntax.exp +194 -181
  87. data/original/examples/syntax/syntax_formatted.exp +354 -787
  88. data/rakelib/cross-ruby.rake +308 -0
  89. data/spec/expressir/express_exp/head_source_spec.rb +38 -0
  90. data/spec/expressir/express_exp/parse_multiple_spec.rb +32 -0
  91. data/spec/expressir/express_exp/parse_remark_spec.rb +122 -56
  92. data/spec/expressir/express_exp/parse_syntax_spec.rb +1619 -1569
  93. data/spec/expressir/express_exp/source_spec.rb +29 -0
  94. data/spec/expressir/model/model_element_spec.rb +59 -0
  95. data/spec/expressir/model/{find_spec.rb → scope_spec.rb} +20 -7
  96. metadata +45 -21
@@ -1,7 +1,7 @@
1
1
  module Expressir
2
2
  module Model
3
3
  module Literals
4
- class String
4
+ class String < ModelElement
5
5
  attr_accessor :value
6
6
  attr_accessor :encoded
7
7
 
@@ -0,0 +1,67 @@
1
+ module Expressir
2
+ module Model
3
+ class ModelElement
4
+ CLASS_KEY = '_class'
5
+
6
+ def to_hash(options = {})
7
+ skip_empty = options[:skip_empty]
8
+
9
+ instance_variables.select{|x| x != :@parent}.each_with_object({ CLASS_KEY => self.class.name }) do |variable, result|
10
+ key = variable.to_s.sub(/^@/, '')
11
+ value = instance_variable_get(variable)
12
+
13
+ # skip default values (nil, empty array)
14
+ if !skip_empty or !(value.nil? or (value.is_a? Array and value.count == 0))
15
+ result[key] = if value.is_a? Array
16
+ value.map do |value|
17
+ if value.is_a? ModelElement
18
+ value.to_hash(options)
19
+ else
20
+ value
21
+ end
22
+ end
23
+ elsif value.is_a? ModelElement
24
+ value.to_hash(options)
25
+ else
26
+ value
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ def self.from_hash(hash)
33
+ node_class = hash[CLASS_KEY]
34
+ node_options = hash.select{|x| x != CLASS_KEY}.each_with_object({}) do |(variable, value), result|
35
+ key = variable.to_sym
36
+
37
+ result[key] = if value.is_a? Array
38
+ value.map do |value|
39
+ if value.is_a? Hash
40
+ self.from_hash(value)
41
+ else
42
+ value
43
+ end
44
+ end
45
+ elsif value.is_a? Hash
46
+ self.from_hash(value)
47
+ else
48
+ value
49
+ end
50
+ end
51
+
52
+ node = Object.const_get(node_class).new(node_options)
53
+
54
+ # attach parent
55
+ if node.class.method_defined? :children
56
+ node.children.each do |child_node|
57
+ if child_node.class.method_defined? :parent and !child_node.parent
58
+ child_node.parent = node
59
+ end
60
+ end
61
+ end
62
+
63
+ node
64
+ end
65
+ end
66
+ end
67
+ end
@@ -1,6 +1,6 @@
1
1
  module Expressir
2
2
  module Model
3
- class Parameter
3
+ class Parameter < ModelElement
4
4
  include Identifier
5
5
 
6
6
  attr_accessor :var
@@ -8,6 +8,8 @@ module Expressir
8
8
 
9
9
  def initialize(options = {})
10
10
  @id = options[:id]
11
+ @remarks = options.fetch(:remarks, [])
12
+ @source = options[:source]
11
13
 
12
14
  @var = options[:var]
13
15
  @type = options[:type]
@@ -1,58 +1,52 @@
1
1
  module Expressir
2
2
  module Model
3
- class Procedure
3
+ class Procedure < ModelElement
4
4
  include Scope
5
5
  include Identifier
6
6
 
7
7
  attr_accessor :parameters
8
- attr_accessor :declarations
8
+ attr_accessor :types
9
+ attr_accessor :entities
10
+ attr_accessor :subtype_constraints
11
+ attr_accessor :functions
12
+ attr_accessor :procedures
9
13
  attr_accessor :constants
10
14
  attr_accessor :variables
11
15
  attr_accessor :statements
12
16
 
13
17
  def initialize(options = {})
14
18
  @id = options[:id]
15
-
16
- @parameters = options[:parameters]
17
- @declarations = options[:declarations]
18
- @constants = options[:constants]
19
- @variables = options[:variables]
20
- @statements = options[:statements]
21
- end
22
-
23
- def types
24
- @declarations.select{|x| x.instance_of? Expressir::Model::Type}
25
- end
26
-
27
- def entities
28
- @declarations.select{|x| x.instance_of? Expressir::Model::Entity}
29
- end
30
-
31
- def subtype_constraints
32
- @declarations.select{|x| x.instance_of? Expressir::Model::SubtypeConstraint}
33
- end
34
-
35
- def functions
36
- @declarations.select{|x| x.instance_of? Expressir::Model::Function}
37
- end
38
-
39
- def procedures
40
- @declarations.select{|x| x.instance_of? Expressir::Model::Procedure}
19
+ @remarks = options.fetch(:remarks, [])
20
+ @source = options[:source]
21
+
22
+ @parameters = options.fetch(:parameters, [])
23
+ @types = options.fetch(:types, [])
24
+ @entities = options.fetch(:entities, [])
25
+ @subtype_constraints = options.fetch(:subtype_constraints, [])
26
+ @functions = options.fetch(:functions, [])
27
+ @procedures = options.fetch(:procedures, [])
28
+ @constants = options.fetch(:constants, [])
29
+ @variables = options.fetch(:variables, [])
30
+ @statements = options.fetch(:statements, [])
41
31
  end
42
32
 
43
33
  def children
44
34
  items = []
45
- items.push(*@parameters) if @parameters
46
- items.push(*@declarations.flat_map do |x|
47
- [
48
- x,
49
- *if x.instance_of? Expressir::Model::Type and x.type.instance_of? Expressir::Model::Types::Enumeration
50
- x.type.items
51
- end
52
- ]
53
- end) if @declarations
54
- items.push(*@constants) if @constants
55
- items.push(*@variables) if @variables
35
+ items.push(*@parameters)
36
+ items.push(*@types)
37
+ items.push(*@types.flat_map do |x|
38
+ if x.type.instance_of? Expressir::Model::Types::Enumeration
39
+ x.type.items
40
+ else
41
+ []
42
+ end
43
+ end)
44
+ items.push(*@entities)
45
+ items.push(*@subtype_constraints)
46
+ items.push(*@functions)
47
+ items.push(*@procedures)
48
+ items.push(*@constants)
49
+ items.push(*@variables)
56
50
  items
57
51
  end
58
52
  end
@@ -1,6 +1,6 @@
1
1
  module Expressir
2
2
  module Model
3
- class RenamedRef
3
+ class RenamedRef < ModelElement
4
4
  attr_accessor :ref
5
5
  attr_accessor :id
6
6
 
@@ -1,17 +1,17 @@
1
1
  module Expressir
2
2
  module Model
3
- class Repository
3
+ class Repository < ModelElement
4
4
  include Scope
5
5
 
6
6
  attr_accessor :schemas
7
7
 
8
8
  def initialize(options = {})
9
- @schemas = options[:schemas]
9
+ @schemas = options.fetch(:schemas, [])
10
10
  end
11
11
 
12
12
  def children
13
13
  items = []
14
- items.push(*@schemas) if @schemas
14
+ items.push(*@schemas)
15
15
  items
16
16
  end
17
17
  end
@@ -1,60 +1,57 @@
1
1
  module Expressir
2
2
  module Model
3
- class Rule
3
+ class Rule < ModelElement
4
4
  include Scope
5
5
  include Identifier
6
6
 
7
7
  attr_accessor :applies_to
8
- attr_accessor :declarations
8
+ attr_accessor :types
9
+ attr_accessor :entities
10
+ attr_accessor :subtype_constraints
11
+ attr_accessor :functions
12
+ attr_accessor :procedures
9
13
  attr_accessor :constants
10
14
  attr_accessor :variables
11
15
  attr_accessor :statements
12
16
  attr_accessor :where
17
+ attr_accessor :informal_propositions
13
18
 
14
19
  def initialize(options = {})
15
20
  @id = options[:id]
21
+ @remarks = options.fetch(:remarks, [])
22
+ @source = options[:source]
16
23
 
17
24
  @applies_to = options[:applies_to]
18
- @declarations = options[:declarations]
19
- @constants = options[:constants]
20
- @variables = options[:variables]
21
- @statements = options[:statements]
22
- @where = options[:where]
23
- end
24
-
25
- def types
26
- @declarations.select{|x| x.instance_of? Expressir::Model::Type}
27
- end
28
-
29
- def entities
30
- @declarations.select{|x| x.instance_of? Expressir::Model::Entity}
31
- end
32
-
33
- def subtype_constraints
34
- @declarations.select{|x| x.instance_of? Expressir::Model::SubtypeConstraint}
35
- end
36
-
37
- def functions
38
- @declarations.select{|x| x.instance_of? Expressir::Model::Function}
39
- end
40
-
41
- def procedures
42
- @declarations.select{|x| x.instance_of? Expressir::Model::Procedure}
25
+ @types = options.fetch(:types, [])
26
+ @entities = options.fetch(:entities, [])
27
+ @subtype_constraints = options.fetch(:subtype_constraints, [])
28
+ @functions = options.fetch(:functions, [])
29
+ @procedures = options.fetch(:procedures, [])
30
+ @constants = options.fetch(:constants, [])
31
+ @variables = options.fetch(:variables, [])
32
+ @statements = options.fetch(:statements, [])
33
+ @where = options.fetch(:where, [])
34
+ @informal_propositions = options.fetch(:informal_propositions, [])
43
35
  end
44
36
 
45
37
  def children
46
38
  items = []
47
- items.push(*@declarations.flat_map do |x|
48
- [
49
- x,
50
- *if x.instance_of? Expressir::Model::Type and x.type.instance_of? Expressir::Model::Types::Enumeration
51
- x.type.items
52
- end
53
- ]
54
- end) if @declarations
55
- items.push(*@constants) if @constants
56
- items.push(*@variables) if @variables
57
- items.push(*@where) if @where
39
+ items.push(*@types)
40
+ items.push(*@types.flat_map do |x|
41
+ if x.type.instance_of? Expressir::Model::Types::Enumeration
42
+ x.type.items
43
+ else
44
+ []
45
+ end
46
+ end)
47
+ items.push(*@entities)
48
+ items.push(*@subtype_constraints)
49
+ items.push(*@functions)
50
+ items.push(*@procedures)
51
+ items.push(*@constants)
52
+ items.push(*@variables)
53
+ items.push(*@where)
54
+ items.push(*@informal_propositions)
58
55
  items
59
56
  end
60
57
  end
@@ -1,65 +1,54 @@
1
1
  module Expressir
2
2
  module Model
3
- class Schema
3
+ class Schema < ModelElement
4
4
  include Scope
5
5
  include Identifier
6
6
 
7
+ attr_accessor :head_source
8
+
7
9
  attr_accessor :version
8
10
  attr_accessor :interfaces
9
11
  attr_accessor :constants
10
- attr_accessor :declarations
12
+ attr_accessor :types
13
+ attr_accessor :entities
14
+ attr_accessor :subtype_constraints
15
+ attr_accessor :functions
16
+ attr_accessor :procedures
17
+ attr_accessor :rules
11
18
 
12
19
  def initialize(options = {})
13
20
  @id = options[:id]
14
- @version = options[:version]
15
- @interfaces = options[:interfaces]
16
- @constants = options[:constants]
17
- @declarations = options[:declarations]
18
- end
19
-
20
- def use_interfaces
21
- @interfaces.select{|x| x.kind == Expressir::Model::Interface::USE}
22
- end
23
-
24
- def reference_interfaces
25
- @interfaces.select{|x| x.kind == Expressir::Model::Interface::REFERENCE}
26
- end
27
-
28
- def types
29
- @declarations.select{|x| x.instance_of? Expressir::Model::Type}
30
- end
21
+ @remarks = options.fetch(:remarks, [])
22
+ @source = options[:source]
23
+ @head_source = options[:head_source]
31
24
 
32
- def entities
33
- @declarations.select{|x| x.instance_of? Expressir::Model::Entity}
34
- end
35
-
36
- def subtype_constraints
37
- @declarations.select{|x| x.instance_of? Expressir::Model::SubtypeConstraint}
38
- end
39
-
40
- def functions
41
- @declarations.select{|x| x.instance_of? Expressir::Model::Function}
42
- end
43
-
44
- def procedures
45
- @declarations.select{|x| x.instance_of? Expressir::Model::Procedure}
46
- end
47
-
48
- def rules
49
- @declarations.select{|x| x.instance_of? Expressir::Model::Rule}
25
+ @version = options[:version]
26
+ @interfaces = options.fetch(:interfaces, [])
27
+ @constants = options.fetch(:constants, [])
28
+ @types = options.fetch(:types, [])
29
+ @entities = options.fetch(:entities, [])
30
+ @subtype_constraints = options.fetch(:subtype_constraints, [])
31
+ @functions = options.fetch(:functions, [])
32
+ @procedures = options.fetch(:procedures, [])
33
+ @rules = options.fetch(:rules, [])
50
34
  end
51
35
 
52
36
  def children
53
37
  items = []
54
- items.push(*@constants) if @constants
55
- items.push(*@declarations.flat_map do |x|
56
- [
57
- x,
58
- *if x.instance_of? Expressir::Model::Type and x.type.instance_of? Expressir::Model::Types::Enumeration
59
- x.type.items
60
- end
61
- ]
62
- end) if @declarations
38
+ items.push(*@constants)
39
+ items.push(*@types)
40
+ items.push(*@types.flat_map do |x|
41
+ if x.type.instance_of? Expressir::Model::Types::Enumeration
42
+ x.type.items
43
+ else
44
+ []
45
+ end
46
+ end)
47
+ items.push(*@entities)
48
+ items.push(*@subtype_constraints)
49
+ items.push(*@functions)
50
+ items.push(*@procedures)
51
+ items.push(*@rules)
63
52
  items
64
53
  end
65
54
  end
@@ -2,10 +2,56 @@ module Expressir
2
2
  module Model
3
3
  module Scope
4
4
  def find(path)
5
- path.downcase.split(".").reduce(self) do |acc, curr|
6
- if acc and acc.class.method_defined? :children
7
- acc.children.find{|x| x.id.downcase == curr}
5
+ current_path, _, rest = path.partition(".")
6
+
7
+ # ignore prefix
8
+ _, _, current_path = current_path.rpartition(":")
9
+
10
+ current_path = current_path.downcase
11
+ child = children.find{|x| x.id and x.id.downcase == current_path}
12
+
13
+ if !rest.empty? and child.class.method_defined? :find
14
+ child.find(rest)
15
+ else
16
+ child
17
+ end
18
+ end
19
+
20
+ def find_or_create(path)
21
+ child = find(path)
22
+
23
+ if !child
24
+ # check if path should create implicit informal proposal
25
+ # see https://github.com/lutaml/expressir/issues/50
26
+ rest, _, current_path = path.rpartition(".")
27
+
28
+ if !rest.empty?
29
+ child = find(rest)
30
+ else
31
+ child = self
32
+ end
33
+
34
+ if child.class.method_defined? :informal_propositions
35
+ # ignore prefix
36
+ _, _, current_path = current_path.rpartition(":")
37
+
38
+ # match informal proposition id
39
+ informal_proposition_id = current_path.match(/^IP\d+$/).to_a[0]
40
+
41
+ if informal_proposition_id
42
+ # create implicit informal proposition
43
+ informal_proposition = Model::InformalProposition.new({
44
+ id: informal_proposition_id
45
+ })
46
+ informal_proposition.parent = child
47
+
48
+ child.informal_propositions << informal_proposition
49
+
50
+ informal_proposition
51
+ end
8
52
  end
53
+ else
54
+ child
9
55
  end
10
56
  end
11
57