lib/treetop/runtime/compiled_parser.rb in treetop-1.1.4 vs lib/treetop/runtime/compiled_parser.rb in treetop-1.2.0
- old
+ new
@@ -1,67 +1,69 @@
module Treetop
module Runtime
class CompiledParser
include Treetop::Runtime
- attr_accessor :consume_all_input
+ attr_reader :input, :index, :terminal_failures, :max_terminal_failure_index
attr_writer :root
+ attr_accessor :consume_all_input
alias :consume_all_input? :consume_all_input
- attr_reader :input, :index
-
+
def initialize
self.consume_all_input = true
end
def parse(input, options = {})
prepare_to_parse(input)
@index = options[:index] if options[:index]
result = send("_nt_#{root}")
- if consume_all_input? && index != input.size
- return ParseFailure.new(input, index, result.nested_failures)
- else
- return result
- end
+ return nil if (consume_all_input? && index != input.size)
+ return result
end
-
+
+ def failure_index
+ max_terminal_failure_index
+ end
+
+ def failure_line
+ terminal_failures && input.line_of(failure_index)
+ end
+
+ def failure_column
+ terminal_failures && input.column_of(failure_index)
+ end
+
+ def failure_reason
+ return nil unless (tf = terminal_failures) && tf.size > 0
+ "Expected " +
+ (tf.size == 1 ?
+ tf[0].expected_string :
+ "one of #{tf.map{|f| f.expected_string}.uniq*', '}"
+ ) +
+ " at line #{failure_line}, column #{failure_column} (byte #{failure_index+1})" +
+ " after #{input[index...failure_index]}"
+ end
+
+
protected
- attr_reader :node_cache
+ attr_reader :node_cache, :input_length
attr_writer :index
def prepare_to_parse(input)
@input = input
+ @input_length = input.length
reset_index
@node_cache = Hash.new {|hash, key| hash[key] = Hash.new}
+ @terminal_failures = []
+ @max_terminal_failure_index = 0
end
def reset_index
@index = 0
end
- def parse_char_class(char_class_re, char_class_string, node_class = SyntaxNode, inline_module = nil)
- if input.index(char_class_re, index) == index
- result = node_class.new(input, index...(index + 1))
- result.extend(inline_module) if inline_module
- @index += 1
- result
- else
- terminal_parse_failure("[#{char_class_string}]")
- end
- end
-
- def parse_terminal(terminal_string, node_class = SyntaxNode, inline_module = nil)
- if input.index(terminal_string, index) == index
- result = node_class.new(input, index...(index + terminal_string.length))
- result.extend(inline_module) if inline_module
- @index += terminal_string.length
- result
- else
- terminal_parse_failure(terminal_string)
- end
- end
-
def parse_anything(node_class = SyntaxNode, inline_module = nil)
if index < input.length
result = node_class.new(input, index...(index + 1))
result.extend(inline_module) if inline_module
@index += 1
@@ -70,10 +72,16 @@
terminal_parse_failure("any character")
end
end
def terminal_parse_failure(expected_string)
- TerminalParseFailure.new(input, index, expected_string)
+ return nil if index < max_terminal_failure_index
+ if index > max_terminal_failure_index
+ @max_terminal_failure_index = index
+ @terminal_failures = []
+ end
+ terminal_failures << TerminalParseFailure.new(index, expected_string)
+ return nil
end
end
end
-end
\ No newline at end of file
+end