lib/ebnf/peg/parser.rb in ebnf-2.1.0 vs lib/ebnf/peg/parser.rb in ebnf-2.1.1
- old
+ new
@@ -73,12 +73,10 @@
# If unset, the terminal rule is used for matching.
# @param [Hash] options
# @option options [Hash{String => String}] :map ({})
# A mapping from terminals, in lower-case form, to
# their canonical value
- # @option options [Boolean] :unescape
- # Cause strings and codepoints to be unescaped.
# @yield [value, prod]
# @yieldparam [String] value
# The scanned terminal value.
# @yieldparam [Symbol] prod
# A symbol indicating the production which referenced this terminal
@@ -267,11 +265,12 @@
#
# @param [String] node Relevant location associated with message
# @param [String] message Error string
# @param [Hash{Symbol => Object}] options
# @option options [URI, #to_s] :production
- # @option options [Token] :token
+ # @option options [Boolean] :raise abort furhter processing
+ # @option options [Array] :backtrace state where error occured
# @see #debug
def error(node, message, **options)
lineno = options[:lineno] || (scanner.lineno if scanner)
m = "ERROR "
m += "[line: #{lineno}] " if lineno
@@ -280,11 +279,15 @@
m += ", production = #{options[:production].inspect}" if options[:production]
@error_log << m unless @recovering
@recovering = true
debug(node, m, level: 3, **options)
if options[:raise] || @options[:validate]
- raise Error.new(m, lineno: lineno, rest: options[:rest], production: options[:production])
+ raise Error.new(m,
+ lineno: lineno,
+ rest: options[:rest],
+ production: options[:production],
+ backtrace: options[:backtrace])
end
end
##
# Warning information, used as level `2` logger messages.
@@ -363,29 +366,31 @@
def onStart(prod)
handler = self.class.start_handlers[prod]
@productions << prod
debug("#{prod}(:start)", "",
lineno: (scanner.lineno if scanner),
- pos: (scanner.pos if scanner),
- depth: (depth + 1)) {"#{prod}, pos: #{scanner ? scanner.pos : '?'}, rest: #{scanner ? scanner.rest[0..20].inspect : '?'}"}
+ pos: (scanner.pos if scanner)
+ ) do
+ "#{prod}, pos: #{scanner ? scanner.pos : '?'}, rest: #{scanner ? scanner.rest[0..20].inspect : '?'}"
+ end
if handler
# Create a new production data element, potentially allowing handler
# to customize before pushing on the @prod_data stack
- data = {}
+ data = {_production: prod}
begin
self.class.eval_with_binding(self) {
handler.call(data, @parse_callback)
}
rescue ArgumentError, Error => e
- error("start", "#{e.class}: #{e.message}", production: prod)
+ error("start", "#{e.class}: #{e.message}", production: prod, backtrace: e.backtrace)
@recovering = false
end
@prod_data << data
elsif self.class.production_handlers[prod]
# Make sure we push as many was we pop, even if there is no
# explicit start handler
- @prod_data << {}
+ @prod_data << {_production: prod}
end
return self.class.start_options.fetch(prod, {}) # any options on this production
end
# Finish of production
@@ -395,25 +400,27 @@
def onFinish(result)
#puts "prod_data(f): " + @prod_data.inspect
prod = @productions.last
handler, clear_packrat = self.class.production_handlers[prod]
data = @prod_data.pop if handler || self.class.start_handlers[prod]
+ error("finish",
+ "prod_data production mismatch: expected #{prod.inspect}, got #{data[:_production].inspect}",
+ production: prod, prod_data: @prod_data) if data && prod != data[:_production]
if handler && !@recovering && result != :unmatched
# Pop production data element from stack, potentially allowing handler to use it
result = begin
self.class.eval_with_binding(self) {
handler.call(result, data, @parse_callback)
}
rescue ArgumentError, Error => e
- error("finish", "#{e.class}: #{e.message}", production: prod)
+ error("finish", "#{e.class}: #{e.message}", production: prod, backtrace: e.backtrace)
@recovering = false
end
end
- progress("#{prod}(:finish)", "",
- depth: (depth + 1),
- lineno: (scanner.lineno if scanner),
- level: result == :unmatched ? 0 : 1) do
+ debug("#{prod}(:finish)", "",
+ lineno: (scanner.lineno if scanner),
+ level: result == :unmatched ? 0 : 1) do
"#{result.inspect}@(#{scanner ? scanner.pos : '?'}), rest: #{scanner ? scanner.rest[0..20].inspect : '?'}"
end
self.clear_packrat if clear_packrat
@productions.pop
result
@@ -431,15 +438,15 @@
value = begin
self.class.eval_with_binding(self) {
handler.call(value, parentProd, @parse_callback)
}
rescue ArgumentError, Error => e
- error("terminal", "#{e.class}: #{e.message}", value: value, production: prod)
+ error("terminal", "#{e.class}: #{e.message}", value: value, production: prod, backtrace: e.backtrace)
@recovering = false
end
end
progress("#{prod}(:terminal)", "",
- depth: (depth + 2),
+ depth: (depth + 1),
lineno: (scanner.lineno if scanner),
level: value == :unmatched ? 0 : 1) do
"#{value.inspect}@(#{scanner ? scanner.pos : '?'})"
end
value