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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +1 -0
- data/.travis.yml +4 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +19 -0
- data/Rakefile +6 -0
- data/activefacts-cql.gemspec +29 -0
- data/bin/setup +7 -0
- data/lib/activefacts/cql.rb +7 -0
- data/lib/activefacts/cql/.gitignore +0 -0
- data/lib/activefacts/cql/Rakefile +14 -0
- data/lib/activefacts/cql/compiler.rb +156 -0
- data/lib/activefacts/cql/compiler/clause.rb +1137 -0
- data/lib/activefacts/cql/compiler/constraint.rb +581 -0
- data/lib/activefacts/cql/compiler/entity_type.rb +457 -0
- data/lib/activefacts/cql/compiler/expression.rb +443 -0
- data/lib/activefacts/cql/compiler/fact.rb +390 -0
- data/lib/activefacts/cql/compiler/fact_type.rb +421 -0
- data/lib/activefacts/cql/compiler/query.rb +106 -0
- data/lib/activefacts/cql/compiler/shared.rb +161 -0
- data/lib/activefacts/cql/compiler/value_type.rb +174 -0
- data/lib/activefacts/cql/parser.rb +234 -0
- data/lib/activefacts/cql/parser/CQLParser.treetop +167 -0
- data/lib/activefacts/cql/parser/Context.treetop +48 -0
- data/lib/activefacts/cql/parser/Expressions.treetop +67 -0
- data/lib/activefacts/cql/parser/FactTypes.treetop +358 -0
- data/lib/activefacts/cql/parser/Language/English.treetop +315 -0
- data/lib/activefacts/cql/parser/Language/French.treetop +315 -0
- data/lib/activefacts/cql/parser/Language/Mandarin.treetop +304 -0
- data/lib/activefacts/cql/parser/LexicalRules.treetop +253 -0
- data/lib/activefacts/cql/parser/ObjectTypes.treetop +210 -0
- data/lib/activefacts/cql/parser/Terms.treetop +183 -0
- data/lib/activefacts/cql/parser/ValueTypes.treetop +202 -0
- data/lib/activefacts/cql/parser/nodes.rb +49 -0
- data/lib/activefacts/cql/require.rb +36 -0
- data/lib/activefacts/cql/verbaliser.rb +804 -0
- data/lib/activefacts/cql/version.rb +5 -0
- data/lib/activefacts/input/cql.rb +43 -0
- data/lib/rubygems_plugin.rb +12 -0
- 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
|