sportdb-parser 0.7.0 → 0.7.2

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1 -1
  3. data/Manifest.txt +18 -4
  4. data/Rakefile +0 -1
  5. data/lib/sportdb/parser/lexer-on_goal.rb +172 -0
  6. data/lib/sportdb/parser/lexer-on_group_def.rb +31 -0
  7. data/lib/sportdb/parser/lexer-on_prop_lineup.rb +79 -0
  8. data/lib/sportdb/parser/lexer-on_prop_misc.rb +110 -0
  9. data/lib/sportdb/parser/lexer-on_prop_penalties.rb +40 -0
  10. data/lib/sportdb/parser/lexer-on_round_def.rb +37 -0
  11. data/lib/sportdb/parser/lexer-on_top.rb +125 -0
  12. data/lib/sportdb/parser/lexer-prep_doc.rb +131 -0
  13. data/lib/sportdb/parser/lexer-prep_line.rb +63 -0
  14. data/lib/sportdb/parser/lexer-tokenize.rb +449 -0
  15. data/lib/sportdb/parser/lexer.rb +133 -1363
  16. data/lib/sportdb/parser/lexer_buffer.rb +8 -37
  17. data/lib/sportdb/parser/lexer_token.rb +126 -0
  18. data/lib/sportdb/parser/parser.rb +1104 -1401
  19. data/lib/sportdb/parser/parser_runtime.rb +379 -0
  20. data/lib/sportdb/parser/racc_parser.rb +36 -32
  21. data/lib/sportdb/parser/racc_tree.rb +65 -98
  22. data/lib/sportdb/parser/token-date--helpers.rb +130 -0
  23. data/lib/sportdb/parser/token-date--names.rb +108 -0
  24. data/lib/sportdb/parser/token-date.rb +20 -192
  25. data/lib/sportdb/parser/token-date_duration.rb +8 -27
  26. data/lib/sportdb/parser/token-geo.rb +16 -16
  27. data/lib/sportdb/parser/token-goals--helpers.rb +114 -0
  28. data/lib/sportdb/parser/token-goals.rb +103 -249
  29. data/lib/sportdb/parser/token-group.rb +8 -22
  30. data/lib/sportdb/parser/token-prop.rb +138 -124
  31. data/lib/sportdb/parser/token-prop_name.rb +48 -39
  32. data/lib/sportdb/parser/token-round.rb +21 -35
  33. data/lib/sportdb/parser/token-score--helpers.rb +189 -0
  34. data/lib/sportdb/parser/token-score.rb +9 -393
  35. data/lib/sportdb/parser/token-score_full.rb +331 -0
  36. data/lib/sportdb/parser/token-status.rb +44 -46
  37. data/lib/sportdb/parser/token-status_inline.rb +112 -0
  38. data/lib/sportdb/parser/token-text.rb +41 -31
  39. data/lib/sportdb/parser/token-time.rb +29 -26
  40. data/lib/sportdb/parser/token.rb +58 -159
  41. data/lib/sportdb/parser/version.rb +1 -1
  42. data/lib/sportdb/parser.rb +50 -19
  43. metadata +20 -20
  44. data/lib/sportdb/parser/blocktxt.rb +0 -99
  45. data/lib/sportdb/parser/lexer_tty.rb +0 -111
  46. data/lib/sportdb/parser/token-table.rb +0 -149
  47. data/lib/sportdb/parser/token_helpers.rb +0 -92
@@ -5,7 +5,7 @@
5
5
  class RaccMatchParser
6
6
 
7
7
  =begin
8
- RefereeLine = Struct.new( :name, :country ) do
8
+ RefereeLine = Struct.new( :name, :country ) do
9
9
  def pretty_print( printer )
10
10
  printer.text( "<RefereeLine " )
11
11
  printer.text( self.name )
@@ -16,7 +16,7 @@ end
16
16
  =end
17
17
 
18
18
  ## support multiple referees (incl. assistant refs etc.)
19
- RefereeLine = Struct.new( :referees ) do
19
+ RefereeLine = Struct.new( :referees ) do
20
20
  def pretty_print( printer )
