activefacts-cql 1.8.1 → 1.8.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile +6 -5
- data/activefacts-cql.gemspec +4 -3
- data/lib/activefacts/cql/compiler.rb +29 -22
- data/lib/activefacts/cql/compiler/clause.rb +86 -84
- data/lib/activefacts/cql/compiler/constraint.rb +53 -53
- data/lib/activefacts/cql/compiler/entity_type.rb +28 -28
- data/lib/activefacts/cql/compiler/expression.rb +27 -27
- data/lib/activefacts/cql/compiler/fact.rb +37 -37
- data/lib/activefacts/cql/compiler/fact_type.rb +91 -85
- data/lib/activefacts/cql/compiler/informal.rb +48 -0
- data/lib/activefacts/cql/compiler/query.rb +52 -52
- data/lib/activefacts/cql/compiler/shared.rb +17 -17
- data/lib/activefacts/cql/compiler/value_type.rb +11 -11
- data/lib/activefacts/cql/parser/CQLParser.treetop +76 -56
- data/lib/activefacts/cql/parser/Context.treetop +15 -17
- data/lib/activefacts/cql/parser/Expressions.treetop +21 -21
- data/lib/activefacts/cql/parser/FactTypes.treetop +216 -216
- data/lib/activefacts/cql/parser/Language/English.treetop +136 -131
- data/lib/activefacts/cql/parser/Language/French.treetop +118 -118
- data/lib/activefacts/cql/parser/Language/Mandarin.treetop +111 -111
- data/lib/activefacts/cql/parser/LexicalRules.treetop +45 -45
- data/lib/activefacts/cql/parser/ObjectTypes.treetop +120 -120
- data/lib/activefacts/cql/parser/Terms.treetop +63 -63
- data/lib/activefacts/cql/parser/ValueTypes.treetop +71 -71
- data/lib/activefacts/cql/require.rb +8 -8
- data/lib/activefacts/cql/verbaliser.rb +88 -88
- data/lib/activefacts/cql/version.rb +1 -1
- data/lib/activefacts/input/cql.rb +7 -7
- metadata +12 -16
@@ -9,18 +9,18 @@ module ActiveFacts
|
|
9
9
|
grammar Context
|
10
10
|
rule context_note
|
11
11
|
'('
|
12
|
-
s w:who_says? s context_type
|
12
|
+
s w:who_says? s context_type description agreed:(',' a:as_agreed_by)? s
|
13
13
|
')' s
|
14
14
|
{
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
15
|
+
def value
|
16
|
+
[ w.empty? ? nil : w.value, context_type.value, description.text_value, agreed.empty? ? [] : agreed.a.value]
|
17
|
+
end
|
18
|
+
def ast
|
19
|
+
who = w.empty? ? nil : w.value
|
20
|
+
ag = agreed.empty? ? [] : agreed.a.value
|
21
|
+
Compiler::ContextNote.new context_type.value, description.text_value, who, ag
|
22
|
+
end
|
23
|
+
}
|
24
24
|
end
|
25
25
|
|
26
26
|
rule who_says
|
@@ -35,13 +35,11 @@ module ActiveFacts
|
|
35
35
|
to_avoid { def value; 'to_avoid'; end }
|
36
36
|
end
|
37
37
|
|
38
|
-
rule
|
39
|
-
(
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
def node_type; :linking; end
|
44
|
-
}
|
38
|
+
rule description
|
39
|
+
'(' description ')' / (!( [()] / ',' as_agreed_by) .)*
|
40
|
+
{
|
41
|
+
def node_type; :linking; end
|
42
|
+
}
|
45
43
|
end
|
46
44
|
end
|
47
45
|
end
|
@@ -14,13 +14,13 @@ module ActiveFacts
|
|
14
14
|
rule sum
|
15
15
|
t0:product s tail:( op:add_op s t1:product s )*
|
16
16
|
{
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
17
|
+
def ast
|
18
|
+
if tail.elements.empty?
|
19
|
+
t0.ast
|
20
|
+
else
|
21
|
+
Compiler::Sum.new(t0.ast, *tail.elements.map{|e| e.op.text_value == '-' ? Compiler::Negate.new(e.t1.ast) : e.t1.ast})
|
22
|
+
end
|
23
|
+
end
|
24
24
|
}
|
25
25
|
end
|
26
26
|
|
@@ -31,22 +31,22 @@ module ActiveFacts
|
|
31
31
|
rule product
|
32
32
|
f0:factor s tail:( op:mul_op s f1:factor s )*
|
33
33
|
{
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
34
|
+
def ast
|
35
|
+
if tail.elements.empty?
|
36
|
+
f0.ast
|
37
|
+
else
|
38
|
+
Compiler::Product.new(f0.ast, *tail.elements.map{|e| e.op.text_value != '*' ? Compiler::Reciprocal.new(e.op.text_value, e.f1.ast) : e.f1.ast})
|
39
|
+
end
|
40
|
+
end
|
41
41
|
}
|
42
42
|
end
|
43
43
|
|
44
44
|
rule factor
|
45
45
|
literal u:unit? s
|
46
46
|
{
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
def ast
|
48
|
+
Compiler::Literal.new(literal.value, u.empty? ? nil : u.text_value)
|
49
|
+
end
|
50
50
|
}
|
51
51
|
/ derived_variable
|
52
52
|
/ !context_note '(' s sum s ')' s { def ast; sum.ast; end }
|
@@ -55,10 +55,10 @@ module ActiveFacts
|
|
55
55
|
rule derived_variable
|
56
56
|
derived:term s role_id:(role_name / subscript )?
|
57
57
|
{
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
58
|
+
def ast quantifier = nil, value_constraint = nil, literal = nil, nested_clauses = nil
|
59
|
+
role_name = role_id.empty? ? nil : role_id.value
|
60
|
+
derived.ast(quantifier, nil, role_name, value_constraint, literal, nested_clauses)
|
61
|
+
end
|
62
62
|
}
|
63
63
|
end
|
64
64
|
|
@@ -8,28 +8,28 @@ module ActiveFacts
|
|
8
8
|
module CQL
|
9
9
|
grammar FactTypes
|
10
10
|
rule query
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
s query_clauses r:returning_clause? '?'
|
12
|
+
{
|
13
|
+
def ast
|
14
|
+
Compiler::FactType.new nil, [], query_clauses.ast, (r.empty? ? nil : r)
|
15
|
+
end
|
16
|
+
}
|
17
17
|
end
|
18
18
|
|
19
19
|
rule named_fact_type
|
20
|
-
|
20
|
+
s each?
|
21
21
|
s term_definition_name
|
22
22
|
mapping_pragmas is_where
|
23
23
|
anonymous_fact_type
|
24
24
|
{
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
25
|
+
def ast
|
26
|
+
ft = anonymous_fact_type.ast
|
27
|
+
ft.name = term_definition_name.value
|
28
|
+
pragmas = mapping_pragmas.value
|
29
|
+
pragmas << 'independent' if is_where.independent
|
30
|
+
ft.pragmas = pragmas
|
31
|
+
ft
|
32
|
+
end
|
33
33
|
}
|
34
34
|
end
|
35
35
|
|
@@ -39,46 +39,46 @@ module ActiveFacts
|
|
39
39
|
returning_clause?
|
40
40
|
s ';'
|
41
41
|
{
|
42
|
-
|
42
|
+
def ast
|
43
43
|
clauses_ast = query_clauses.ast
|
44
44
|
conditions = !ctail.empty? ? ctail.a.ast : []
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
45
|
+
returning = respond_to?(:returning_clause) ? returning_clause.ast : nil
|
46
|
+
value_derivation = clauses_ast.detect{|r| r.is_equality_comparison}
|
47
|
+
if !value_derivation and
|
48
|
+
conditions.empty? and
|
49
|
+
clauses_ast.detect{|r| r.includes_literals}
|
50
|
+
raise "Fact instances may not contain conditions" unless conditions.empty? && !returning
|
51
|
+
Compiler::Fact.new clauses_ast
|
52
|
+
elsif (clauses_ast.size == 1 &&
|
53
|
+
clauses_ast[0].phrases.size == 1 &&
|
54
|
+
(popname = clauses_ast[0].phrases[0]) &&
|
55
|
+
!popname.is_a?(Compiler::Reference) &&
|
56
|
+
conditions.detect{|r| r.includes_literals}
|
57
|
+
)
|
58
|
+
Compiler::Fact.new conditions, popname
|
59
|
+
else
|
60
|
+
Compiler::FactType.new nil, clauses_ast, conditions, returning
|
61
|
+
end
|
62
|
+
end
|
63
63
|
}
|
64
64
|
end
|
65
65
|
|
66
66
|
rule query_clauses
|
67
67
|
qualified_clauses
|
68
|
-
|
69
|
-
|
68
|
+
# REVISIT: This creates no precedence between and/or, which could cause confusion.
|
69
|
+
# Should disallow mixed conjuntions - using a sempred?
|
70
70
|
ftail:( conjunction:(',' / and / or ) s qualified_clauses s )*
|
71
|
-
|
72
|
-
|
71
|
+
{
|
72
|
+
def ast
|
73
73
|
clauses_ast = qualified_clauses.ast
|
74
74
|
ftail.elements.each{|e|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
75
|
+
conjunction = e.conjunction.text_value
|
76
|
+
# conjunction = 'and' if conjunction == ',' # ',' means AND, but disallows left-contractions
|
77
|
+
clauses_ast += e.qualified_clauses.ast(conjunction)
|
78
|
+
}
|
79
|
+
clauses_ast
|
80
|
+
end
|
81
|
+
}
|
82
82
|
end
|
83
83
|
|
84
84
|
rule returning_clause
|
@@ -86,33 +86,33 @@ module ActiveFacts
|
|
86
86
|
end
|
87
87
|
|
88
88
|
rule return
|
89
|
-
|
89
|
+
ordering_prefix? phrase+
|
90
90
|
end
|
91
91
|
|
92
92
|
rule qualified_clauses
|
93
93
|
s certainty s contracted_clauses s p:post_qualifiers? s c:context_note?
|
94
94
|
{
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
95
|
+
def ast(conjunction = nil)
|
96
|
+
r = contracted_clauses.ast # An array of clause asts
|
97
|
+
r[0].conjunction = conjunction
|
98
|
+
# pre-qualifiers apply to the first clause, post_qualifiers and context_note to the last
|
99
|
+
# REVISIT: This may be incorrect where the last is a nested clause
|
100
|
+
r[0].certainty = certainty.value
|
101
|
+
r[-1].qualifiers += p.list unless p.empty?
|
102
|
+
r[-1].context_note = c.ast unless c.empty?
|
103
|
+
r
|
104
|
+
end
|
105
105
|
}
|
106
106
|
end
|
107
107
|
|
108
108
|
rule certainty
|
109
|
-
|
110
|
-
|
109
|
+
negative_prefix { def value; false; end }
|
110
|
+
/
|
111
111
|
maybe { def value; nil; end }
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
112
|
+
/
|
113
|
+
definitely { def value; true; end }
|
114
|
+
/
|
115
|
+
'' { def value; true; end }
|
116
116
|
end
|
117
117
|
|
118
118
|
rule post_qualifiers
|
@@ -126,110 +126,110 @@ module ActiveFacts
|
|
126
126
|
|
127
127
|
rule post_qualifier
|
128
128
|
static / transient /
|
129
|
-
|
129
|
+
intransitive / stronglyintransitive / transitive / acyclic / symmetric / asymmetric / antisymmetric / reflexive / irreflexive
|
130
130
|
end
|
131
131
|
|
132
132
|
rule clauses_list
|
133
133
|
clauses tail:( ',' s clauses )*
|
134
134
|
{
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
135
|
+
def ast
|
136
|
+
[clauses.ast, *tail.elements.map{|e| e.clauses.ast }]
|
137
|
+
end
|
138
|
+
}
|
139
139
|
end
|
140
140
|
|
141
141
|
rule clauses
|
142
142
|
contracted_clauses s tail:( and s contracted_clauses s )*
|
143
143
|
{
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
144
|
+
def ast
|
145
|
+
clauses = contracted_clauses.ast
|
146
|
+
tail.elements.map{|e| clauses += e.contracted_clauses.ast }
|
147
|
+
clauses
|
148
|
+
end
|
149
|
+
}
|
150
150
|
end
|
151
151
|
|
152
152
|
rule contracted_clauses
|
153
|
-
|
154
|
-
|
153
|
+
comparison
|
154
|
+
/
|
155
155
|
(
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
156
|
+
contraction # A contraction will terminate this repetition by eating to the end
|
157
|
+
/
|
158
|
+
phrase
|
159
|
+
)+
|
160
160
|
{
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
161
|
+
def ast
|
162
|
+
asts = elements.map{ |r| r.ast }
|
163
|
+
contracted_clauses = []
|
164
|
+
qualifiers = []
|
165
|
+
if asts[-1].is_a?(Array) # A contraction (Array of [role, qualifiers, *clauses])
|
166
|
+
contracted_clauses = asts.pop # Pull off the contracted_clauses
|
167
|
+
contracted_role = contracted_clauses.shift
|
168
|
+
qualifiers = contracted_clauses.shift
|
169
|
+
asts.push(contracted_role) # And replace it by the role removed from the contracted_clauses
|
170
|
+
end
|
171
|
+
clause_ast = Compiler::Clause.new(asts, qualifiers)
|
172
|
+
[clause_ast] + contracted_clauses
|
173
|
+
end
|
174
174
|
}
|
175
175
|
end
|
176
176
|
|
177
177
|
rule contraction
|
178
|
-
|
179
|
-
|
178
|
+
reading_contraction /
|
179
|
+
condition_contraction
|
180
180
|
end
|
181
181
|
|
182
182
|
rule reading_contraction
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
183
|
+
role p:post_qualifiers? conjunction:(that/who) s certainty s contracted_clauses s
|
184
|
+
{
|
185
|
+
def ast
|
186
|
+
# contracted_clauses.ast will return an array of Clauses, but the first clause is special. We must:
|
187
|
+
# * prepend a new role (we get the Role to build *two* ast nodes)
|
188
|
+
# * attach the qualifiers
|
189
|
+
clauses_ast = contracted_clauses.ast
|
190
|
+
clauses_ast[0].conjunction = conjunction.text_value
|
191
|
+
clauses_ast[0].phrases.unshift(role.ast)
|
192
|
+
clauses_ast[0].certainty = certainty.value
|
193
193
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
194
|
+
# A contraction returns an array containing:
|
195
|
+
# * a role AST
|
196
|
+
# * a qualifiers array
|
197
|
+
# * an array of Clauses
|
198
|
+
[role.ast, p.empty? ? [] : p.list] + clauses_ast
|
199
|
+
end
|
200
|
+
}
|
201
201
|
end
|
202
202
|
|
203
203
|
rule condition_contraction
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
204
|
+
role pq:post_qualifiers? certainty s comparator s e2:expression
|
205
|
+
!phrase # The contracted_clauses must not continue here!
|
206
|
+
{
|
207
|
+
def ast
|
208
|
+
c = Compiler::Comparison.new(comparator.text_value, role.ast, e2.ast, certainty.value)
|
209
|
+
c.conjunction = comparator.text_value
|
210
|
+
[ role.ast, pq.empty? ? [] : pq.list, c ]
|
211
|
+
end
|
212
|
+
}
|
213
213
|
end
|
214
214
|
|
215
215
|
rule comparison
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
216
|
+
e1:expression s certainty s comparator s contraction p:post_qualifiers?
|
217
|
+
{
|
218
|
+
def ast
|
219
|
+
role, qualifiers, *clauses_ast = *contraction.ast
|
220
|
+
clauses_ast[0].qualifiers += p.list unless p.empty? # apply post_qualifiers to the contracted clause
|
221
|
+
# clauses_ast[0].conjunction = 'and' # AND is implicit for a contraction
|
222
|
+
c = Compiler::Comparison.new(comparator.text_value, e1.ast, role, certainty.value)
|
223
|
+
[c] + clauses_ast
|
224
|
+
end
|
225
|
+
}
|
226
226
|
/
|
227
|
-
|
227
|
+
certainty e1:expression s comparator s e2:expression # comparisons have no post-qualifiers: p:post_qualifiers?
|
228
228
|
{
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
229
|
+
def ast
|
230
|
+
c = Compiler::Comparison.new(comparator.text_value, e1.ast, e2.ast, certainty.value)
|
231
|
+
[c]
|
232
|
+
end
|
233
233
|
}
|
234
234
|
end
|
235
235
|
|
@@ -238,109 +238,109 @@ module ActiveFacts
|
|
238
238
|
end
|
239
239
|
|
240
240
|
rule phrase
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
241
|
+
role # A role reference containing a term, perhaps with attached paraphernalia
|
242
|
+
/ # A hyphenated non-term. Important: no embedded spaces
|
243
|
+
id tail:('-' !term id)+ s
|
244
|
+
{
|
245
|
+
def ast
|
246
|
+
[id.value, *tail.elements.map{|e| e.id.value}]*"-"
|
247
|
+
end
|
248
|
+
def node_type; :linking; end
|
249
|
+
}
|
250
|
+
/ # A normal non-term
|
251
|
+
!non_phrase id s
|
252
|
+
{
|
253
|
+
def ast
|
254
|
+
id.value
|
255
|
+
end
|
256
|
+
def node_type; :linking; end
|
257
|
+
}
|
258
258
|
end
|
259
259
|
|
260
260
|
rule role
|
261
|
-
|
262
|
-
|
263
|
-
|
261
|
+
aggregate
|
262
|
+
/
|
263
|
+
simple_role
|
264
264
|
end
|
265
265
|
|
266
266
|
rule aggregate
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
267
|
+
aggregate:id s
|
268
|
+
agg_of s term_or_unary s agg_in s # REVISIT: this term may need to pre-scanned in the qualified_clauses
|
269
|
+
'(' qualified_clauses s ')' # REVISIT: Need to test to verify this is the right level (not query_clauses, etc)
|
270
|
+
{
|
271
|
+
def ast
|
272
|
+
raise "Not implemented: AST for '#{aggregate.text_value} of #{term_or_unary.text_value}'"
|
273
|
+
# This returns just the role with the nested clauses, which doesn't even work:
|
274
|
+
term.ast(
|
275
|
+
nil, # No quantifier
|
276
|
+
nil, # No function call
|
277
|
+
nil, # No role_name
|
278
|
+
nil, # No value_constraint
|
279
|
+
nil, # No literal
|
280
|
+
qualified_clauses.ast
|
281
|
+
)
|
282
|
+
end
|
283
|
+
}
|
284
284
|
end
|
285
285
|
|
286
286
|
rule role_quantifier
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
287
|
+
quantifier mapping_pragmas enforcement cn:context_note?
|
288
|
+
{
|
289
|
+
def ast
|
290
|
+
Compiler::Quantifier.new(
|
291
|
+
quantifier.value[0],
|
292
|
+
quantifier.value[1],
|
293
|
+
enforcement.ast,
|
294
|
+
cn.empty? ? nil : cn.ast,
|
295
|
+
mapping_pragmas.value
|
296
|
+
)
|
297
|
+
end
|
298
|
+
}
|
299
299
|
end
|
300
300
|
|
301
301
|
# This is the rule that causes most back-tracking. I think you can see why.
|
302
302
|
rule simple_role
|
303
|
-
|
303
|
+
q:role_quantifier?
|
304
304
|
player:derived_variable
|
305
305
|
lr:(
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
306
|
+
literal u:unit?
|
307
|
+
/
|
308
|
+
value_constraint enforcement
|
309
|
+
)?
|
310
|
+
oj:objectification_step?
|
311
311
|
{
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
312
|
+
def ast
|
313
|
+
if !q.empty? && q.quantifier.value
|
314
|
+
quantifier = q.ast
|
315
|
+
end
|
316
|
+
if !lr.empty?
|
317
|
+
if lr.respond_to?(:literal)
|
318
|
+
literal = Compiler::Literal.new(lr.literal.value, lr.u.empty? ? nil : lr.u.text_value)
|
319
|
+
end
|
320
|
+
value_constraint = Compiler::ValueConstraint.new(lr.value_constraint.ast, lr.enforcement.ast) if lr.respond_to?(:value_constraint)
|
321
|
+
raise "It is not permitted to provide both a literal value and a value constraint" if value_constraint and literal
|
322
|
+
end
|
323
323
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
324
|
+
nested_clauses =
|
325
|
+
if oj.empty?
|
326
|
+
nil
|
327
|
+
else
|
328
|
+
ast = oj.ast
|
329
|
+
ast[0].conjunction = 'where'
|
330
|
+
ast
|
331
|
+
end
|
332
|
+
player.ast(quantifier, value_constraint, literal, nested_clauses)
|
333
|
+
end
|
334
334
|
}
|
335
335
|
end
|
336
336
|
|
337
337
|
rule objectification_step
|
338
338
|
'(' s in_which s facts:query_clauses s ')' s
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
339
|
+
{
|
340
|
+
def ast
|
341
|
+
facts.ast
|
342
|
+
end
|
343
|
+
}
|
344
344
|
end
|
345
345
|
|
346
346
|
rule role_name
|