activefacts-cql 1.7.1

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.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +10 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +19 -0
  8. data/Rakefile +6 -0
  9. data/activefacts-cql.gemspec +29 -0
  10. data/bin/setup +7 -0
  11. data/lib/activefacts/cql.rb +7 -0
  12. data/lib/activefacts/cql/.gitignore +0 -0
  13. data/lib/activefacts/cql/Rakefile +14 -0
  14. data/lib/activefacts/cql/compiler.rb +156 -0
  15. data/lib/activefacts/cql/compiler/clause.rb +1137 -0
  16. data/lib/activefacts/cql/compiler/constraint.rb +581 -0
  17. data/lib/activefacts/cql/compiler/entity_type.rb +457 -0
  18. data/lib/activefacts/cql/compiler/expression.rb +443 -0
  19. data/lib/activefacts/cql/compiler/fact.rb +390 -0
  20. data/lib/activefacts/cql/compiler/fact_type.rb +421 -0
  21. data/lib/activefacts/cql/compiler/query.rb +106 -0
  22. data/lib/activefacts/cql/compiler/shared.rb +161 -0
  23. data/lib/activefacts/cql/compiler/value_type.rb +174 -0
  24. data/lib/activefacts/cql/parser.rb +234 -0
  25. data/lib/activefacts/cql/parser/CQLParser.treetop +167 -0
  26. data/lib/activefacts/cql/parser/Context.treetop +48 -0
  27. data/lib/activefacts/cql/parser/Expressions.treetop +67 -0
  28. data/lib/activefacts/cql/parser/FactTypes.treetop +358 -0
  29. data/lib/activefacts/cql/parser/Language/English.treetop +315 -0
  30. data/lib/activefacts/cql/parser/Language/French.treetop +315 -0
  31. data/lib/activefacts/cql/parser/Language/Mandarin.treetop +304 -0
  32. data/lib/activefacts/cql/parser/LexicalRules.treetop +253 -0
  33. data/lib/activefacts/cql/parser/ObjectTypes.treetop +210 -0
  34. data/lib/activefacts/cql/parser/Terms.treetop +183 -0
  35. data/lib/activefacts/cql/parser/ValueTypes.treetop +202 -0
  36. data/lib/activefacts/cql/parser/nodes.rb +49 -0
  37. data/lib/activefacts/cql/require.rb +36 -0
  38. data/lib/activefacts/cql/verbaliser.rb +804 -0
  39. data/lib/activefacts/cql/version.rb +5 -0
  40. data/lib/activefacts/input/cql.rb +43 -0
  41. data/lib/rubygems_plugin.rb +12 -0
  42. metadata +167 -0
