sportdb-parser 0.7.1 → 0.8.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 +4 -4
- data/CHANGELOG.md +1 -1
- data/Manifest.txt +25 -7
- data/Rakefile +23 -0
- data/lib/sportdb/parser/debuggable.rb +53 -0
- data/lib/sportdb/parser/lexer-logger.rb +20 -0
- data/lib/sportdb/parser/lexer-on_goal.rb +167 -0
- data/lib/sportdb/parser/lexer-on_group_def.rb +31 -0
- data/lib/sportdb/parser/lexer-on_prop_lineup.rb +79 -0
- data/lib/sportdb/parser/lexer-on_prop_misc.rb +123 -0
- data/lib/sportdb/parser/lexer-on_prop_penalties.rb +40 -0
- data/lib/sportdb/parser/lexer-on_round_def.rb +37 -0
- data/lib/sportdb/parser/lexer-on_top.rb +133 -0
- data/lib/sportdb/parser/lexer-prep_doc.rb +131 -0
- data/lib/sportdb/parser/lexer-prep_line.rb +63 -0
- data/lib/sportdb/parser/lexer-tokenize.rb +468 -0
- data/lib/sportdb/parser/lexer.rb +122 -1376
- data/lib/sportdb/parser/lexer_buffer.rb +8 -37
- data/lib/sportdb/parser/lexer_token.rb +126 -0
- data/lib/sportdb/parser/parse_tree--core.rb +29 -0
- data/lib/sportdb/parser/parse_tree-match.rb +309 -0
- data/lib/sportdb/parser/parse_tree-props.rb +233 -0
- data/lib/sportdb/parser/parse_tree.rb +202 -0
- data/lib/sportdb/parser/parser-top.rb +102 -0
- data/lib/sportdb/parser/parser.rb +1253 -1392
- data/lib/sportdb/parser/token-date--helpers.rb +130 -0
- data/lib/sportdb/parser/token-date--names.rb +108 -0
- data/lib/sportdb/parser/token-date.rb +20 -192
- data/lib/sportdb/parser/token-date_duration.rb +8 -27
- data/lib/sportdb/parser/token-geo.rb +16 -16
- data/lib/sportdb/parser/token-goals--helpers.rb +114 -0
- data/lib/sportdb/parser/token-goals.rb +101 -255
- data/lib/sportdb/parser/token-group.rb +8 -22
- data/lib/sportdb/parser/token-prop.rb +178 -124
- data/lib/sportdb/parser/token-prop_name.rb +48 -39
- data/lib/sportdb/parser/token-round.rb +21 -35
- data/lib/sportdb/parser/token-score--helpers.rb +189 -0
- data/lib/sportdb/parser/token-score.rb +9 -393
- data/lib/sportdb/parser/token-score_full.rb +331 -0
- data/lib/sportdb/parser/token-status.rb +44 -46
- data/lib/sportdb/parser/token-status_inline.rb +112 -0
- data/lib/sportdb/parser/token-text.rb +41 -31
- data/lib/sportdb/parser/token-time.rb +29 -26
- data/lib/sportdb/parser/token.rb +90 -158
- data/lib/sportdb/parser/version.rb +2 -2
- data/lib/sportdb/parser.rb +88 -62
- metadata +27 -9
- data/lib/sportdb/parser/blocktxt.rb +0 -99
- data/lib/sportdb/parser/lexer_tty.rb +0 -111
- data/lib/sportdb/parser/racc_parser.rb +0 -88
- data/lib/sportdb/parser/racc_tree.rb +0 -557
- data/lib/sportdb/parser/token-table.rb +0 -149
- data/lib/sportdb/parser/token_helpers.rb +0 -92
- /data/lib/sportdb/parser/{parser_runtime.rb → parser-runtime.rb} +0 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
module SportDb
|
|
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 SportDb
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
####
|
|
3
|
+
# Parser support machinery (incl. node classes/abstract syntax tree)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
module SportDb
|
|
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 SportDb
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
module SportDb
|
|
4
|
+
|
|
5
|
+
class ParserResult
|
|
6
|
+
attr_reader :tree, :errors
|
|
7
|
+
def initialize( tree, errors=[] )
|
|
8
|
+
@tree, @errors = tree, errors
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def ok?() @errors.size == 0; end
|
|
12
|
+
def nok?() !ok?; end
|
|
13
|
+
end # class ParserResult
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Parser
|
|
17
|
+
include Debuggable ## auto-adds debug?, _trace, _info, etc.
|
|
18
|
+
|
|
19
|
+
def initialize( txt )
|
|
20
|
+
@tree = []
|
|
21
|
+
@errors = []
|
|
22
|
+
|
|
23
|
+
lexer = Lexer.new( txt )
|
|
24
|
+
## note - use tokenize_with_errors and add/collect tokenize errors
|
|
25
|
+
@tokens, @errors = lexer.tokenize_with_errors
|
|
26
|
+
## pp @tokens
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def next_token
|
|
31
|
+
tok = @tokens.shift
|
|
32
|
+
## _trace( "next_token => #{tok.pretty_inspect}" )
|
|
33
|
+
|
|
34
|
+
## convert to racc format single char literal tokens e.g. '@' etc.
|
|
35
|
+
## note - literal token MUST be string (NOT symbol)
|
|
36
|
+
## note - racc expects array with to items
|
|
37
|
+
## - item[0] is the token id
|
|
38
|
+
## - item[1] is the token value
|
|
39
|
+
|
|
40
|
+
## note - returns nil for end-of-file !!!
|
|
41
|
+
tok = [tok.type, tok] if tok
|
|
42
|
+
|
|
43
|
+
tok
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# on_error do |error_token_id, error_value, value_stack|
|
|
48
|
+
# puts "Parse error on token: #{error_token_id}, value: #{error_value}"
|
|
49
|
+
# end
|
|
50
|
+
|
|
51
|
+
def parse_with_errors
|
|
52
|
+
_trace( "start parse:" )
|
|
53
|
+
do_parse
|
|
54
|
+
|
|
55
|
+
_trace( "#{@tree.size} parse tree node(s): " + @tree.pretty_inspect)
|
|
56
|
+
|
|
57
|
+
[@tree, @errors]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def parse ## convenience shortcut (ignores errors)
|
|
62
|
+
puts "[DEPRECATED] parse; use new (porcelain/public) Fbtxt.parse api!!"
|
|
63
|
+
tree, _ = parse_with_errors
|
|
64
|
+
tree
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
attr_reader :errors
|
|
68
|
+
def errors?
|
|
69
|
+
puts "[DEPRECATED] errors?; use new (porcelain/public) Fbtxt.parse api!!"
|
|
70
|
+
@errors.size > 0;
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def on_error(error_token_id, error_value, value_stack)
|
|
75
|
+
## note - get error_token (as string) e.g. MINUTE, DATE, etc.
|
|
76
|
+
error_token = Racc_token_to_s_table[error_token_id]
|
|
77
|
+
|
|
78
|
+
msg = "parse error on token: #{error_token}"
|
|
79
|
+
|
|
80
|
+
## add error_value - might be Lexer::Token or value
|
|
81
|
+
if error_value.is_a?( Lexer::Token)
|
|
82
|
+
if error_value.type == :NEWLINE
|
|
83
|
+
## skip print of "literal" newline
|
|
84
|
+
else
|
|
85
|
+
msg << " >#{error_value.text}<"
|
|
86
|
+
end
|
|
87
|
+
msg << " @#{error_value.lineno}"
|
|
88
|
+
else
|
|
89
|
+
msg << " >#{error_value.inspect}"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
## add stack - why? why not?
|
|
93
|
+
## "stack: #{value_stack.inspect}"
|
|
94
|
+
|
|
95
|
+
_error( msg )
|
|
96
|
+
|
|
97
|
+
@errors << msg
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
end # class Parser
|
|
102
|
+
end # module SportDb
|