Class: ANTLR3::Profile::Profiler

Inherits:
Object
  • Object
show all
Includes:
Constants, Debug::EventListener
Defined in:
lib/antlr3/profile.rb

Overview

When ANTLR is run with the -profile switch, it generates recognition code that performs accounting about the decision logic performed while parsing any given input. This information can be used to help refactor a slow grammar. Profiler is an event-listener that performs all of the profiling accounting and builds a simple report to present the various statistics.

Constant Summary

PROTOCOL_VERSION =
2

Constants included from Constants

Constants::BUILT_IN_TOKEN_NAMES, Constants::DEFAULT, Constants::DOWN, Constants::EOF, Constants::EOF_TOKEN, Constants::EOR_TOKEN_TYPE, Constants::HIDDEN, Constants::INVALID_TOKEN, Constants::INVALID_TOKEN_TYPE, Constants::MEMO_RULE_FAILED, Constants::MEMO_RULE_UNKNOWN, Constants::MIN_TOKEN_TYPE, Constants::SKIP_TOKEN, Constants::UP

Constants included from Debug::EventListener

Debug::EventListener::EVENTS

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Debug::EventListener

#add_child, #backtrack, #become_root, #begin_backtrack, #begin_resync, #consume_node, #create_node, #end_resync, #enter_alternative, #enter_subrule, #error_node, #exit_subrule, #flat_node, #location, #mark, #on, #resync, #rewind, #set_token_boundaries

Constructor Details

#initialize(parser = nil, output = nil) ⇒ Profiler



217
218
219
220
221
222
223
224
225
226
# File 'lib/antlr3/profile.rb', line 217

def initialize( parser = nil, output = nil )
  @parser = parser
  @profile = nil
  @rule_level = 0
  @decision_level = 0
  @decision_look = 0
  @last_token = nil
  @look_stack = []
  @output = output
end

Instance Attribute Details

#decision_levelObject (readonly)

Returns the value of attribute decision_level



203
204
205
# File 'lib/antlr3/profile.rb', line 203

def decision_level
  @decision_level
end

#decision_lookObject (readonly)

tracks the maximum look value for the current decision (maxLookaheadInCurrentDecision in java Profiler)



207
208
209
# File 'lib/antlr3/profile.rb', line 207

def decision_look
  @decision_look
end

#last_tokenObject (readonly)

the last token consumed (lastTokenConsumed in java Profiler)



211
212
213
# File 'lib/antlr3/profile.rb', line 211

def last_token
  @last_token
end

#look_stackObject (readonly)

Returns the value of attribute look_stack



212
213
214
# File 'lib/antlr3/profile.rb', line 212

def look_stack
  @look_stack
end

#outputObject

Returns the value of attribute output



215
216
217
# File 'lib/antlr3/profile.rb', line 215

def output
  @output
end

#parserObject

Returns the value of attribute parser



201
202
203
# File 'lib/antlr3/profile.rb', line 201

def parser
  @parser
end

#profileObject (readonly)

Returns the value of attribute profile



213
214
215
# File 'lib/antlr3/profile.rb', line 213

def profile
  @profile
end

#rule_levelObject (readonly)

Returns the value of attribute rule_level



202
203
204
# File 'lib/antlr3/profile.rb', line 202

def rule_level
  @rule_level
end

Instance Method Details

#commenceObject



228
229
230
231
232
233
234
235
# File 'lib/antlr3/profile.rb', line 228

def commence
  @profile = Profile.new
  @rule_level = 0
  @decision_level = 0
  @decision_look = 0
  @last_token = nil
  @look_stack = []
end

#consume_hidden_token(token) ⇒ Object



295
296
297
# File 'lib/antlr3/profile.rb', line 295

def consume_hidden_token( token )
  @last_token = token
end

#consume_token(token) ⇒ Object



287
288
289
# File 'lib/antlr3/profile.rb', line 287

def consume_token( token )
  @last_token = token
end

#end_backtrack(level, successful) ⇒ Object



311
312
313
# File 'lib/antlr3/profile.rb', line 311

def end_backtrack( level, successful )
  @profile.syntactic_predicate_looks << @decision_look
end

#enter_decision(decision_number) ⇒ Object



269
270
271
272
273
# File 'lib/antlr3/profile.rb', line 269

def enter_decision( decision_number )
  @decision_level += 1
  starting_look_index = @parser.input.index
  @look_stack << starting_look_index
end

