fbtxt-lexer 0.0.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 (49) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +3 -0
  3. data/Manifest.txt +47 -0
  4. data/README.md +18 -0
  5. data/Rakefile +30 -0
  6. data/lib/fbtxt/lexer/debuggable.rb +58 -0
  7. data/lib/fbtxt/lexer/lexer-logger.rb +20 -0
  8. data/lib/fbtxt/lexer/lexer-on_goal.rb +167 -0
  9. data/lib/fbtxt/lexer/lexer-on_group_def.rb +31 -0
  10. data/lib/fbtxt/lexer/lexer-on_prop_cards.rb +61 -0
  11. data/lib/fbtxt/lexer/lexer-on_prop_lineup.rb +82 -0
  12. data/lib/fbtxt/lexer/lexer-on_prop_misc.rb +108 -0
  13. data/lib/fbtxt/lexer/lexer-on_prop_penalties.rb +44 -0
  14. data/lib/fbtxt/lexer/lexer-on_round_def.rb +37 -0
  15. data/lib/fbtxt/lexer/lexer-on_top.rb +133 -0
  16. data/lib/fbtxt/lexer/lexer-prep_doc.rb +131 -0
  17. data/lib/fbtxt/lexer/lexer-prep_line.rb +63 -0
  18. data/lib/fbtxt/lexer/lexer-props.rb +66 -0
  19. data/lib/fbtxt/lexer/lexer-tokenize_line.rb +381 -0
  20. data/lib/fbtxt/lexer/lexer-tokenize_norm.rb +93 -0
  21. data/lib/fbtxt/lexer/lexer.rb +192 -0
  22. data/lib/fbtxt/lexer/lexer_buffer.rb +68 -0
  23. data/lib/fbtxt/lexer/lexer_context.rb +70 -0
  24. data/lib/fbtxt/lexer/lexer_token.rb +127 -0
  25. data/lib/fbtxt/lexer/token-date--helpers.rb +130 -0
  26. data/lib/fbtxt/lexer/token-date--names.rb +108 -0
  27. data/lib/fbtxt/lexer/token-date.rb +200 -0
  28. data/lib/fbtxt/lexer/token-date_duration.rb +171 -0
  29. data/lib/fbtxt/lexer/token-geo.rb +173 -0
  30. data/lib/fbtxt/lexer/token-goals--helpers.rb +114 -0
  31. data/lib/fbtxt/lexer/token-goals.rb +306 -0
  32. data/lib/fbtxt/lexer/token-group.rb +29 -0
  33. data/lib/fbtxt/lexer/token-note.rb +40 -0
  34. data/lib/fbtxt/lexer/token-prop.rb +334 -0
  35. data/lib/fbtxt/lexer/token-prop_name.rb +83 -0
  36. data/lib/fbtxt/lexer/token-round.rb +88 -0
  37. data/lib/fbtxt/lexer/token-score--helpers.rb +189 -0
  38. data/lib/fbtxt/lexer/token-score.rb +60 -0
  39. data/lib/fbtxt/lexer/token-score_full.rb +331 -0
  40. data/lib/fbtxt/lexer/token-score_fuller.rb +434 -0
  41. data/lib/fbtxt/lexer/token-score_legs.rb +59 -0
  42. data/lib/fbtxt/lexer/token-status.rb +192 -0
  43. data/lib/fbtxt/lexer/token-status_inline.rb +112 -0
  44. data/lib/fbtxt/lexer/token-text.rb +221 -0
  45. data/lib/fbtxt/lexer/token-time.rb +144 -0
  46. data/lib/fbtxt/lexer/token.rb +224 -0
  47. data/lib/fbtxt/lexer/version.rb +24 -0
  48. data/lib/fbtxt/lexer.rb +118 -0
  49. metadata +142 -0