21
21
  printer.text( "<RefereeLine " )
22
22
  printer.text( self.referees.pretty_inspect )
@@ -28,16 +28,16 @@ Referee = Struct.new( :name, :country ) do
28
28
  def to_s
29
29
  buf = String.new
30
30
  buf << self.name
31
- buf << " (#{self.country})" if self.country
31
+ buf << " (#{self.country})" if self.country
32
32
  buf
33
33
  end
34
34
 
35
35
  def pretty_print( printer )
36
36
  printer.text( to_s )
37
- end
37
+ end
38
38
  end
39
39
 
40
- AttendanceLine = Struct.new( :att ) do
40
+ AttendanceLine = Struct.new( :att ) do
41
41
  def pretty_print( printer )
42
42
  printer.text( "<AttendanceLine #{self.att}>" )
43
43
  end
@@ -45,7 +45,7 @@ end
45
45
 
46
46
 
47
47
 
48
- PenaltiesLine = Struct.new( :penalties ) do
48
+ PenaltiesLine = Struct.new( :penalties ) do
49
49
  def pretty_print( printer )
50
50
  printer.text( "<PenaltiesLine " )
51
51
  printer.text( self.penalties.pretty_inspect )
@@ -59,21 +59,21 @@ Penalty = Struct.new( :name, :score, :note ) do
59
59
  buf = String.new
60
60
  buf << "#{self.score[0]}-#{self.score[1]} " if self.score
61
61
  buf << self.name
62
- buf << " (#{self.note})" if self.note
62
+ buf << " (#{self.note})" if self.note
63
63
  buf
64
64
  end
65
65
 
66
66
 
67
67
  def pretty_print( printer )
68
68
  printer.text( to_s )
69
- end
69
+ end
70
70
  end
71
71
 
72
72
 
73
73
 
74
74
 
75
75
  ## find a better name for player (use bookings?) - note - red/yellow card for trainer possible
76
- CardsLine = Struct.new( :type, :bookings ) do
76
+ CardsLine = Struct.new( :type, :bookings ) do
77
77
  def pretty_print( printer )
78
78
  printer.text( "<CardsLine " )
79
79
  printer.text( self.type )
@@ -92,7 +92,7 @@ Booking = Struct.new( :name, :minute ) do
92
92
 
93
93
  def pretty_print( printer )
94
94
  printer.text( to_s )
95
- end
95
+ end
96
96
  end
97
97
 
98
98
 
@@ -111,11 +111,11 @@ end
111
111
  Lineup = Struct.new( :name, :captain, :cards, :sub ) do
112
112
  def pretty_print( printer )
113
113
  buf = String.new
114
- buf << self.name
114
+ buf << self.name
115
115
  buf << " [c]" if captain
116
116
  buf << " cards=" + self.cards.pretty_inspect if cards
117
117
  buf << " sub=" + self.sub.pretty_inspect if sub
118
- printer.text( buf )
118
+ printer.text( buf )
119
119
  end
120
120
  end
121
121
 
@@ -130,18 +130,18 @@ Card = Struct.new( :name, :minute ) do
130
130
 
131
131
  def pretty_print( printer )
132
132
  printer.text( to_s )
133
- end
133
+ end
134
134
  end
135
135
 
136
136
 
137
137
  Sub = Struct.new( :minute, :sub ) do
138
138
  def pretty_print( printer )
139
- buf = String.new
139
+ buf = String.new
140
140
  buf << "(" ## note - possibly recursive (thus, let minute go first/print first/upfront)
141
- buf << "#{self.minute.to_s} " if self.minute
142
- buf << "#{self.sub.pretty_inspect}"
141
+ buf << "#{self.minute.to_s} " if self.minute
142
+ buf << "#{self.sub.pretty_inspect}"
143
143
  buf << ")"
144
- printer.text( buf )
144
+ printer.text( buf )
145
145
  end
146
146
  end
147
147
 
@@ -201,13 +201,6 @@ class BlankLine
201
201
  end
