Class: Antlr4::Runtime::Parser

Inherits:
Recognizer show all
Defined in:
lib/antlr4/runtime/parser.rb

Defined Under Namespace

Classes: TraceListener, TrimToSizeListener

Constant Summary collapse

@@bypass_alts_atn_cache =
{}

Constants inherited from Recognizer

Recognizer::EOF

Instance Attribute Summary collapse

Attributes inherited from Recognizer

#_interp, #_state_number

Instance Method Summary collapse

Methods inherited from Recognizer

#action, #add_error_listener, #error_header, #error_listener_dispatch, #get_rule_index_map, #get_serialized_atn, #get_token_type, #get_token_type_map, #get_vocabulary, #remove_error_listener, #remove_error_listeners, #rule_names, #sempred, #token_error_display, #token_names

Constructor Details

#initialize(input) ⇒ Parser

Returns a new instance of Parser



48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/antlr4/runtime/parser.rb', line 48

def initialize(input)
  super()
  @_err_handler = DefaultErrorStrategy.new
  @_input = nil
  @_precedence_stack = []
  @_precedence_stack.push(0)
  @_ctx = nil
  @_build_parse_trees = true
  @_tracer = nil
  @_parse_listeners = nil
  @_syntax_errors = nil
  @matched_eof = nil
  set_token_stream(input)
end

Instance Attribute Details

#_ctxObject

Returns the value of attribute _ctx



43
44
45
# File 'lib/antlr4/runtime/parser.rb', line 43

def _ctx
  @_ctx
end

#_inputObject (readonly)

Returns the value of attribute _input



44
45
46
# File 'lib/antlr4/runtime/parser.rb', line 44

def _input
  @_input
end

Instance Method Details

#add_context_to_parse_treeObject



267
268
269
270
271
# File 'lib/antlr4/runtime/parser.rb', line 267

def add_context_to_parse_tree
  parent = @_ctx.parent
  # add current context to parent if we have a parent
  parent.add_child_rule_invocation(@_ctx) unless parent.nil?
end

#add_parse_listener(listener) ⇒ Object

Raises:

  • (nilPointerException)


132
133
134
135
136
137
138
# File 'lib/antlr4/runtime/parser.rb', line 132

def add_parse_listener(listener)
  raise nilPointerException, 'listener' if listener.nil?

  @_parse_listeners = [] if @_parse_listeners.nil?

  @_parse_listeners << listener
end

#compile_parse_tree_pattern1(pattern, patter_rule_index) ⇒ Object



195
196
197
198
199
200
201
202
203
204
# File 'lib/antlr4/runtime/parser.rb', line 195

def compile_parse_tree_pattern1(pattern, patter_rule_index)
  unless getTokenStream.nil?
    token_source = getTokenStream.token_source
    if token_source.is_a? Lexer
      lexer = token_source
      return compile_parse_tree_pattern2(pattern, patter_rule_index, lexer)
    end
  end
  raise UnsupportedOperationException, "Parser can't discover a lexer to use"
end

#compile_parse_tree_pattern2(pattern, patternRuleIndex, lexer) ⇒ Object



206
207
208
209
# File 'lib/antlr4/runtime/parser.rb', line 206

def compile_parse_tree_pattern2(pattern, patternRuleIndex, lexer)
  m = ParseTreePatternMatcher.new(lexer, self)
  m.compile(pattern, patternRuleIndex)
end

#consumeObject



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/antlr4/runtime/parser.rb', line 234

def consume
  o = current_token
  @_input.consume if o.type != EOF
  has_listener = !@_parse_listeners.nil? && !@_parse_listeners.empty?
  if @_build_parse_trees || has_listener
    if @_err_handler.in_error_recovery_mode(self)
      node = @_ctx.add_error_node(create_error_node(@_ctx, o))
      unless @_parse_listeners.nil?
        @_parse_listeners.each do |listener|
          listener.visit_error_node(node)
        end
      end
    else
      node = @_ctx.add_child_terminal_node(create_terminal_node(@_ctx, o))
      unless @_parse_listeners.nil?
        @_parse_listeners.each do |listener|
          listener.visit_terminal(node, @_ctx)
        end
      end
    end
  end

  o
