activefacts 1.6.0 → 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +14 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +60 -0
  8. data/Rakefile +3 -80
  9. data/activefacts.gemspec +36 -0
  10. data/bin/afgen +4 -2
  11. data/bin/cql +5 -1
  12. data/lib/activefacts.rb +3 -12
  13. data/lib/activefacts/{vocabulary/query_evaluator.rb → query/evaluator.rb} +0 -0
  14. data/lib/activefacts/version.rb +2 -2
  15. metadata +48 -296
  16. data/History.txt +0 -4
  17. data/LICENSE +0 -19
  18. data/Manifest.txt +0 -165
  19. data/README.rdoc +0 -81
  20. data/css/offline.css +0 -3
  21. data/css/orm2.css +0 -124
  22. data/css/print.css +0 -8
  23. data/css/style-print.css +0 -357
  24. data/css/style.css +0 -387
  25. data/download.html +0 -110
  26. data/examples/CQL/Address.cql +0 -44
  27. data/examples/CQL/Blog.cql +0 -54
  28. data/examples/CQL/CompanyDirectorEmployee.cql +0 -56
  29. data/examples/CQL/Death.cql +0 -17
  30. data/examples/CQL/Diplomacy.cql +0 -48
  31. data/examples/CQL/Genealogy.cql +0 -98
  32. data/examples/CQL/Insurance.cql +0 -320
  33. data/examples/CQL/Marriage.cql +0 -18
  34. data/examples/CQL/Metamodel.cql +0 -493
  35. data/examples/CQL/Monogamy.cql +0 -24
  36. data/examples/CQL/MultiInheritance.cql +0 -22
  37. data/examples/CQL/NonRoleId.cql +0 -14
  38. data/examples/CQL/OddIdentifier.cql +0 -18
  39. data/examples/CQL/OilSupply.cql +0 -53
  40. data/examples/CQL/OneToOnes.cql +0 -17
  41. data/examples/CQL/Orienteering.cql +0 -111
  42. data/examples/CQL/PersonPlaysGame.cql +0 -18
  43. data/examples/CQL/RedundantDependency.cql +0 -34
  44. data/examples/CQL/SchoolActivities.cql +0 -33
  45. data/examples/CQL/SeparateSubtype.cql +0 -30
  46. data/examples/CQL/ServiceDirector.cql +0 -276
  47. data/examples/CQL/SimplestUnary.cql +0 -12
  48. data/examples/CQL/Supervision.cql +0 -34
  49. data/examples/CQL/WaiterTips.cql +0 -33
  50. data/examples/CQL/Warehousing.cql +0 -101
  51. data/examples/CQL/WindowInRoomInBldg.cql +0 -28
  52. data/examples/CQL/unit.cql +0 -474
  53. data/examples/index.html +0 -420
  54. data/examples/intro.html +0 -327
  55. data/examples/local.css +0 -24
  56. data/index.html +0 -111
  57. data/lib/activefacts/cql.rb +0 -35
  58. data/lib/activefacts/cql/CQLParser.treetop +0 -158
  59. data/lib/activefacts/cql/Context.treetop +0 -48
  60. data/lib/activefacts/cql/Expressions.treetop +0 -67
  61. data/lib/activefacts/cql/FactTypes.treetop +0 -358
  62. data/lib/activefacts/cql/Language/English.treetop +0 -315
  63. data/lib/activefacts/cql/LexicalRules.treetop +0 -253
  64. data/lib/activefacts/cql/ObjectTypes.treetop +0 -210
  65. data/lib/activefacts/cql/Rakefile +0 -14
  66. data/lib/activefacts/cql/Terms.treetop +0 -183
  67. data/lib/activefacts/cql/ValueTypes.treetop +0 -202
  68. data/lib/activefacts/cql/compiler.rb +0 -156
  69. data/lib/activefacts/cql/compiler/clause.rb +0 -1137
  70. data/lib/activefacts/cql/compiler/constraint.rb +0 -581
  71. data/lib/activefacts/cql/compiler/entity_type.rb +0 -457
  72. data/lib/activefacts/cql/compiler/expression.rb +0 -443
  73. data/lib/activefacts/cql/compiler/fact.rb +0 -390
  74. data/lib/activefacts/cql/compiler/fact_type.rb +0 -421
  75. data/lib/activefacts/cql/compiler/query.rb +0 -106
  76. data/lib/activefacts/cql/compiler/shared.rb +0 -161
  77. data/lib/activefacts/cql/compiler/value_type.rb +0 -174
  78. data/lib/activefacts/cql/nodes.rb +0 -49
  79. data/lib/activefacts/cql/parser.rb +0 -241
  80. data/lib/activefacts/dependency_analyser.rb +0 -182
  81. data/lib/activefacts/generate/absorption.rb +0 -70
  82. data/lib/activefacts/generate/composition.rb +0 -118
  83. data/lib/activefacts/generate/cql.rb +0 -714
  84. data/lib/activefacts/generate/dm.rb +0 -279
  85. data/lib/activefacts/generate/help.rb +0 -64
  86. data/lib/activefacts/generate/helpers/inject.rb +0 -16
  87. data/lib/activefacts/generate/helpers/oo.rb +0 -162
  88. data/lib/activefacts/generate/helpers/ordered.rb +0 -605
  89. data/lib/activefacts/generate/helpers/rails.rb +0 -57
  90. data/lib/activefacts/generate/html/glossary.rb +0 -461
  91. data/lib/activefacts/generate/json.rb +0 -337
  92. data/lib/activefacts/generate/null.rb +0 -32
  93. data/lib/activefacts/generate/rails/models.rb +0 -246
  94. data/lib/activefacts/generate/rails/schema.rb +0 -216
  95. data/lib/activefacts/generate/records.rb +0 -46
  96. data/lib/activefacts/generate/ruby.rb +0 -133
  97. data/lib/activefacts/generate/sql/mysql.rb +0 -280
  98. data/lib/activefacts/generate/sql/server.rb +0 -273
  99. data/lib/activefacts/generate/stats.rb +0 -69
  100. data/lib/activefacts/generate/text.rb +0 -27
  101. data/lib/activefacts/generate/topics.rb +0 -265
  102. data/lib/activefacts/generate/traits/datavault.rb +0 -241
  103. data/lib/activefacts/generate/traits/oo.rb +0 -73
  104. data/lib/activefacts/generate/traits/ordered.rb +0 -33
  105. data/lib/activefacts/generate/traits/ruby.rb +0 -210
  106. data/lib/activefacts/generate/transform/datavault.rb +0 -266
  107. data/lib/activefacts/generate/transform/surrogate.rb +0 -214
  108. data/lib/activefacts/generate/version.rb +0 -26
  109. data/lib/activefacts/input/cql.rb +0 -43
  110. data/lib/activefacts/input/orm.rb +0 -1636
  111. data/lib/activefacts/mapping/rails.rb +0 -132
  112. data/lib/activefacts/persistence.rb +0 -15
  113. data/lib/activefacts/persistence/columns.rb +0 -446
  114. data/lib/activefacts/persistence/foreignkey.rb +0 -187
  115. data/lib/activefacts/persistence/index.rb +0 -240
  116. data/lib/activefacts/persistence/object_type.rb +0 -198
  117. data/lib/activefacts/persistence/reference.rb +0 -434
  118. data/lib/activefacts/persistence/tables.rb +0 -380
  119. data/lib/activefacts/registry.rb +0 -11
  120. data/lib/activefacts/support.rb +0 -132
  121. data/lib/activefacts/vocabulary.rb +0 -9
  122. data/lib/activefacts/vocabulary/extensions.rb +0 -1348
  123. data/lib/activefacts/vocabulary/metamodel.rb +0 -570
  124. data/lib/activefacts/vocabulary/verbaliser.rb +0 -804
  125. data/script/txt2html +0 -71
  126. data/spec/absorption_spec.rb +0 -95
  127. data/spec/cql/comparison_spec.rb +0 -89
  128. data/spec/cql/context_spec.rb +0 -94
  129. data/spec/cql/contractions_spec.rb +0 -224
  130. data/spec/cql/deontic_spec.rb +0 -88
  131. data/spec/cql/entity_type_spec.rb +0 -320
  132. data/spec/cql/expressions_spec.rb +0 -66
  133. data/spec/cql/fact_type_matching_spec.rb +0 -338
  134. data/spec/cql/french_spec.rb +0 -21
  135. data/spec/cql/parser/bad_literals_spec.rb +0 -86
  136. data/spec/cql/parser/constraints_spec.rb +0 -19
  137. data/spec/cql/parser/entity_types_spec.rb +0 -106
  138. data/spec/cql/parser/expressions_spec.rb +0 -199
  139. data/spec/cql/parser/fact_types_spec.rb +0 -44
  140. data/spec/cql/parser/literals_spec.rb +0 -312
  141. data/spec/cql/parser/pragmas_spec.rb +0 -89
  142. data/spec/cql/parser/value_types_spec.rb +0 -42
  143. data/spec/cql/role_matching_spec.rb +0 -148
  144. data/spec/cql/samples_spec.rb +0 -244
  145. data/spec/cql_cql_spec.rb +0 -73
  146. data/spec/cql_dm_spec.rb +0 -136
  147. data/spec/cql_mysql_spec.rb +0 -69
  148. data/spec/cql_parse_spec.rb +0 -34
  149. data/spec/cql_ruby_spec.rb +0 -73
  150. data/spec/cql_sql_spec.rb +0 -72
  151. data/spec/cql_symbol_tables_spec.rb +0 -261
  152. data/spec/cqldump_spec.rb +0 -170
  153. data/spec/helpers/array_matcher.rb +0 -23
  154. data/spec/helpers/ctrl_c_support.rb +0 -52
  155. data/spec/helpers/diff_matcher.rb +0 -39
  156. data/spec/helpers/file_matcher.rb +0 -34
  157. data/spec/helpers/parse_to_ast_matcher.rb +0 -80
  158. data/spec/helpers/string_matcher.rb +0 -30
  159. data/spec/helpers/test_parser.rb +0 -15
  160. data/spec/norma_cql_spec.rb +0 -66
  161. data/spec/norma_ruby_spec.rb +0 -62
  162. data/spec/norma_ruby_sql_spec.rb +0 -107
  163. data/spec/norma_sql_spec.rb +0 -57
  164. data/spec/norma_tables_spec.rb +0 -95
  165. data/spec/ruby_api_spec.rb +0 -23
  166. data/spec/spec_helper.rb +0 -35
  167. data/spec/transform_surrogate_spec.rb +0 -59
  168. data/status.html +0 -138
  169. data/why.html +0 -60
