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,112 @@
1
+ module Fbtxt
2
+ class Lexer
3
+
4
+ ## (match) status inline versions
5
+
6
+
7
+
8
+
9
+ ## "inline" match status e.g.
10
+ ## Clapham Rovers w/o Hitchin
11
+ ## Queen's Park bye
12
+
13
+ ## add support for WO or W-0 too - why? why not?
14
+ INLINE_WO_RE = %r{
15
+ (?<inline_wo>
16
+ \b (?: w/o | W/O ) \b
17
+ )}x ## note - NOT case insensitive
18
+
19
+ INLINE_BYE_RE = %r{
20
+ (?<inline_bye>
21
+ \b (?: bye | BYE ) \b
22
+ )}x ## note - NOT case insensitive
23
+
24
+
25
+ ###
26
+ # A n/p B (note - basically a inline short form of A v B [cancelled] )
27
+ # N/P
28
+ INLINE_NP_RE = %r{
29
+ (?<inline_np>
30
+ \b (?: n/p | N/P ) \b
31
+ )}x ## note - NOT case insensitive
32
+
33
+
34
+ ###
35
+ # abd/abd. or aban/aban. [abandoned]
36
+ # ABD/ABAN
37
+ INLINE_ABD_RE = %r{
38
+ (?<inline_abd>
39
+ \b (?: abd\.? |
40
+ aban\.? |
41
+ ABD | ABAN
42
+ )
43
+ ## POSITIVE lookahead - requires space
44
+ (?= [ ])
45
+ )}x ## note - NOT case insensitive
46
+
47
+ ####
48
+ # susp/susp. [suspended]
49
+ # SUSP
50
+ INLINE_SUSP_RE = %r{
51
+ (?<inline_susp>
52
+ \b (?: susp\.? |
53
+ SUSP )
54
+ ## POSITIVE lookahead - requires space
55
+ (?= [ ])
56
+ )}x ## note - NOT case insensitive
57
+
58
+
59
+ ####
60
+ # ppd/ppd. or pst/pst. or pstp/pstp. or postp/postp. [postponed]
61
+ # PPD/PSTP/POSTP/P-P
62
+ # todo/check - add/allow p-p too - why? why not?
63
+ INLINE_PPD_RE = %r{
64
+ (?<inline_ppd>
65
+ \b (?: ppd\.? |
66
+ pst\.? |
67
+ po?stp\.? |
68
+ PPD | PST | PO?STP | P-P
69
+ )
70
+ ## POSITIVE lookahead - requires space
71
+ (?= [ ])
72
+ )}x ## note - NOT case insensitive
73
+
74
+ ####
75
+ # void via x-x X-X
76
+ # todo/check - only allow X-X - why? why not?
77
+ INLINE_VOID_RE = %r{
78
+ (?<inline_void>
79
+ \b (?: x-x |
80
+ X-X
81
+ )
82
+ ## POSITIVE lookahead - requires space
83
+ (?= [ ])
84
+ )}x ## note - NOT case insensitive
85
+
86
+
87
+ ####
88
+ # awd/awd. [awarded]
89
+ # AWD
90
+ # note - recommendation is to allways include score
91
+ # thus, use/prefer SCORE_AWD e.g. 0-3 awd
92
+ INLINE_AWD_RE = %r{
93
+ (?<inline_awd>
94
+ \b (?: awd\.? | AWD )
95
+ ## POSITIVE lookahead - requires space
96
+ (?= [ ])
97
+ )}x ## note - NOT case insensitive
98
+
99
+ ###
100
+ # canc/canc. [cancelled]
101
+ # CANC
102
+ INLINE_CANC_RE = %r{
103
+ (?<inline_canc>
104
+ \b (?: canc\.? | CANC )
105
+ ## POSITIVE lookahead - requires space
106
+ (?= [ ])
107
+ )}x ## note - NOT case insensitive
108
+
109
+
110
+
111
+ end # class Lexer
112
+ end # module Fbtxt
@@ -0,0 +1,221 @@
1
+ module Fbtxt
2
+ class Lexer
3
+
4
+
5
+ ##
6
+ ## todo/fix - change TEXT_RE to TEAM_RE !!!!
7
+ ## do NOT use (anymore) as generic TEXT_RE
8
+
9
+
10
+ ## note - TEXT_RE used for TEAM_NAMES
11
+ ## plus as "legacy" shortcut for (simple) group or round names e.g.
12
+ ## Group A, Group 1, ..
13
+ ## Matchday 1, 1. Round,
14
+ ## note - no exception for (shortcut) group or round (MUST match team name pattern!)
15
+
16
+
17
+
18
+ ## note - do NOT allow single alpha text for now
19
+ ## add later?? A - B C - D - why?
20
+ ## opt 1) one alpha
21
+ ## (?<text_i> [a-z]) # only allow single letter text (not numbers!!)
22
+
23
+ ## opt 2) more than one alphanum
24
+
25
+
26
+ ### allow special case - starting text with number e.g.
27
+ ## number must be follow by space or dot ()
28
+ # 1 FC ## allow 1-FC or 1FC - why? why not?
29
+ # 1FC"
30
+ # 1. FC
31
+ # 1.FC
32
+ # 23° Noviembre
33
+ # 1890 Munich
34
+ # 1-FC - XXXX - not allowed for now, parse error
35
+ # 1/FC - XXXX - not allowed for now
36
+
37
+
38
+ ##
39
+ # allow Cote'd Ivoir or such
40
+ ## e.g. add '
41
+
42
+ ## note:
43
+ ## make sure these do NOT match!!!
44
+ ## TEXT => "Matchday 1 / Group A"
45
+ ## TEXT => "Matchday 2 / Group A"
46
+ ## TEXT => "Matchday 3 / Group A"
47
+
48
+
49
+
50
+ TEXT_RE = %r{
51
+ ## must start with alpha (allow unicode letters!!)
52
+ (?<text>
53
+ ## positive lookbehind
54
+ ## (MUST be fixed number of chars - no quantifier e.g. +? etc.)
55
+ (?<=[ ,;@|\[\]]
56
+ |^
57
+ )
58
+ (?:
59
+ # opt 1 - start with alpha
60
+ \p{L}+ ## all unicode letters (e.g. [a-z])
61
+ |
62
+
63
+ # opt 2 - start with num!! - allow special case (e.g. 1. FC)
64
+ \d+ # check for num lookahead (MUST be space or dot)
65
+ ## MUST be followed by (optional dot) and
66
+ ## required space !!!
67
+ ## MUST be follow by a to z!!!!
68
+ [.°]? ## optional dot (.) or degree(°) - todo - add number sign too!!
69
+ [ ]? ## make space optional too - why? why not?
70
+ ## yes - eg. 1st, 2nd, 5th etc.
71
+ \p{L}+
72
+ |
73
+ ## opt 3 - add another weirdo case
74
+ ## e.g. 's Gravenwezel-Schilde
75
+ '[s] [ ] \p{L}+
76
+ )
77
+
78
+
79
+ (?:(?: (?:[ ] # only single spaces allowed inline!!!
80
+ ## note - exclude (v[ ]/vs[ ]/vs.[ ])
81
+ ## AND switch to case-sensitive (via -i!!!)
82
+ (?! (?-i: (?: ## note - (big) V not matching for versus!!!
83
+ vs\.?|v|
84
+
85
+ n/p|N/P|
86
+ w/o|W/O|
87
+ abd\.?|ABD|
88
+ aban\.?|ABAN|
89
+ susp\.?|SUSP|
90
+ ppd\.?|PPD|
91
+ pst\.?|PST|
92
+ po?stp\.?|PO?STP|P-P|
93
+ x-x|X-X|
94
+ awd\.?|AWD|
95
+ canc\.?|CANC ) [ ]
96
+ |
97
+ (?: bye|BYE ) (?:[ ]|$))
98
+ )
99
+ )
100
+ |
101
+ [/-] ## must NOT be surrounded by spaces
102
+ )?
103
+ (?:
104
+ \p{L}
105
+ |
106
+ (?: ## note - restrict [.&'] to single char usage (no doubled e.g. && etc.)
107
+ \. (?! \.) ## allow single points only (now two or more etc.)
108
+ |
109
+ & (?! &)
110
+ |
111
+ ' (?! ')
112
+ )
113
+ |
114
+ (?:
115
+ \d+
116
+ (?!
117
+ [0-9h'+] | ## protected break on 12h / 12' / 1-1
118
+ ## check usege for 3+4 - possible? where ? why?
119
+ (?:[.:-]\d) ## protected/exclude/break on 12.03 / 12:03 / 12-12
120
+ ## BUT allow Park21-Arena for example e.g. 21-A :-)
121
+ )
122
+ [°]? ## followed by optional ord
123
+ ## negative lookahead for numbers
124
+ ## note - include digits itself!!!
125
+ ## note - remove / (slash) e.g. allows UDI'19/Beter Bed
126
+ )
127
+ )
128
+ )* ## must NOT end with space or dash(-)
129
+ ## todo/fix - possible in regex here
130
+ ## only end in alphanum a-z0-9 (not dot or & ???)
131
+
132
+
133
+ ## allow optional at the end
134
+ ## tag or year
135
+ ## make it and in the future - why? why not?
136
+ ##
137
+ ## change - fix
138
+ ## do NOT use (A) for amateur
139
+ ## use A or A. with NO ()!!!
140
+ ## (A) - allow with predined alpha only for now
141
+ ## e.g. (A) - amateur a team or b?
142
+ ### same for U21 or U9 etc
143
+ ## use with NO ()!!! - why? why not?
144
+ ## or U21 U9 etc. - why? why not?
145
+ ## or etc.
146
+ ## (1879-1893) or allow years e.g. (1879-1893)
147
+ ###
148
+ ## add allow country code three to five letters for now
149
+ ## change to generic 1 to 5 - why? why not?
150
+ ## e.g. (A), (I),
151
+ ## (AUT)
152
+ ## (TRNC) five? for UEFA code for northern cyprus
153
+ ## change to 1 to 4 - why? why not?
154
+ ## check - fix possible for upper case only here
155
+ ## inline for this group only?
156
+ (?:
157
+ [ ]
158
+ \(
159
+ \d{4}-\d{4}
160
+ \)
161
+ )?
162
+ (?:
163
+ ######
164
+ # check for country code (cc)
165
+ # e.g. (AUT) or ,AUT or AUT
166
+ (?:
167
+ [ ] ## note - do NOT allow more than one space!!! - why? why not?
168
+ \(
169
+ ## note - auto-exclude reserved (aet) from SCORE_FULLER_MORE!!!
170
+ ## plus golden goal (gg)/sudden death (sd), silver goal (sg)
171
+ ## (ht), (ft)
172
+ (?! (?: aet | agget | asdet | asget | ht | ft )
173
+ \)
174
+ )
175
+ (?:
176
+ [A-Z]{1,5}
177
+ )
178
+ \)
179
+ )
180
+ |
181
+ (?:
182
+ [ ]*[,›>][ ]*
183
+ [A-Z]{1,5}
184
+ \b
185
+ )
186
+ )?
187
+ ## add lookahead/lookbehind
188
+ ## must be space!!!
189
+ ## (or comma or start/end of string)
190
+ ## kind of \b !!!
191
+ ## positive lookahead
192
+ (?=[ ,;@|\[\]]
193
+ |$
194
+ )
195
+ )
196
+ }ix
197
+
198
+
199
+
200
+
201
+
202
+ ###
203
+ ## helper for testing regex match for team names
204
+
205
+ def self._parse_team( str )
206
+ ## note - strip - leading/trailing spaces
207
+ m = TEXT_RE.match( str.strip )
208
+ if m && m.pre_match == '' && m.post_match == ''
209
+ m
210
+ elsif m
211
+ ## note - match BUT not anchored to start and end-of-string!!!
212
+ ## report, error somehow??
213
+ nil
214
+ else
215
+ nil ## no match - return nil
216
+ end
217
+ end
218
+
219
+
220
+ end # class Lexer
221
+ end # module Fbtxt
@@ -0,0 +1,144 @@
1
+ module Fbtxt
2
+ class Lexer
3
+
4
+
5
+
6
+ ##
7
+ # keep 18h30 - why? why not?
8
+ # add support for 6:30pm 8:20am etc. - why? why not?
9
+ #
10
+ # check - only support h e.g. 18h30 or 18H30 too - why? why not?
11
+ # e.g. 18:30 (or 18h30)
12
+ # note - optional timezone possible e.g.
13
+ # 18:30 UTC+1 or 18:30 BST/UTC+1 or such!!!
14
+ # 18:30 UTC+01 or 18:30 BST/UTC+01
15
+ #
16
+ #
17
+ # note 18.30 no longer supported - MUST use 18:30 or 18h30 !!!
18
+ #
19
+ #
20
+ #
21
+ # note - local time is now (inline) part of time!!!
22
+ # and, thus, must always follow time
23
+ # e.g. 18:30 (19:30 BST)
24
+ #
25
+ ## local time e.g (19:30 UTC+1) or (19:30 BST/UTC+1) or
26
+ ## note - timezone is optional! e.g. (19:30) works too
27
+
28
+
29
+ TIME_RE = %r{
30
+ \b
31
+ (?<time>
32
+ (?<hour>\d{1,2})
33
+ [:h]
34
+ (?<minute>\d{2})
35
+
36
+ #### optional (inline) timezone
37
+ ## note - non-utc timezone MUST be hard-coded (added) here!!!
38
+ ## avoids eating-up team names (separated by one space)
39
+ ## e.g. 18:30 MEX v MEX
40
+ (?:
41
+ [ ] ## require space - why? why not
42
+ (?<timezone>
43
+ (?:
44
+ ## GMT - Greenwich Mean Time
45
+ ## BST - British Summer Time
46
+ ## CES?T - Central European (Summer) Time
47
+ ## EES?T - Eastern European (Summer) Time
48
+ ##
49
+ (?: GMT|BST|CES?T|EES?T)
50
+ (?: /
51
+ UTC (?: [+-]\d{1,4} | ±0)
52
+ )?
53
+ )
54
+ |
55
+ (?:
56
+ UTC (?: [+-]\d{1,4} | ±0)
57
+ )
58
+ )
59
+ )?
60
+ )
61
+ \b
62
+
63
+ ####
64
+ ### note - local time is now INLINE and MUST follow time
65
+ (?:
66
+ [ ]+ ## todo/check - make space optional - why? why not?
67
+ \(
68
+ (?<time_local>
69
+ (?<local_hour>\d{1,2})
70
+ [:h] ### todo/fix - MUST match style in time above!!!
71
+ ### use capture with backref!!!!
72
+ (?<local_minute>\d{2})
73
+
74
+ ####
75
+ ## optional "local" timezone name eg. BRT or CEST etc.
76
+ (?:
77
+ [ ] ## require space - why? why not
78
+ (?<local_timezone>
79
+ (?: [A-Z]{3,4}
80
+ (?: /
81
+ UTC (?: [+-]\d{1,4} | ±0)
82
+ )?
83
+ )
84
+ |
85
+ (?: ## e.g. 0 or 00 or 0000
86
+ UTC (?: [+-]\d{1,4} | ±0)
87
+ )
88
+ )
89
+ )? # note - make timezone optional!!!
90
+ )
91
+ \)
92
+ )?
93
+ }ix
94
+
95
+
96
+ def self._build_time( m )
97
+ ## unify to iso-format
98
+ ### 12.40 => 12:40
99
+ ## 12h40 => 12:40 etc.
100
+ ## keep string (no time-only type in ruby)
101
+ data = { time: {} }
102
+
103
+ hour = m[:hour].to_i(10) ## allow 08/07/etc.
104
+ minute = m[:minute].to_i(10)
105
+
106
+ ## check if 24:00 possible? or only 0:00 (23:59)
107
+ unless (hour >=0 && hour <=23) &&
108
+ (minute >=0 && minute <=59)
109
+ raise ArgumentError, "parse error - time >#{m[:time]}< out-of-range"
110
+ end
111
+
112
+ data[:time][:h] = hour
113
+ data[:time][:m] = minute
114
+ data[:time][:timezone] = m[:timezone] if m[:timezone]
115
+
116
+
117
+ ## check if local time present e.g.
118
+ ## 18:30 (19:30)
119
+ ## 18:30 (19:30 BST) etc.
120
+ if m[:time_local]
121
+ data[:time_local] = {}
122
+
123
+ local_hour = m[:local_hour].to_i(10) ## allow 08/07/etc.
124
+ local_minute = m[:local_minute].to_i(10)
125
+
126
+ ## check if 24:00 possible? or only 0:00 (23:59)
127
+ unless (hour >=0 && hour <=23) &&
128
+ (minute >=0 && minute <=59)
129
+ raise ArgumentError, "parse error - local time >#{m[:time_local]}< out-of-range"
130
+ end
131
+
132
+ data[:time_local][:h] = local_hour
133
+ data[:time_local][:m] = local_minute
134
+ data[:time_local][:timezone] = m[:local_timezone] if m[:local_timezone]
135
+ end
136
+
137
+ data
138
+ end
139
+ def _build_time(m) self.class._build_time(m); end
140
+
141
+
142
+
143
+ end # class Lexer
144
+ end # module Fbtxt
@@ -0,0 +1,224 @@
1
+
2
+
3
+ module Fbtxt
4
+ class Lexer
5
+
6
+
7
+
8
+ ###
9
+ ## add att(endance) e.g. att: 18000
10
+ ##
11
+ ## A v B 2-1 att: 18000
12
+
13
+ ATTENDANCE_RE = %r{
14
+ (?<attendance>
15
+ \b
16
+ (?: attendance|att )
17
+ : [ ]*
18
+ (?<value>
19
+ [1-9]
20
+ (?: _? \d+ )*
21
+ )
22
+ \b
23
+ )}ix
24
+
25
+
26
+
27
+
28
+ ###
29
+ ## home/away/neutral - (h), (a), (n)
30
+ ## add support for h/a/n
31
+ ## with (?-i \b [han] \b) lower-case and \b boundry - why? why not?
32
+
33
+ TEAM_HOME_RE = %r{ (?<team_home> \(h\) )}ix
34
+ TEAM_AWAY_RE = %r{ (?<team_away> \(a\) )}ix
35
+ TEAM_NEUTRAL_RE = %r{ (?<team_neutral> \(n\) )}ix
36
+
37
+
38
+
39
+
40
+
41
+ ##
42
+ ## note VS
43
+ ## remove VS for now
44
+ ## e.g. Olympia Wijgmaal v VS Kortenaken
45
+
46
+
47
+
48
+ ## note - only match case sensitive (downcased letters)!!!
49
+ ## note - bigger match first e.g. vs than v etc.
50
+ VS_RE = %r{
51
+ (?<vs>
52
+ (?<=[ ]) # positive lookBEHIND for space
53
+ (?-i:
54
+ vs\.?|v
55
+ )
56
+ (?=[ ]) # positive lookAHEAD for space
57
+ )
58
+ }ix
59
+
60
+
61
+ ##
62
+ ## ▪SF or ▪1,▪17, etc.
63
+ ## note - only numbers and upcase allowed
64
+ ## limited to two-letters for now - make more generic - why? why not?
65
+ ## may add SF1, SF2, or such later !!!
66
+ INLINE_ROUND_SHORT_RE = %r{
67
+ (?<inline_round_short>
68
+
69
+ (?<inline_round_text>
70
+ [0-9]+
71
+ | [A-Z]{1,2} [0-9]*
72
+ )
73
+ (?= [ ]|$) # positive lookAHEAD for space (or end-of-line)
74
+ )}x
75
+
76
+ ###
77
+ ## ▪ Replay
78
+ ## ▪ 1st Leg
79
+ INLINE_ROUND_BIG_RE = %r{
80
+ (?<inline_round_big>
81
+ ▪ [ ]
82
+ (?<inline_round_text>
83
+ [^\[\(@]+? ## note - non-greedy
84
+ ## allow commas (,) or slash(/) - why? why not?
85
+ )
86
+ (?= [ ]{2}|$) # positive lookAHEAD for TWO(!) spaces (or end-of-line)
87
+ )}x
88
+
89
+
90
+
91
+
92
+ ##############
93
+ ## "top-level" regex used for:
94
+ ## - date_header
95
+ ## - match_header & match_line_more
96
+ ## - match_line
97
+
98
+ RE = Regexp.union(
99
+ SPACES_RE,
100
+
101
+ INLINE_ROUND_SHORT_RE,
102
+ INLINE_ROUND_BIG_RE,
103
+
104
+ STATUS_RE, ## match status e.g. [cancelled], etc.
105
+
106
+ INLINE_WO_RE, ## (inline) match status - w/o (walkout)
107
+ INLINE_NP_RE, ## (inline) match status - n/p (not played)
108
+ INLINE_BYE_RE, ## (inline) match status - bye (advance to next round)
109
+ INLINE_ABD_RE, ## (inline) match status - abd/abd. (abandoned)
110
+ INLINE_SUSP_RE, ## (inline) match status - susp/susp. (suspended)
111
+ INLINE_PPD_RE, ## (inline) match status - ppd/ppd. or pstp/pstp. or postp/postp. or p-p (postponed)
112
+ INLINE_VOID_RE, ## (inline) match status - x-x (voided)
113
+ INLINE_AWD_RE, ## (inline) match status - awd/awd. (awarded)
114
+ INLINE_CANC_RE, ## (inline) match status - canc/canc. (cancelled/canceled)
115
+
116
+
117
+ TEAM_HOME_RE, ## (H)
118
+ TEAM_AWAY_RE, ## (A)
119
+ TEAM_NEUTRAL_RE, ## (N)
120
+
121
+ NOTE_RE, ### fix - change to INLINE_NOTE !!!
122
+ DATE_LEGS_RE, # note - must go before date!!!
123
+ DATE_RE, ## note - date must go before time (e.g. 12.12. vs 12.12)
124
+ TIME_RE,
125
+
126
+ ATTENDANCE_RE, # note - allow att: for now inline in matches too - why? why not?
127
+
128
+ SCORE_FULL_1ST_RE, # note - MUST go before SCORE_LEGS_RE!!
129
+ ## e.g. 2-2, 5-1 pen.
130
+ SCORE_LEGS_RE,
131
+ SCORE_FULL_RE,
132
+ SCORE_FULLER_RE,
133
+ SCORE_FULLER_MORE_RE,
134
+ SCORE_AWD_RE, # (inline) score awarded e.g. 3-0 awd or 0-1 awd. etc.
135
+ SCORE_ABD_RE, # (inline) score abandoned e.g. 2-1 abd.
136
+ SCORE_RE, ## note basic score e.g. 1-1 must go after SCORE_FULL_RE!!!
137
+
138
+ VS_RE,
139
+
140
+ TEXT_RE,
141
+
142
+ %r{ (?<sym> [,@()-] ) }x, ## todo - check if "standalone" comma (,) in use?
143
+ ANY_RE,
144
+ )
145
+
146
+
147
+
148
+
149
+
150
+
151
+ ## ord (for ordinal number)
152
+ ## e.g. (51) or (1) etc. - limit digits of number - why? why not???
153
+
154
+ START_WITH_ORD = %r{
155
+ \A
156
+ [ ]* ## ignore leading spaces (if any)
157
+ (?<ord>
158
+ \(
159
+ (?<value>\d+)
160
+ \)
161
+ )}ix
162
+
163
+
164
+ ###
165
+ ## e.g. 1930, 1986, 2002, 2010, 2022, 2026
166
+ ## note - only YYYY
167
+ ## note - look out for clubs like 1860 München (de) !!!
168
+ ## 1899 Hoffenheim (de)
169
+ ## 1896 Löwenherz (ch - a.k.a. FC Winterthur ??)
170
+ ## any others starting with YYYY ?!
171
+ ## note - YEAR requires TWO (trailing) spaces !!!!! e.g.
172
+ ## 1930 Uruguay 4-2 Argentina
173
+ ## 1934 Italy 2-1 Czechoslovakia (AET)
174
+ ## 2022 Argentina 3-3 France (AET, 4-2 pen)
175
+ ##
176
+ ## do NOT match (iso date!!) - 2020-11-12
177
+ ## 2020/11/12
178
+ ## 2020.11.12 etc.
179
+
180
+ START_WITH_YEAR = %r{
181
+ \A
182
+ [ ]* ## ignore leading spaces (if any)
183
+ (?<year>
184
+ \d{4}
185
+ )
186
+ ## positive lookahead
187
+ (?= [ ]{2} | ## min. TWO spaces!!! or
188
+ [ ]@ | ## space with geo marker or
189
+ [ ]* \z ## year (date) header (end-of-line/string)
190
+ )
191
+ }x
192
+
193
+
194
+
195
+ ###
196
+ ## check for headings
197
+ ## e.g. = heading 1
198
+ ## == heading 2 etc.
199
+ ## =Eurochampionship=
200
+ ## note - no spaces required (same as in wikipedia!!)
201
+ ## same as in wikipedia support six (6) levels
202
+ ##
203
+ ## note - use \A (instead of ^) - \A strictly matches the start of the string.
204
+
205
+
206
+ HEADING_RE = %r{ \A
207
+ [ ]* ## ignore leading spaces (if any)
208
+ (?<heading_marker> ={1,6} )
209
+ [ ]*
210
+ (?<heading>
211
+ ## must start with letter - why? why not?
212
+ ### 1st round
213
+ ## allow numbers e.g. Group A - 1
214
+ [^=]+? ## use non-greedy
215
+ )
216
+ [ ]* ## ignore trailing spaces (if any)
217
+ (?: =*) ## allow any trailing heading markers
218
+ [ ]* ## ignore trailing spaces (if any)
219
+ \z
220
+ }ix
221
+
222
+
223
+ end # class Lexer
224
+ end # module Fbtxt