202
202
  end
203
203
 
204
- ## todo/check - find a better name for hruler - divider? or ??? - why? why not?
205
- class HRuler ## h(orizontal) ruler (for breaks; new scopes)
206
- def pretty_print( printer )
207
- printer.text( "<HRuler>" )
208
- end
209
- end
210
-
211
204
 
212
205
 
213
206
  NoteLine = Struct.new( :text ) do
@@ -223,32 +216,6 @@ NotaBene = Struct.new( :text ) do
223
216
  end
224
217
 
225
218
 
226
- ## todo/check - rename TableHeading to TableHeader - why? why not?
227
- TableHeading = Struct.new( :text ) do
228
- def pretty_print( printer )
229
- printer.text( "<TableHeading #{self.text}>" )
230
- end
231
- end
232
-
233
- ## todo/check - rename TableDivider to TableRule/TableRuler/TableLine - why? why not?
234
- TableDivider = Struct.new( :text ) do
235
- def pretty_print( printer )
236
- printer.text( "<TableDivider #{self.text}>" )
237
- end
238
- end
239
-
240
- TableLine = Struct.new( :text ) do
241
- def pretty_print( printer )
242
- printer.text( "<TableLine #{self.text}>" )
243
- end
244
- end
245
-
246
- TableNote = Struct.new( :text ) do
247
- def pretty_print( printer )
248
- printer.text( "<TableNote #{self.text}>" )
249
- end
250
- end
251
-
252
219
 
253
220
 
254
221
  ## todo/check - use a generic Heading instead of Heading1/2/3 - why? why not?
@@ -278,7 +245,7 @@ MatchLineBye = Struct.new( :team, :note ) do
278
245
  printer.text( "#{self.team} bye")
279
246
  printer.text( " note=#{self.note.pretty_inspect}" ) if self.note
280
247
  printer.text( ">" )
281
- end
248
+ end
282
249
  end
283
250
 
284
251
  MatchLineWalkover = Struct.new( :team1, :team2, :note ) do
@@ -287,10 +254,10 @@ MatchLineWalkover = Struct.new( :team1, :team2, :note ) do
287
254
  printer.text( "#{self.team1} w/o #{self.team2}")
288
255
  printer.text( " note=#{self.note.pretty_inspect}" ) if self.note
289
256
  printer.text( ">" )
290
- end
257
+ end
291
258
  end
292
259
 