@@ -1,161 +0,0 @@
1
- module ActiveFacts
2
- module CQL
3
- class Compiler < ActiveFacts::CQL::Parser
4
-
5
- # In a declaration, a Binding has one or more Reference's.
6
- # A Binding is for a single ObjectType, normally related to just one Role,
7
- # and the references (References) to it will normally be the object_type name
8
- # with the same adjectives (modulo loose binding),
9
- # or a role name or subscript reference.
10
- #
11
- # In some situations a Binding will have some References with the same adjectives,
12
- # and one or more References with no adjectives - this is called "loose binding".
13
- class Binding
14
- attr_reader :player # The ObjectType (object type)
15
- attr_reader :refs # an array of the References
16
- attr_reader :role_name
17
- attr_accessor :rebound_to # Loose binding may set this to another binding
18
- attr_reader :variable
19
- attr_accessor :instance # When binding fact instances, the instance goes here
20
-
21
- def initialize player, role_name = nil
22
- @player = player
23
- @role_name = role_name
24
- @refs = []
25
- end
26
-
27
- def inspect
28
- "#{@player.name}#{@role_name and @role_name.is_a?(Integer) ? " (#{@role_name})" : " (as #{@role_name})"}"
29
- end
30
-
31
- def key
32
- "#{@player.name}#{@role_name && " (as #{@role_name})"}"
33
- end
34
-
35
- def <=>(other)
36
- key <=> other.key
37
- end
38
-
39
- def variable= v
40
- @variable = v # A place for a breakpoint :)
41
- end
42
-
43
- def add_ref ref
44
- @refs << ref
45
- ref
46
- end
47
-
48
- def delete_ref ref
49
- @refs.delete ref
50
- end
51
- end
52
-
53
- class CompilationContext
54
- attr_accessor :vocabulary
55
- attr_accessor :allowed_forward_terms
56
- attr_accessor :left_contraction_allowed
57
- attr_accessor :left_contractable_clause
58
- attr_accessor :left_contraction_conjunction
59
- attr_reader :bindings # The Bindings in this declaration
60
- attr_reader :player_by_role_name
61
-
62
- def initialize vocabulary
63
- @vocabulary = vocabulary
64
- @vocabulary_identifier = @vocabulary.identifying_role_values
65
- @allowed_forward_terms = []
66
- @bindings = {}
67
- @player_by_role_name = {}
68
- @left_contraction_allowed = false
69
- end
70
-
71
- # Look up this object_type by its name
72
- def object_type(name)
73
- constellation = @vocabulary.constellation
74
- player = constellation.ObjectType[[@vocabulary_identifier, name]]
75
-
76
- # Bind to an existing role which has a role name (that's why we bind those first)
77
- player ||= @player_by_role_name[name]
78
-
79
- if !player && @allowed_forward_terms.include?(name)
80
- @vocabulary.valid_entity_type_name(name) # No need for the result here, just no exceptional condition
81
- player = constellation.EntityType(@vocabulary, name, :concept => :new)
82
- end
83
-
84
- player
85
- end
86
-
87
- # Pass in an array of clauses or References for player identification and binding (creating the Bindings)
88
- # It's necessary to identify all players that define a role name first,
89
- # so those names exist in the context for where they're used.
90
- def bind *clauses
91
- cl = clauses.flatten
92
- cl.each { |clause| clause.identify_players_with_role_name(self) }
93
- cl.each { |clause| clause.identify_other_players(self) }
94
- cl.each { |clause| clause.bind(self) }
95
- end
96
- end
97
-
98
- class Definition
99
- attr_accessor :constellation, :vocabulary, :tree
100
- def compile
101
- raise "#{self.class} should implement the compile method"
102
- end
103
-
104
- def to_s
105
- @vocabulary ? "#{vocabulary.to_s}::" : ''
106
- end
107
-
108
- def source
109
- @tree.text_value
110
- end
111
- end
112
-
113
- class Vocabulary < Definition
114
- def initialize name
115
- @name = name
116
- end
117
-
118
- def compile
119
- if @constellation.Vocabulary.size > 0
120
- @constellation.Topic @name
121
- else
122
- @constellation.Vocabulary @name
123
- end
124
- end
125
-
126
- def to_s
127
- @name
128
- end
129
- end
130
-
131
- class Import < Definition
132
- def initialize parser, name, alias_hash
133
- @parser = parser
134
- @name = name
135
- @alias_hash = alias_hash
136
- end
137
-
138
- def to_s
139
- "#{@vocabulary.to_s} imports #{@alias_hash.map{|k,v| "#{k} as #{v}" }*', '};"
140
- end
141
-
142
- def compile
143
- @parser.compile_import(@name, @alias_hash)
144
- end
145
- end
146
-
147
- class ObjectType < Definition
148
- attr_reader :name
149
-
150
- def initialize name
151
- @name = name
152
- end
153
-
154
- def to_s
155
- "#{super}#{@name}"
156
- end
157
- end
158
-
159
- end
160
- end
161
- end
@@ -1,174 +0,0 @@
1
- module ActiveFacts
2
- module CQL
3
- class Compiler < ActiveFacts::CQL::Parser
4
-
5
- class Unit < Definition
6
- def initialize singular, plural, numerator, denominator, offset, base_units, approximately, ephemera_url
7
- @singular = singular
8
- @plural = plural
9
- @numerator, @denominator = numerator, denominator
10
- @offset = offset
11
- @base_units = base_units # An array of pairs, each [unit_name, power]
12
- @approximately = approximately
13
- @ephemera_url = ephemera_url
14
- end
15
-
16
- def compile
17
- if (@numerator.to_f / @denominator.to_i != 1.0)
18
- coefficient = @constellation.Coefficient(
19
- @numerator,
20
- @denominator.to_i,
21
- !@approximately
22
- # REVISIT: Activefacts-api is complaining at present. The following is better and should work:
23
- # :numerator => @numerator,
24
- # :denominator => @denominator.to_i,
25
- # :is_precise => !@approximately
26
- )
27
- else
28
- coefficient = nil
29
- end
30
- @offset = nil if @offset.to_f == 0
31
-
32
- trace :units, "Defining new unit #{@singular}#{@plural ? "/"+@plural : ""}" do
33
- trace :units, "Coefficient is #{coefficient.numerator}#{coefficient.denominator != 1 ? "/#{coefficient.denominator}" : ""} #{coefficient.is_precise ? "exactly" : "approximately"}" if coefficient
34
- trace :units, "Offset is #{@offset}" if @offset
35
- raise "Redefinition of unit #{@singular}" if @constellation.Unit.values.detect{|u| u.name == @singular}
36
- raise "Redefinition of unit #{@plural}" if @constellation.Unit.values.detect{|u| u.name == @plural}
37
- unit = @constellation.Unit(:new,
38
- :name => @singular,
39
- :plural_name => @plural,
40
- :coefficient => coefficient,
41
- :offset => @offset,
42
- :is_fundamental => @base_units.empty?,
43
- :ephemera_url => @ephemera_url,
44
- :vocabulary => @vocabulary
45
- )
46
- @base_units.each do |base_unit, exponent|
47
- base = @constellation.Unit.values.detect{|u| u.name == base_unit || u.plural_name == base_unit }
48
- trace :units, "Base unit #{base_unit}^#{exponent} #{base ? "" : "(implicitly fundamental)"}"
49
- base ||= @constellation.Unit(:new, :name => base_unit, :is_fundamental => true, :vocabulary => @vocabulary)
50
- @constellation.Derivation(:derived_unit => unit, :base_unit => base, :exponent => exponent)
51
- end
52
- =begin
53
- if @plural
54
- plural_unit = @constellation.Unit(:new,
55
- :name => @plural,
56
- :is_fundamental => false,
57
- :vocabulary => @vocabulary
58
- )
59
- @constellation.Derivation(:derived_unit => plural_unit, :base_unit => unit, :exponent => 1)
60
- end
61
- =end
62
- unit
63
- end
64
- end
65
-
66
- def inspect
67
- to_s
68
- end
69
-
70
- def to_s
71
- super + "Unit(#{
72
- @singular
73
- }#{
74
- @plural ? '/'+@plural : ''
75
- }) is #{
76
- @numerator
77
- }/#{
78
- @denominator
79
- }+#{
80
- @offset
81
- } #{
82
- @base_units.map{|b,e|
83
- b+'^'+e.to_s
84
- }*'*'
85
- }"
86
- end
87
- end
88
-
89
- class ValueType < ObjectType
90
- def initialize name, base, parameters, unit, value_constraint, pragmas, context_note, auto_assigned_at
91
- super name
92
- @base_type_name = base
93
- @parameters = parameters
94
- @unit = unit
95
- @value_constraint = value_constraint
96
- @pragmas = pragmas
97
- @context_note = context_note
98
- @auto_assigned_at = auto_assigned_at
99
- end
100
-
101
- def compile
102
- length, scale = *@parameters
103
-
104
- # Create the base type unless it already exists:
105
- base_type = nil
106
- if (@base_type_name != @name)
107
- unless base_type = @vocabulary.valid_value_type_name(@base_type_name)
108
- base_type = @constellation.ValueType(@vocabulary, @base_type_name, :concept => :new)
109
- return base_type if @base_type_name == @name
110
- end
111
- end
112
-
113
- # Create and initialise the ValueType:
114
- vt = @vocabulary.valid_value_type_name(@name) ||
115
- @constellation.ValueType(@vocabulary, @name, :concept => :new)
116
- vt.is_independent = true if @pragmas.delete('independent')
117
- @pragmas.each do |p|
118
- @constellation.ConceptAnnotation(:concept => vt.concept, :mapping_annotation => p)
119
- end if @pragmas
120
- vt.supertype = base_type if base_type
121
- vt.length = length if length
122
- vt.scale = scale if scale
123
- vt.transaction_phase = @auto_assigned_at
124
-
125
- unless @unit.empty?
126
- unit_name, exponent = *@unit[0]
127
- unit = @constellation.Name[unit_name].unit ||
128
- @constellation.Name[unit_name].plural_named_unit
129
- raise "Unit #{unit_name} for value type #{@name} is not defined" unless unit
130
- if exponent != 1
131
- base_unit = unit
132
- unit_name = base_unit.name+"^#{exponent}"
133
- unless unit = @constellation.Unit.detect{|k,v| v.name == unit_name }
134
- # Define a derived unit (these are skipped on output)
135
- unit = @constellation.Unit(:new,
136
- :vocabulary => @vocabulary,
137
- :name => unit_name,
138
- :is_fundamental => false
139
- )
140
- @constellation.Derivation(unit, base_unit).exponent = exponent
141
- end
142
- end
143
- vt.unit = unit
144
- end
145
-
146
- if @value_constraint
147
- @value_constraint.constellation = @constellation
148
- vt.value_constraint = @value_constraint.compile
149
- end
150
-
151
- if @context_note
152
- @context_note.compile(@constellation, vt)
153
- end
154
-
155
- vt
156
- end
157
-
158
- def to_s
159
- "ValueType: #{super} is written as #{
160
- @base_type_name
161
- }#{
162
- @parameters.size > 0 ? "(#{ @parameters.map{|p|p.to_s}*', ' })" : ''
163
- }#{
164
- @unit && @unit.length > 0 ? " in #{@unit.inspect}" : ''
165
- }#{
166
- @value_constraint ? " "+@value_constraint.to_s : ''
167
- }#{
168
- @pragmas.size > 0 ? ", pragmas [#{@pragmas*','}]" : ''
169
- };"
170
- end
171
- end
172
- end
173
- end
174
- end
@@ -1,49 +0,0 @@
1
- module ActiveFacts
2
- module CQL
3
- class Parser
4
- class TermNode < Treetop::Runtime::SyntaxNode
5
- def ast quantifier = nil, function_call = nil, role_name = nil, value_constraint = nil, literal = nil, nested_clauses = nil
6
- t = x.context[:term]
7
- gt = x.context[:global_term]
8
- if t.size > gt.size and t[-gt.size..-1] == gt
9
- leading_adjective = t[0...-gt.size-1]
10
- leading_adjective.sub!(/ /, '-') if !tail.elements[0].dbl.empty?
11
- end
12
- if t.size > gt.size and t[0...gt.size] == gt
13
- trailing_adjective = t[gt.size+1..-1]
14
- trailing_adjective.sub!(/ (\S*)\Z/, '-\1') if !tail.elements[-1].dbl.empty?
15
- end
16
- Compiler::Reference.new(gt, leading_adjective, trailing_adjective, quantifier, function_call, role_name, value_constraint, literal, nested_clauses)
17
- end
18
-
19
- def value # Sometimes we just want the full term name
20
- x.context[:term]
21
- end
22
-
23
- def node_type
24
- :term
25
- end
26
- end
27
-
28
- class TermLANode < TermNode
29
- def ast quantifier = nil, function_call = nil, role_name = nil, value_constraint = nil, literal = nil, nested_clauses = nil
30
- ast = term.ast(quantifier, function_call, role_name, value_constraint, literal, nested_clauses)
31
- ast.leading_adjective = head.text_value
32
- ast
33
- end
34
- end
35
-
36
- class TermDefinitionNameNode < TermNode
37
- def value
38
- t.elements.inject([
39
- id.value
40
- ]){|a, e| a << e.id.value}*' '
41
- end
42
-
43
- def node_type
44
- :term
45
- end
46
- end
47
- end
48
- end
49
- end
@@ -1,241 +0,0 @@
1
- #
2
- # ActiveFacts CQL Parser.
3
- # The parser turns CQL strings into abstract syntax trees ready for semantic analysis.
4
- #
5
- # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
6
- #
7
- require 'rubygems'
8
- require 'treetop'
9
-
10
- # These are Treetop files, which Polyglot will compile on the fly if precompiled ones aren't found:
11
- require 'activefacts/cql/LexicalRules'
12
- require 'activefacts/cql/Language/English'
13
- require 'activefacts/cql/Expressions'
14
- require 'activefacts/cql/Terms'
15
- require 'activefacts/cql/ObjectTypes'
16
- require 'activefacts/cql/ValueTypes'
17
- require 'activefacts/cql/FactTypes'
18
- require 'activefacts/cql/Context'
19
- require 'activefacts/cql/CQLParser'
20
-
21
- module ActiveFacts
22
- module CQL
23
- class Parser < CQLParser
24
- end
25
- end
26
- end
27
- require 'activefacts/cql/nodes'
28
-
29
- class Treetop::Runtime::SyntaxNode
30
- def node_type
31
- terminal? ? :keyword : :composite
32
- end
33
- end
34
-
35
- module ActiveFacts
36
- module CQL
37
- module Terms
38
- class SavedContext < Treetop::Runtime::SyntaxNode
39
- attr_accessor :context
40
- end
41
- end
42
-
43
- # Extend the generated parser:
44
- class Parser
45
- include ActiveFacts
46
-
47
- # The Context manages some key information revealed or needed during parsing
48
- # These methods are semantic predicates; if they return false this parse rule will fail.
49
- class Context
50
- attr_reader :term, :global_term
51
- attr_reader :terms
52
-
53
- def initialize(parser)
54
- @parser = parser
55
- @terms = {}
56
- @role_names = {}
57
- @allowed_forward_terms = []
58
- end
59
-
60
- def object_type(name, kind)
61
- index_name(@terms, name) && trace(:context, "new #{kind} '#{name}'")
62
- true
63
- end
64
-
65
- def reset_role_names
66
- trace :context, "\tresetting role names #{@role_names.keys.sort*", "}" if @role_names && @role_names.size > 0
67
- @role_names = {}
68
- end
69
-
70
- def allowed_forward_terms(terms)
71
- @allowed_forward_terms = terms
72
- end
73
-
74
- def new_leading_adjective_term(adj, term)
75
- index_name(@role_names, "#{adj} #{term}", term) && trace(:context, "new compound term '#{adj}- #{term}'")
76
- true
77
- end
78
-
79
- def new_trailing_adjective_term(adj, term)
80
- index_name(@role_names, "#{term} #{adj}", term) && trace(:context, "new compound term '#{term} -#{adj}'")
81
- true
82
- end
83
-
84
- def role_name(name)
85
- index_name(@role_names, name) && trace(:context, "new role '#{name}'")
86
- true
87
- end
88
-
89
- def term_starts?(s, context_saver)
90
- @term = @global_term = nil
91
-
92
- @term_part = s
93
- @context_saver = context_saver
94
- t = @terms[s] || @role_names[s] || system_term(s)
95
- if t
96
- # s is a prefix of the keys of t.
97
- if t[s]
98
- @global_term = @term = @term_part
99
- @context_saver.context = {:term => @term, :global_term => @global_term }
100
- end
101
- trace :context, "Term #{t[s] ? "is" : "starts"} '#{@term_part}'"
102
- elsif @allowed_forward_terms.include?(@term_part)
103
- @term = @term_part
104
- @context_saver.context = {:term => @term, :global_term => @term }
105
- trace :context, "Term #{s} is an allowed forward"
106
- return true
107
- end
108
- t
109
- end
110
-
111
- def term_continues?(s)
112
- @term_part = "#{@term_part} #{s}"
113
- t = @terms[@term_part]
114
- r = @role_names[@term_part]
115
- if t && (!r || !r[@term_part]) # Part of a term and not a complete role name
116
- w = "term"
117
- else
118
- t = r
119
- w = "role_name"
120
- end
121
- if t
122
- trace :context, "Multi-word #{w} #{t[@term_part] ? 'ends at' : 'continues to'} #{@term_part.inspect}"
123
-
124
- # Record the name of the full term and the underlying global term:
125
- if t[@term_part]
126
- @term = @term_part if t[@term_part]
127
- @global_term = (t = t[@term_part]) == true ? @term_part : t
128
- trace :context, "saving context #{@term}/#{@global_term}"
129
- @context_saver.context = {:term => @term, :global_term => @global_term }
130
- end
131
- end
132
- t
133
- end
134
-
135
- def term_complete?
136
- return true if @allowed_forward_terms.include?(@term)
137
- return true if system_term(@term)
138
- (t = @terms[@term] and t[@term]) or
139
- (t = @role_names[@term] and t[@term])
140
- end
141
-
142
- def system_term(s)
143
- false
144
- end
145
-
146
- def unit? s
147
- @parser.unit? s
148
- end
149
-
150
- private
151
- # Index the name by all prefixes
152
- def index_name(index, name, value = true)
153
- added = false
154
- words = name.split(/\s+/)
155
- words.inject("") do |n, w|
156
- # Index all prefixes up to the full term
157
- n = n.empty? ? w : "#{n} #{w}"
158
- index[n] ||= {}
159
- added = true unless index[n][name]
160
- index[n][name] = value # Save all possible completions of this prefix
161
- n
162
- end
163
- added
164
- end
165
- end
166
-
167
- class InputProxy
168
- attr_reader :context, :parser
169
-
170
- def initialize(input, context, parser)
171
- @input = input
172
- @context = context
173
- @parser = parser
174
- end
175
-
176
- def length
177
- @input.length
178
- end
179
-
180
- def size
181
- length
182
- end
183
-
184
- def [](*a)
185
- @input[*a]
186
- end
187
-
188
- def index(*a)
189
- @input.index(*a)
190
- end
191
-
192
- def line_of(x)
193
- @input.line_of(x)
194
- end
195
-
196
- def column_of(x)
197
- @input.column_of(x)
198
- end
199
- end
200
-
201
- def context
202
- @context ||= Context.new(self)
203
- end
204
-
205
- def unit?(s)
206
- # puts "Asking whether #{s.inspect} is a unit"
207
- true
208
- end
209
-
210
- def parse(input, options = {})
211
- input = InputProxy.new(input, context, self) unless input.respond_to?(:context)
212
- super(input, options)
213
- end
214
-
215
- def parse_all(input, rule_name = nil, &block)
216
- self.root = rule_name if rule_name
217
-
218
- @index = 0 # Byte offset to start next parse
219
- @block = block
220
- self.consume_all_input = false
221
- nodes = []
222
- begin
223
- node = parse(InputProxy.new(input, context, self), :index => @index)
224
- unless node
225
- raise failure_reason unless @index == input.size
226
- return nil # No input, or no more input
227
- end
228
- if @block
229
- @block.call(node)
230
- else
231
- nodes << node
232
- end
233
- end until self.index == @input_length
234
- @block ? true : nodes
235
- end
236
- end
237
-
238
- end
239
-
240
- Polyglot.register('cql', CQL::Parser)
241
- end