activefacts 0.7.3 → 0.8.5
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +19 -0
- data/Manifest.txt +24 -2
- data/Rakefile +25 -3
- data/bin/afgen +1 -1
- data/bin/cql +13 -2
- data/css/offline.css +3 -0
- data/css/orm2.css +24 -0
- data/css/print.css +8 -0
- data/css/style-print.css +357 -0
- data/css/style.css +387 -0
- data/download.html +85 -0
- data/examples/CQL/Address.cql +3 -3
- data/examples/CQL/Blog.cql +13 -14
- data/examples/CQL/CompanyDirectorEmployee.cql +4 -4
- data/examples/CQL/Death.cql +3 -2
- data/examples/CQL/Genealogy.cql +13 -11
- data/examples/CQL/Marriage.cql +2 -2
- data/examples/CQL/Metamodel.cql +136 -93
- data/examples/CQL/MultiInheritance.cql +2 -2
- data/examples/CQL/OilSupply.cql +14 -10
- data/examples/CQL/Orienteering.cql +22 -19
- data/examples/CQL/PersonPlaysGame.cql +3 -2
- data/examples/CQL/SchoolActivities.cql +4 -2
- data/examples/CQL/SimplestUnary.cql +1 -1
- data/examples/CQL/SubtypePI.cql +6 -7
- data/examples/CQL/Warehousing.cql +16 -19
- data/examples/CQL/unit.cql +584 -0
- data/examples/index.html +276 -0
- data/examples/intro.html +497 -0
- data/examples/local.css +20 -0
- data/index.html +96 -0
- data/lib/activefacts/api/concept.rb +48 -46
- data/lib/activefacts/api/constellation.rb +43 -23
- data/lib/activefacts/api/entity.rb +2 -2
- data/lib/activefacts/api/instance.rb +6 -2
- data/lib/activefacts/api/instance_index.rb +5 -0
- data/lib/activefacts/api/value.rb +8 -2
- data/lib/activefacts/api/vocabulary.rb +15 -10
- data/lib/activefacts/cql/CQLParser.treetop +109 -88
- data/lib/activefacts/cql/Concepts.treetop +32 -10
- data/lib/activefacts/cql/Context.treetop +34 -0
- data/lib/activefacts/cql/Expressions.treetop +9 -9
- data/lib/activefacts/cql/FactTypes.treetop +30 -31
- data/lib/activefacts/cql/Language/English.treetop +50 -0
- data/lib/activefacts/cql/LexicalRules.treetop +2 -1
- data/lib/activefacts/cql/Terms.treetop +117 -0
- data/lib/activefacts/cql/ValueTypes.treetop +152 -0
- data/lib/activefacts/cql/compiler.rb +1718 -0
- data/lib/activefacts/cql/parser.rb +124 -57
- data/lib/activefacts/generate/absorption.rb +1 -1
- data/lib/activefacts/generate/cql.rb +111 -100
- data/lib/activefacts/generate/cql/html.rb +5 -5
- data/lib/activefacts/generate/oo.rb +3 -3
- data/lib/activefacts/generate/ordered.rb +51 -19
- data/lib/activefacts/generate/ruby.rb +10 -8
- data/lib/activefacts/generate/sql/mysql.rb +14 -10
- data/lib/activefacts/generate/sql/server.rb +29 -24
- data/lib/activefacts/input/cql.rb +9 -1264
- data/lib/activefacts/input/orm.rb +213 -200
- data/lib/activefacts/persistence/columns.rb +11 -10
- data/lib/activefacts/persistence/index.rb +15 -18
- data/lib/activefacts/persistence/reference.rb +17 -17
- data/lib/activefacts/persistence/tables.rb +50 -51
- data/lib/activefacts/version.rb +1 -1
- data/lib/activefacts/vocabulary/extensions.rb +79 -8
- data/lib/activefacts/vocabulary/metamodel.rb +183 -114
- data/spec/absorption_ruby_spec.rb +99 -0
- data/spec/absorption_spec.rb +3 -4
- data/spec/api/constellation.rb +1 -1
- data/spec/api/entity_type.rb +3 -1
- data/spec/api/instance.rb +4 -2
- data/spec/api/roles.rb +8 -6
- data/spec/api_spec.rb +1 -2
- data/spec/cql/context_spec.rb +71 -0
- data/spec/cql/samples_spec.rb +154 -0
- data/spec/cql/unit_spec.rb +375 -0
- data/spec/cql_cql_spec.rb +31 -21
- data/spec/cql_mysql_spec.rb +70 -0
- data/spec/cql_parse_spec.rb +15 -9
- data/spec/cql_ruby_spec.rb +27 -13
- data/spec/cql_sql_spec.rb +42 -16
- data/spec/cql_symbol_tables_spec.rb +2 -3
- data/spec/cqldump_spec.rb +7 -7
- data/spec/helpers/file_matcher.rb +39 -0
- data/spec/norma_cql_spec.rb +20 -12
- data/spec/norma_ruby_spec.rb +6 -3
- data/spec/norma_sql_spec.rb +6 -3
- data/spec/norma_tables_spec.rb +6 -4
- data/spec/spec_helper.rb +27 -8
- data/status.html +69 -0
- data/why.html +60 -0
- metadata +34 -11
- data/lib/activefacts/cql/DataTypes.treetop +0 -81
- data/spec/cql_unit_spec.rb +0 -330
@@ -5,106 +5,127 @@
|
|
5
5
|
# Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
|
6
6
|
#
|
7
7
|
module ActiveFacts
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
module CQL
|
9
|
+
grammar CQL
|
10
|
+
include LexicalRules
|
11
|
+
include Language # One of the language modules provides this module
|
12
|
+
include Expressions
|
13
|
+
include Terms
|
14
|
+
include Concepts
|
15
|
+
include ValueTypes
|
16
|
+
include FactTypes
|
17
|
+
include Context
|
15
18
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
19
|
+
rule cql_file
|
20
|
+
s seq:definition*
|
21
|
+
{
|
22
|
+
def definitions
|
23
|
+
seq.elements.map{|e|
|
24
|
+
e.value rescue $stderr.puts "Can't call value() on #{e.inspect}"
|
25
|
+
}
|
26
|
+
end
|
27
|
+
}
|
28
|
+
end
|
26
29
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
# Each definition has a value() method that returns an array like
|
31
|
+
# either [name, [kind, definition]] or [name, kind]:
|
32
|
+
rule definition
|
33
|
+
vocabulary_definition
|
34
|
+
/ import_definition
|
35
|
+
/ prescan
|
36
|
+
/ constraint
|
37
|
+
/ unit_definition
|
38
|
+
/ concept
|
39
|
+
end
|
35
40
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
rule vocabulary_definition
|
42
|
+
s vocabulary S id s ';' s &{|e| input.context.vocabulary(e[3].text_value); true }
|
43
|
+
{
|
44
|
+
def value
|
45
|
+
[ id.value, [ :vocabulary ] ]
|
46
|
+
end
|
47
|
+
}
|
48
|
+
end
|
44
49
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
50
|
+
rule import_definition
|
51
|
+
s import S id alias_list ';' s
|
52
|
+
{
|
53
|
+
def value
|
54
|
+
puts "import #{id.value}: not implemented"
|
55
|
+
[ id.value, [ :import ], alias_list.value ]
|
56
|
+
end
|
57
|
+
}
|
58
|
+
end
|
54
59
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
60
|
+
# REVISIT: Need a way to define equivalent readings for fact types here (and in the metamodel)
|
61
|
+
rule alias_list
|
62
|
+
( s ',' s alias S aliased_from:id S as S alias_to:id s )*
|
63
|
+
{
|
64
|
+
def value
|
65
|
+
elements.inject({}){|h, e| h[e.aliased_from.value] = e.alias_to; h }
|
66
|
+
end
|
67
|
+
}
|
68
|
+
end
|
64
69
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
70
|
+
rule constraint
|
71
|
+
subset_constraint /
|
72
|
+
equality_constraint /
|
73
|
+
set_constraint /
|
74
|
+
presence_constraint
|
75
|
+
# REVISIT: / value_constraint
|
76
|
+
end
|
72
77
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
78
|
+
# presence constraint:
|
79
|
+
rule presence_constraint
|
80
|
+
s 'each' s ('combination' S)? role_list s 'occurs' s quantifier s 'time' s 'in' s
|
81
|
+
readings_list s
|
82
|
+
c:context? ';' s
|
83
|
+
{ def value; [ nil, [ :constraint, :presence, role_list.roles, quantifier.value, readings_list.value, c.empty? ? nil : c.value ] ]; end }
|
84
|
+
end
|
80
85
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
86
|
+
# set (exclusion, mandatory exclusion, complex equality) constraint
|
87
|
+
rule set_constraint
|
88
|
+
s 'for' s 'each' s role_list s quantifier s 'of' s 'these' s 'holds' s ':' s
|
89
|
+
readings_list s
|
90
|
+
c:context? ';' s
|
91
|
+
{ def value; [ nil, [ :constraint, :set, role_list.roles, quantifier.value, readings_list.value, c.empty? ? nil : c.value ] ]; end }
|
92
|
+
/
|
93
|
+
s either? s r1:readings s or s r2:readings exclusion:(but s not s both s)? c:context? ';' s
|
94
|
+
{ def value;
|
95
|
+
[ nil, [ :constraint, :set,
|
96
|
+
nil, # No roles names, rely on the join
|
97
|
+
exclusion.text_value.empty? ?
|
98
|
+
[1, nil] : # At least one (meaning 1 or 2/more)
|
99
|
+
[1,1], # Exactly one (1 and only 1)
|
100
|
+
[r1.value, r2.value],
|
101
|
+
c.empty? ? nil : c.value
|
102
|
+
] ];
|
103
|
+
end
|
104
|
+
}
|
105
|
+
end
|
85
106
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
{ def value; [ nil, [ :constraint, :set, role_list.roles, quantifier.value, *readings_list.value ] ]; end }
|
92
|
-
end
|
107
|
+
rule subset_constraint
|
108
|
+
s readings s only s if s r2:readings s
|
109
|
+
c:context? ';' s
|
110
|
+
{ def value; [ nil, [ :constraint, :subset, [readings.value, r2.value], c.empty? ? nil : c.value ] ]; end }
|
111
|
+
end
|
93
112
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
113
|
+
rule equality_constraint
|
114
|
+
s readings s tail:( if s and s only s if s readings s)+
|
115
|
+
c:context? ';' s
|
116
|
+
{ def value; [ nil, [ :constraint, :equality, [readings.value] + tail.elements.map{|e| e.readings.value }, c.empty? ? nil : c.value ]]; end }
|
117
|
+
end
|
98
118
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
119
|
+
rule readings_list
|
120
|
+
readings tail:( ',' s readings )*
|
121
|
+
{ def value; [readings.value]+tail.elements.map{|e| e.readings.value }; end }
|
122
|
+
end
|
103
123
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
124
|
+
rule readings
|
125
|
+
reading s tail:( and s reading s )*
|
126
|
+
{ def value; [reading.value]+tail.elements.map{|e| e.reading.value }; end }
|
127
|
+
end
|
108
128
|
|
129
|
+
end
|
109
130
|
end
|
110
131
|
end
|
@@ -8,20 +8,28 @@ module ActiveFacts
|
|
8
8
|
module CQL
|
9
9
|
grammar Concepts
|
10
10
|
rule concept
|
11
|
-
|
12
|
-
/
|
11
|
+
value_type
|
12
|
+
/ entity_type
|
13
13
|
/ named_fact_type
|
14
14
|
/ anonymous_fact_type
|
15
15
|
end
|
16
16
|
|
17
17
|
rule entity_type
|
18
|
-
s
|
18
|
+
s term_definition_name
|
19
19
|
sup:(basetype / subtype)
|
20
|
+
&{|e| input.context.entity_type(e[1].value); true }
|
21
|
+
mapping_pragmas
|
20
22
|
ec:entity_conditions?
|
21
23
|
';' s
|
22
24
|
{
|
25
|
+
def defined_type
|
26
|
+
[ :entity_type, sup.supers, sup.identifier, mapping_pragmas.value, (ec.empty? ? nil : ec.conditions) ]
|
27
|
+
end
|
28
|
+
|
23
29
|
def value
|
24
|
-
[
|
30
|
+
[ term_definition_name.value,
|
31
|
+
defined_type
|
32
|
+
]
|
25
33
|
end
|
26
34
|
}
|
27
35
|
end
|
@@ -54,15 +62,15 @@ module ActiveFacts
|
|
54
62
|
primary:id s
|
55
63
|
alternate_supertypes:( ',' s !identified_by name:id s )*
|
56
64
|
{ def value
|
57
|
-
[primary.
|
65
|
+
[primary.value]+alternate_supertypes.elements.map{|sup| sup.name.value}
|
58
66
|
end
|
59
67
|
}
|
60
68
|
end
|
61
69
|
|
62
70
|
rule identification
|
63
71
|
# REVISIT: Consider distinguishing "-Id" from just "Id", and not prepending the entity type name if no "-"
|
64
|
-
identified_by its s id
|
65
|
-
{ def value; {:mode => id.text_value }; end }
|
72
|
+
identified_by its s id value_type_parameters r:restriction? # Reference Mode; restriction may be needed for the ValueType
|
73
|
+
{ def value; {:mode => id.value, :restriction => (r.text_value.empty? ? nil : r.ranges), :parameters => value_type_parameters.values }; end }
|
66
74
|
/
|
67
75
|
identified_by role_list
|
68
76
|
{ def value; {:roles => role_list.roles }; end }
|
@@ -93,15 +101,16 @@ module ActiveFacts
|
|
93
101
|
l:lead_adj? tail:(s role_player_id)+ s t:trail_adj?
|
94
102
|
{
|
95
103
|
def value
|
96
|
-
(l.empty? ? [] : [l.role_player_id.
|
97
|
-
tail.elements.map{|e| e.role_player_id.
|
98
|
-
(t.empty? ? [] : [t.role_player_id.
|
104
|
+
(l.empty? ? [] : [l.role_player_id.value]) +
|
105
|
+
tail.elements.map{|e| e.role_player_id.value } +
|
106
|
+
(t.empty? ? [] : [t.role_player_id.value])
|
99
107
|
end
|
100
108
|
}
|
101
109
|
end
|
102
110
|
|
103
111
|
rule role_player_id
|
104
112
|
!(role_list_sep / quantifier) id
|
113
|
+
{ def value; id.value; end }
|
105
114
|
end
|
106
115
|
|
107
116
|
rule role_list_sep
|
@@ -113,6 +122,19 @@ module ActiveFacts
|
|
113
122
|
'(' s '.' s mode_name:id s ')' s
|
114
123
|
end
|
115
124
|
|
125
|
+
rule mapping_pragmas
|
126
|
+
'[' s h:mapping_pragma t:(s ',' s mapping_pragma)* s ']' s
|
127
|
+
{ def value; [h.value] + t.elements.map{|e| e.mapping_pragma.value}; end }
|
128
|
+
/
|
129
|
+
''
|
130
|
+
{ def value; []; end }
|
131
|
+
end
|
132
|
+
|
133
|
+
rule mapping_pragma
|
134
|
+
(independent / separate / partitioned / personal / feminine / masculine)
|
135
|
+
{ def value; text_value; end }
|
136
|
+
end
|
137
|
+
|
116
138
|
rule entity_conditions
|
117
139
|
(':' / where) s c:conditions?
|
118
140
|
{
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#
|
2
|
+
# ActiveFacts CQL Parser.
|
3
|
+
# Parse rules relating to definition context.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
|
6
|
+
#
|
7
|
+
module ActiveFacts
|
8
|
+
module CQL
|
9
|
+
grammar Context
|
10
|
+
rule context
|
11
|
+
'('
|
12
|
+
w:who_says? s context_type discussion agreed:(',' a:as_agreed_by)? s
|
13
|
+
')'
|
14
|
+
{ def value; [ w.empty? ? nil : w.value, context_type.value, discussion.text_value, agreed.empty? ? [] : agreed.a.value]; end }
|
15
|
+
end
|
16
|
+
|
17
|
+
rule who_says
|
18
|
+
according_to people s ','
|
19
|
+
{ def value; people.value; end }
|
20
|
+
end
|
21
|
+
|
22
|
+
rule context_type
|
23
|
+
because { def value; 'because'; end } /
|
24
|
+
as_opposed_to { def value; 'as_opposed_to'; end } /
|
25
|
+
so_that { def value; 'so_that'; end } /
|
26
|
+
to_avoid { def value; 'to_avoid'; end }
|
27
|
+
end
|
28
|
+
|
29
|
+
rule discussion
|
30
|
+
'(' discussion ')' / (!( [()] / ',' as_agreed_by) .)*
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -30,14 +30,14 @@ module ActiveFacts
|
|
30
30
|
end
|
31
31
|
|
32
32
|
rule sum
|
33
|
-
t0:
|
33
|
+
t0:product s tail:( op:add_op s t1:product s )*
|
34
34
|
{
|
35
35
|
def value
|
36
36
|
return t0.value if tail.empty?
|
37
37
|
[ :"+",
|
38
38
|
*([t0.value] +
|
39
39
|
tail.elements.map{|e|
|
40
|
-
e.
|
40
|
+
e.op.text_value == '-' ? [ :"-", e.t1.value ] : e.t1.value
|
41
41
|
}
|
42
42
|
)
|
43
43
|
]
|
@@ -49,15 +49,15 @@ module ActiveFacts
|
|
49
49
|
'+' / '-'
|
50
50
|
end
|
51
51
|
|
52
|
-
rule
|
53
|
-
f0:factor s tail:(
|
52
|
+
rule product
|
53
|
+
f0:factor s tail:( op:mul_op s f1:factor s )*
|
54
54
|
{
|
55
55
|
def value
|
56
56
|
return f0.value if tail.empty?
|
57
57
|
[ :"*",
|
58
58
|
*([f0.value] +
|
59
59
|
tail.elements.map{|e|
|
60
|
-
e.
|
60
|
+
e.op.text_value != '*' ? [ :"-", e.f1.value ] : e.f1.value
|
61
61
|
}
|
62
62
|
)
|
63
63
|
]
|
@@ -72,7 +72,7 @@ module ActiveFacts
|
|
72
72
|
end
|
73
73
|
}
|
74
74
|
/ derived_variable
|
75
|
-
/ '(' s sum s ')' s { def value; sum.value; end }
|
75
|
+
/ !context '(' s sum s ')' s { def value; sum.value; end }
|
76
76
|
end
|
77
77
|
|
78
78
|
rule derived_variable
|
@@ -92,8 +92,8 @@ module ActiveFacts
|
|
92
92
|
{
|
93
93
|
def value
|
94
94
|
# Variable names may consist of one or two words (optional adjective and a noun):
|
95
|
-
r = [ :variable, id0.
|
96
|
-
r += [ o0.id1.
|
95
|
+
r = [ :variable, id0.value ]
|
96
|
+
r += [ o0.id1.value ] unless o0.empty?
|
97
97
|
r
|
98
98
|
end
|
99
99
|
}
|
@@ -103,7 +103,7 @@ module ActiveFacts
|
|
103
103
|
'.' s func:id s param_list:( '(' s params:( p0:expression s tail:( ',' s p1:expression s )* )? ')' s )?
|
104
104
|
{
|
105
105
|
def value
|
106
|
-
r = [ :"(", func.
|
106
|
+
r = [ :"(", func.value ]
|
107
107
|
return r if param_list.empty? || param_list.params.empty?
|
108
108
|
r += [ param_list.params.p0.value ]
|
109
109
|
param_list.params.tail.elements.each{|e|
|
@@ -8,12 +8,16 @@ module ActiveFacts
|
|
8
8
|
module CQL
|
9
9
|
grammar FactTypes
|
10
10
|
rule named_fact_type
|
11
|
-
s
|
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
16
|
anonymous_fact_type
|
13
17
|
{
|
14
18
|
def value
|
15
19
|
f = anonymous_fact_type.value
|
16
|
-
f[0] =
|
20
|
+
f[0] = term_definition_name.value
|
17
21
|
f
|
18
22
|
end
|
19
23
|
}
|
@@ -27,14 +31,9 @@ module ActiveFacts
|
|
27
31
|
s ';' s
|
28
32
|
{
|
29
33
|
def value
|
30
|
-
[
|
31
|
-
|
32
|
-
|
33
|
-
:fact_type,
|
34
|
-
[ f0.body, *ftail.elements.map{|e| e.f1.body } ],
|
35
|
-
!ctail.empty? ? ctail.c.condition_list : []
|
36
|
-
]
|
37
|
-
]
|
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 ] ]
|
38
37
|
end
|
39
38
|
}
|
40
39
|
end
|
@@ -71,6 +70,7 @@ module ActiveFacts
|
|
71
70
|
end
|
72
71
|
|
73
72
|
rule clause
|
73
|
+
# REVISIT: No context for comparisons, yet
|
74
74
|
(comparison / fact_clause)
|
75
75
|
{
|
76
76
|
def clause
|
@@ -80,13 +80,14 @@ module ActiveFacts
|
|
80
80
|
end
|
81
81
|
|
82
82
|
rule fact_clause
|
83
|
-
s q:qualifier? s reading s p:post_qualifiers? s
|
83
|
+
s q:qualifier? s reading s p:post_qualifiers? s c:context?
|
84
84
|
{
|
85
85
|
def body
|
86
86
|
[ :fact_clause,
|
87
87
|
(q.empty? ? [] : [ q.text_value ]) +
|
88
88
|
(p.empty? ? [] : p.list),
|
89
|
-
reading.value
|
89
|
+
reading.value,
|
90
|
+
c.empty? ? nil : c.value
|
90
91
|
]
|
91
92
|
end
|
92
93
|
}
|
@@ -110,8 +111,6 @@ module ActiveFacts
|
|
110
111
|
end
|
111
112
|
|
112
113
|
rule reading
|
113
|
-
subtype_invocation
|
114
|
-
/
|
115
114
|
role+
|
116
115
|
{
|
117
116
|
def value
|
@@ -120,18 +119,6 @@ module ActiveFacts
|
|
120
119
|
}
|
121
120
|
end
|
122
121
|
|
123
|
-
# REVISIT: This allows invocation from subtype to supertype. We need the reverse as well (Employee is a Manager).
|
124
|
-
# Now that subtyping fact types have readings created during compilation, perhaps these custom rules can be removed?
|
125
|
-
rule subtype_invocation
|
126
|
-
(('some'/'that') S)? subtype:id s subtype_prefix (('some'/'that') S)? supertype:id
|
127
|
-
{
|
128
|
-
def value
|
129
|
-
[{:subtype => subtype.text_value, :supertype => supertype.text_value }]
|
130
|
-
# [subtype.text_value, "is", "a", "subtype", "of", supertype.text_value].map{|w| {:word => w}}
|
131
|
-
end
|
132
|
-
}
|
133
|
-
end
|
134
|
-
|
135
122
|
# This is the rule that causes most back-tracking. I think you can see why.
|
136
123
|
# When we have an expression, we will come down here perhaps multiple times,
|
137
124
|
# but find no way out as soon as we hit the trailing non_role.
|
@@ -141,7 +128,7 @@ module ActiveFacts
|
|
141
128
|
player:role_word !'-' s?
|
142
129
|
adj1:( '-' a:(a:role_word s)? )?
|
143
130
|
func:function_call?
|
144
|
-
|
131
|
+
role_id:(role_name / subscript )?
|
145
132
|
lr:( literal / restriction )?
|
146
133
|
!non_role
|
147
134
|
{
|
@@ -150,13 +137,13 @@ module ActiveFacts
|
|
150
137
|
quantifier = !q.empty? && q.value # "some" quantifier has nil value
|
151
138
|
|
152
139
|
r[:quantifier] = quantifier if quantifier
|
153
|
-
r[:leading_adjective] = adj0.a.
|
140
|
+
r[:leading_adjective] = adj0.a.value unless adj0.empty?
|
154
141
|
|
155
|
-
r[:word] = player.
|
142
|
+
r[:word] = player.value
|
156
143
|
|
157
|
-
r[:trailing_adjective] = adj1.a.a.
|
144
|
+
r[:trailing_adjective] = adj1.a.a.value unless adj1.empty?
|
158
145
|
r[:function] = func.value if !func.empty?
|
159
|
-
r[:role_name] =
|
146
|
+
r[:role_name] = role_id.value unless role_id.empty?
|
160
147
|
r[:restriction] = lr.ranges if !lr.empty? && lr.respond_to?(:ranges)
|
161
148
|
r[:literal] = lr.value if !lr.empty? && lr.respond_to?(:value)
|
162
149
|
|
@@ -165,6 +152,16 @@ module ActiveFacts
|
|
165
152
|
}
|
166
153
|
end
|
167
154
|
|
155
|
+
rule role_name
|
156
|
+
'(' s as S r:id s ')' s
|
157
|
+
{ def value; r.value; end }
|
158
|
+
end
|
159
|
+
|
160
|
+
rule subscript
|
161
|
+
'(' i:([1-9] [0-9]*) ')' s
|
162
|
+
{ def value; i.text_value.to_i; end }
|
163
|
+
end
|
164
|
+
|
168
165
|
rule non_role
|
169
166
|
# Any of these is illegal in or following a reading:
|
170
167
|
comparator
|
@@ -174,6 +171,7 @@ module ActiveFacts
|
|
174
171
|
|
175
172
|
rule role_word
|
176
173
|
!non_role_word id
|
174
|
+
{ def value; id.value; end }
|
177
175
|
end
|
178
176
|
|
179
177
|
rule non_role_word
|
@@ -184,6 +182,7 @@ module ActiveFacts
|
|
184
182
|
/ or
|
185
183
|
/ quantifier
|
186
184
|
/ restriction
|
185
|
+
/ but
|
187
186
|
end
|
188
187
|
|
189
188
|
end
|