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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +4 -0
- data/Manifest.txt +50 -0
- data/README.md +22 -0
- data/Rakefile +53 -0
- data/lib/fbtxt/parser/debuggable.rb +53 -0
- data/lib/fbtxt/parser/lexer-logger.rb +20 -0
- data/lib/fbtxt/parser/lexer-on_goal.rb +167 -0
- data/lib/fbtxt/parser/lexer-on_group_def.rb +31 -0
- data/lib/fbtxt/parser/lexer-on_prop_lineup.rb +79 -0
- data/lib/fbtxt/parser/lexer-on_prop_misc.rb +123 -0
- data/lib/fbtxt/parser/lexer-on_prop_penalties.rb +40 -0
- data/lib/fbtxt/parser/lexer-on_round_def.rb +37 -0
- data/lib/fbtxt/parser/lexer-on_top.rb +133 -0
- data/lib/fbtxt/parser/lexer-prep_doc.rb +131 -0
- data/lib/fbtxt/parser/lexer-prep_line.rb +63 -0
- data/lib/fbtxt/parser/lexer-tokenize.rb +468 -0
- data/lib/fbtxt/parser/lexer.rb +231 -0
- data/lib/fbtxt/parser/lexer_buffer.rb +68 -0
- data/lib/fbtxt/parser/lexer_token.rb +126 -0
- data/lib/fbtxt/parser/parse_tree--core.rb +29 -0
- data/lib/fbtxt/parser/parse_tree-match.rb +309 -0
- data/lib/fbtxt/parser/parse_tree-props.rb +233 -0
- data/lib/fbtxt/parser/parse_tree.rb +202 -0
- data/lib/fbtxt/parser/parser-runtime.rb +379 -0
- data/lib/fbtxt/parser/parser-top.rb +102 -0
- data/lib/fbtxt/parser/parser.rb +2343 -0
- data/lib/fbtxt/parser/token-date--helpers.rb +130 -0
- data/lib/fbtxt/parser/token-date--names.rb +108 -0
- data/lib/fbtxt/parser/token-date.rb +200 -0
- data/lib/fbtxt/parser/token-date_duration.rb +171 -0
- data/lib/fbtxt/parser/token-geo.rb +134 -0
- data/lib/fbtxt/parser/token-goals--helpers.rb +114 -0
- data/lib/fbtxt/parser/token-goals.rb +306 -0
- data/lib/fbtxt/parser/token-group.rb +29 -0
- data/lib/fbtxt/parser/token-note.rb +40 -0
- data/lib/fbtxt/parser/token-prop.rb +309 -0
- data/lib/fbtxt/parser/token-prop_name.rb +83 -0
- data/lib/fbtxt/parser/token-round.rb +88 -0
- data/lib/fbtxt/parser/token-score--helpers.rb +189 -0
- data/lib/fbtxt/parser/token-score.rb +60 -0
- data/lib/fbtxt/parser/token-score_full.rb +331 -0
- data/lib/fbtxt/parser/token-score_fuller.rb +434 -0
- data/lib/fbtxt/parser/token-score_legs.rb +59 -0
- data/lib/fbtxt/parser/token-status.rb +192 -0
- data/lib/fbtxt/parser/token-status_inline.rb +112 -0
- data/lib/fbtxt/parser/token-text.rb +221 -0
- data/lib/fbtxt/parser/token-time.rb +144 -0
- data/lib/fbtxt/parser/token.rb +224 -0
- data/lib/fbtxt/parser/version.rb +24 -0
- data/lib/fbtxt/parser.rb +140 -0
- metadata +145 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
module Fbtxt
|
|
2
|
+
class Parser
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
=begin
|
|
6
|
+
RefereeLine = Struct.new( :name, :country ) do
|
|
7
|
+
def pretty_print( printer )
|
|
8
|
+
printer.text( "<RefereeLine " )
|
|
9
|
+
printer.text( name )
|
|
10
|
+
printer.text( " (#{country})" ) if country
|
|
11
|
+
printer.text( ">" )
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
=end
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## support multiple referees (incl. assistant refs etc.)
|
|
18
|
+
RefereeLine = Struct.new( :referees ) do
|
|
19
|
+
def pretty_print( q )
|
|
20
|
+
q.group( 4, '<RefereeLine ', '>') do
|
|
21
|
+
q.pp( referees )
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end # RefereeLine
|
|
25
|
+
|
|
26
|
+
Referee = Struct.new( :name, :country ) do
|
|
27
|
+
def to_s
|
|
28
|
+
buf = String.new
|
|
29
|
+
buf << name
|
|
30
|
+
buf << " (#{country})" if country
|
|
31
|
+
buf
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def pretty_print( q )
|
|
35
|
+
q.text( to_s )
|
|
36
|
+
end
|
|
37
|
+
end # Referee
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
AttendanceLine = Struct.new( :att ) do
|
|
41
|
+
def pretty_print( q )
|
|
42
|
+
q.group( 4, '<AttendanceLine ', '>') do
|
|
43
|
+
q.pp( att )
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end # AttendanceLine
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
PenaltiesLine = Struct.new( :penalties ) do
|
|
52
|
+
def as_json(*)
|
|
53
|
+
['<PenaltiesLine>', { 'penalties' => penalties.as_json }]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def pretty_print( q )
|
|
57
|
+
q.group( 4, '< ', '>') do
|
|
58
|
+
q.pp( penalties )
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end # PenaltiesLine
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
Penalty = Struct.new( :name, :score, :note ) do
|
|
65
|
+
def as_json(*)
|
|
66
|
+
h = { 'name' => name }
|
|
67
|
+
h['score'] = "#{score[0]}-#{score[1]}" if score
|
|
68
|
+
h['note'] = "(#{note})" if note
|
|
69
|
+
|
|
70
|
+
## ['<Penalty>', h]
|
|
71
|
+
h # note - return "inline" json object
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def to_s
|
|
75
|
+
buf = String.new
|
|
76
|
+
buf << "#{score[0]}-#{score[1]} " if score
|
|
77
|
+
buf << name
|
|
78
|
+
buf << " (#{note})" if note
|
|
79
|
+
buf
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def pretty_print( q )
|
|
84
|
+
q.text( to_s )
|
|
85
|
+
end
|
|
86
|
+
end # Penalty
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
## find a better name for player (use bookings?) - note - red/yellow card for trainer possible
|
|
92
|
+
CardsLine = Struct.new( :type,
|
|
93
|
+
:bookings,
|
|
94
|
+
) do
|
|
95
|
+
def pretty_print( q )
|
|
96
|
+
q.group( 4, '<CardsLine ', '>') do
|
|
97
|
+
q.text( type )
|
|
98
|
+
## note - either (all-in-one or undetermined) bookings: []
|
|
99
|
+
## or bookings1/2 aka: [[],[]]
|
|
100
|
+
q.text( " bookings=" )
|
|
101
|
+
q.pp( bookings )
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end # CardsLine
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
Booking = Struct.new( :name, :minute ) do
|
|
108
|
+
def to_s
|
|
109
|
+
buf = String.new
|
|
110
|
+
buf << "#{name}"
|
|
111
|
+
buf << " #{minute.to_s}" if minute
|
|
112
|
+
buf
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def pretty_print( q )
|
|
116
|
+
q.text( to_s )
|
|
117
|
+
end
|
|
118
|
+
end # Booking
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
##
|
|
124
|
+
## change :lineup to :lineups (e.g. requires array of lineups)
|
|
125
|
+
LineupLine = Struct.new( :team, :lineup, :coach ) do
|
|
126
|
+
def as_json(*)
|
|
127
|
+
h = { 'team' => team.as_json,
|
|
128
|
+
'lineups' => lineup.as_json
|
|
129
|
+
}
|
|
130
|
+
h['coach'] = coach.as_json if coach
|
|
131
|
+
|
|
132
|
+
['<LineupLine>', h]
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def pretty_print( q )
|
|
136
|
+
q.group( 4, '<LineupLine ', '>') do
|
|
137
|
+
q.text( team )
|
|
138
|
+
q.text( ' ' )
|
|
139
|
+
|
|
140
|
+
## todo/fix - check for "flat" items - no formation
|
|
141
|
+
## or empty lineup (possible?)
|
|
142
|
+
## add formation e.g. (1-) 3-4-2-1
|
|
143
|
+
formation = lineup.map { |item| item.size }
|
|
144
|
+
## note - remove first entry (assume it's 1 for goalee!)
|
|
145
|
+
formation.shift
|
|
146
|
+
q.text( formation.join('-'))
|
|
147
|
+
q.text( ' ')
|
|
148
|
+
|
|
149
|
+
q.pp( lineup )
|
|
150
|
+
|
|
151
|
+
if coach
|
|
152
|
+
q.breakable
|
|
153
|
+
q.text( "coach=" + coach )
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end # LineupLine
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
Lineup = Struct.new( :name, :captain, :cards, :sub ) do
|
|
161
|
+
def as_json(*)
|
|
162
|
+
h = { 'name' => name.as_json }
|
|
163
|
+
h['captain'] = captain.as_json if captain
|
|
164
|
+
h['cards'] = cards.as_json if cards
|
|
165
|
+
h['sub'] = sub.as_json if sub
|
|
166
|
+
|
|
167
|
+
## ['<Lineup>', h]
|
|
168
|
+
h ## note - return "inline" json object (not tagged array with json object)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def pretty_print( q )
|
|
172
|
+
q.group( 0, '', '') do ## group( indent, open, close)
|
|
173
|
+
q.text( name )
|
|
174
|
+
q.text( ' [c]' ) if captain
|
|
175
|
+
|
|
176
|
+
if cards
|
|
177
|
+
q.text( ' ' )
|
|
178
|
+
q.pp( cards )
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
if sub
|
|
182
|
+
q.breakable ## can become either a space or a newline
|
|
183
|
+
q.pp( sub )
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end # Lineup
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
Card = Struct.new( :name, :minute ) do
|
|
194
|
+
def as_json(*) to_s; end
|
|
195
|
+
|
|
196
|
+
def to_s
|
|
197
|
+
buf = String.new
|
|
198
|
+
buf << "#{name}"
|
|
199
|
+
buf << " #{minute.to_s}" if minute
|
|
200
|
+
buf
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def pretty_print( q )
|
|
204
|
+
q.text( to_s )
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
##
|
|
211
|
+
## fix-fix-fix
|
|
212
|
+
## change :sub to :lineup - why? why not?
|
|
213
|
+
|
|
214
|
+
Sub = Struct.new( :minute, :sub ) do
|
|
215
|
+
def as_json(*)
|
|
216
|
+
h = { 'lineup' => sub.as_json }
|
|
217
|
+
h['minute'] = minute.as_json if minute
|
|
218
|
+
|
|
219
|
+
## ['<Sub>', h]
|
|
220
|
+
h # note - return "inline" json object (not tagged array with json object)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def pretty_print( q )
|
|
224
|
+
q.group( 0, '(', ')') do
|
|
225
|
+
q.text( "#{minute.to_s} " ) if minute
|
|
226
|
+
q.pp( sub )
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end # Sub
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
end # class Parser
|
|
233
|
+
end # module Fbtxt
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
####
|
|
3
|
+
# Parser support machinery (incl. node classes/abstract syntax tree)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
module Fbtxt
|
|
7
|
+
class Parser
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
GroupDef = Struct.new( :name, :teams ) do
|
|
11
|
+
|
|
12
|
+
def as_json(*)
|
|
13
|
+
["<GroupDef>", { 'name' => name.as_json,
|
|
14
|
+
'teams' => teams.as_json }
|
|
15
|
+
]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def pretty_print( q )
|
|
19
|
+
q.group( 4, '<GroupDef ', '>' ) do ## group( indent, open, close)
|
|
20
|
+
q.text( name )
|
|
21
|
+
q.text( " teams=" )
|
|
22
|
+
q.pp( teams )
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end # GroupDef
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
##
|
|
30
|
+
## note - for now exclusive really
|
|
31
|
+
## either date OR duration
|
|
32
|
+
RoundDef = Struct.new( :name, :date, :duration ) do
|
|
33
|
+
|
|
34
|
+
def as_json(*)
|
|
35
|
+
h = { 'name' => name.as_json }
|
|
36
|
+
|
|
37
|
+
h['date'] = date.as_json if date
|
|
38
|
+
h['duration'] = duration.as_json if duration
|
|
39
|
+
|
|
40
|
+
["<RoundDef>", h]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def pretty_print( q )
|
|
44
|
+
q.group( 4, '<RoundDef ', '>' ) do
|
|
45
|
+
q.text( name )
|
|
46
|
+
if date
|
|
47
|
+
q.text( " date=")
|
|
48
|
+
q.pp( date )
|
|
49
|
+
end
|
|
50
|
+
if duration
|
|
51
|
+
q.text( " duration=")
|
|
52
|
+
q.pp( duration )
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
end # RoundDef
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
##
|
|
61
|
+
## note - for now exclusive really
|
|
62
|
+
## either date OR year
|
|
63
|
+
DateHeader = Struct.new( :date, :year ) do
|
|
64
|
+
|
|
65
|
+
def as_json(*)
|
|
66
|
+
h = {}
|
|
67
|
+
h['date'] = date.as_json if date
|
|
68
|
+
h['year'] = year.as_json if year
|
|
69
|
+
|
|
70
|
+
['<DateHeader>', h]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def pretty_print( q )
|
|
75
|
+
q.group( 4, '<DateHeader ', '>' ) do
|
|
76
|
+
q.pp( date ) if date
|
|
77
|
+
q.pp( year ) if year
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end # DateHeader
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
DateHeaderLegs = Struct.new( :date1, :date2 ) do
|
|
85
|
+
|
|
86
|
+
def as_json(*)
|
|
87
|
+
['<DateHeaderLegs>', { 'leg1' => date1.as_json,
|
|
88
|
+
'leg2' => date2.as_json,
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def pretty_print( q )
|
|
94
|
+
q.group( 4, '<DateHeaderLegs ', '>' ) do
|
|
95
|
+
q.text( "leg1=" )
|
|
96
|
+
q.pp( date1 )
|
|
97
|
+
q.text( " leg2=" )
|
|
98
|
+
q.pp( date2 )
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end # DateHeaderLegs
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
RoundOutline = Struct.new( :outline, :level ) do
|
|
106
|
+
def as_json(*)
|
|
107
|
+
['<RoundOutline>', { 'outline' => outline.as_json,
|
|
108
|
+
'level' => level.as_json, }
|
|
109
|
+
]
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def pretty_print( q )
|
|
113
|
+
q.group( 4, '<RoundOutline ', '>' ) do
|
|
114
|
+
q.text( outline )
|
|
115
|
+
q.text( " level=#{level}" )
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end # RoundOutline
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class BlankLine
|
|
125
|
+
def as_json(*)
|
|
126
|
+
['<BlankLine>']
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def pretty_print( q )
|
|
130
|
+
q.text( "<BlankLine>" )
|
|
131
|
+
end
|
|
132
|
+
end # BlankLine
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
NoteLine = Struct.new( :text ) do
|
|
137
|
+
def as_json(*)
|
|
138
|
+
['<NoteLine>', { 'text' => text.as_json } ]
|
|
139
|
+
end
|
|
140
|
+
def pretty_print( q )
|
|
141
|
+
q.group( 4, '<NoteLine ', '>' ) do
|
|
142
|
+
q.text( text )
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end # NoteLine
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
NotaBene = Struct.new( :text ) do
|
|
149
|
+
def as_json(*)
|
|
150
|
+
['<NotaBene>', { 'text' => text.as_json } ]
|
|
151
|
+
end
|
|
152
|
+
def pretty_print( q )
|
|
153
|
+
q.group( 4, '<NotaBene ', '>' ) do
|
|
154
|
+
q.text( text )
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end # NotaBene
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
## todo/check - use a generic Heading instead of Heading1/2/3 - why? why not?
|
|
164
|
+
Heading1 = Struct.new( :text ) do
|
|
165
|
+
def as_json(*)
|
|
166
|
+
['<Heading1>', { 'text' => text.as_json }]
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def pretty_print( q )
|
|
170
|
+
q.group( 4, '<Heading1 ', '>' ) do
|
|
171
|
+
q.text( text )
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end # Heading1
|
|
175
|
+
|
|
176
|
+
Heading2 = Struct.new( :text ) do
|
|
177
|
+
def as_json(*)
|
|
178
|
+
['<Heading2>', { 'text' => text.as_json }]
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def pretty_print( q )
|
|
182
|
+
q.group( 4, '<Heading2 ', '>' ) do
|
|
183
|
+
q.text( text )
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end # Heading2
|
|
187
|
+
|
|
188
|
+
Heading3 = Struct.new( :text ) do
|
|
189
|
+
def as_json(*)
|
|
190
|
+
['<Heading3>', { 'text' => text.as_json }]
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def pretty_print( q )
|
|
194
|
+
q.group( 4, '<Heading3 ', '>' ) do
|
|
195
|
+
q.text( text )
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end # Heading3
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
end # class Parser
|
|
202
|
+
end # module Fbtxt
|