activefacts 0.8.6 → 0.8.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/Manifest.txt +33 -2
  2. data/README.rdoc +30 -36
  3. data/Rakefile +16 -20
  4. data/bin/afgen +17 -11
  5. data/bin/cql +313 -36
  6. data/download.html +43 -19
  7. data/examples/CQL/Address.cql +15 -15
  8. data/examples/CQL/Blog.cql +8 -8
  9. data/examples/CQL/CompanyDirectorEmployee.cql +6 -5
  10. data/examples/CQL/Death.cql +3 -3
  11. data/examples/CQL/Diplomacy.cql +48 -0
  12. data/examples/CQL/Genealogy.cql +41 -41
  13. data/examples/CQL/Insurance.cql +311 -0
  14. data/examples/CQL/JoinEquality.cql +35 -0
  15. data/examples/CQL/Marriage.cql +1 -1
  16. data/examples/CQL/Metamodel.cql +290 -185
  17. data/examples/CQL/MetamodelNext.cql +420 -0
  18. data/examples/CQL/Monogamy.cql +24 -0
  19. data/examples/CQL/MonthInSeason.cql +27 -0
  20. data/examples/CQL/Moon.cql +23 -0
  21. data/examples/CQL/MultiInheritance.cql +4 -4
  22. data/examples/CQL/NonRoleId.cql +14 -0
  23. data/examples/CQL/OddIdentifier.cql +18 -0
  24. data/examples/CQL/OilSupply.cql +24 -24
  25. data/examples/CQL/OneToOnes.cql +17 -0
  26. data/examples/CQL/Orienteering.cql +55 -55
  27. data/examples/CQL/OrienteeringER.cql +58 -0
  28. data/examples/CQL/PersonPlaysGame.cql +2 -2
  29. data/examples/CQL/RedundantDependency.cql +34 -0
  30. data/examples/CQL/SchoolActivities.cql +5 -5
  31. data/examples/CQL/SeparateSubtype.cql +28 -0
  32. data/examples/CQL/ServiceDirector.cql +283 -0
  33. data/examples/CQL/SimplestUnary.cql +2 -2
  34. data/examples/CQL/SubtypePI.cql +11 -11
  35. data/examples/CQL/Supervision.cql +38 -0
  36. data/examples/CQL/Tests.Test5.Load.cql +38 -0
  37. data/examples/CQL/WaiterTips.cql +33 -0
  38. data/examples/CQL/Warehousing.cql +55 -53
  39. data/examples/CQL/WindowInRoomInBldg.cql +9 -9
  40. data/examples/CQL/unit.cql +433 -544
  41. data/examples/index.html +314 -170
  42. data/examples/intro.html +6 -176
  43. data/examples/local.css +8 -4
  44. data/index.html +40 -25
  45. data/lib/activefacts/api/concept.rb +2 -2
  46. data/lib/activefacts/api/constellation.rb +4 -4
  47. data/lib/activefacts/api/instance.rb +2 -2
  48. data/lib/activefacts/api/instance_index.rb +4 -0
  49. data/lib/activefacts/api/numeric.rb +3 -1
  50. data/lib/activefacts/api/role.rb +1 -1
  51. data/lib/activefacts/api/standard_types.rb +23 -16
  52. data/lib/activefacts/api/support.rb +3 -1
  53. data/lib/activefacts/api/vocabulary.rb +4 -0
  54. data/lib/activefacts/cql/CQLParser.treetop +87 -39
  55. data/lib/activefacts/cql/Concepts.treetop +95 -69
  56. data/lib/activefacts/cql/Context.treetop +11 -2
  57. data/lib/activefacts/cql/Expressions.treetop +23 -59
  58. data/lib/activefacts/cql/FactTypes.treetop +141 -95
  59. data/lib/activefacts/cql/Language/English.treetop +33 -21
  60. data/lib/activefacts/cql/LexicalRules.treetop +6 -1
  61. data/lib/activefacts/cql/Terms.treetop +75 -26
  62. data/lib/activefacts/cql/ValueTypes.treetop +52 -54
  63. data/lib/activefacts/cql/compiler.rb +46 -1691
  64. data/lib/activefacts/cql/compiler/constraint.rb +602 -0
  65. data/lib/activefacts/cql/compiler/entity_type.rb +425 -0
  66. data/lib/activefacts/cql/compiler/fact.rb +300 -0
  67. data/lib/activefacts/cql/compiler/fact_type.rb +230 -0
  68. data/lib/activefacts/cql/compiler/reading.rb +832 -0
  69. data/lib/activefacts/cql/compiler/shared.rb +109 -0
  70. data/lib/activefacts/cql/compiler/value_type.rb +104 -0
  71. data/lib/activefacts/cql/parser.rb +132 -81
  72. data/lib/activefacts/generate/cql.rb +397 -274
  73. data/lib/activefacts/generate/oo.rb +13 -12
  74. data/lib/activefacts/generate/ordered.rb +107 -117
  75. data/lib/activefacts/generate/ruby.rb +34 -38
  76. data/lib/activefacts/generate/sql/mysql.rb +62 -45
  77. data/lib/activefacts/generate/sql/server.rb +59 -42
  78. data/lib/activefacts/input/cql.rb +6 -3
  79. data/lib/activefacts/input/orm.rb +991 -557
  80. data/lib/activefacts/persistence/columns.rb +16 -12
  81. data/lib/activefacts/persistence/foreignkey.rb +7 -4
  82. data/lib/activefacts/persistence/index.rb +3 -4
  83. data/lib/activefacts/persistence/reference.rb +5 -2
  84. data/lib/activefacts/support.rb +20 -14
  85. data/lib/activefacts/version.rb +1 -1
  86. data/lib/activefacts/vocabulary.rb +1 -0
  87. data/lib/activefacts/vocabulary/extensions.rb +328 -44
  88. data/lib/activefacts/vocabulary/metamodel.rb +145 -20
  89. data/lib/activefacts/vocabulary/verbaliser.rb +621 -0
  90. data/spec/absorption_spec.rb +4 -4
  91. data/spec/api/value_type.rb +1 -1
  92. data/spec/cql/context_spec.rb +45 -22
  93. data/spec/cql/deontic_spec.rb +88 -0
  94. data/spec/cql/matching_spec.rb +517 -0
  95. data/spec/cql/samples_spec.rb +88 -31
  96. data/spec/cql/unit_spec.rb +58 -37
  97. data/spec/cql_cql_spec.rb +12 -7
  98. data/spec/cql_mysql_spec.rb +3 -7
  99. data/spec/cql_parse_spec.rb +0 -4
  100. data/spec/cql_ruby_spec.rb +1 -4
  101. data/spec/cql_sql_spec.rb +5 -18
  102. data/spec/cql_symbol_tables_spec.rb +3 -0
  103. data/spec/cqldump_spec.rb +0 -2
  104. data/spec/helpers/array_matcher.rb +35 -0
  105. data/spec/helpers/ctrl_c_support.rb +52 -0
  106. data/spec/helpers/diff_matcher.rb +38 -0
  107. data/spec/helpers/file_matcher.rb +5 -3
  108. data/spec/helpers/string_matcher.rb +39 -0
  109. data/spec/helpers/test_parser.rb +13 -0
  110. data/spec/norma_cql_spec.rb +13 -5
  111. data/spec/norma_ruby_spec.rb +11 -3
  112. data/spec/{absorption_ruby_spec.rb → norma_ruby_sql_spec.rb} +37 -32
  113. data/spec/norma_sql_spec.rb +11 -5
  114. data/spec/norma_tables_spec.rb +33 -29
  115. data/spec/spec_helper.rb +4 -1
  116. data/status.html +92 -23
  117. metadata +102 -36
  118. data/lib/activefacts/generate/cql/html.rb +0 -403