end

#create_error_node(_parent, t) ⇒ Object



263
264
265
# File 'lib/antlr4/runtime/parser.rb', line 263

def create_error_node(_parent, t)
  ErrorNodeImpl.new(t)
end

#create_terminal_node(_parent, t) ⇒ Object



259
260
261
# File 'lib/antlr4/runtime/parser.rb', line 259

def create_terminal_node(_parent, t)
  TerminalNodeImpl.new(t)
end

#current_tokenObject



217
218
219
# File 'lib/antlr4/runtime/parser.rb', line 217

def current_token
  @_input.lt(1)
end

#dfa_stringsObject



448
449
450
451
452
453
454
455
456
457
# File 'lib/antlr4/runtime/parser.rb', line 448

def dfa_strings
  s = []
  d = 0
  while d < @_interp.decision_to_dfa.length
    dfa = @_interp.decision_to_dfa[d]
    s.push(dfa.to_s(get_vocabulary))
    d += 1
  end
  s
end

#dump_dfaObject



459
460
461
462
463
464
465
466
467
468
469
470
471
472
# File 'lib/antlr4/runtime/parser.rb', line 459

def dump_dfa
  seen_one = false
  d = 0
  while d < @_interp.decision_to_dfa.length
    dfa = @_interp.decision_to_dfa[d]
    unless dfa.states.empty?
      puts if seen_one
      puts('Decision ' << dfa.decision << ':')
      puts(dfa.to_s(get_vocabulary))
      seen_one = true
    end
    d += 1
  end
end

#enter_outer_alt(local_ctx, alt_num) ⇒ Object



295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/antlr4/runtime/parser.rb', line 295

def enter_outer_alt(local_ctx, alt_num)
  local_ctx.set_alt_number(alt_num)
  # if we have new local_ctx, make sure we replace existing ctx
  # that is previous child of parse tree
  if @_build_parse_trees && @_ctx != local_ctx
    parent = @_ctx.parent
    unless parent.nil?
      parent.remove_last_child
      parent.addChild(local_ctx)
    end
  end
  @_ctx = local_ctx
end

#enter_recursion_rule(local_ctx, state, _rule_index, precedence) ⇒ Object



315
316
317
318
319
320
321
322
323
# File 'lib/antlr4/runtime/parser.rb', line 315

def enter_recursion_rule(local_ctx, state, _rule_index, precedence)
  setState(state)
  @_precedence_stack.push(precedence)
  @_ctx = local_ctx
  @_ctx.start = @_input.lt(1)
  unless @_parse_listeners.nil?
    trigger_enter_rule_event # simulates rule entry for left-recursive rules
  end
end

#enter_rule(local_ctx, state, _rule_index) ⇒ Object



273
274
275
276
277
278
279
# File 'lib/antlr4/runtime/parser.rb', line 273

def enter_rule(local_ctx, state, _rule_index)
  @_state_number = state
  @_ctx = local_ctx
  @_ctx.start = @_input.lt(1)
  add_context_to_parse_tree if @_build_parse_trees
  trigger_enter_rule_event unless @_parse_listeners.nil?
end

#exit_ruleObject



281
282
283
284
285
286
287
288
289
290
291
292
293
# File 'lib/antlr4/runtime/parser.rb', line 281

def exit_rule
  if @matched_eof
    # if we have matched EOF, it cannot consume past EOF so we use lt(1) here
    @_ctx.stop = @_input.lt(1) # lt(1) will be end of file
  else
    @_ctx.stop = @_input.lt(-1) # stop node is what we just matched
  end

  # trigger event on @_ctx, before it reverts to parent
  trigger_exit_rule_event unless @_parse_listeners.nil?
  @_state_number = @_ctx.invoking_state
  @_ctx = @_ctx.parent
end

#expected_token?(symbol) ⇒ Boolean

Returns:

  • (Boolean)


