lib/ebnf/peg/parser.rb in ebnf-2.0.0 vs lib/ebnf/peg/parser.rb in ebnf-2.1.0

- old
+ new

@@ -49,10 +49,11 @@ end # DSL for creating terminals and productions module ClassMethods def start_handlers; (@start_handlers ||= {}); end + def start_options; (@start_hoptions ||= {}); end def production_handlers; (@production_handlers ||= {}); end def terminal_handlers; (@terminal_handlers ||= {}); end def terminal_regexps; (@terminal_regexps ||= {}); end ## @@ -95,21 +96,26 @@ # current production. Block is called in an evaluation block from # the enclosing parser. # # @param [Symbol] term # The rule name + # @param [Hash{Symbol => Object}] options + # Options which are returned from {Parser#onStart}. + # @option options [Boolean] :as_hash (false) + # If the production is a `seq`, causes the value to be represented as a single hash, rather than an array of individual hashes for each sub-production. Note that this is not always advisable due to the possibility of repeated productions within the sequence. # @yield [data, block] # @yieldparam [Hash] data # A Hash defined for the current production, during :start # may be initialized with data to pass to further productions, # during :finish, it contains data placed by earlier productions # @yieldparam [Proc] block # Block passed to initialization for yielding to calling parser. # Should conform to the yield specs for #initialize # Yield to generate a triple - def start_production(term, &block) + def start_production(term, **options, &block) start_handlers[term] = block + start_options[term] = options.freeze end ## # Defines a production called when production of associated # non-terminals has completed @@ -202,10 +208,11 @@ # Take whitespace from options, a named rule, a `pass` rule, a rule named :WS, or a default @whitespace = case options[:whitespace] when Regexp then options[:whitespace] when Symbol then @rules[options[:whitespace]] + else options[:whitespace] end || @rules.values.detect(&:pass?) || /(?:\s|(?:#[^x][^\n\r]*))+/m.freeze @options = options.dup @@ -327,23 +334,34 @@ # @param [Array<String>] args Relevant location associated with message # @param [Hash] options # @option options [Integer] :depth # Recursion depth for indenting output # @yieldreturn [String] additional string appended to `message`. - def debug(*args) + def debug(*args, &block) return unless @options[:logger] options = args.last.is_a?(Hash) ? args.pop : {} lineno = options[:lineno] || (scanner.lineno if scanner) level = options.fetch(:level, 0) - depth = options[:depth] || self.depth - args << yield if block_given? - @options[:logger].add(level, "[#{lineno}]" + (" " * depth) + args.join(" ")) + + if self.respond_to?(:log_debug) + level = [:debug, :info, :warn, :error, :fatal][level] + log_debug(*args, **options.merge(level: level, lineno: lineno, depth: depth), &block) + elsif @options[:logger].respond_to?(:add) + args << yield if block_given? + @options[:logger].add(level, "[#{lineno}]" + (" " * depth) + args.join(" ")) + elsif @options[:logger].respond_to?(:<<) + args << yield if block_given? + @options[:logger] << "[#{lineno}]" + (" " * depth) + args.join(" ") + end end # Start for production # Adds data avoiable during the processing of the production + # + # @return [Hash] composed of production options. Currently only `as_hash` is supported. + # @see ClassMethods#start_production def onStart(prod) handler = self.class.start_handlers[prod] @productions << prod debug("#{prod}(:start)", "", lineno: (scanner.lineno if scanner), @@ -365,9 +383,10 @@ 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 << {} end + return self.class.start_options.fetch(prod, {}) # any options on this production end # Finish of production # # @param [Object] result parse result