@@ -0,0 +1,83 @@
1
+ module Fbtxt
2
+ class Lexer
3
+
4
+
5
+ ##
6
+ ## see token-text for TEXT_RE
7
+ ## change PROP_NAME_RE to TEXT_II or TEXT_??? - why? why not?
8
+ ### no do NO change
9
+ ## change TEXT_RE to TEAM_RE or TEAM_NAME_RE !!!!
10
+ ## it is NOT generic TEXT regex!!!
11
+
12
+
13
+
14
+
15
+ PROP_NAME_WORD_ = %r{
16
+ \p{L}+
17
+ \.? ## optional dot
18
+ }ix
19
+
20
+
21
+ ## todo/fix - remove support for double quotes e.g. "Rodri" - why? why not?
22
+ ##
23
+
24
+ ## name different from text (**does NOT allow number in name/text**)
25
+ ## different from PROP_KEY too
26
+ PROP_NAME_RE = %r{
27
+ (?<prop_name>
28
+ \b
29
+ (?<name>
30
+ #{PROP_NAME_WORD_}
31
+
32
+ ## connectors
33
+ (?:
34
+ ## (i) space - only one single space allowed inline!!!
35
+ (?:
36
+ ### check if negative lookbehind is redudant!!
37
+ ## next char is \p{L} and NOT space
38
+ ## thus double space not possible!!
39
+ (?<! [ ]) ## use negative lookbehind
40
+ [ ]
41
+ (?= \p{L}|['"]\p{L}) ## use lookahead
42
+ )
43
+ ## (ii) support (inline) quoted name e.g. "Rodri" or such
44
+ | (?:
45
+ (?<=[ ]) ## use positive lookbehind
46
+ " \p{L}+ "
47
+ ## require space here too - why? why not?
48
+ )
49
+ ## (iii) dash (-)
50
+ | (?:
51
+ ## use POSITIVE lookBEHIND
52
+ ## note - allow leading dot (.) e.g. K.-H.Förster
53
+ ## short for Karl-Heinz Förster
54
+ ##
55
+ ## change to negative lookBEHIND [ '"-]
56
+ ## \p{L}\. | \p{L} - not MUST be fixed size
57
+ (?<=
58
+ [\p{L}.]
59
+ )
60
+ [-] ## must be surrounded by letters
61
+ ## e.g. One-Two NOT
62
+ ## One- Two or One - Two or One -Two etc.
63
+ (?= \p{L}) ## use lookahead
64
+ )
65
+ |
66
+ (?: ## flex rule for quote - allow any
67
+ ## only check for double quotes e.g. cannot follow other ' for now - why? why not?
68
+ ## allows rodrigez 'rodri' for example
69
+ (?<!') ## use negative lookbehind
70
+ '
71
+ )
72
+ | ## standard case with letter(s) and optional dot
73
+ #{PROP_NAME_WORD_}
74
+ )*
75
+ )
76
+ ## add lookahead - must be non-alphanum
77
+ ## add colon (:) too - why? why not?
78
+ (?= [ ,;\]\)]|$)
79
+ )}ix
80
+
81
+
82
+ end # class Lexer
83
+ end # module Fbtxt
@@ -0,0 +1,88 @@
1
+ module Fbtxt
2
+ class Lexer
3
+
4
+ ####
5
+ #
6
+ ## note - use \A (instead of ^) - \A strictly matches the start of the string.
7
+ ##
8
+ ## todo - add support for trailing markers e.g.
9
+ ## ▪ Round 1 ▪▪▪▪▪▪▪▪
10
+ ## :: Round 1 ::::::::::::
11
+ ##
12
+ ## check - allow without space (like in heading =Heading 1=) - why? why not?
13
+ ## ▪Round 1▪▪▪▪▪▪▪▪
14
+ ## ::Round 1::::::::::::
15
+
16
+ ROUND_OUTLINE_I_RE = %r{ \A
17
+ [ ]* ## ignore leading spaces (if any)
18
+ (?<round_marker>
19
+ [▪]{1,3} ## BLACK SMALL SQUARE e.g. ▪,▪▪,▪▪▪
20
+ )
21
+ [ ]+
22
+ (?<round_outline>
23
+ ## must start with letter - why? why not?
24
+ ### 1st round
25
+ ## allow numbers e.g. Group A - 1
26
+ ##
27
+ ## note - CANNOT incl. :| !!!
28
+ ## used for markers for defs/definitions
29
+ [^:|]+? ## use non-greedy
30
+ )
31
+ (?:
32
+ [ ]+
33
+ [▪]+
34
+ )?
35
+ [ ]* ## ignore trailing spaces (if any)
36
+ \z
37
+ }xi
38
+
39
+ ROUND_OUTLINE_II_RE = %r{ \A
40
+ [ ]* ## ignore leading spaces (if any)
41
+ (?<round_marker>
42
+ ::{1,3} ## e.g. ::,:::,::::
43
+ )
44
+ [ ]+
45
+ (?<round_outline>
46
+ ## must start with letter - why? why not?
47
+ ### 1st round
48
+ ## allow numbers e.g. Group A - 1
49
+ ##
50
+ ## note - CANNOT incl. :| !!!
51
+ ## used for markers for defs/definitions
52
+ [^:|]+? ## use non-greedy
53
+ )
54
+ (?:
55
+ [ ]+
56
+ ::+
57
+ )?
58
+ [ ]* ## ignore trailing spaces (if any)
59
+ \z
60
+ }xi
61
+
62
+ ROUND_OUTLINE_RE = Regexp.union( ROUND_OUTLINE_I_RE,
63
+ ROUND_OUTLINE_II_RE,
64
+ )
65
+
66
+
67
+ ###
68
+ # note - for def(initions) only one level support
69
+ # that is, no round outline additions possible (e.g ▪▪ 1st leg etc.)
70
+ ROUND_DEF_OUTLINE_RE = %r{ \A
71
+ [ ]* ## ignore leading spaces (if any)
72
+ (?: [▪] ## BLACK SMALL SQUARE
73
+ |
74
+ :: )
75
+ [ ]+
76
+ (?<round_outline>
77
+ [^:|]+? ## use non-greedy
78
+ )
79
+ [ ]* ## ignore trailing spaces (if any)
80
+ ### possitive lookahead MUST be : OR |
81
+ (?= [:|]
82
+ [ ]) ## note: requires space for now after [:|] - keep - why? why not?
83
+ }ix
84
+
85
+
86
+
87
+ end # class Lexer
88
+ end # module Fbtxt
@@ -0,0 +1,189 @@
1
+ module Fbtxt
2
+ class Lexer
3
+
4
+
5
+ def self._build_score( m )
6
+ ## note - score is "generic"
7
+ ## might be full-time (ft) or
8
+ ## after extra-time (aet) or such
9
+ ## or even undecided/unknown
10
+ ## thus, use score1/score2 and NOT ft1/ft2
11
+ ## thus, use (simply an) array e.g. [1,2]
12
+ ## and NOT hash (table) e.g. { ft: [1,2] } !!!
13
+
14
+ score = [m[:score1].to_i(10),
15
+ m[:score2].to_i(10)]
16
+
17
+ score
18
+ end
19
+
20
+ def self._build_score_awd( m ) # score awarded (awd/awd.)
21
+ ### note - use "generic" score for now
22
+ ## to match A 3-0 B [awarded] etc.
23
+ score = [m[:score1].to_i(10),
24
+ m[:score2].to_i(10)]
25
+ ## add score[:awarded] = true ???
26
+ ## note - for now uses its own token e.g SCORE_AWD
27
+ score
28
+ end
29
+
30
+ def self._build_score_abd( m ) # score abandonded (abd/abd.)
31
+ ### note - use "generic" score for now
32
+ score = [m[:score1].to_i(10),
33
+ m[:score2].to_i(10)]
34
+ ## add score[:abd] = true ???
35
+ ## note - for now uses its own token e.g SCORE_ABD
36
+ score
37
+ end
38
+
39
+
40
+ def self._build_score_full( m )
41
+ score = {}
42
+ score[:p] = [m[:p1].to_i(10),
43
+ m[:p2].to_i(10)] if m[:p1] && m[:p2]
44
+ score[:et] = [m[:et1].to_i(10),
45
+ m[:et2].to_i(10)] if m[:et1] && m[:et2]
46
+ score[:ft] = [m[:ft1].to_i(10),
47
+ m[:ft2].to_i(10)] if m[:ft1] && m[:ft2]
48
+ score[:ht] = [m[:ht1].to_i(10),
49
+ m[:ht2].to_i(10)] if m[:ht1] && m[:ht2]
50
+
51
+ ## add golden/silver flags
52
+ score[:golden] = true if m[:aetgg] ## golden goal (gg)/sudden death (sd)
53
+ score[:silver] = true if m[:aetsg] ## silver goal (sg)
54
+
55
+ score
56
+ end
57
+
58
+ def self._build_score_fuller( m )
59
+ score = {}
60
+ score[:p] = [m[:p1].to_i(10),
61
+ m[:p2].to_i(10)] if m[:p1] && m[:p2]
62
+ score[:et] = [m[:et1].to_i(10),
63
+ m[:et2].to_i(10)] if m[:et1] && m[:et2]
64
+ score[:ft] = [m[:ft1].to_i(10),
65
+ m[:ft2].to_i(10)] if m[:ft1] && m[:ft2]
66
+ score[:ht] = [m[:ht1].to_i(10),
67
+ m[:ht2].to_i(10)] if m[:ht1] && m[:ht2]
68
+ score[:agg] = [m[:agg1].to_i(10),
69
+ m[:agg2].to_i(10)] if m[:agg1] && m[:agg2]
70
+
71
+ if m[:away1] && m[:away2]
72
+ score[:away] = [m[:away1].to_i(10),
73
+ m[:away2].to_i(10)]
74
+ elsif m[:away] ## fallback if no away score; check away flag
75
+ score[:away] = true
76
+ end
77
+
78
+ ## add golden/silver flags
79
+ score[:golden] = true if m[:aetgg] ## golden goal (gg)/sudden death (sd)
80
+ score[:silver] = true if m[:aetsg] ## silver goal (sg)
81
+
82
+ score
83
+ end
84
+
85
+
86
+ def self._build_score_fuller_more( m )
87
+ ## SCORE + SCORE_FULLER_MORE
88
+ ## note - after extra-time (aet) or full-time (ft)
89
+ ## score may be present in SCORE!!!
90
+ score = {}
91
+ score[:p] = [m[:p1].to_i(10),
92
+ m[:p2].to_i(10)] if m[:p1] && m[:p2]
93
+ score[:et] = [m[:et1].to_i(10),
94
+ m[:et2].to_i(10)] if m[:et1] && m[:et2]
95
+ score[:ft] = [m[:ft1].to_i(10),
96
+ m[:ft2].to_i(10)] if m[:ft1] && m[:ft2]
97
+ score[:ht] = [m[:ht1].to_i(10),
98
+ m[:ht2].to_i(10)] if m[:ht1] && m[:ht2]
99
+ score[:agg] = [m[:agg1].to_i(10),
100
+ m[:agg2].to_i(10)] if m[:agg1] && m[:agg2]
101
+
102
+ if m[:away1] && m[:away2]
103
+ score[:away] = [m[:away1].to_i(10),
104
+ m[:away2].to_i(10)]
105
+ elsif m[:away] ## fallback if no away score; check away flag
106
+ score[:away] = true
107
+ end
108
+
109
+ ## add golden/silver flags
110
+ score[:golden] = true if m[:aetgg] ## golden goal (gg)/sudden death (sd)
111
+ score[:silver] = true if m[:aetsg] ## silver goal (sg)
112
+
113
+ ## add flag in score for et/ft/ht
114
+ ## used for "dangling" (generic) score
115
+ score[:score] = 'et' if m[:aet] || m[:aetgg] || m[:aetsg]
116
+ score[:score] = 'ft' if m[:ft]
117
+ score[:score] = 'ht' if m[:ht]
118
+
119
+ score
120
+ end
121
+
122
+
123
+ def self._build_score_legs( m )
124
+ legs = {}
125
+
126
+ ############
127
+ ### build leg1 (score)
128
+ score = {}
129
+ score[:ft] = [m[:leg1_ft1].to_i(10),
130
+ m[:leg1_ft2].to_i(10)]
131
+ legs['leg1'] = score
132
+
133
+ ##################
134
+ ### build leg2 (score)
135
+ score = {}
136
+ score[:ft] = [m[:leg2_ft1].to_i(10),
137
+ m[:leg2_ft2].to_i(10)] if m[:leg2_ft1] && m[:leg2_ft2]
138
+ score[:et] = [m[:leg2_et1].to_i(10),
139
+ m[:leg2_et2].to_i(10)] if m[:leg2_et1] && m[:leg2_et2]
140
+ score[:p] = [m[:leg2_p1].to_i(10),
141
+ m[:leg2_p2].to_i(10)] if m[:leg2_p1] && m[:leg2_p2]
142
+ legs['leg2'] = score
143
+
144
+ ## check for (opt) aggregate - keep on "top-level"
145
+ legs[:agg] = [m[:agg1].to_i(10),
146
+ m[:agg2].to_i(10)] if m[:agg1] && m[:agg2]
147
+ legs[:away] = true if m[:away]
148
+
149
+ legs
150
+ end
151
+
152
+
153
+ def _build_score( m ) self.class._build_score( m ); end
154
+ def _build_score_awd( m ) self.class._build_score_awd( m ); end
155
+ def _build_score_abd( m ) self.class._build_score_abd( m ); end
156
+ def _build_score_full( m ) self.class._build_score_full( m ); end
157
+ def _build_score_fuller( m ) self.class._build_score_fuller( m ); end
158
+ def _build_score_fuller_more( m ) self.class._build_score_fuller_more( m ); end
159
+ def _build_score_legs( m ) self.class._build_score_legs( m ); end
160
+
161
+
162
+
163
+
164
+ ###
165
+ ## add parser helpers
166
+
167
+ def self._parse_score_full( str )
168
+ ## note - strip - leading/trailing spaces automatic - why? why not?
169
+
170
+ m = Regexp.union(
171
+ SCORE_FULL_1ST_RE,
172
+ SCORE_FULL_RE ).match( str.strip )
173
+
174
+ if m && m.pre_match == '' && m.post_match == ''
175
+ pp m
176
+ _build_score_full( m )
177
+ elsif m
178
+ ## note - match BUT not anchored to start and end-of-string!!!
179
+ ## report, error somehow??
180
+ nil
181
+ else
182
+ nil ## no match - return nil
183
+ end
184
+ end
185
+
186
+
187
+
188
+ end # class Lexer
189
+ end # module Fbtxt
@@ -0,0 +1,60 @@
1
+ module Fbtxt
2
+ class Lexer
3
+
4
+
5
+ ###
6
+ ##
7
+ ## add support for score awarded (inline style)
8
+ ## 3-0 awd 3-0 awd. 3-0awd
9
+ ## 0-1 awd or 0-1 AWD etc.
10
+
11
+ ##
12
+ ## note - keep AWD w/o dot - why? why not?
13
+
14
+ SCORE_AWD_RE = %r{
15
+ (?<score_awd>
16
+ \b
17
+ (?<score1>\d{1,2}) - (?<score2>\d{1,2})
18
+ [ ]?
19
+ (?-i: awd\.? | AWD )
20
+ ## POSITIVE lookahead - requires space
21
+ (?= [ ])
22
+ )}ix
23
+
24
+ ###
25
+ ##
26
+ ## add support for score abandoned (inline style)
27
+ ## 2-1 abd. or 2-1 ABD
28
+ SCORE_ABD_RE = %r{
29
+ (?<score_abd>
30
+ \b
31
+ (?<score1>\d{1,2}) - (?<score2>\d{1,2})
32
+ [ ]?
33
+ (?-i: abd\.? | ABD )
34
+ ## POSITIVE lookahead - requires space
35
+ (?= [ ])
36
+ )}ix
37
+
38
+ #####
39
+ ## 2-1
40
+ ###
41
+ ### note - was SCORE__FT__RE
42
+ ### changed to "generic" SCORE_RE
43
+ ### and
44
+ ## (?<ft1>\d{1,2}) - (?<ft2>\d{1,2})
45
+ ## changed
46
+ ## (?<score1>\d{1,2}) - (?<score2>\d{1,2})
47
+ ## to
48
+ ## pattern match not necessarily the full-time (ft) scoreline!!!
49
+ ## - pattern also used for goal seq(uence) e.g. 1-0 Kane, 1-1 Johnson
50
+ SCORE_RE = %r{
51
+ (?<score>
52
+ \b
53
+ (?<score1>\d{1,2}) - (?<score2>\d{1,2})
54
+ \b
55
+ )}ix
56
+
57
+
58
+
59
+ end # class Lexer
60
+ end # module Fbtxt