#enter_rule(grammar_file_name, rule_name) ⇒ Object



237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/antlr3/profile.rb', line 237

def enter_rule( grammar_file_name, rule_name )
  if @rule_level.zero?
    commence
    @profile.grammar_file = grammar_file_name
    @profile.parser_class = @parser.class
    @profile.top_rule = rule_name
  end
  @rule_level += 1
  @profile.rule_invocations += 1
  @profile.rule_invocation_depth < @rule_level and
    @profile.rule_invocation_depth = @rule_level
end

#examine_rule_memoization(rule) ⇒ Object



254
255
256
257
258
259
260
261
262
# File 'lib/antlr3/profile.rb', line 254

def examine_rule_memoization( rule )
  stop_index = parser.rule_memoization( rule, @parser.input.index )
  if stop_index == MEMO_RULE_UNKNOWN
    @profile.memoization_cache_misses += 1
    @profile.guessing_rule_invocations += 1
  else
    @profile.memoization_cache_hits += 1
  end
end

#exit_decision(decision_number) ⇒ Object



275
276
277
278
279
280
281
282
283
284
285
# File 'lib/antlr3/profile.rb', line 275

def exit_decision( decision_number )
  @look_stack.pop
  @decision_level -= 1
  if @parser.cyclic_decision? then
    @profile.cyclic_looks << @decision_look
  else @profile.fixed_looks << @decision_look
  end
  
  @parser.cyclic_decision = false
  @decision_look = 0    
end

#exit_rule(grammar_file_name, rule_name) ⇒ Object



250
251
252
# File 'lib/antlr3/profile.rb', line 250

def exit_rule( grammar_file_name, rule_name )
  @rule_level -= 1
end

#in_decision?Boolean



291
292
293
# File 'lib/antlr3/profile.rb', line 291

def in_decision?
  return( @decision_level > 0 )
end

#look(i, token) ⇒ Object



299
300
301
302
303
304
305
306
307
308
309
# File 'lib/antlr3/profile.rb', line 299

def look( i, token )
  in_decision? or return
  starting_index = look_stack.last
  input = @parser.input
  this_ref_index = input.index
  num_hidden = input.tokens( starting_index, this_ref_index ).count { |t| t.hidden? }
  depth = i + this_ref_index - starting_index - num_hidden
  if depth > @decision_look
    @decision_look = depth
  end
end

#memoize(rule, start_index, success) ⇒ Object



264
265
266
# File 'lib/antlr3/profile.rb', line 264

def memoize( rule, start_index, success )
  @profile.memoization_cache_entries += 1
end

#recognition_exception(error) ⇒ Object



315
316
317
# File 'lib/antlr3/profile.rb', line 315

def recognition_exception( error )
  @profile.reported_errors += 1
end

#reportObject Also known as: to_s



353
354
355
# File 'lib/antlr3/profile.rb', line 353

def report
  @profile.generate_report
end

#semantic_predicate(result, predicate) ⇒ Object



319
320
321
# File 'lib/antlr3/profile.rb', line 319

def semantic_predicate( result, predicate )
  in_decision? and @profile.semantic_predicates += 1
end

#terminateObject



323
324
325
326
327
328
329
330
331
332
333
# File 'lib/antlr3/profile.rb', line 323

def terminate
  input = @parser.input
  hidden_tokens = input.select { |token| token.hidden? }
  @profile.hidden_tokens = hidden_tokens.length
  @profile.tokens = input.tokens.length
  @profile.hidden_characters_matched = hidden_tokens.inject( 0 ) do |count, token|
    count + token.text.length rescue count
  end
  @profile.characters_matched = ( @last_token || input.tokens.last ).stop + 1 rescue 0
  write_report
end

#write_reportObject



336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
# File 'lib/antlr3/profile.rb', line 336

def write_report
  @output << @profile.generate_report unless @output.nil?
rescue NoMethodError => error
  if error.name.to_s == '<<'
    warn( <<-END.strip! % [ __FILE__, __LINE__, @output ] )
      [%s @ %s]: failed to write report to %p as it does not respond to :<<
    END
  else raise
  end
rescue IOError => error
  $stderr.puts( Util.tidy( <<-END ) % [ __FILE__, __LINE__, @output, error.class, error.message ] )
  | [%s @ %s]: failed to write profile report to %p due to an IO Error:
  |   %s: %s
  END
  $stderr.puts( error.backtrace.map { |call| "  - #{ call }" }.join( "\n" ) )
end