@@ -8,14 +8,12 @@ module ActiveFacts
8
8
  module CQL
9
9
  grammar Expressions
10
10
  rule comparison
11
- e1:expression s comparator s e2:expression
11
+ e1:expression s
12
+ comparator s e2:expression
12
13
  {
13
- def body
14
- [ comparator.text_value,
15
- e1.value,
16
- e2.value
17
- ]
18
- end
14
+ def ast
15
+ Compiler::Comparison.new comparator.text_value, e1.ast, e2.ast
16
+ end
19
17
  }
20
18
  end
21
19
 
@@ -32,16 +30,9 @@ module ActiveFacts
32
30
  rule sum
33
31
  t0:product s tail:( op:add_op s t1:product s )*
34
32
  {
35
- def value
36
- return t0.value if tail.empty?
37
- [ :"+",
38
- *([t0.value] +
39
- tail.elements.map{|e|
40
- e.op.text_value == '-' ? [ :"-", e.t1.value ] : e.t1.value
41
- }
42
- )
43
- ]
44
- end
33
+ def ast
34
+ Compiler::Sum.new(t0.ast, *tail.elements.map{|e| e.op.text_value == '-' ? Compiler::Negate.new(e.t1.ast) : e.t1.ast})
35
+ end
45
36
  }
46
37
  end