383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
# File 'lib/antlr4/runtime/parser.rb', line 383

def expected_token?(symbol)
  atn = @_interp.atn
  ctx = @_ctx
  s = atn.states.get(getState)
  following = atn.next_tokens(s)
  return true if following.include?(symbol)

  return false unless following.contains(Token::EPSILON)

  while !ctx.nil? && ctx.invoking_state >= 0 && following.include?(Token::EPSILON)
    invoking_state = atn.states.get(ctx.invoking_state)
    rt = invoking_state.transition(0)
    following = atn.next_tokens(rt.follow_state)
    return true if following.include?(symbol)

    ctx = ctx.parent
  end

  return true if following.include?(Token::EPSILON) && symbol == Token::EOF

  false
end

#expected_tokensObject



410
411
412
413
# File 'lib/antlr4/runtime/parser.rb', line 410

def expected_tokens
  atn = @_interp.atn
  atn.expected_tokens(@_state_number, @_ctx)
end

#expected_tokens_within_current_ruleObject



415
416
417
418
419
# File 'lib/antlr4/runtime/parser.rb', line 415

def expected_tokens_within_current_rule
  atn = @_interp.atn
  s = atn.states.get(getState)
  atn.next_tokens(s)
end

#get_atn_with_bypass_altsObject



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/antlr4/runtime/parser.rb', line 178

def get_atn_with_bypass_alts
  serialized_atn = get_serialized_atn
  if serialized_atn.nil?
    raise UnsupportedOperationException, 'The current parser does not support an ATN with bypass alternatives.'
  end

  result = @@bypass_alts_atn_cache.get(serialized_atn)
  if result.nil?
    deserialization_options = ATNDeserializationOptions.new
    deserialization_options.generate_rule_bypass_transitions(true)
    result = ATNDeserializer.new(deserialization_options).deserialize(serialized_atn)
    @@bypass_alts_atn_cache.put(serialized_atn, result)
  end

  result
end

#get_parse_listenersObject



125
126
127
128
129
130
# File 'lib/antlr4/runtime/parser.rb', line 125

def get_parse_listeners
  listeners = @_parse_listeners
  return [] if listeners.nil?

  listeners
end

#get_trim_parse_treeObject



121
122
123
# File 'lib/antlr4/runtime/parser.rb', line 121

def get_trim_parse_tree
  get_parse_listeners.contains(TrimToSizeListener.INSTANCE)
end

#in_context?(_context) ⇒ Boolean

Returns:

  • (Boolean)


379
380
381
# File 'lib/antlr4/runtime/parser.rb', line 379

def in_context?(_context)
  false
end

#invoking_context(rule_index) ⇒ Object



365
366
367
368
369
370
371
372
373
# File 'lib/antlr4/runtime/parser.rb', line 365

def invoking_context(rule_index)
  p = @_ctx
  until p.nil?
    return p if p.rule_index == rule_index

    p = p.parent
  end
  nil
end

#match(ttype) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/antlr4/runtime/parser.rb', line 76

def match(ttype)
  t = current_token
  if t.type == ttype
    @matched_eof = true if ttype == Token::EOF
    @_err_handler.report_match(self)
    consume
  else
    t = @_err_handler.recover_in_line(self)
    if @_build_parse_trees && t.index == -1
      # we must have conjured up a new token during single token insertion
      # if it's not the current symbol
      @_ctx.add_error_node(create_error_node(@_ctx, t))
    end
  end

  t
end

#match_wildcardObject



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/antlr4/runtime/parser.rb', line 94

def match_wildcard
  t = current_token
  if t.type > 0
    @_err_handler.report_match(this)
    consume
  else
    t = @_err_handler.recover_in_line(this)
    if @_build_parse_trees && t.token_index == -1
      # we must have conjured up a new token during single token insertion
      # if it's not the current symbol
      @_ctx.add_error_node(create_error_node(@_ctx, t))
    end
  end

  t
end

#matched_eof?Boolean

Returns:

  • (Boolean)


406
407
408
# File 'lib/antlr4/runtime/parser.rb', line 406