@@ -0,0 +1,304 @@
1
+ # Encoding: UTF-8
2
+ #
3
+ # ActiveFacts CQL Parser for Mandarin
4
+ #
5
+ # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
6
+ #
7
+ module ActiveFacts
8
+ module CQL
9
+ grammar Mandarin
10
+
11
+ # >>>>>>>>>>>>>>>>>>>> Object Types <<<<<<<<<<<<<<<<<<<<
12
+ # The pattern to introduce a Value Type
13
+ rule written_as
14
+ s est s 'écrit' S 'en' s
15
+ end
16
+
17
+ # The pattern to introduce an Entity Type
18
+ rule identified_by
19
+ 'identifié' s 'par' s
20
+ end
21
+
22
+ rule basetype_expression
23
+ is s i:( independent s )? identification
24
+ end
25
+
26
+ # The pattern to introduce an Entity Subtype
27
+ rule subtype_prefix
28
+ est s un s ('type'/'genre') s 'de' S
29
+ end
30
+
31
+ rule subtype_expression
32
+ subtype_prefix i:( independent s )? supertype_list ident:identification?
33
+ end
34
+
35
+ # The pattern to introduce an objectified fact type with implicit identification
36
+ rule is_where
37
+ existe s i:(independent s)? si
38
+ { def independent; !i.empty?; end }
39
+ end
40
+
41
+ rule in_which # Introduce an objectification step
42
+ where / # Old syntax
43
+ dans s laquel # preferred syntax
44
+ end
45
+
46
+ # Units conversion keyword
47
+ rule conversion
48
+ converts s a:(approximately s)? to s
49
+ {
50
+ def approximate?
51
+ !a.empty?
52
+ end
53
+ }
54
+ end
55
+
56
+ # >>>>>>>>>>>>>>>>>>>> Constraints <<<<<<<<<<<<<<<<<<<<
57
+ # External presence constraint syntax:
58
+ rule each_occurs_in_clauses
59
+ s chaque s ('combinaison' S)? role_list s existe s quantifier 'fois' S
60
+ 'parmis' S ce S 'qui' S 'suit' s ':' s
61
+ clauses_list s c:context_note? ';'
62
+ {
63
+ def role_list_ast
64
+ role_list.ast
65
+ end
66
+ def quantifier_ast
67
+ quantifier.ast
68
+ end
69
+ def clauses_ast
70
+ clauses_list.ast
71
+ end
72
+ }
73
+ end
74
+
75
+ rule either_or
76
+ s soit s r1:clauses s 'ou' S r2:clauses
77
+ s c:context_note? enforcement ';'
78
+ {
79
+ def role_list_ast
80
+ nil
81
+ end
82
+ def quantifier_ast
83
+ Compiler::Quantifier.new(1, nil)
84
+ end
85
+ def clauses_ast
86
+ [r1.ast, r2.ast]
87
+ end
88
+ }
89
+ end
90
+
91
+ # Used for exclusion (at most one) and mandatory exclusion (exactly one)
92
+ rule for_each_how_many
93
+ 'pour' S 'chaque' S role_list s
94
+ quantifier s 'des' S 'suivants' S 's\'applique' s ':' s
95
+ clauses_list s c:context_note? ';'
96
+ {
97
+ def role_list_ast
98
+ role_list.ast
99
+ end
100
+ def quantifier_ast
101
+ quantifier.ast
102
+ end
103
+ def clauses_ast
104
+ clauses_list.ast
105
+ end
106
+ }
107
+ end
108
+
109
+ rule either_or_not_both
110
+ s soit s r1:clauses s 'ou' S r2:clauses 'mais' S 'pas' S 'les' S 'deux'
111
+ s c:context_note? enforcement ';'
112
+ {
113
+ def role_list_ast
114
+ nil
115
+ end
116
+ def quantifier_ast
117
+ Compiler::Quantifier.new(1, 1)
118
+ end
119
+ def clauses_ast
120
+ [r1.ast, r2.ast]
121
+ end
122
+ }
123
+ end
124
+
125
+ rule a_only_if_b
126
+ s clauses s only_if r2:clauses s c:context_note? enforcement ';'
127
+ end
128
+
129
+ rule only_if
130
+ que s si s
131
+ end
132
+
133
+ rule if_b_then_a
134
+ s 'si' S clauses s 'puis' S r2:clauses s c:context_note? enforcement ';'
135
+ end
136
+
137
+ rule if_and_only_if
138
+ s clauses s tail:( 'si' S 'et' S ('seulement'/'uniquement'/'que') S 'si' S clauses s)+
139
+ c:context_note? enforcement ';'
140
+ end
141
+
142
+ # During the prescan we need to know where terms in a role list finish.
143
+ # This rule matches any non-term expressions that may follow a role list.
144
+ rule role_list_constraint_followers
145
+ existe
146
+ end
147
+
148
+ # >>>>>>>>>>>>>>>>>>>> Quantifiers <<<<<<<<<<<<<<<<<<<<
149
+ rule quantifier
150
+ (
151
+ ( chaque s # "each"
152
+ { def value; [1, nil]; end }
153
+ / un s 'certain' 'e'? ) s # "some"
154
+ { def value; nil; end }
155
+ / ce s # "that"
156
+ { def value; nil; end }
157
+ / un s # "one"; masculine or feminine
158
+ { def value; [1, 1]; end }
159
+ / 'pas' s 'de' s # REVISIT: Example: "Personne n'a pas de Casier-judiciaire"
160
+ { def value; [0, 0]; end }
161
+ / exactement s quantity
162
+ { def value; q = quantity.value; [q, q]; end }
163
+ / au s moins s quantity most:( et s au s plus q:quantity )? # At least (or at most)
164
+ { def value; [ quantity.value, most.empty? ? nil : most.q.value ]; end }
165
+ / au s plus s quantity # At most
166
+ { def value; [ nil, quantity.value ]; end }
167
+ / entre s numeric_range s # within numeric_range
168
+ { def value; numeric_range.value; end }
169
+ / soit s tous s soit s aucun # either all or none
170
+ { def value; [ -1, 1 ]; end }
171
+ )
172
+ {
173
+ def ast
174
+ v = value
175
+ Compiler::Quantifier.new(v[0], v[1])
176
+ end
177
+ }
178
+ end
179
+
180
+ rule quantity
181
+ un s { def value; 1; end }
182
+ / number s { def value; number.value; end }
183
+ end
184
+
185
+ # >>>>>>>>>>>>>>>>>>>> Context Notes <<<<<<<<<<<<<<<<<<<<
186
+ rule as_agreed_by
187
+ s 'comme' S 'convenu' S d:('le' s date s)? 'par' S agents
188
+ { def value; [ d.empty? ? nil : d.date.value, agents.value ]; end }
189
+ end
190
+
191
+ rule date
192
+ s d:(!(by/')') .)+
193
+ { def value; d.text_value.strip; end }
194
+ end
195
+
196
+ rule agents
197
+ s h:agent s t:(',' s !context_type agent s)*
198
+ {
199
+ def value; [h.text_value] + t.elements.map{|e| e.agent.text_value }; end
200
+ def node_type; :linking; end
201
+ }
202
+ end
203
+
204
+ rule agent
205
+ id (s id)*
206
+ end
207
+
208
+ rule negative_prefix
209
+ s 'ce' S "n'est" s 'pas' s 'le' s 'cas' s 'que'
210
+ end
211
+
212
+ rule agg_of de end
213
+ rule agg_in dans end
214
+ rule restricted_to 'limité' s 'à' !alphanumeric s end
215
+ rule any un !alphanumeric end
216
+
217
+ # >>>>>>>>>>>>>>>>>>>> Internal vocabulary <<<<<<<<<<<<<<<<<<<<
218
+ rule all 'tous' !alphanumeric end
219
+ rule at 'a' !alphanumeric end
220
+ rule both 'les deux' !alphanumeric end
221
+ rule ce ('cette'/'cet'/'ce') !alphanumeric end # ce is masculine, cette feminine, cet is ce before a noun
222
+ rule chaque 'chaque' !alphanumeric end
223
+ rule converts 'convertit' !alphanumeric end
224
+ rule de 'de' !alphanumeric end
225
+ rule dans 'dans' !alphanumeric end
226
+ rule laquel 'laquel' 'le'? !alphanumeric end
227
+ rule descending 'descendant' !alphanumeric end
228
+ rule each chaque end
229
+ rule either 'soit' !alphanumeric end
230
+ rule entity 'entité' !alphanumeric end
231
+ rule est 'est' !alphanumeric end
232
+ rule exactement 'exactement' !alphanumeric end
233
+ rule existe 'existe' !alphanumeric end
234
+ rule from 'à partir de' !alphanumeric end # REVISIT: google translate
235
+ rule includes 'comprend' !alphanumeric end
236
+ rule matches 'matches' !alphanumeric end
237
+ rule moins 'moins' !alphanumeric end
238
+ rule none 'aucun' !alphanumeric end
239
+ rule not 'not' !alphanumeric end # REVISIT: Used in constraints
240
+ rule plus 'plus' !alphanumeric end
241
+ rule some 'quelques' !alphanumeric end
242
+ rule un 'un' 'e'? !alphanumeric end # un is masculine, une is feminine
243
+ rule que 'que' !alphanumeric end
244
+
245
+ # >>>>>>>>>>>>>>>>>>>> External vocabulary <<<<<<<<<<<<<<<<<<<<
246
+ rule according_to 'selon' !alphanumeric end
247
+ rule acyclic 'acyclique' !alphanumeric end
248
+ rule alias 'alias' !alphanumeric end
249
+ rule and 'et' !alphanumeric end
250
+ rule antisymmetric 'antisymmetric' !alphanumeric end
251
+ rule approximately 'environ' !alphanumeric end # REVISIT: google translate
252
+ rule as 'comme' !alphanumeric end
253
+ rule as_opposed_to 'au' S 'lieu' S 'de' !alphanumeric end
254
+ rule asymmetric 'asymétrique' !alphanumeric end
255
+ rule au 'au' !alphanumeric end
256
+ rule because ('parce' s 'que' / 'car') !alphanumeric end
257
+ rule but 'mais' !alphanumeric end
258
+ rule by 'par' !alphanumeric end
259
+ rule definitely 'définitivement' !alphanumeric end
260
+ rule entre 'entre' !alphanumeric end
261
+ rule ephemera 'éphémère' !alphanumeric end
262
+ rule existe 'existe' !alphanumeric end
263
+ rule false 'faux' !alphanumeric end
264
+ rule feminine 'féminin' !alphanumeric end
265
+ rule identified ('identifié') !alphanumeric end
266
+ rule if 'si' !alphanumeric end
267
+ rule import 'import' !alphanumeric end # REVISIT: translation?
268
+ rule independent 'indépendant' !alphanumeric end
269
+ rule stronglyintransitive 'stronglyintransitif' !alphanumeric end
270
+ rule intransitive 'intransitif' !alphanumeric end
271
+ rule irreflexive 'irréflexive' !alphanumeric end
272
+ rule is est end # Called from ObjectTypes.treetop in "is identified by"
273
+ rule its ('sa' / 'son') !alphanumeric end
274
+ rule masculine 'masculin' !alphanumeric end
275
+ rule maybe 'peut-être' !alphanumeric end # REVISIT: eventuellement = possibly?
276
+ rule only 'que' !alphanumeric end # REVISIT: Used in constraints
277
+ rule or 'ou' !alphanumeric end
278
+ rule ordering_prefix by s (ascending/descending)? s end
279
+ rule otherwise 'sinon' !alphanumeric end
280
+ rule partitioned 'partitionné' !alphanumeric end
281
+ rule personal 'personelle' !alphanumeric end
282
+ rule radix_point ',' end
283
+ rule reflexive 'réflexive' !alphanumeric end
284
+ rule returning 'retour' !alphanumeric end
285
+ rule separate 'distincte' !alphanumeric end
286
+ rule si 'si' !alphanumeric end
287
+ rule so_that 'pour' s 'que' !alphanumeric end
288
+ rule soit 'soit' !alphanumeric end
289
+ rule static 'statique' !alphanumeric end
290
+ rule symmetric 'symétrique' !alphanumeric end
291
+ rule that que end
292
+ rule then 'puis' !alphanumeric end
293
+ rule to 'à' !alphanumeric end
294
+ rule to_avoid ('pour' s 'empecher' s 'de' / 'pour' s 'ne' s 'pas') !alphanumeric end
295
+ rule transient 'transitoires' !alphanumeric end
296
+ rule transitive 'transitif' !alphanumeric end
297
+ rule true 'vrai' !alphanumeric end
298
+ rule vocabulary 'vocabulaire' !alphanumeric end
299
+ rule where 'où' !alphanumeric end
300
+ rule who 'qui' !alphanumeric end
301
+
302
+ end
303
+ end
304
+ end
@@ -0,0 +1,253 @@
1
+ #
2
+ # ActiveFacts CQL Parser.
3
+ # Various lexical rules for CQL.
4
+ #
5
+ # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
6
+ #
7
+ module ActiveFacts
8
+ module CQL
9
+ grammar LexicalRules
10
+
11
+ rule range
12
+ (numeric_range / string_range)
13
+ {
14
+ def node_type; :literal; end
15
+ }
16
+ end
17
+
18
+ rule numeric_range
19
+ number s tail:( '..' s end:number? s )?
20
+ {
21
+ def value
22
+ if !tail.empty?
23
+ last = tail.end.value unless tail.end.empty?
24
+ [ number.value, last ]
25
+ else
26
+ number.value
27
+ end
28
+ end
29
+ }
30
+ / '..' s number s
31
+ {
32
+ def value
33
+ [ nil, number.value ]
34
+ end
35
+ }
36
+ end
37
+
38
+ rule string_range
39
+ string s tail:( '..' s end:string? s )?
40
+ {
41
+ # Ranges require the original text of the string, not the content:
42
+ def value
43
+ first = string.text_value
44
+ if !tail.empty?
45
+ last = tail.end.text_value unless tail.end.empty?
46
+ [ first, last ]
47
+ else
48
+ first
49
+ end
50
+ end
51
+ }
52
+ / '..' s string s
53
+ {
54
+ def value
55
+ [ nil, string.value ]
56
+ end
57
+ }
58
+ end
59
+
60
+ rule url
61
+ # url_scheme ':' (user ( ':' !(port '/') password )? '@' )? hostname ( ':' port )? '/' path query? fragment?
62
+ ( !(white / ';') .)+
63
+ {
64
+ def node_type; :literal; end
65
+ }
66
+ end
67
+
68
+ rule literal
69
+ ( boolean_literal
70
+ / string
71
+ / number
72
+ ) s
73
+ {
74
+ def value
75
+ elements[0].value
76
+ end
77
+ def node_type; :literal; end
78
+ }
79
+ end
80
+
81
+ rule boolean_literal
82
+ ( true { def value; true; end }
83
+ / false { def value; false; end }
84
+ ) !alphanumeric
85
+ {
86
+ def value; elements[0].value end
87
+ }
88
+ end
89
+
90
+ rule string
91
+ "'" (string_char)* "'"
92
+ {
93
+ def value
94
+ text_value
95
+ eval(text_value.sub(/\A'(.*)'\Z/,'"\1"'))
96
+ end
97
+ }
98
+ end
99
+
100
+ rule number
101
+ ( real /
102
+ fractional_real /
103
+ hexnumber /
104
+ octalnumber
105
+ ) !alphanumeric
106
+ {
107
+ def value
108
+ eval(text_value)
109
+ end
110
+ def node_type; :literal; end
111
+ }
112
+ end
113
+
114
+ # All purely lexical rules from here down, no-one looks at the structure, just the text_value:
115
+
116
+ rule string_char
117
+ ( '\\' [befntr\\']
118
+ / '\\' [0-7] [0-7] [0-7]
119
+ / '\\' [\r]* [\n] [\r]*
120
+ / '\\0'
121
+ / '\\x' [0-9A-Fa-f] [0-9A-Fa-f]
122
+ / '\\u' [0-9A-Fa-f] [0-9A-Fa-f] [0-9A-Fa-f] [0-9A-Fa-f]
123
+ / (![\'\\\0-\x07\x0A-\x1F] .)
124
+ )
125
+ end
126
+
127
+ rule real
128
+ [-+]? [1-9] [0-9]* fraction? exponent?
129
+ end
130
+
131
+ rule fractional_real
132
+ [-+]? '0' fraction exponent?
133
+ end
134
+
135
+ rule fraction
136
+ radix_point [0-9]+
137
+ end
138
+
139
+ rule exponent
140
+ ( [Ee] [-+]? [0-9]+ )
141
+ end
142
+
143
+ rule hexnumber
144
+ '0x' [0-9A-Fa-f]+
145
+ end
146
+
147
+ rule octalnumber
148
+ '0' [0-7]*
149
+ end
150
+
151
+ rule mul_op
152
+ '/' / '%' / '*'
153
+ end
154
+
155
+ rule id
156
+ alpha alphanumeric*
157
+ { def value; text_value; end }
158
+ end
159
+
160
+ rule alpha
161
+ [[:alpha:]_]
162
+ end
163
+
164
+ rule alphanumeric
165
+ alpha / [0-9]
166
+ end
167
+
168
+ rule s # Optional space
169
+ S?
170
+ end
171
+
172
+ rule S # Mandatory space
173
+ (white / comment_to_eol / comment_c_style)+
174
+ end
175
+
176
+ rule white
177
+ [ \t\n\r]+
178
+ end
179
+
180
+ rule comment_to_eol
181
+ '//' (!"\n" .)*
182
+ {
183
+ def node_type; :comment; end
184
+ }
185
+ end
186
+
187
+ rule comment_c_style
188
+ '/*' (!'*/' . )* '*/'
189
+ {
190
+ def node_type; :comment; end
191
+ }
192
+ end
193
+
194
+ rule regular_expression
195
+ '/' !'/' regular_expression_contents '/'
196
+ {
197
+ def contents
198
+ regular_expression_contents.text_value
199
+ end
200
+ }
201
+ end
202
+
203
+ rule regular_expression_contents
204
+ regular_expression_alternate ( '|' regular_expression_alternate )*
205
+ end
206
+
207
+ rule regular_expression_alternate
208
+ regular_expression_sequence
209
+ end
210
+
211
+ rule regular_expression_sequence
212
+ regular_expression_atom*
213
+ end
214
+
215
+ rule regular_expression_atom
216
+ (
217
+ '[' character_classes ']'
218
+ / regular_expression_group
219
+ / ![*+?()|/] string_char
220
+ ) regular_expression_multiplicity?
221
+ end
222
+
223
+ rule character_classes
224
+ character_class+
225
+ end
226
+
227
+ rule character_class
228
+ !']' string_char '-' !']' string_char
229
+ / '-'
230
+ / !']' string_char
231
+ end
232
+
233
+ rule regular_expression_multiplicity
234
+ '*' / '+' / '?'
235
+ end
236
+
237
+ rule regular_expression_group
238
+ '('
239
+ regular_expression_group_extension?
240
+ regular_expression_contents
241
+ ')'
242
+ end
243
+
244
+ rule regular_expression_group_extension
245
+ '?' (
246
+ '<' ( !'>' .)+ '>' # A tag for a regular expression group
247
+ # REVISIT: Add more group extensions as needed
248
+ )
249
+ end
250
+
251
+ end
252
+ end
253
+ end