Class: Pegparse::ParserErrors

Inherits:
Object
  • Object
show all
Defined in:
lib/pegparse/parser_errors.rb

Instance Method Summary collapse

Constructor Details

#initializeParserErrors



17
18
19
20
# File 'lib/pegparse/parser_errors.rb', line 17

def initialize
  @farthest_pos = 0
  @farthest_errors = []
end

Instance Method Details

#best_errorsArray<Pegparse::ParseError>

get meaningful errors



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# 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_errorsObject

remove all stored errors



93
94
95
96
# File 'lib/pegparse/parser_errors.rb', line 93

def clear_errors
  @farthest_pos = 0
  @farthest_errors = []
end

#compare_optional_memo(a, b) ⇒ Object

compare two errors which is better by parsing descent path

(optional matching starts more earlier, priority becomes lower)


41
42
43
44
45
46
47
48
49
50
51
52
53
54
# 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) ⇒ Object

just save parsing error



26
27
28
29
30
31
32
33
34
35
# 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