def matched_eof?
  @matched_eof
end

#notify_error_listeners(offending_token, msg, e) ⇒ Object



225
226
227
228
229
230
231
232
# File 'lib/antlr4/runtime/parser.rb', line 225

def notify_error_listeners(offending_token, msg, e)
  @_syntax_errors += 1
  line = offending_token.line
  char_position_in_line = offending_token.char_position_in_line

  listener = error_listener_dispatch
  listener.syntax_error(self, offending_token, line, char_position_in_line, msg, e)
end

#notify_error_listeners_simple(msg) ⇒ Object



221
222
223
# File 'lib/antlr4/runtime/parser.rb', line 221

def notify_error_listeners_simple(msg)
  notify_error_listeners(current_token, msg, nil)
end

#parse_infoObject



478
479
480
481
482
483
# File 'lib/antlr4/runtime/parser.rb', line 478

def parse_info
  interp = @_interp
  return ParseInfo.new(interp) if interp.is_a? ProfilingATNSimulator

  nil
end

#precedenceObject



309
310
311
312
313
# File 'lib/antlr4/runtime/parser.rb', line 309

def precedence
  return -1 if @_precedence_stack.empty?

  @_precedence_stack.peek
end

#precpred(_localctx, precedence) ⇒ Object



375
376
377
# File 'lib/antlr4/runtime/parser.rb', line 375

def precpred(_localctx, precedence)
  precedence >= @_precedence_stack.peek
end

#push_new_recursion_context(local_ctx, state, _rule_index) ⇒ Object



325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/antlr4/runtime/parser.rb', line 325

def push_new_recursion_context(local_ctx, state, _rule_index)
  previous = @_ctx
  previous.parent = local_ctx
  previous.invoking_state = state
  previous.stop = @_input.lt(-1)

  @_ctx = local_ctx
  @_ctx.start = previous.start
  @_ctx.addChild(previous) if @_build_parse_trees

  unless @_parse_listeners.nil?
    trigger_enter_rule_event # simulates rule entry for left-recursive rules
  end
end

#remove_parse_listener(listener) ⇒ Object



140
141
142
143
144
145
146
# File 'lib/antlr4/runtime/parser.rb', line 140

def remove_parse_listener(listener)
  unless @_parse_listeners.nil?
    if @_parse_listeners.remove(listener)
      @_parse_listeners = nil if @_parse_listeners.empty?
    end
  end
end

#remove_parse_listenersObject



148
149
150
# File 'lib/antlr4/runtime/parser.rb', line 148

def remove_parse_listeners
  @_parse_listeners = nil
end

#resetObject



63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/antlr4/runtime/parser.rb', line 63

def reset
  @_input.seek(0) unless @_input.nil?
  @_err_handler.reset(self)
  @_ctx = nil
  @_syntax_errors = 0
  @matched_eof = false
  set_trace(false)
  @_precedence_stack.clear
  @_precedence_stack.push(0)
  interpreter = @_interp
  interpreter.reset unless interpreter.nil?
end

#rule_index(rule_name) ⇒ Object



421
422
423
424
425
426
# File 'lib/antlr4/runtime/parser.rb', line 421

def rule_index(rule_name)
  index = get_rule_index_map.get(rule_name)
  return index unless index.nil?

  -1
end

#rule_invocation_stack1Object



428
429
430
# File 'lib/antlr4/runtime/parser.rb', line 428

def rule_invocation_stack1
  rule_invocation_stack2(@_ctx)
end

#rule_invocation_stack2(p) ⇒ Object



432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
# File 'lib/antlr4/runtime/parser.rb', line 432

def rule_invocation_stack2(p)
  rule_names = rule_names
  stack = []
  until p.nil?
    # compute what follows who invoked us
    rule_index = p.rule_index
    if rule_index < 0
      stack.push('n/a')
    else
      stack.push(rule_names[rule_index])
    end
    p = p.parent
  end
  stack
end

#set_profile(profile) ⇒ Object



