fbtxt-parser 0.9.0

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 (52) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +4 -0
  3. data/Manifest.txt +50 -0
  4. data/README.md +22 -0
  5. data/Rakefile +53 -0
  6. data/lib/fbtxt/parser/debuggable.rb +53 -0
  7. data/lib/fbtxt/parser/lexer-logger.rb +20 -0
  8. data/lib/fbtxt/parser/lexer-on_goal.rb +167 -0
  9. data/lib/fbtxt/parser/lexer-on_group_def.rb +31 -0
  10. data/lib/fbtxt/parser/lexer-on_prop_lineup.rb +79 -0
  11. data/lib/fbtxt/parser/lexer-on_prop_misc.rb +123 -0
  12. data/lib/fbtxt/parser/lexer-on_prop_penalties.rb +40 -0
  13. data/lib/fbtxt/parser/lexer-on_round_def.rb +37 -0
  14. data/lib/fbtxt/parser/lexer-on_top.rb +133 -0
  15. data/lib/fbtxt/parser/lexer-prep_doc.rb +131 -0
  16. data/lib/fbtxt/parser/lexer-prep_line.rb +63 -0
  17. data/lib/fbtxt/parser/lexer-tokenize.rb +468 -0
  18. data/lib/fbtxt/parser/lexer.rb +231 -0
  19. data/lib/fbtxt/parser/lexer_buffer.rb +68 -0
  20. data/lib/fbtxt/parser/lexer_token.rb +126 -0
  21. data/lib/fbtxt/parser/parse_tree--core.rb +29 -0
  22. data/lib/fbtxt/parser/parse_tree-match.rb +309 -0
  23. data/lib/fbtxt/parser/parse_tree-props.rb +233 -0
  24. data/lib/fbtxt/parser/parse_tree.rb +202 -0
  25. data/lib/fbtxt/parser/parser-runtime.rb +379 -0
  26. data/lib/fbtxt/parser/parser-top.rb +102 -0
  27. data/lib/fbtxt/parser/parser.rb +2343 -0
  28. data/lib/fbtxt/parser/token-date--helpers.rb +130 -0
  29. data/lib/fbtxt/parser/token-date--names.rb +108 -0
  30. data/lib/fbtxt/parser/token-date.rb +200 -0
  31. data/lib/fbtxt/parser/token-date_duration.rb +171 -0
  32. data/lib/fbtxt/parser/token-geo.rb +134 -0
  33. data/lib/fbtxt/parser/token-goals--helpers.rb +114 -0
  34. data/lib/fbtxt/parser/token-goals.rb +306 -0
  35. data/lib/fbtxt/parser/token-group.rb +29 -0
  36. data/lib/fbtxt/parser/token-note.rb +40 -0
  37. data/lib/fbtxt/parser/token-prop.rb +309 -0
  38. data/lib/fbtxt/parser/token-prop_name.rb +83 -0
  39. data/lib/fbtxt/parser/token-round.rb +88 -0
  40. data/lib/fbtxt/parser/token-score--helpers.rb +189 -0
  41. data/lib/fbtxt/parser/token-score.rb +60 -0
  42. data/lib/fbtxt/parser/token-score_full.rb +331 -0
  43. data/lib/fbtxt/parser/token-score_fuller.rb +434 -0
  44. data/lib/fbtxt/parser/token-score_legs.rb +59 -0
  45. data/lib/fbtxt/parser/token-status.rb +192 -0
  46. data/lib/fbtxt/parser/token-status_inline.rb +112 -0
  47. data/lib/fbtxt/parser/token-text.rb +221 -0
  48. data/lib/fbtxt/parser/token-time.rb +144 -0
  49. data/lib/fbtxt/parser/token.rb +224 -0
  50. data/lib/fbtxt/parser/version.rb +24 -0
  51. data/lib/fbtxt/parser.rb +140 -0
  52. metadata +145 -0
