activefacts 1.6.0 → 1.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +21 -0
- data/README.md +60 -0
- data/Rakefile +3 -80
- data/activefacts.gemspec +36 -0
- data/bin/afgen +4 -2
- data/bin/cql +5 -1
- data/lib/activefacts.rb +3 -12
- data/lib/activefacts/{vocabulary/query_evaluator.rb → query/evaluator.rb} +0 -0
- data/lib/activefacts/version.rb +2 -2
- metadata +48 -296
- data/History.txt +0 -4
- data/LICENSE +0 -19
- data/Manifest.txt +0 -165
- data/README.rdoc +0 -81
- data/css/offline.css +0 -3
- data/css/orm2.css +0 -124
- data/css/print.css +0 -8
- data/css/style-print.css +0 -357
- data/css/style.css +0 -387
- data/download.html +0 -110
- data/examples/CQL/Address.cql +0 -44
- data/examples/CQL/Blog.cql +0 -54
- data/examples/CQL/CompanyDirectorEmployee.cql +0 -56
- data/examples/CQL/Death.cql +0 -17
- data/examples/CQL/Diplomacy.cql +0 -48
- data/examples/CQL/Genealogy.cql +0 -98
- data/examples/CQL/Insurance.cql +0 -320
- data/examples/CQL/Marriage.cql +0 -18
- data/examples/CQL/Metamodel.cql +0 -493
- data/examples/CQL/Monogamy.cql +0 -24
- data/examples/CQL/MultiInheritance.cql +0 -22
- data/examples/CQL/NonRoleId.cql +0 -14
- data/examples/CQL/OddIdentifier.cql +0 -18
- data/examples/CQL/OilSupply.cql +0 -53
- data/examples/CQL/OneToOnes.cql +0 -17
- data/examples/CQL/Orienteering.cql +0 -111
- data/examples/CQL/PersonPlaysGame.cql +0 -18
- data/examples/CQL/RedundantDependency.cql +0 -34
- data/examples/CQL/SchoolActivities.cql +0 -33
- data/examples/CQL/SeparateSubtype.cql +0 -30
- data/examples/CQL/ServiceDirector.cql +0 -276
- data/examples/CQL/SimplestUnary.cql +0 -12
- data/examples/CQL/Supervision.cql +0 -34
- data/examples/CQL/WaiterTips.cql +0 -33
- data/examples/CQL/Warehousing.cql +0 -101
- data/examples/CQL/WindowInRoomInBldg.cql +0 -28
- data/examples/CQL/unit.cql +0 -474
- data/examples/index.html +0 -420
- data/examples/intro.html +0 -327
- data/examples/local.css +0 -24
- data/index.html +0 -111
- data/lib/activefacts/cql.rb +0 -35
- data/lib/activefacts/cql/CQLParser.treetop +0 -158
- data/lib/activefacts/cql/Context.treetop +0 -48
- data/lib/activefacts/cql/Expressions.treetop +0 -67
- data/lib/activefacts/cql/FactTypes.treetop +0 -358
- data/lib/activefacts/cql/Language/English.treetop +0 -315
- data/lib/activefacts/cql/LexicalRules.treetop +0 -253
- data/lib/activefacts/cql/ObjectTypes.treetop +0 -210
- data/lib/activefacts/cql/Rakefile +0 -14
- data/lib/activefacts/cql/Terms.treetop +0 -183
- data/lib/activefacts/cql/ValueTypes.treetop +0 -202
- data/lib/activefacts/cql/compiler.rb +0 -156
- data/lib/activefacts/cql/compiler/clause.rb +0 -1137
- data/lib/activefacts/cql/compiler/constraint.rb +0 -581
- data/lib/activefacts/cql/compiler/entity_type.rb +0 -457
- data/lib/activefacts/cql/compiler/expression.rb +0 -443
- data/lib/activefacts/cql/compiler/fact.rb +0 -390
- data/lib/activefacts/cql/compiler/fact_type.rb +0 -421
- data/lib/activefacts/cql/compiler/query.rb +0 -106
- data/lib/activefacts/cql/compiler/shared.rb +0 -161
- data/lib/activefacts/cql/compiler/value_type.rb +0 -174
- data/lib/activefacts/cql/nodes.rb +0 -49
- data/lib/activefacts/cql/parser.rb +0 -241
- data/lib/activefacts/dependency_analyser.rb +0 -182
- data/lib/activefacts/generate/absorption.rb +0 -70
- data/lib/activefacts/generate/composition.rb +0 -118
- data/lib/activefacts/generate/cql.rb +0 -714
- data/lib/activefacts/generate/dm.rb +0 -279
- data/lib/activefacts/generate/help.rb +0 -64
- data/lib/activefacts/generate/helpers/inject.rb +0 -16
- data/lib/activefacts/generate/helpers/oo.rb +0 -162
- data/lib/activefacts/generate/helpers/ordered.rb +0 -605
- data/lib/activefacts/generate/helpers/rails.rb +0 -57
- data/lib/activefacts/generate/html/glossary.rb +0 -461
- data/lib/activefacts/generate/json.rb +0 -337
- data/lib/activefacts/generate/null.rb +0 -32
- data/lib/activefacts/generate/rails/models.rb +0 -246
- data/lib/activefacts/generate/rails/schema.rb +0 -216
- data/lib/activefacts/generate/records.rb +0 -46
- data/lib/activefacts/generate/ruby.rb +0 -133
- data/lib/activefacts/generate/sql/mysql.rb +0 -280
- data/lib/activefacts/generate/sql/server.rb +0 -273
- data/lib/activefacts/generate/stats.rb +0 -69
- data/lib/activefacts/generate/text.rb +0 -27
- data/lib/activefacts/generate/topics.rb +0 -265
- data/lib/activefacts/generate/traits/datavault.rb +0 -241
- data/lib/activefacts/generate/traits/oo.rb +0 -73
- data/lib/activefacts/generate/traits/ordered.rb +0 -33
- data/lib/activefacts/generate/traits/ruby.rb +0 -210
- data/lib/activefacts/generate/transform/datavault.rb +0 -266
- data/lib/activefacts/generate/transform/surrogate.rb +0 -214
- data/lib/activefacts/generate/version.rb +0 -26
- data/lib/activefacts/input/cql.rb +0 -43
- data/lib/activefacts/input/orm.rb +0 -1636
- data/lib/activefacts/mapping/rails.rb +0 -132
- data/lib/activefacts/persistence.rb +0 -15
- data/lib/activefacts/persistence/columns.rb +0 -446
- data/lib/activefacts/persistence/foreignkey.rb +0 -187
- data/lib/activefacts/persistence/index.rb +0 -240
- data/lib/activefacts/persistence/object_type.rb +0 -198
- data/lib/activefacts/persistence/reference.rb +0 -434
- data/lib/activefacts/persistence/tables.rb +0 -380
- data/lib/activefacts/registry.rb +0 -11
- data/lib/activefacts/support.rb +0 -132
- data/lib/activefacts/vocabulary.rb +0 -9
- data/lib/activefacts/vocabulary/extensions.rb +0 -1348
- data/lib/activefacts/vocabulary/metamodel.rb +0 -570
- data/lib/activefacts/vocabulary/verbaliser.rb +0 -804
- data/script/txt2html +0 -71
- data/spec/absorption_spec.rb +0 -95
- data/spec/cql/comparison_spec.rb +0 -89
- data/spec/cql/context_spec.rb +0 -94
- data/spec/cql/contractions_spec.rb +0 -224
- data/spec/cql/deontic_spec.rb +0 -88
- data/spec/cql/entity_type_spec.rb +0 -320
- data/spec/cql/expressions_spec.rb +0 -66
- data/spec/cql/fact_type_matching_spec.rb +0 -338
- data/spec/cql/french_spec.rb +0 -21
- data/spec/cql/parser/bad_literals_spec.rb +0 -86
- data/spec/cql/parser/constraints_spec.rb +0 -19
- data/spec/cql/parser/entity_types_spec.rb +0 -106
- data/spec/cql/parser/expressions_spec.rb +0 -199
- data/spec/cql/parser/fact_types_spec.rb +0 -44
- data/spec/cql/parser/literals_spec.rb +0 -312
- data/spec/cql/parser/pragmas_spec.rb +0 -89
- data/spec/cql/parser/value_types_spec.rb +0 -42
- data/spec/cql/role_matching_spec.rb +0 -148
- data/spec/cql/samples_spec.rb +0 -244
- data/spec/cql_cql_spec.rb +0 -73
- data/spec/cql_dm_spec.rb +0 -136
- data/spec/cql_mysql_spec.rb +0 -69
- data/spec/cql_parse_spec.rb +0 -34
- data/spec/cql_ruby_spec.rb +0 -73
- data/spec/cql_sql_spec.rb +0 -72
- data/spec/cql_symbol_tables_spec.rb +0 -261
- data/spec/cqldump_spec.rb +0 -170
- data/spec/helpers/array_matcher.rb +0 -23
- data/spec/helpers/ctrl_c_support.rb +0 -52
- data/spec/helpers/diff_matcher.rb +0 -39
- data/spec/helpers/file_matcher.rb +0 -34
- data/spec/helpers/parse_to_ast_matcher.rb +0 -80
- data/spec/helpers/string_matcher.rb +0 -30
- data/spec/helpers/test_parser.rb +0 -15
- data/spec/norma_cql_spec.rb +0 -66
- data/spec/norma_ruby_spec.rb +0 -62
- data/spec/norma_ruby_sql_spec.rb +0 -107
- data/spec/norma_sql_spec.rb +0 -57
- data/spec/norma_tables_spec.rb +0 -95
- data/spec/ruby_api_spec.rb +0 -23
- data/spec/spec_helper.rb +0 -35
- data/spec/transform_surrogate_spec.rb +0 -59
- data/status.html +0 -138
- 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
|