47
38
 
@@ -52,65 +43,38 @@ module ActiveFacts
52
43
  rule product
53
44
  f0:factor s tail:( op:mul_op s f1:factor s )*
54
45
  {
55
- def value
56
- return f0.value if tail.empty?
57
- [ :"*",
58
- *([f0.value] +
59
- tail.elements.map{|e|
60
- e.op.text_value != '*' ? [ :"-", e.f1.value ] : e.f1.value
61
- }
62
- )
63
- ]
64
- end
46
+ def ast
47
+ Compiler::Product.new(f0.ast, *tail.elements.map{|e| e.op.text_value != '*' ? Compiler::DivideBy.new(e.op.text_value, e.f1.ast) : e.t1.ast})
48
+ end
65
49
  }
66
50
  end
67
51
 
68
52
  rule factor
69
53
  literal u:unit? s
70
- { def value
71
- u.empty? ? literal.value : [ literal.value, u.text_value ]
72
- end
54
+ {
55
+ def ast
56
+ Compiler::Literal.new(literal.value, u.empty? ? nil : u.text_value)
57
+ end
73
58
  }
74
59
  / derived_variable
75
- / !context '(' s sum s ')' s { def value; sum.value; end }
60
+ / !context_note '(' s sum s ')' s { def ast; sum.ast; end }
76
61
  end
77
62
 
78
63
  rule derived_variable
79
- variable s p:function_call*
64
+ variable:term s p:function_call*
80
65
  {
81
- def value
82
- r = variable.value
83
- # Apply the function_call operators in order:
84
- p.elements.each{|p| r = [ p.value, r ] }
85
- r
86
- end
87
- }
88
- end
89
-
90
- rule variable
91
- id0:id o0:( !written_as s id1:id )?
92
- {
93
- def value
94
- # Variable names may consist of one or two words (optional adjective and a noun):
95
- r = [ :variable, id0.value ]
96
- r += [ o0.id1.value ] unless o0.empty?
97
- r
98
- end
66
+ def ast
67
+ Compiler::FunctionCallChain.new(term.ast, *p.elements.each{|f| f.ast})
68
+ end
99
69
  }
100
70
  end
101
71
 
102
72
  rule function_call
103
73
  '.' s func:id s param_list:( '(' s params:( p0:expression s tail:( ',' s p1:expression s )* )? ')' s )?
104
74
  {
105
- def value
106
- r = [ :"(", func.value ]
107
- return r if param_list.empty? || param_list.params.empty?
108
- r += [ param_list.params.p0.value ]
109
- param_list.params.tail.elements.each{|e|
110
- r += [ e.p1.value ]
111
- }
112
- r
113
- end
75
+ def ast
76
+ Compiler::FunctionCall.new(func.value, *param_list.elements.map{|param| param.ast })
77
+ end
114
78
  }
115
79
  end
116
80
 
@@ -9,32 +9,43 @@ module ActiveFacts
9
9
  grammar FactTypes
10
10
  rule named_fact_type
11
11
  s term_definition_name
12
- ( written_as # REVISIT: What on earth was I thinking when I wrote this?
13
- / s is s mapping_pragmas where # REVISIT: Need a place to put mapping pragmas like [independent]
14
- )
15
- &{|e| input.context.objectified_fact_type(e[1].value); true }
12
+ s is s mapping_pragmas where # REVISIT: Need a place to put mapping pragmas like [independent]
16
13
  anonymous_fact_type
17
14
  {
18
- def value
19
- f = anonymous_fact_type.value
20
- f[0] = term_definition_name.value
21
- f
22
- end
15
+ def ast
16
+ ft = anonymous_fact_type.ast
17
+ ft.name = term_definition_name.value
18
+ ft
19
+ end
23
20
  }
24
21
  end
25
22
 
26
23
  rule anonymous_fact_type
27
- f0:fact_clause
28
- ftail:( (',' / and ) s f1:fact_clause s )*
24
+ fact_clause
25
+ ftail:( (',' / and ) s fact_clause s )*
29
26
  ctail:( (':' / where) s c:conditions s)?
30
27
  returning_clause?
31
- s ';' s
28
+ s ';'
32
29
  {
33
- def value
34
- readings = [ f0.body, *ftail.elements.map{|e| e.f1.body } ]
35
- conditions = !ctail.empty? ? ctail.c.condition_list : []
36
- [ nil, [ :fact_type, readings, conditions ] ]
37
- end
30
+ def ast
31
+ readings = fact_clause.ast
32
+ ftail.elements.each{|e| readings += e.fact_clause.ast }
33
+ conditions = !ctail.empty? ? ctail.c.ast : []
34
+ returning = respond_to?(:returning_clause) ? returning_clause.ast : nil
35
+ if (conditions.empty? && readings.detect{|r| r.includes_literals})
36
+ raise "Fact instances may not contain conditions" unless conditions.empty? && !returning
37
+ Compiler::Fact.new readings
38
+ elsif (readings.size == 1 &&
39
+ readings[0].phrases.size == 1 &&
40
+ (popname = readings[0].phrases[0]) &&
41
+ !popname.is_a?(Compiler::RoleRef) &&
42
+ conditions.detect{|r| r.includes_literals}
43
+ )
44
+ Compiler::Fact.new conditions, popname
45
+ else
46
+ Compiler::FactType.new nil, readings, conditions, returning
47
+ end
48
+ end
38
49
  }
39
50
  end
40
51
 
@@ -49,47 +60,40 @@ module ActiveFacts
49
60
  rule conditions
50
61
  head:condition s tail:( (',' s / and S) next:condition s )*
51
62
  {
52
- def condition_list
53
- [head.value] + tail.elements.map{|i| i.next.value}
54
- end
63
+ def ast
64
+ conditions = head.ast
65
+ tail.elements.each{|i| conditions += i.next.ast}
66
+ conditions
67
+ end
55
68
  }
56
69
  end
57
70
 
58
71
  rule condition
59
- head:clause s
60
- # tail:(or S alternate:clause s )*
72
+ head:clause s # tail:(or S alternate:clause s )*
61
73
  {
62
- def value
63
- # if tail.elements.size == 0
64
- head.clause
65
- # else
66
- # [:"||", head.clause] + tail.elements.map{|i| i.alternate.clause}
67
- # end
68
- end
74
+ def ast
75
+ head.ast
76
+ # Compiler::Alternates.new(head.ast, *tail.elements.map{|i| i.alternate.ast})
77
+ # REVISIT: alternate conditions are not yet implemented
78
+ end
69
79
  }
70
80
  end
71
81
 
72
82
  rule clause
73
83
  # REVISIT: No context for comparisons, yet
74
- (comparison / fact_clause)
75
- {
76
- def clause
77
- self.body
78
- end
79
- }
84
+ comparison / fact_clause
80
85
  end
81
86
 
82
87
  rule fact_clause
83
- s q:qualifier? s reading s p:post_qualifiers? s c:context?
88
+ s q:qualifier? s reading s p:post_qualifiers? s c:context_note?
84
89
  {
85
- def body
86
- [ :fact_clause,
87
- (q.empty? ? [] : [ q.text_value ]) +
88
- (p.empty? ? [] : p.list),
89
- reading.value,
90
- c.empty? ? nil : c.value
91
- ]
92
- end
90
+ def ast
91
+ r = reading.ast # An array of readings
92
+ r[0].qualifiers << q.text_value unless q.empty?
93
+ r[-1].qualifiers += p.list unless p.empty?
94
+ r[-1].context_note = c.ast unless c.empty?
95
+ r
96
+ end
93
97
  }
94
98
  end
95
99
 
@@ -101,96 +105,138 @@ module ActiveFacts
101
105
  '[' s q0:post_qualifier tail:( s ',' s q1:post_qualifier )* s ']' s
102
106
  {
103
107
  def list
104
- [q0.text_value] + tail.elements.map{|e| e.q1.text_value}
108
+ [q0.text_value, *tail.elements.map{|e| e.q1.text_value}]
105
109
  end
106
110
  }
107
111
  end
108
112
 
109
113
  rule post_qualifier
110
- static / transient / intransitive / transitive / acyclic / symmetric
114
+ static / transient /
115
+ intransitive / transitive / acyclic / symmetric / asymmetric / antisymmetric / reflexive / irreflexive
111
116
  end
112
117
 
113
118
  rule reading
114
- role+
119
+ (
120
+ contracted_reading
121
+ /
122
+ role # A role reference containing a term, perhaps with attached paraphernalia
123
+ / # A hyphenated non-term. Important: no embedded spaces
124
+ id tail:('-' !term id)+ s
125
+ {
126
+ def ast
127
+ [id.value, *tail.elements.map{|e| e.id.value}]*"-"
128
+ end
129
+ }
130
+ / # A normal non-term
131
+ !non_role_word id s
132
+ {
133
+ def ast
134
+ id.value
135
+ end
136
+ }
137
+ )+
115
138
  {
116
- def value
117
- elements.map{|r| r.value}
118
- end
139
+ def ast
140
+ asts = elements.map{ |r| r.ast }
141
+ contraction = []
142
+ qualifiers = []
143
+ if asts[-1].is_a?(Array) # A contracted_reading (Array of [role, qualifiers, *readings])
144
+ contraction = asts.pop # Pull off the contraction
145
+ contracted_role = contraction.shift
146
+ qualifiers = contraction.shift
147
+ asts.push(contracted_role) # And replace it by the role removed from the contraction
148
+ end
149
+ reading = Compiler::Reading.new(asts)
150
+ reading.qualifiers += qualifiers
151
+ [reading] + contraction
152
+ end
119
153
  }
120
154
  end
121
155
 
156
+ # REVISIT: and later, similarly for contracted conditions (including comparisons)
157
+ rule contracted_reading
158
+ role p:post_qualifiers? that s q:qualifier? s reading s
159
+ {
160
+ def ast
161
+ # reading.ast will return an array of Readings, but the first reading is special. We must:
162
+ # * prepend a new role
163
+ # * attach the qualifiers
164
+ readings = reading.ast
165
+ readings[0].phrases.unshift(role.ast)
166
+ readings[0].qualifiers << q.text_value unless q.empty? # Add maybe/definitely
167
+
168
+ # A contracted_reading returns an array containing:
169
+ # * a role AST
170
+ # * a qualifiers array
171
+ # * an array of Readings
172
+ [role.ast, p.empty? ? [] : p.list] + readings
173
+ end
174
+ }
175
+ end
176
+
122
177
  # This is the rule that causes most back-tracking. I think you can see why.
123
178
  # When we have an expression, we will come down here perhaps multiple times,
124
179
  # but find no way out as soon as we hit the trailing non_role.
125
180
  rule role
126
181
  q:(quantifier enforcement)?
127
- adj0:(a:role_word '-' s)?
128
- player:role_word !'-' s?
129
- adj1:( '-' a:(a:role_word s)? )?
130
- func:function_call?
182
+ player:term
183
+ func:function_call? s
131
184
  role_id:(role_name / subscript )?
132
- lr:( literal / restriction enforcement )?
133
- !non_role
185
+ lr:(
186
+ literal u:unit?
187
+ /
188
+ value_constraint enforcement
189
+ )?
190
+ oj:objectification_join?
191
+ !non_role # If we integrate fact_clauses with comparisons, this can go.
134
192
  {
135
- def value
136
- r = {}
137
- if !q.empty?
138
- quantifier = q.quantifier.value # "some" quantifier has nil value
139
- r[:quantifier_restriction] = q.enforcement.value
193
+ def ast
194
+ if !q.empty? && q.quantifier.value
195
+ quantifier = Compiler::Quantifier.new(q.quantifier.value[0], q.quantifier.value[1], q.enforcement.ast)
140
196
  end
141
-
142
- r[:quantifier] = quantifier if quantifier
143
- r[:leading_adjective] = adj0.a.value unless adj0.empty?
144
-
145
- r[:word] = player.value
146
-
147
- r[:trailing_adjective] = adj1.a.a.value unless adj1.empty?
148
- r[:function] = func.value if !func.empty?
149
- r[:role_name] = role_id.value unless role_id.empty?
150
- if !lr.empty? && lr.respond_to?(:restriction)
151
- r[:restriction] = lr.restriction.ranges
152
- r[:restriction_enforcement] = lr.enforcement.value
197
+ role_name = role_id.empty? ? nil : role_id.value
198
+ function_call = nil
199
+ if !lr.empty?
200
+ if lr.respond_to?(:literal)
201
+ literal = lr.literal.value
202
+ raise "Literals with units are not yet processed" unless lr.u.empty?
203
+ end
204
+ value_constraint = Compiler::ValueConstraint.new(lr.value_constraint.ranges, lr.enforcement.ast) if lr.respond_to?(:value_constraint)
205
+ raise "It is not permitted to provide both a literal value and a value restriction" if value_constraint and literal
153
206
  end
154
- r[:literal] = lr.value if !lr.empty? && lr.respond_to?(:value)
155
207
 
156
- r
157
- end
208
+ objectification_join = oj.empty? ? nil : oj.ast
209
+ player.ast(quantifier, function_call, role_name, value_constraint, literal, objectification_join)
210
+ end
158
211
  }
159
212
  end
160
213
 
214
+ rule objectification_join
215
+ '(' s where s fact_clause s ')' s
216
+ {
217
+ def ast
218
+ fact_clause.ast
219
+ end
220
+ }
221
+ end
222
+
161
223
  rule role_name
162
- '(' s as S r:id s ')' s
224
+ '(' s as S r:term s ')' s
163
225
  { def value; r.value; end }
164
226
  end
165
227
 
166
228
  rule subscript
167
- '(' i:([1-9] [0-9]*) ')' s
229
+ '(' s i:([1-9] [0-9]*) s ')' s
168
230
  { def value; i.text_value.to_i; end }
169
231
  end
170
232
 
171
233
  rule non_role
172
- # Any of these is illegal in or following a reading:
234
+ # Any of these is illegal in or following a reading (they indicate a comparison is coming). Later, this will change:
173
235
  comparator
174
236
  / add_op
175
237
  / mul_op
176
238
  end
177
239
 
178
- rule role_word
179
- !non_role_word id
180
- { def value; id.value; end }
181
- end
182
-
183
- rule non_role_word
184
- # These words are illegal in (but maybe ok following) a reading where a role word is expected:
185
- and
186
- / if
187
- / only
188
- / or
189
- / quantifier
190
- / restriction
191
- / but
192
- end
193
-
194
240
  end
195
241
  end
196
242
  end
@@ -21,25 +21,33 @@ module ActiveFacts
21
21
  end
22
22
 
23
23
  rule quantifier
24
- each s { def value; [1, nil]; end }
25
- / some s { def value; nil; end }
26
- # REVISIT: "Some" means that any prior occurrence of this role player is to be ignored; this is a new occurrence
27
- # "that" on the other hand means that this role player was *previously* designated using "some".
28
- # These distinctions are lost here
29
- / that s { def value; nil; end }
30
- / one s { def value; [1, 1]; end }
31
- / no s { def value; [0, 0]; end }
32
- / exactly s quantity { def value; q = quantity.value; [q, q]; end }
33
- / at s least s quantity most:( and s at s most s q:quantity )?
34
- { def value;
35
- [ quantity.value,
36
- most.empty? ? nil : most.q.value
37
- ]
38
- end
39
- }
40
- / at s most s quantity { def value; [ nil, quantity.value ]; end }
41
- / from s numeric_range s { def value; numeric_range.value; end }
42
- / either_all_or_none s { def value; [ -1, 1 ]; end }
24
+ (
25
+ each s { def value; [1, nil]; end }
26
+ / some s { def value; nil; end }
27
+ # REVISIT: "Some" means that any prior occurrence of this role player is to be ignored; this is a new occurrence
28
+ # "that" on the other hand means that this role player was *previously* designated using "some".
29
+ # These distinctions are lost here
30
+ / that s { def value; nil; end }
31
+ / one s { def value; [1, 1]; end }
32
+ / no s { def value; [0, 0]; end }
33
+ / exactly s quantity { def value; q = quantity.value; [q, q]; end }
34
+ / at s least s quantity most:( and s at s most s q:quantity )?
35
+ { def value;
36
+ [ quantity.value,
37
+ most.empty? ? nil : most.q.value
38
+ ]
39
+ end
40
+ }
41
+ / at s most s quantity { def value; [ nil, quantity.value ]; end }
42
+ / from s numeric_range s { def value; numeric_range.value; end }
43
+ / either_all_or_none s { def value; [ -1, 1 ]; end }
44
+ )
45
+ {
46
+ def ast
47
+ v = value
48
+ Compiler::Quantifier.new(v[0], v[1])
49
+ end
50
+ }
43
51
  end
44
52
 
45
53
  rule quantity
@@ -92,6 +100,8 @@ module ActiveFacts
92
100
  end
93
101
 
94
102
  rule acyclic 'acyclic' !alphanumeric end
103
+ rule antisymmetric 'antisymmetric' !alphanumeric end
104
+ rule asymmetric 'asymmetric' !alphanumeric end
95
105
  rule alias 'alias' !alphanumeric end
96
106
  rule all 'all' !alphanumeric end
97
107
  rule and 'and' !alphanumeric end
@@ -106,7 +116,7 @@ module ActiveFacts
106
116
  rule each 'each' !alphanumeric end
107
117
  rule either 'either' !alphanumeric end
108
118
  rule entity 'entity' !alphanumeric end
109
- rule ephemeral 'ephemeral' !alphanumeric end
119
+ rule ephemera 'ephemera' !alphanumeric end
110
120
  rule exactly 'exactly' !alphanumeric end
111
121
  rule false 'false' !alphanumeric end
112
122
  rule feminine 'feminine' !alphanumeric end
@@ -117,6 +127,7 @@ module ActiveFacts
117
127
  rule import 'import' !alphanumeric end
118
128
  rule includes 'includes' !alphanumeric end
119
129
  rule intransitive 'intransitive' !alphanumeric end
130
+ rule irreflexive 'irreflexive' !alphanumeric end
120
131
  rule is 'is' !alphanumeric end
121
132
  rule its 'its' !alphanumeric end
122
133
  rule least 'least' !alphanumeric end
@@ -127,7 +138,7 @@ module ActiveFacts
127
138
  rule no 'no' !alphanumeric end
128
139
  rule none 'none' !alphanumeric end
129
140
  rule not 'not' !alphanumeric end
130
- rule either_all_or_none either s all s or s none end
141
+ rule either_all_or_none either s all s or s ( none / no ) end
131
142
  rule one 'one' !alphanumeric end
132
143
  rule only 'only' !alphanumeric end
133
144
  rule or 'or' !alphanumeric end
@@ -135,6 +146,7 @@ module ActiveFacts
135
146
  rule partitioned 'partitioned' !alphanumeric end
136
147
  rule personal 'personal' !alphanumeric end
137
148
  rule restricted 'restricted' !alphanumeric end
149
+ rule reflexive 'reflexive' !alphanumeric end
138
150
  rule returning 'returning' !alphanumeric end
139
151
  rule separate 'separate' !alphanumeric end
140
152
  rule some 'some' !alphanumeric end