activefacts 0.7.3 → 0.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|