293
- MatchLineLegs = Struct.new( :team1, :team2,
260
+ MatchLineLegs = Struct.new( :team1, :team2,
294
261
  :score ) do ## change to geos - why? why not?
295
262
  def pretty_print( printer )
296
263
  printer.text( "<MatchLineLegs " )
@@ -300,26 +267,26 @@ MatchLineLegs = Struct.new( :team1, :team2,
300
267
  members.zip(values) do |name, value|
301
268
  next if [:team1, :team2].include?( name )
302
269
  next if value.nil?
303
-
270
+
304
271
  printer.text( "#{name}=#{value.pretty_inspect}" )
305
- end
272
+ end
306
273
 
307
274
  printer.text( ">" )
308
- end
275
+ end
309
276
  end
310
277
 
311
278
 
312
279
  #
313
280
  # note: use two status attributes for now
314
281
  # 1) inline_status and 2) (note_)status
315
- # for now e.g. A abd. B vs A v B [abadoned]
282
+ # for now e.g. A abd. B vs A v B [abadoned]
316
283
  # A 3-0 awd B vs A 3-0 B [awarded]
317
284
  # note - BOTH might be present at the same time
318
285
 
319
286
 
320
287
  MatchLine = Struct.new( :header, :tty, ## tty = TELETYPE MODE for teams and score!!
321
288
  :num, :date, :time, :time_local, :year,
322
- :team1, :team2,
289
+ :team1, :team2,
323
290
  :score,
324
291
  :status, :status_inline, :status_note,
325
292
  :geo,
@@ -335,12 +302,12 @@ MatchLine = Struct.new( :header, :tty, ## tty = TELETYPE MODE for teams and
335
302
  members.zip(values) do |name, value|
336
303
  next if [:team1, :team2].include?( name )
337
304
  next if value.nil?
338
-
305
+
339
306
  printer.text( "#{name}=#{value.pretty_inspect}" )
340
- end
307
+ end
341
308
 
342
309
  printer.text( ">" )
343
- end
310
+ end
344
311
 
345
312
  end
346
313
 
@@ -351,12 +318,12 @@ GoalLine = Struct.new( :goals1, :goals2 ) do
351
318
  printer.text( "goals1=" + self.goals1.pretty_inspect + "," )
352
319
  printer.breakable
353
320
  printer.text( "goals2=" + self.goals2.pretty_inspect + ">" )
354
- end
321
+ end
355
322
 
356
323
  ## def clone
357
- ## _clone = GoalLine.new( goals1: goals1.clone,
324
+ ## _clone = GoalLine.new( goals1: goals1.clone,
358
325
  ## goals2: goals2.clone )
359
- ##
326
+ ##
360
327
  ## puts "[debug] clone #{self.pretty_inspect} => #{_clone.pretty_inspect}"
361
328
  ##
362
329
  ## _clone
@@ -386,7 +353,7 @@ Goal = Struct.new( :player, :minutes, :count ) do
386
353
 
387
354
  def pretty_print( printer )
388
355
  printer.text( to_s )
389
- end
356
+ end
390
357
 
391
358
  ## def clone
392
359
  ## puts "[debug] clone #{self.pretty_inspect}"
@@ -402,7 +369,7 @@ GoalLineAlt = Struct.new( :goals ) do
402
369
  def pretty_print( printer )
403
370
  printer.text( "<GoalLineAlt " )
404
371
  printer.text( "goals=" + self.goals.pretty_inspect + ">" )
405
- end
372
+ end
406
373
  end
407
374
 
408
375
 
@@ -423,7 +390,7 @@ GoalAlt = Struct.new( :score, :player, :minute, :goal_type ) do
423
390
 
424
391
  def pretty_print( printer )
425
392
  printer.text( to_s )
426
- end
393
+ end
427
394
  end
428
395
 
429
396
 
@@ -432,7 +399,7 @@ GoalLineCompat = Struct.new( :goals ) do
432
399
  def pretty_print( printer )
433
400
  printer.text( "<GoalLineCompat " )
434
401
  printer.text( "goals=" + self.goals.pretty_inspect + ">" )
435
- end
402
+ end
436
403
  end
437
404
 
438
405
  ##
@@ -443,7 +410,7 @@ end
443
410
  GoalCompat = Struct.new( :score, :player, :minute, :goal_type ) do
444
411
  def to_s
445
412
  buf = String.new
446
- buf << "#{self.minute}"
413
+ buf << "#{self.minute}"
447
414
  buf << " #{self.player}"
448
415
  buf << " #{self.goal_type}" if self.goal_type
449
416
  buf << " #{self.score[0]}-#{self.score[1]}" if self.score
@@ -452,7 +419,7 @@ GoalCompat = Struct.new( :score, :player, :minute, :goal_type ) do
452
419
 
453
420
  def pretty_print( printer )
454
421
  printer.text( to_s )
455
- end
422
+ end
456
423
  end
457
424
 
458
425
 
@@ -477,31 +444,31 @@ GoalMinute = Struct.new( :m, :offset, :secs,
477
444
  buf = String.new
478
445
  buf << "#{self.m}"
479
446
  buf << "'"
480
- buf << "+#{self.offset}" if self.offset
481
- buf << " (og)" if self.og
482
- buf << " (pen)" if self.pen
483
- buf << " (f)" if self.freekick
484
- buf << " (h)" if self.header
447
+ buf << "+#{self.offset}" if self.offset
448
+ buf << "(og)" if self.og
449
+ buf << "(p)" if self.pen
450
+ buf << "(f)" if self.freekick
451
+ buf << "(h)" if self.header
485
452
  buf << " (#{self.secs} secs)" if self.secs
486
453
  buf
487
454
  end
488
-
489
- def pretty_print( printer )
490
- printer.text( to_s )
491
- end
455
+
456
+ def pretty_print( printer )
457
+ printer.text( to_s )
458
+ end
492
459
 
493
460
  ### quick hack:
494
461
  ### split struct into Minute+GoalType structs
495
462
  def to_minute
496
- Minute.new( m: self.m,
463
+ Minute.new( m: self.m,
497
464
  offset: self.offset,
498
465
  secs: self.secs )
499
466
  end
500
467
 
501
468
  def to_goal_type
502
- if self.og || self.pen || self.header || self.freekick
503
- GoalType.new( og: self.og,
504
- pen: self.pen,
469
+ if self.og || self.pen || self.header || self.freekick
470
+ GoalType.new( og: self.og,
471
+ pen: self.pen,
505
472
  header: self.header,
506
473
  freekick: self.freekick )
507
474
  else
@@ -511,14 +478,14 @@ GoalMinute = Struct.new( :m, :offset, :secs,
511
478
 
512
479
  ## def clone
513
480
  ## puts "[debug] clone #{self.pretty_inspect}"
514
- ## GoalMinute.new( m: m.clone,
515
- ## offset: offset.clone,
481
+ ## GoalMinute.new( m: m.clone,
482
+ ## offset: offset.clone,
516
483
  ## secs: secs.clone,
517
- ## og: og.clone,
518
- ## pen: pen.clone,
519
- ## header: header.clone,
484
+ ## og: og.clone,
485
+ ## pen: pen.clone,
486
+ ## header: header.clone,
520
487
  ## freekick: freekick.clone )
521
- ##
488
+ ##
522
489
  ## end
523
490
  end
524
491
 
@@ -532,10 +499,10 @@ GoalType = Struct.new( :og, :pen, :header, :freekick ) do
532
499
  buf << "(h)" if self.header
533
500
  buf
534
501
  end
535
-
536
- def pretty_print( printer )
537
- printer.text( to_s )
538
- end
502
+
503
+ def pretty_print( printer )
504
+ printer.text( to_s )
505
+ end
539
506
  end
540
507
 
541
508
 
@@ -544,14 +511,14 @@ Minute = Struct.new( :m, :offset, :secs ) do
544
511
  buf = String.new
545
512
  buf << "#{self.m}"
546
513
  buf << "'"
547
- buf << "+#{self.offset}" if self.offset
514
+ buf << "+#{self.offset}" if self.offset
548
515
  buf << "/#{self.secs} secs" if self.secs
549
516
  buf
550
517
  end
551
-
552
- def pretty_print( printer )
553
- printer.text( to_s )
554
- end
518
+
519
+ def pretty_print( printer )
520
+ printer.text( to_s )
521
+ end
555
522
  end
556
523
 
557
524
  end # class RaccMatchParser
@@ -0,0 +1,130 @@
1
+ module SportDb
2
+ class Lexer
3
+
4
+
5
+ ## "internal" date helpers
6
+ def self._build_date( m )
7
+ date = {}
8
+ ## map month names
9
+ ## note - allow any/upcase JULY/JUL etc. thus ALWAYS downcase for lookup
10
+ date[:y] = m[:year].to_i(10) if m[:year]
11
+ ## check - use y too for two-digit year or keep separate - why? why not?
12
+ date[:yy] = m[:yy].to_i(10) if m[:yy] ## two digit year (e.g. 25 or 78 etc.)
13
+ date[:m] = m[:month].to_i(10) if m[:month]
14
+ date[:m] = MONTH_MAP[ m[:month_name].downcase ] if m[:month_name]
15
+ date[:d] = m[:day].to_i(10) if m[:day]
16
+ date[:wday] = DAY_MAP[ m[:day_name].downcase ] if m[:day_name]
17
+
18
+ date
19
+ end
20
+
21
+ def self._build_date_legs( m )
22
+ legs = {}
23
+ ## map month names
24
+ ## note - allow any/upcase JULY/JUL etc. thus ALWAYS downcase for lookup
25
+ date = {}
26
+ date[:m] = MONTH_MAP[ m[:month_name1].downcase ]
27
+ date[:d] = m[:day1].to_i(10)
28
+ legs[:date1] = date
29
+
30
+ date = {}
31
+ date[:m] = MONTH_MAP[ m[:month_name2].downcase ] if m[:month_name2]
32
+ date[:d] = m[:day2].to_i(10)
33
+ legs[:date2] = date
34
+
35
+ legs
36
+ end
37
+
38
+
39
+ def self._build_duration( m )
40
+ ## todo/check/fix - if end: works for kwargs!!!!!
41
+ duration = { start: {}, end: {}}
42
+
43
+ duration[:start][:y] = m[:year1].to_i(10) if m[:year1]
44
+ duration[:start][:m] = MONTH_MAP[ m[:month_name1].downcase ] if m[:month_name1]
45
+ duration[:start][:d] = m[:day1].to_i(10) if m[:day1]
46
+ duration[:start][:wday] = DAY_MAP[ m[:day_name1].downcase ] if m[:day_name1]
47
+
48
+ duration[:end][:y] = m[:year2].to_i(10) if m[:year2]
49
+ duration[:end][:m] = MONTH_MAP[ m[:month_name2].downcase ] if m[:month_name2]
50
+ duration[:end][:d] = m[:day2].to_i(10) if m[:day2]
51
+ duration[:end][:wday] = DAY_MAP[ m[:day_name2].downcase ] if m[:day_name2]
52
+
53
+ duration
54
+ end
55
+
56
+
57
+
58
+
59
+ def _build_date( m ) self.class._build_date( m ); end
60
+ def _build_date_legs( m ) self.class._build_date_legs( m ); end
61
+ def _build_duration( m ) self.class._build_duration( m ); end
62
+
63
+
64
+
65
+
66
+ #############
67
+ ## "top-level" add a date parser helper
68
+
69
+ ## note: parse_date - returns Date object
70
+ ## _parse_date (with underscore) - return hash of "parsed" regex match data!!
71
+
72
+ def self.parse_date( str, start: nil )
73
+ if m = _parse_date( str )
74
+ year = m[:y]
75
+ yy = m[:yy]
76
+
77
+ ####
78
+ ## support two digit shortcut for year
79
+ if yy && year.nil?
80
+ ###
81
+ ## for now assume 00,01 to 30 is 2000,2001 to 2030
82
+ ## and 31 to 99 is 1931 to 1999
83
+ year = yy <= 30 ? 2000+yy : 1900+yy
84
+ end
85
+
86
+ month = m[:m]
87
+ day = m[:d]
88
+ wday = m[:wday]
89
+
90
+
91
+ if year.nil? ## try to calculate year
92
+ raise ArgumentError, "year required in date >#{str}< or pass along start date" if start.nil?
93
+
94
+ year = if month > start.month ||
95
+ (month == start.month && day >= start.day)
96
+ # assume same year as start_at event (e.g. 2013 for 2013/14 season)
97
+ start.year
98
+ else
99
+ # assume year+1 as start_at event (e.g. 2014 for 2013/14 season)
100
+ start.year+1
101
+ end
102
+ end
103
+ Date.new( year,month,day )
104
+ else
105
+ raise ArgumentError, "unexpected date format; cannot parse >#{str}<"
106
+ end
107
+ end
108
+
109
+
110
+
111
+ def self._parse_date( str )
112
+ ## note - strip - leading/trailing spaces automatic - why? why not?
113
+ m = DATE_RE.match( str.strip )
114
+
115
+ if m && m.pre_match == '' && m.post_match == ''
116
+ ## return hash table with captured components
117
+ date = _build_date( m )
118
+ date
119
+ elsif m
120
+ ## note - match BUT not anchored to start and end-of-string!!!
121
+ ## report, error somehow??
122
+ nil
123
+ else
124
+ nil ## no match - return nil
125
+ end
126
+ end
127
+
128
+
129
+ end # class Lexer
130
+ end # module SportDb
@@ -0,0 +1,108 @@
1
+ module SportDb
2
+ class Lexer
3
+
4
+
5
+ def self.parse_names( txt )
6
+ lines = [] # array of lines (with words)
7
+
8
+ txt.each_line do |line|
9
+ line = line.strip
10
+
11
+ next if line.empty?
12
+ next if line.start_with?( '#' ) ## skip comments too
13
+
14
+ ## strip inline (until end-of-line) comments too
15
+ ## e.g. Janvier Janv Jan ## check janv in use??
16
+ ## => Janvier Janv Jan
17
+
18
+ line = line.sub( /#.*/, '' ).strip
19
+ ## pp line
20
+
21
+ values = line.split( /[ \t]+/ )
22
+ ## pp values
23
+
24
+ ## todo/fix -- add check for duplicates
25
+ lines << values
26
+ end
27
+ lines
28
+
29
+ end # method parse
30
+
31
+
32
+ def self.build_names( lines )
33
+ ## join all words together into a single string e.g.
34
+ ## January|Jan|February|Feb|March|Mar|April|Apr|May|June|Jun|...
35
+ lines.map { |line| line.join('|') }.join('|')
36
+ end
37
+
38
+
39
+ def self.build_map( lines, downcase: false )
40
+ ## note: downcase name!!!
41
+ ## build a lookup map that maps the word to the index (line no) plus 1 e.g.
42
+ ## {"january" => 1, "jan" => 1,
43
+ ## "february" => 2, "feb" => 2,
44
+ ## "march" => 3, "mar" => 3,
45
+ ## "april" => 4, "apr" => 4,
46
+ ## "may" => 5,
47
+ ## "june" => 6, "jun" => 6, ...
48
+ lines.each_with_index.reduce( {} ) do |h,(line,i)|
49
+ line.each do |name|
50
+ h[ downcase ? name.downcase : name ] = i+1
51
+ end ## note: start mapping with 1 (and NOT zero-based, that is, 0)
52
+ h
53
+ end
54
+ end
55
+
56
+
57
+
58
+
59
+ MONTH_LINES = parse_names( <<TXT )
60
+ January Jan
61
+ February Feb
62
+ March Mar
63
+ April Apr
64
+ May
65
+ June Jun
66
+ July Jul
67
+ August Aug
68
+ September Sept Sep
69
+ October Oct
70
+ November Nov
71
+ December Dec
72
+ TXT
73
+
74
+ MONTH_NAMES = build_names( MONTH_LINES )
75
+ # pp MONTH_NAMES
76
+ MONTH_MAP = build_map( MONTH_LINES, downcase: true )
77
+ # pp MONTH_MAP
78
+
79
+
80
+
81
+ DAY_LINES = parse_names( <<TXT )
82
+ Monday Mon Mo
83
+ Tuesday Tues Tue Tu
84
+ Wednesday Wed We
85
+ Thursday Thurs Thur Thu Th
86
+ Friday Fri Fr
87
+ Saturday Sat Sa
88
+ Sunday Sun Su
89
+ TXT
90
+
91
+ DAY_NAMES = build_names( DAY_LINES )
92
+ # pp DAY_NAMES
93
+ DAY_MAP = build_map( DAY_LINES, downcase: true )
94
+ # pp DAY_MAP
95
+
96
+
97
+ #=>
98
+ # "January|Jan|February|Feb|March|Mar|April|Apr|May|June|Jun|
99
+ # July|Jul|August|Aug|September|Sept|Sep|October|Oct|
100
+ # November|Nov|December|Dec"
101
+ #
102
+ # "Monday|Mon|Mo|Tuesday|Tues|Tue|Tu|Wednesday|Wed|We|
103
+ # Thursday|Thurs|Thur|Thu|Th|Friday|Fri|Fr|
104
+ # Saturday|Sat|Sa|Sunday|Sun|Su"
105
+
106
+
107
+ end # class Lexer
108
+ end # module SportDb