Class: Pegparse::ParserErrors

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

Instance Method Summary collapse

Constructor Details

#initializeParserErrors

Returns a new instance of ParserErrors.



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

Returns:

  • (Array<Pegparse::ParseError>)


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