class Pegparse::ParserErrors

Public Class Methods

new() click to toggle source
# File lib/pegparse/parser_errors.rb, line 17
def initialize
  @farthest_pos = 0
  @farthest_errors = []
end

Public Instance Methods

best_errors() click to toggle source

get meaningful errors @return [Array<Pegparse::ParseError>]

# File lib/pegparse/parser_errors.rb, line 58
def best_errors
  optional_memos = @farthest_errors.map.with_index do |stack, index|
    Pegparse::ParseErrorLocation.new(
      index_in_errors: index,
      start_positions_of_optional: stack.select{|rule| rule.reason == :optional}.map{|rule| rule.pos}
    )
  end

  best_memos = []
  optional_memos.each do |memo|
    if best_memos.empty?
      best_memos << memo
      next
    end
    cmp = compare_optional_memo(memo, best_memos[0])
    if cmp < 0
      best_memos = [memo]
      next
    elsif cmp == 0
      best_memos << memo
      next
    else
      next
    end
  end

  bests = best_memos.map{|x| @farthest_errors[x.index_in_errors]}
  
  result = bests.map do |stack|
    stack.select{|x| x.reason != :optional}.last(2)
  end
  result
end
clear_errors() click to toggle source

remove all stored errors

# File lib/pegparse/parser_errors.rb, line 93
def clear_errors
  @farthest_pos = 0
  @farthest_errors = []
end
compare_optional_memo(a, b) click to toggle source

compare two errors which is better by parsing descent path

(optional matching starts more earlier, priority becomes lower)

@params a [Pegparse::ParseErrorLocation] @params b [Pegparse::ParseErrorLocation]

# File lib/pegparse/parser_errors.rb, line 41
def compare_optional_memo(a, b)
  a_opts = a.start_positions_of_optional
  b_opts = b.start_positions_of_optional

  for i in 0...[a_opts.size, b_opts.size].min
    if a_opts[i] > b_opts[i]
      return -1
    end
    if a_opts[i] < b_opts[i]
      return 1
    end
  end
  return a_opts.size <=> b_opts.size
end
save_error(pos, rule_stack, reason) click to toggle source

just save parsing error @params pos [Integer] @params rule_stack [Array] array of [matching start pos, matching symbol] @params reason [Object]

# File lib/pegparse/parser_errors.rb, line 26
def save_error(pos, rule_stack, reason)
  return if pos < @farthest_pos
  if pos > @farthest_pos
    @farthest_errors.clear
  end
  @farthest_pos = pos
  copy_stack = rule_stack.map{|pos, reason| Pegparse::ParserError.new(pos: pos, reason: reason) }
  copy_stack << Pegparse::ParserError.new(pos: pos, reason: reason)
  @farthest_errors << copy_stack
end