lib/ebnf/base.rb in ebnf-1.1.2 vs lib/ebnf/base.rb in ebnf-1.1.3
- old
+ new
@@ -115,23 +115,23 @@
# Parse the string or file input generating an abstract syntax tree
# in S-Expressions (similar to SPARQL SSE)
#
# @param [#read, #to_s] input
# @param [Hash{Symbol => Object}] options
- # @option options [Boolean, Array] :debug
- # Output debug information to an array or STDOUT.
- # @option options [Symbol] :format (:ebnf)
+ # @param [Symbol] :format (:ebnf)
# Format of input, one of :ebnf, or :sxp
- def initialize(input, options = {})
- @options = {format: :ebnf}.merge(options)
+ # @option options [Boolean, Array] :debug
+ # Output debug information to an array or $stdout.
+ def initialize(input, format: :ebnf, **options)
+ @options = options.dup
@lineno, @depth, @errors = 1, 0, []
terminal = false
@ast = []
input = input.respond_to?(:read) ? input.read : input.to_s
- case @options[:format]
+ case format
when :sxp
require 'sxp' unless defined?(SXP)
@ast = SXP::Reader::Basic.read(input).map {|e| Rule.from_sxp(e)}
when :ebnf
scanner = StringScanner.new(input)
@@ -142,11 +142,11 @@
when /^@terminals/
# Switch mode to parsing terminals
terminal = true
when /^@pass\s*(.*)$/m
expr = expression($1).first
- rule = Rule.new(nil, nil, expr, kind: :pass)
+ rule = Rule.new(nil, nil, expr, kind: :pass, ebnf: self)
rule.orig = expr
@ast << rule
else
rule = depth {ruleParts(r)}
@@ -154,11 +154,11 @@
rule.orig = r
@ast << rule
end
end
else
- raise "unknown input format #{options[:format].inspect}"
+ raise "unknown input format #{format.inspect}"
end
end
# Iterate over each rule or terminal, except empty
# @param [:termina, :rule] kind
@@ -192,31 +192,31 @@
##
# Output Ruby parser files
#
# @param [IO, StringIO] output
- # @param [Hash{Symbol => Object}] options
- # @option options [String] :grammarFile
- def to_ruby(output = STDOUT, options = {})
- unless output == STDOUT
+ # @param [String] :grammarFile
+ # @param [String] :mod_name ('Branch')
+ def to_ruby(output = $stdout, grammarFile: nil, mod_name: 'Branch')
+ unless output == $stdout
output.puts "# This file is automatically generated by #{__FILE__}"
- output.puts "# BRANCH derived from #{options[:grammarFile]}" if options[:grammarFile]
+ output.puts "# BRANCH derived from #{grammarFile}" if grammarFile
unless self.errors.empty?
output.puts "# Note, tables completed with errors, may need to be resolved manually:"
#output.puts "# #{pp.conflicts.map{|c| c.join("\n# ")}.join("\n# ")}"
end
- output.puts "module #{options.fetch(:mod_name, 'Branch')}"
+ output.puts "module #{mod_name}"
output.puts " START = #{self.start.inspect}"
output.puts
end
self.outputTable(output, 'BRANCH', self.branch, 1)
self.outputTable(output, 'TERMINALS', self.terminals, 1)
self.outputTable(output, 'FIRST', self.first, 1)
self.outputTable(output, 'FOLLOW', self.follow, 1)
self.outputTable(output, 'CLEANUP', self.cleanup, 1)
self.outputTable(output, 'PASS', [self.pass], 1) if self.pass
- unless output == STDOUT
+ unless output == $stdout
output.puts "end"
end
end
def dup
@@ -236,23 +236,23 @@
##
# Write out syntax tree as Turtle
# @param [String] prefix for language
# @param [String] ns URI for language
# @return [String]
- def to_ttl(prefix, ns)
+ def to_ttl(prefix = nil, ns = "http://example.org/")
unless ast.empty?
[
"@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.",
"@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.",
- "@prefix #{prefix}: <#{ns}>.",
+ ("@prefix #{prefix}: <#{ns}>." if prefix),
"@prefix : <#{ns}>.",
"@prefix re: <http://www.w3.org/2000/10/swap/grammar/regex#>.",
"@prefix g: <http://www.w3.org/2000/10/swap/grammar/ebnf#>.",
"",
":language rdfs:isDefinedBy <>; g:start :#{ast.first.id}.",
"",
- ]
+ ].compact
end.join("\n") +
ast.sort.map(&:to_ttl).join("\n")
end
@@ -262,24 +262,22 @@
@depth -= 1
ret
end
# Progress output, less than debugging
- def progress(*args)
+ def progress(*args, **options)
return unless @options[:progress] || @options[:debug]
- options = args.last.is_a?(Hash) ? args.pop : {}
depth = options[:depth] || @depth
args << yield if block_given?
message = "#{args.join(': ')}"
str = "[#{@lineno}]#{' ' * depth}#{message}"
@options[:debug] << str if @options[:debug].is_a?(Array)
$stderr.puts(str) if @options[:progress] || @options[:debug] == true
end
# Error output
- def error(*args)
- options = args.last.is_a?(Hash) ? args.pop : {}
+ def error(*args, **options)
depth = options[:depth] || @depth
args << yield if block_given?
message = "#{args.join(': ')}"
@errors << message
str = "[#{@lineno}]#{' ' * depth}#{message}"
@@ -296,12 +294,11 @@
#
# @overload debug(message)
# @param [String] message ("")
#
# @yieldreturn [String] added to message
- def debug(*args)
+ def debug(*args, **options)
return unless @options[:debug]
- options = args.last.is_a?(Hash) ? args.pop : {}
depth = options[:depth] || @depth
args << yield if block_given?
message = "#{args.join(': ')}"
str = "[#{@lineno}]#{' ' * depth}#{message}"
@options[:debug] << str if @options[:debug].is_a?(Array)
\ No newline at end of file