@@ -0,0 +1,434 @@
1
+ module Fbtxt
2
+ class Lexer
3
+
4
+ ###
5
+ # alternate (more literate) score style
6
+ # found in books & magazines
7
+ # (with no half-time score)
8
+ #
9
+ # 4-4 (aet, 6-6 on aggregate, win 3-5 on pens)
10
+ # -or-
11
+ # 4-4 (aet, 6-6 an aggregate, 3-5 on pens)
12
+ # -or-
13
+ # 4-4 (aet, 6-6agg, 3-5p)
14
+ #
15
+ # 2-2 (3-3 on aggregate, win on away goals)
16
+ # -or-
17
+ # 2-2 (3-3 agg, away goals)
18
+ # etc.
19
+
20
+
21
+ ## regex score helpers
22
+ ## note - MUST double escape \d e.g. \\d!!! if not "simple" string (e.g. '' but %Q<>)
23
+
24
+ def self._mk_score_fuller_agg( win: ) ## with optional win - true|false
25
+ %Q<
26
+ (?:
27
+ ############
28
+ ## opt 1) with win
29
+ (?:
30
+ #{ win ? '(?: win [ ] )?' : '' }
31
+ (?<agg1>\\d{1,2}) - (?<agg2>\\d{1,2})
32
+ [ ] on [ ] agg (?: regate )?
33
+ )
34
+ |
35
+ #####
36
+ ## opt 2) "classic" (post)
37
+ (?:
38
+ (?<agg1>\\d{1,2}) - (?<agg2>\\d{1,2})
39
+ [ ]*
40
+ #{AGG_EN}
41
+ )
42
+ |
43
+ #####
44
+ ## opt 3) agg up-front (pre)
45
+ (?:
46
+ agg [ ]
47
+ (?<agg1>\\d{1,2}) - (?<agg2>\\d{1,2})
48
+ )
49
+ )
50
+ >
51
+ end
52
+
53
+ def self._mk_score_fuller_p( win: ) ## with optional win - true|false
54
+ %Q<
55
+ (?:
56
+ ############
57
+ ## opt 1) with win
58
+ (?:
59
+ #{ win ? '(?: win [ ] )?' : '' }
60
+ (?<p1>\\d{1,2}) - (?<p2>\\d{1,2})
61
+ [ ] on [ ] pens
62
+ )
63
+ |
64
+ #####
65
+ ## opt 2) "classic" (post)
66
+ (?:
67
+ (?<p1>\\d{1,2}) - (?<p2>\\d{1,2})
68
+ [ ]*
69
+ #{P_EN}
70
+ )
71
+ |
72
+ #####
73
+ ## opt 3) up-front (pre)
74
+ (?:
75
+ (?: pen|p) [ ]
76
+ (?<p1>\\d{1,2}) - (?<p2>\\d{1,2})
77
+ )
78
+ )
79
+ >
80
+ end
81
+
82
+
83
+ SCORE_FULLER_AGG = _mk_score_fuller_agg( win: false )
84
+ SCORE_FULLER_AGG_WIN = _mk_score_fuller_agg( win: true )
85
+
86
+ SCORE_FULLER_P = _mk_score_fuller_p( win: false )
87
+ SCORE_FULLER_P_WIN = _mk_score_fuller_p( win: true )
88
+
89
+ SCORE_FULLER_AWAY_WIN = %Q<
90
+ (?:
91
+ (?<away>
92
+ ############
93
+ ## opt 1) with win
94
+ (?:
95
+ (?: win [ ] )?
96
+ (?: (?<away1>\\d{1,2}) - (?<away2>\\d{1,2}) [ ] )?
97
+ on [ ] away [ ] goals? # goal or goals
98
+ )
99
+ |
100
+ #####
101
+ ## opt 2) "classic" (post)
102
+ (?:
103
+ (?: (?<away1>\\d{1,2}) - (?<away2>\\d{1,2}) [ ] )?
104
+ [ ]* away
105
+ )
106
+ |
107
+ #####
108
+ ## opt 3) up-front (pre)
109
+ (?:
110
+ away
111
+ (?: [ ]
112
+ (?<away1>\\d{1,2}) - (?<away2>\\d{1,2})
113
+ )?
114
+ )
115
+ ))
116
+ >
117
+
118
+
119
+
120
+ SCORE_FULLER_HT_OPT = %Q<
121
+ (?: HT [ ]
122
+ (?: (?<ht1>\\d{1,2}) - (?<ht2>\\d{1,2}))
123
+ [ ]*,[ ]*
124
+ )? ## note - make optional
125
+ >
126
+
127
+ SCORE_FULLER_FT_OPT = %Q<
128
+ (?: FT [ ]
129
+ (?: (?<ft1>\\d{1,2}) - (?<ft2>\\d{1,2}))
130
+ [ ]*,[ ]*
131
+ )? ## note - make optional
132
+ >
133
+
134
+
135
+ #############
136
+ # 4-4 (HT 2-1)
137
+ # or
138
+ # Team A 4-1 Team B (HT 2-1)
139
+
140
+ SCORE_FULLER__HT = %Q<
141
+ \\( HT [ ]
142
+ (?<ht1>\\d{1,2}) - (?<ht2>\\d{1,2})
143
+ \\)
144
+ >
145
+
146
+ SCORE_FULLER__HT_FT__RE = %r{
147
+ (?<score_fuller>
148
+ \b
149
+ (?<ft1>\d{1,2}) - (?<ft2>\d{1,2})
150
+ [ ]+
151
+ #{SCORE_FULLER__HT}
152
+ )}ix
153
+
154
+ SCORE_FULLER_MORE__HT_FT__RE = %r{
155
+ (?<score_fuller_more>
156
+ #{SCORE_FULLER__HT}
157
+ )}ix
158
+
159
+
160
+
161
+
162
+ ############
163
+ # 4-4 (aet)
164
+ # 4-4 (a.e.t.)
165
+ # or
166
+ # add golden goal/sudden death and silver goal e.g.
167
+ # 5-4 (aet/gg) - note: adds golden (goal) flag
168
+ # 5-4 (a.e.t./g.g.) - note: adds silver (goal) flag
169
+ #
170
+ # Team A 4-4 Team B (aet)
171
+ # Team A 4-4 Team B (a.e.t.)
172
+ #
173
+ # or
174
+ # 4-4 (FT 3-2, AET)
175
+ # 4-4 (HT 2-1, FT 3-2, AET)
176
+
177
+
178
+ SCORE_FULLER__ET = %Q<
179
+ \\(
180
+ #{SCORE_FULLER_HT_OPT}
181
+ #{SCORE_FULLER_FT_OPT}
182
+ (?:
183
+ (?<aetgg> #{AETGG_EN})
184
+ |
185
+ (?<aetsg> #{AETSG_EN})
186
+ |
187
+ (?<aet> #{ET_EN})
188
+ )
189
+ \\)
190
+ >
191
+
192
+ SCORE_FULLER__ET__RE = %r{
193
+ (?<score_fuller>
194
+ \b
195
+ (?<et1>\d{1,2}) - (?<et2>\d{1,2})
196
+ [ ]+
197
+ #{SCORE_FULLER__ET}
198
+ )}ix
199
+
200
+ SCORE_FULLER_MORE__ET__RE = %r{
201
+ (?<score_fuller_more>
202
+ #{SCORE_FULLER__ET}
203
+ )}ix
204
+
205
+
206
+ #############
207
+ # 4-4 (aet, win 3-5 on pens)
208
+ # 4-4 (aet, 3-5 on pens)
209
+ # 4-4 (aet, 3-5 pen)
210
+ # 4-4 (a.e.t., 3-5 pen.)
211
+ # or
212
+ # Team A 4-4 Team B (aet, win 3-5 on pens)
213
+ # Team A 4-4 Team B (aet, 3-5 on pens)
214
+ # Team A 4-4 Team B (aet, 3-5 pen)
215
+ # Team A 4-4 Team B (a.e.t., 3-5 pen.)
216
+
217
+ SCORE_FULLER__ET_P = %Q<
218
+ \\(
219
+ #{SCORE_FULLER_HT_OPT}
220
+ #{SCORE_FULLER_FT_OPT}
221
+ (?<aet> #{ET_EN})
222
+ [ ]*,[ ]*
223
+ #{SCORE_FULLER_P_WIN}
224
+ \\)
225
+ >
226
+
227
+ SCORE_FULLER__ET_P__RE = %r{
228
+ (?<score_fuller>
229
+ \b
230
+ (?<et1>\d{1,2}) - (?<et2>\d{1,2})
231
+ [ ]+
232
+ #{SCORE_FULLER__ET_P}
233
+ )}ix
234
+
235
+ SCORE_FULLER_MORE__ET_P__RE = %r{
236
+ (?<score_fuller_more>
237
+ #{SCORE_FULLER__ET_P}
238
+ )}ix
239
+
240
+
241
+ ##########################
242
+ # 4-4 (win 3-5 on pens)
243
+ # 4-4 (3-5 pen)
244
+ # 4-4 (3-5p)
245
+ # or
246
+ # Team A 4-4 Team B (win 3-5 on pens)
247
+ # Team A 4-4 Team B (3-5 pen)
248
+ # Team A 4-4 Team B (3-5p)
249
+
250
+ SCORE_FULLER__FT_P = %Q<
251
+ \\(
252
+ #{SCORE_FULLER_HT_OPT}
253
+ #{SCORE_FULLER_P_WIN}
254
+ \\)
255
+ >
256
+
257
+ SCORE_FULLER__FT_P__RE = %r{
258
+ (?<score_fuller>
259
+ \b
260
+ (?<ft1>\d{1,2}) - (?<ft2>\d{1,2})
261
+ [ ]+
262
+ \(
263
+ #{SCORE_FULLER_P_WIN}
264
+ \)
265
+ )}ix
266
+
267
+ SCORE_FULLER_MORE__FT_P__RE = %r{
268
+ (?<score_fuller_more>
269
+ #{SCORE_FULLER__FT_P}
270
+ )}ix
271
+
272
+
273
+ #####################
274
+ # 3-2 (win 4-5 on aggregate)
275
+ # 3-2 (4-5 on aggregate)
276
+ # 3-2 (4-5 on agg)
277
+ # 3-2 (4-5 agg)
278
+ # 3-2 (4-5 agg.)
279
+ # or
280
+ # 3-2 (agg 4-5)
281
+
282
+ SCORE_FULLER__FT_AGG = %Q<
283
+ \\(
284
+ #{SCORE_FULLER_HT_OPT}
285
+ #{SCORE_FULLER_AGG_WIN}
286
+ \\)
287
+ >
288
+
289
+ SCORE_FULLER__FT_AGG__RE = %r{
290
+ (?<score_fuller>
291
+ \b
292
+ (?<ft1>\d{1,2}) - (?<ft2>\d{1,2})
293
+ [ ]+
294
+ #{SCORE_FULLER__FT_AGG}
295
+ )}ix
296
+
297
+ SCORE_FULLER_MORE__FT_AGG__RE = %r{
298
+ (?<score_fuller_more>
299
+ #{SCORE_FULLER__FT_AGG}
300
+ )}ix
301
+
302
+ ####
303
+ # ft + agg + away
304
+ # 2-1 (3-3 on aggregate, win on away goals)
305
+ # 2-1 (3-3 on aggregate, win 2-1 on away goals)
306
+
307
+ SCORE_FULLER__FT_AGG_AWAY = %Q<
308
+ \\(
309
+ #{SCORE_FULLER_HT_OPT}
310
+ #{SCORE_FULLER_AGG}
311
+ [ ]*,[ ]*
312
+ #{SCORE_FULLER_AWAY_WIN}
313
+ \\)
314
+ >
315
+
316
+ SCORE_FULLER__FT_AGG_AWAY__RE = %r{
317
+ (?<score_fuller>
318
+ \b
319
+ (?<ft1>\d{1,2}) - (?<ft2>\d{1,2})
320
+ [ ]+
321
+ #{SCORE_FULLER__FT_AGG_AWAY}
322
+ )}ix
323
+
324
+ SCORE_FULLER_MORE__FT_AGG_AWAY__RE = %r{
325
+ (?<score_fuller_more>
326
+ #{SCORE_FULLER__FT_AGG_AWAY}
327
+ )}ix
328
+
329
+
330
+ #####################
331
+ # 2-1 (aet, 3-3 on aggregate, win 5-2 on pens)
332
+ # 2-1 (aet, 3-3 agg, 5-2 pen.)
333
+
334
+ SCORE_FULLER__ET_AGG_P = %Q<
335
+ \\(
336
+ #{SCORE_FULLER_HT_OPT}
337
+ #{SCORE_FULLER_FT_OPT}
338
+ (?<aet> #{ET_EN})
339
+ [ ]*,[ ]*
340
+ #{SCORE_FULLER_AGG}
341
+ [ ]*,[ ]*
342
+ #{SCORE_FULLER_P_WIN}
343
+ \\)
344
+ >
345
+
346
+ SCORE_FULLER__ET_AGG_P__RE = %r{
347
+ (?<score_fuller>
348
+ \b
349
+ (?<et1>\d{1,2}) - (?<et2>\d{1,2})
350
+ [ ]+
351
+ #{SCORE_FULLER__ET_AGG_P}
352
+ )}ix
353
+
354
+ SCORE_FULLER_MORE__ET_AGG_P__RE = %r{
355
+ (?<score_fuller_more>
356
+ #{SCORE_FULLER__ET_AGG_P}
357
+ )}ix
358
+
359
+
360
+ #############################################
361
+ # map tables
362
+ # note: order matters - first come-first matched/served
363
+
364
+ SCORE_FULLER_RE = Regexp.union(
365
+ SCORE_FULLER__HT_FT__RE, ## e.g. 3-2 (HT 2-1)
366
+ SCORE_FULLER__ET_P__RE, ## e.g. 2-2 (aet, win 5-3 on pens)
367
+ SCORE_FULLER__ET__RE, ## e.g. 2-3 (aet)
368
+ SCORE_FULLER__FT_P__RE, ## e.g. 2-2 (win 5-3 on pens)
369
+ SCORE_FULLER__FT_AGG__RE, ## e.g. 2-3 (win 5-4 on aggregate)
370
+ SCORE_FULLER__FT_AGG_AWAY__RE, ## e.g. 2-1 (3-3 on aggreate, win 2-1 on away goals)
371
+ SCORE_FULLER__ET_AGG_P__RE, ## e.g. 2-1 (aet, 3-3 on aggregate, win 5-2 on pens)
372
+ )
373
+
374
+
375
+
376
+ ##
377
+ ## add support for "stand-alone" (HT) and (FT) - keep why? why not?
378
+ SCORE_FULLER_MORE__HT__RE = %r{
379
+ (?<score_fuller_more>
380
+ \( (?<ht> ht ) \)
381
+ )}ix
382
+
383
+ SCORE_FULLER_MORE__FT__RE = %r{
384
+ (?<score_fuller_more>
385
+ \( (?<ft> ft ) \)
386
+ )}ix
387
+
388
+
389
+ ###
390
+ # add special for fuller_more
391
+ # (aet 4-3) - core score is ft, and fuller more incl. et!!!
392
+
393
+ SCORE_FULLER_MORE__FT_ET__RE = %r{
394
+ (?<score_fuller_more>
395
+ \(#{ET_EN}
396
+ [ ]
397
+ (?<et1>\d{1,2}) - (?<et2>\d{1,2})
398
+ \)
399
+ )}ix
400
+
401
+
402
+
403
+ ##
404
+ # note - simply (1-1) !!!!!
405
+ ## note - special attention needed for placemenent in processing error!!!
406
+ ## make sure it is the last (or on of the last) match(es)
407
+
408
+ SCORE_FULLER_MORE__HT_FT__CLASSIC_RE = %r{
409
+ (?<score_fuller_more>
410
+ \(
411
+ (?<ht1>\d{1,2}) - (?<ht2>\d{1,2})
412
+ \)
413
+ )}ix
414
+
415
+
416
+ SCORE_FULLER_MORE_RE = Regexp.union(
417
+ SCORE_FULLER_MORE__FT__RE, ## e.g. (ft)
418
+ SCORE_FULLER_MORE__HT__RE, ## e.g. (ht)
419
+ SCORE_FULLER_MORE__HT_FT__RE, ## e.g. (HT 2-1)
420
+ SCORE_FULLER_MORE__ET_P__RE, ## e.g. (aet, win 5-3 on pens)
421
+ SCORE_FULLER_MORE__ET__RE, ## e.g. (aet)
422
+ SCORE_FULLER_MORE__FT_ET__RE, ## e.g. (aet 3-2) - (SPECIAL) incl. after extra-time score!!
423
+ SCORE_FULLER_MORE__FT_P__RE, ## e.g. (win 5-3 on pens)
424
+ SCORE_FULLER_MORE__FT_AGG__RE, ## e.g. (win 5-4 on aggregate)
425
+ SCORE_FULLER_MORE__FT_AGG_AWAY__RE, ## e.g. (3-3 on aggreate, win 2-1 on away goals)
426
+ SCORE_FULLER_MORE__ET_AGG_P__RE, ## e.g. (aet, 3-3 on aggregate, win 5-2 on pens)
427
+
428
+ SCORE_FULLER_MORE__HT_FT__CLASSIC_RE, ## e.g. (2-1) half-time !!!!
429
+ )
430
+
431
+
432
+
433
+ end # class Lexer
434
+ end # module Fbtxt
@@ -0,0 +1,59 @@
1
+ module Fbtxt
2
+ class Lexer
3
+
4
+
5
+ ##
6
+ ## note - for now only two legs (1st,2nd) supported
7
+ ## maybe more in the future (if there is a real-world sample/use)
8
+
9
+ ##
10
+ ## win on away goals
11
+ ## aet
12
+ ##
13
+
14
+ SCORE_LEGS_RE = %r{
15
+ (?<score_legs>
16
+ \b
17
+ (?<leg1_ft1>\d{1,2}) - (?<leg1_ft2>\d{1,2})
18
+ (?: [ ]+ | [ ]*,[ ]*) # separate by spaces OR comma
19
+ (?:
20
+ ## opt 1 - after extra-time (et) score
21
+ (?<leg2_et1>\d{1,2}) - (?<leg2_et2>\d{1,2})
22
+ [ ]? #{ET_EN} ## a.e.t./aet
23
+ ### note - might end in dot (.) not alpha
24
+ ### thus, wordboundary NOT working
25
+ #{SCORE_LOOKAHEAD}
26
+ |
27
+ ## opt 2 - full-time (ft)
28
+ (?<leg2_ft1>\d{1,2}) - (?<leg2_ft2>\d{1,2})
29
+ \b
30
+ )
31
+ (?: ## check optional aggregate e.g. (agg 4-4)
32
+ [ ]+
33
+ \(
34
+ agg [ ]
35
+ (?<agg1>\d{1,2}) - (?<agg2>\d{1,2})
36
+
37
+ ### add win options
38
+ (?:
39
+ ## opt 1 - on away goals
40
+ (?<away> [ ]*,[ ]*
41
+ (?:win [ ])? on [ ] away [ ] goals?
42
+ )
43
+ |
44
+ ## opt 2 - on penalties
45
+ (?:
46
+ [ ]*,[ ]*
47
+ (?:win [ ])?
48
+ (?<leg2_p1>\d{1,2}) - (?<leg2_p2>\d{1,2})
49
+ [ ] on [ ] pens
50
+ )
51
+ )?
52
+ \)
53
+ )?
54
+ )}ix
55
+
56
+
57
+
58
+ end # class Lexer
59
+ end # module Fbtxt
@@ -0,0 +1,192 @@
1
+ module Fbtxt
2
+ class Lexer
3
+
4
+ ## (match) status
5
+ ## note: english usage - cancelled (in UK), canceled (in US)
6
+ ##
7
+ ## add more variants - why? why not?
8
+
9
+
10
+ POSTPONED = %Q{ (?<postponed> postponed | pst\\.? | po?stp\\.? | ppd\\.? ) }
11
+ CANCELED = %Q{ (?<canceled> cancell?ed | canc\\.? ) } ## add can/can. - why? why not?
12
+ WALKOVER = %Q{ (?<walkover> walkover | w/o | wo ) } ## add o/w too - why? why not?
13
+ AWARDED = %Q{ (?<awarded> awarded | awd\\.? ) }
14
+ SUSPENDED = %Q{ (?<suspended> suspended | susp\\.? ) }
15
+ ABANDONED = %Q{ (?<abandoned> abandoned | aban\\.? | abd\\.? ) }
16
+ ANNULLED = %Q{ (?<annulled> annulled ) }
17
+ VOIDED = %Q{ (?<voided> voided | void ) } ### note - alternative (name) to annulled
18
+
19
+ REPLAY = %Q{ (?<replay> replay | repl\\.? ) }
20
+
21
+
22
+ ##
23
+ ## note - status_note incl. complete text incl. <status> (not normalized)
24
+ ## <status> gets normalized e.g. ppt => postponed etc.
25
+
26
+ STATUS_RE = %r{
27
+ \[
28
+ (?:
29
+ #############################################
30
+ ### opt 1 - allow long forms with note/comment for some stati
31
+ ## e.g. [postponed due to tropical storm "Hanna"]
32
+ ## [suspended at 84' by storm; result stood]
33
+ #########################
34
+ (?: (?<status_note>
35
+ (?<status>
36
+ ####################
37
+ ## pre-match (not played)
38
+ #{POSTPONED}
39
+ |
40
+ #{CANCELED}
41
+ |
42
+ #{WALKOVER}
43
+ |
44
+ ######################
45
+ ## pre/post match
46
+ #{AWARDED}
47
+ |
48
+ ########################
49
+ ## post match - (partially) played
50
+ #{SUSPENDED}
51
+ |
52
+ #{ABANDONED}
53
+ |
54
+ #{ANNULLED}
55
+ |
56
+ #{VOIDED} ### note - alternative to annulled
57
+ ) ## end-of-<status>
58
+ [ :;,-]+ ## leading spaces (or separators)
59
+ [^\]]+? ## note - add non-greedy match
60
+ ) ## end-of-<status-note>
61
+ [ ]* ## eat-up optional trailing spaces
62
+ )
63
+ |
64
+ ########################################
65
+ ## opt 2 - short form only (no note/comments) e.g. [postponed], [Canceled], etc.
66
+ ####################################
67
+ (?<status>
68
+ ####################
69
+ ## pre-match (not played)
70
+ #{POSTPONED}
71
+ |
72
+ #{CANCELED}
73
+ |
74
+ #{WALKOVER}
75
+ |
76
+ ######################
77
+ ## pre/post match
78
+ #{AWARDED}
79
+ |
80
+ ########################
81
+ ## post match - (partially) played
82
+ #{SUSPENDED}
83
+ |
84
+ #{ABANDONED}
85
+ |
86
+ #{ANNULLED}
87
+ |
88
+ #{VOIDED} ### note - alternative to annulled
89
+ |
90
+ #{REPLAY} ### todo/fix - keep replay - why? why not?
91
+ ### prefer replay in round e.g.
92
+ ## ▪ Round 17, Replay
93
+ ## ▪ Semi-finals, Replays
94
+ )
95
+ )
96
+ \]
97
+ }ix
98
+
99
+
100
+ def self._build_status( m )
101
+ status = {}
102
+ ## note - norm status text - why? why not?
103
+ status[:status] = if m[:postponed] then 'postponed'
104
+ elsif m[:canceled] then 'canceled'
105
+ elsif m[:walkover] then 'walkover'
106
+ elsif m[:awarded] then 'awarded'
107
+ elsif m[:suspended] then 'suspended'
108
+ elsif m[:abandoned] then 'abandoned'
109
+ elsif m[:annulled] ||
110
+ m[:voided] then 'annulled'
111
+ elsif m[:replay] then 'replay'
112
+ else ## fallback on "generic" status (shouldn't happen)
113
+ m[:status]
114
+ end
115
+
116
+ ## includes note? e.g. awarded; originally 2-0
117
+ status[:status_note] = m[:status_note] if m[:status_note]
118
+
119
+ status
120
+ end
121
+ def _build_status( m ) self.class._build_status( m ); end
122
+
123
+
124
+ end # class Lexer
125
+ end # module Fbtxt
126
+
127
+
128
+ __END__
129
+
130
+
131
+
132
+
133
+ ####################
134
+ ## pre-match (not played)
135
+ postponed|postp\.|ppd\.
136
+ ## e.g. [postponed due to problems with the screen of the stadium]
137
+ ## [postponed by storm]
138
+ ## [postponed due to tropical storm "Hanna"]
139
+ ## [postponed from Sep 10-12 due to death Queen Elizabeth II]
140
+
141
+ cancell?ed|canc.\
142
+
143
+ walkover|w/o|wo
144
+ ## A victory awarded to one team because the opponent was unable
145
+ ## or unwilling to compete (e.g., failing to show up or being disqualified).
146
+ ## -or-
147
+ ## A walkover or "win over" reveals when a team has won a game
148
+ ## without it being played.
149
+ ## -or-
150
+ ## see <https://en.wikipedia.org/wiki/Walkover>
151
+
152
+
153
+
154
+ ######################
155
+ ## pre/post match
156
+ awarded|awd\.
157
+
158
+ ## e.g. [awarded match to Leones Negros by undue alignment; original result 1-2]
159
+ ## [awarded 3-0 to Cafetaleros by undue alignment; originally ended 2-0]
160
+ ## [awarded 3-0; originally 0-2, América used ineligible player (Federico Viñas)]
161
+
162
+ ## A result that is decided by a governing body
163
+ ## (like FIFA or a domestic league) rather than by the play on the pitch.
164
+ ## Usually follows a Forfeit or Walkover.
165
+ ## If a team refuses to play, abandons a match, or fields an ineligible player,
166
+ ## the opponent is typically awarded a 3-0 victory.
167
+
168
+ ########################
169
+ ## post match - (partially) played
170
+ suspended|susp\.
171
+
172
+ ## e.g. [suspended at 0-0 in 12' due to storm]
173
+ ## [suspended at 84' by storm; result stood]
174
+
175
+ ## The match is temporarily halted but intended to be resumed or restarted later.
176
+
177
+ abandoned|aban.\|abd\.
178
+
179
+ ## e.g. [abandoned at 1-1 in 65' due to cardiac arrest
180
+ ## Luton player Tom Lockyer]
181
+ ## [abandoned at 0-0 in 6' due to waterlogged pitch]
182
+ ## [abandoned at 5-0 in 80' due to attack
183
+ ## on assistant referee by Cerro; result stood]
184
+ ## [abandoned at 1-0 in 31']
185
+ ## [abandoned at 0-1' in 85 due to crowd trouble]
186
+
187
+ ## The match started but was stopped by the referee before the final whistle
188
+ ## (e.g., due to a waterlogged pitch or player injury) and did not resume
189
+
190
+ annulled OR voided|void
191
+ ## The match result is struck from the record entirely,
192
+ ## usually due to a team's withdrawal from the league or a severe rule violation.