485
486
487
488
489
490
491
492
493
494
495
496
497
# File 'lib/antlr4/runtime/parser.rb', line 485

def set_profile(profile)
  interp = @_interp
  save_mode = interp.getPredictionMode
  if profile
    unless interp.is_a? ProfilingATNSimulator
      @_interp = ProfilingATNSimulator.new(self)
    end
  elsif @_interp.is_a? ProfilingATNSimulator
    sim = ParserATNSimulator.new(self, atn, interp.decision_to_dfa, interp.shared_context_cache)
    @_interp = sim
  end
  @_interp.setPredictionMode(save_mode)
end

#set_token_factory(factory) ⇒ Object



174
175
176
# File 'lib/antlr4/runtime/parser.rb', line 174

def set_token_factory(factory)
  @_input.token_source.set_token_factory(factory)
end

#set_token_stream(input) ⇒ Object



211
212
213
214
215
# File 'lib/antlr4/runtime/parser.rb', line 211

def set_token_stream(input)
  @_input = nil
  reset
  @_input = input
end

#set_trace(trace) ⇒ Object



499
500
501
502
503
504
505
506
507
508
509
510
511
# File 'lib/antlr4/runtime/parser.rb', line 499

def set_trace(trace)
  if !trace
    remove_parse_listener(@_tracer)
    @_tracer = nil
  else
    if !@_tracer.nil?
      remove_parse_listener(@_tracer)
    else
      @_tracer = new TraceListener
    end
    add_parse_listener(@_tracer)
  end
end

#set_trim_parse_tree(trimParseTrees) ⇒ Object



111
112
113
114
115
116
117
118
119
# File 'lib/antlr4/runtime/parser.rb', line 111

def set_trim_parse_tree(trimParseTrees)
  if trimParseTrees
    return if get_trim_parse_tree

    add_parse_listener(TrimToSizeListener.INSTANCE)
  else
    remove_parse_listener(TrimToSizeListener.INSTANCE)
  end
end

#source_nameObject



474
475
476
# File 'lib/antlr4/runtime/parser.rb', line 474

def source_name
  @_input.get_source_name
end

#token_factoryObject



170
171
172
# File 'lib/antlr4/runtime/parser.rb', line 170

def token_factory
  @_input.token_source.token_factory
end

#trace?Boolean

Returns:

  • (Boolean)


513
514
515
# File 'lib/antlr4/runtime/parser.rb', line 513

def trace?
  !@_tracer.nil?
end

#trigger_enter_rule_eventObject



152
153
154
155
156
157
# File 'lib/antlr4/runtime/parser.rb', line 152

def trigger_enter_rule_event
  @_parse_listeners.each do |listener|
    listener.enter_every_rule(@_ctx)
    @_ctx.enter_rule(listener)
  end
end

#trigger_exit_rule_eventObject

reverse order walk of listeners



159
160
161
162
163
164
165
166
167
168
# File 'lib/antlr4/runtime/parser.rb', line 159

def trigger_exit_rule_event # reverse order walk of listeners
  i = @_parse_listeners.length - 1
  while i >= 0

    listener = @_parse_listeners[i]
    @_ctx.exit_rule(listener)
    listener.exit_every_rule(@_ctx)
    i -= 1
  end
end

#unroll_recursion_contexts(_parent_ctx) ⇒ Object



340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
# File 'lib/antlr4/runtime/parser.rb', line 340

def unroll_recursion_contexts(_parent_ctx)
  @_precedence_stack.pop
  @_ctx.stop = @_input.lt(-1)
  retctx = @_ctx # save current ctx (return value)

  # unroll so @_ctx is as it was before call to recursive method
  if !@_parse_listeners.nil?
    while @_ctx != _parent_ctx
      trigger_exit_rule_event
      @_ctx = @_ctx.parent
    end

  else
    _ctx = _parent_ctx
  end

  # hook into tree
  retctx.parent = _parent_ctx

  if @_build_parse_trees && !_parent_ctx.nil?
    # add return ctx into invoking rule's tree
    _parent_ctx.addChild(retctx)
  end
end