Skip to content

Commit

Permalink
Finish 1.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
gkellogg committed Dec 16, 2019
2 parents ac7743d + c08bc1d commit f9dd085
Show file tree
Hide file tree
Showing 25 changed files with 119 additions and 103 deletions.
12 changes: 4 additions & 8 deletions .travis.yml
@@ -1,20 +1,16 @@
language: ruby
bundler_args: --without debug
script: "bundle exec rspec spec"
before_install: "gem update --system"
env:
- CI=true
rvm:
- 2.2
- 2.3
- 2.4
- 2.5
- jruby-9
- rbx-3
- 2.6
- 2.7
- jruby
cache: bundler
sudo: false
matrix:
allow_failures:
- rvm: jruby-9
- rvm: rbx-3
- rvm: jruby
dist: trusty
10 changes: 2 additions & 8 deletions Gemfile
Expand Up @@ -8,16 +8,10 @@ group :development do
gem 'rdf-spec', github: "ruby-rdf/rdf-spec", branch: "develop"
gem "byebug", platforms: :mri
gem 'psych', platforms: [:mri, :rbx]
gem "rocco", platforms: :mri, github: "rtomayko/rocco"
gem "redcarpet", platforms: :mri
end

group :development, :test do
gem 'simplecov', require: false
gem 'coveralls', require: false
end

platforms :rbx do
gem 'rubysl', '~> 2.0'
gem 'rubinius', '~> 2.0'
gem 'simplecov', platforms: :mri
gem 'coveralls', '~> 0.8', platforms: :mri
end
2 changes: 1 addition & 1 deletion VERSION
@@ -1 +1 @@
1.1.3
1.2.0
6 changes: 3 additions & 3 deletions bin/ebnf
Expand Up @@ -75,19 +75,19 @@ end

input = File.open(ARGV[0]) if ARGV[0]

ebnf = EBNF.parse(input || STDIN, options)
ebnf = EBNF.parse(input || STDIN, **options)
ebnf.make_bnf if options[:bnf] || options[:ll1]
if options[:ll1]
ebnf.first_follow(*options[:ll1])
ebnf.build_tables
end

res = case options[:output_format]
when :ebnf then ebnf.to_s
when :html then ebnf.to_html
when :sxp then ebnf.to_sxp
when :ttl then ebnf.to_ttl(options[:prefix], options[:namespace])
when :rb then ebnf.to_ruby(out, options.merge(grammarFile: ARGV[0]))
when :rb then ebnf.to_ruby(out, grammarFile: ARGV[0], **options)
else ebnf.ast.inspect
end

Expand Down
16 changes: 8 additions & 8 deletions ebnf.gemspec
Expand Up @@ -22,16 +22,16 @@ Gem::Specification.new do |gem|
gem.executables = %w(ebnf)
gem.require_paths = %w(lib)

gem.required_ruby_version = '>= 2.2.2'
gem.required_ruby_version = '>= 2.4'
gem.requirements = []
gem.add_runtime_dependency 'sxp', '~> 1.0'
gem.add_runtime_dependency 'rdf', '~> 3.0' # Required by sxp
gem.add_development_dependency 'rdf-spec', '~> 3.0'
gem.add_runtime_dependency 'sxp', '~> 1.1'
gem.add_runtime_dependency 'rdf', '~> 3.1' # Required by sxp
gem.add_development_dependency 'rdf-spec', '~> 3.1'
gem.add_development_dependency 'haml', '~> 5.0'
gem.add_development_dependency 'rspec', '~> 3.7'
gem.add_development_dependency 'rspec-its', '~> 1.2'
gem.add_development_dependency 'yard', '~> 0.9.12'
gem.add_development_dependency 'rake', '~> 12.0'
gem.add_development_dependency 'rspec', '~> 3.9'
gem.add_development_dependency 'rspec-its', '~> 1.3'
gem.add_development_dependency 'yard', '~> 0.9'
gem.add_development_dependency 'rake', '~> 13.0'

gem.post_install_message = nil
end
2 changes: 1 addition & 1 deletion examples/ebnf-parser/parse
Expand Up @@ -49,6 +49,6 @@ end
input = File.open(ARGV[0]) if ARGV[0]

# Collect rules
ebnf = EBNFParser.new(input || STDIN, options)
ebnf = EBNFParser.new(input || STDIN, **options)

puts ebnf.to_sxp
16 changes: 9 additions & 7 deletions examples/ebnf-parser/parser.rb
Expand Up @@ -262,18 +262,19 @@ def inspect
# @option options [Boolean] :progress
# Show progress of parser productions
# @return [EBNFParser]
def initialize(input, options = {}, &block)
def initialize(input, **options, &block)
@options = options.dup
@input = input.respond_to?(:read) ? input.read : input.to_s

parsing_terminals = false
@ast = []
parse(@input, START.to_sym, @options.merge(branch: BRANCH,
first: FIRST,
follow: FOLLOW,
cleanup: CLEANUP,
whitespace: EBNFParserTerminals::PASS,
reset_on_start: true)
parse(@input, START.to_sym, branch: BRANCH,
first: FIRST,
follow: FOLLOW,
cleanup: CLEANUP,
whitespace: EBNFParserTerminals::PASS,
reset_on_start: true,
**options)
) do |context, *data|
rule = case context
when :terminal
Expand All @@ -299,6 +300,7 @@ def initialize(input, options = {}, &block)

# Output formatted S-Expression of grammar
def to_sxp
require 'sxp' unless defined?(SXP)
# Output rules as a formatted S-Expression
SXP::Generator.string(@ast.map(&:for_sxp))
end
Expand Down
2 changes: 1 addition & 1 deletion examples/opt-parser/parse
Expand Up @@ -48,4 +48,4 @@ end
input = File.open(ARGV[0]) if ARGV[0]

# Collect rules
OptParser.new(input || STDIN, options)
OptParser.new(input || STDIN, **options)
13 changes: 7 additions & 6 deletions examples/opt-parser/parser.rb
Expand Up @@ -19,17 +19,18 @@ class OptParser
input[:terminal] = token.value
end

def initialize(input, options = {}, &block)
def initialize(input, **options, &block)
@options = options.dup
@input = input.respond_to?(:read) ? input.read : input.to_s

parsing_terminals = false
@ast = []
parse(@input, START.to_sym, @options.merge(branch: BRANCH,
first: FIRST,
follow: FOLLOW,
cleanup: CLEANUP,
reset_on_start: true)
parse(@input, START.to_sym, branch: BRANCH,
first: FIRST,
follow: FOLLOW,
cleanup: CLEANUP,
reset_on_start: true,
**options)
) do |context, *data|
rule = case context
when :trace
Expand Down
2 changes: 1 addition & 1 deletion examples/plus-parser/parse
Expand Up @@ -48,4 +48,4 @@ end
input = File.open(ARGV[0]) if ARGV[0]

# Collect rules
PlusParser.new(input || STDIN, options)
PlusParser.new(input || STDIN, **options)
13 changes: 7 additions & 6 deletions examples/plus-parser/parser.rb
Expand Up @@ -19,17 +19,18 @@ class PlusParser
input[:terminal] = token.value
end

def initialize(input, options = {}, &block)
def initialize(input, **options, &block)
@options = options.dup
@input = input.respond_to?(:read) ? input.read : input.to_s

parsing_terminals = false
@ast = []
parse(@input, START.to_sym, @options.merge(branch: BRANCH,
first: FIRST,
follow: FOLLOW,
cleanup: CLEANUP,
whitespace: /\s+/)
parse(@input, START.to_sym, branch: BRANCH,
first: FIRST,
follow: FOLLOW,
cleanup: CLEANUP,
whitespace: /\s+/,
**options)
) do |context, *data|
rule = case context
when :trace
Expand Down
2 changes: 1 addition & 1 deletion examples/star-parser/parse
Expand Up @@ -48,4 +48,4 @@ end
input = File.open(ARGV[0]) if ARGV[0]

# Collect rules
StarParser.new(input || STDIN, options)
StarParser.new(input || STDIN, **options)
13 changes: 7 additions & 6 deletions examples/star-parser/parser.rb
Expand Up @@ -19,17 +19,18 @@ class StarParser
input[:terminal] = token.value
end

def initialize(input, options = {}, &block)
def initialize(input, **options, &block)
@options = options.dup
@input = input.respond_to?(:read) ? input.read : input.to_s

parsing_terminals = false
@ast = []
parse(@input, START.to_sym, @options.merge(branch: BRANCH,
first: FIRST,
follow: FOLLOW,
cleanup: CLEANUP,
whitespace: /\s+/)
parse(@input, START.to_sym, branch: BRANCH,
first: FIRST,
follow: FOLLOW,
cleanup: CLEANUP,
whitespace: /\s+/,
**options)
) do |context, *data|
rule = case context
when :trace
Expand Down
4 changes: 2 additions & 2 deletions lib/ebnf.rb
Expand Up @@ -17,7 +17,7 @@ module EBNF
# @param [Hash{Symbol => Object}] options
# @return [EBNF::Base]
# @raise [Exception] on invalid input
def self.parse(input, options = {})
query = ::EBNF::Base.new(input, options)
def self.parse(input, **options)
query = ::EBNF::Base.new(input, **options)
end
end
10 changes: 7 additions & 3 deletions lib/ebnf/ll1.rb
Expand Up @@ -168,6 +168,10 @@ def first_follow(*starts)
progress("first_follow") {"(#{ittr}) firsts #{firsts}, follows #{follows}"}
ittr += 1
end while (firsts + follows) > 0

debug("Fi.2-post: non-terminals without first") do
ast.reject(&:terminal?).reject(&:first).map(&:sym)
end if ast.reject(&:terminal?).any? {|r| r.first.nil?}
end
end

Expand Down Expand Up @@ -287,16 +291,16 @@ def do_production(lhs)

if rule.expr.first == :matches
debug("prod") {"Rule is regexp: #{rule}"}

error("No record of what token #{lhs} can start with") unless rule.first
return
end

error("No record of what token #{lhs.inspect} can start with") unless rule.first

if rule.alt?
# A First/Follow conflict appears when _eps is in the first
# of one rule and there is a token in the first and
# follow of the same rule
if rule.first.include?(:_eps) && !(overlap = ((rule.first & (rule.follow || [])) - [:eps])).empty?
if Array(rule.first).include?(:_eps) && !(overlap = ((Array(rule.first) & (rule.follow || [])) - [:eps])).empty?
error("First/Follow Conflict: #{overlap.first.inspect} is both first and follow of #{rule.sym}")
end

Expand Down
27 changes: 17 additions & 10 deletions lib/ebnf/ll1/lexer.rb
Expand Up @@ -98,8 +98,8 @@ def self.unescape_string(input)
# @yieldparam [Lexer] lexer
# @return [Lexer]
# @raise [Lexer::Error] on invalid input
def self.tokenize(input, terminals, options = {}, &block)
lexer = self.new(input, terminals, options)
def self.tokenize(input, terminals, **options, &block)
lexer = self.new(input, terminals, **options)
block_given? ? block.call(lexer) : lexer
end

Expand All @@ -115,17 +115,24 @@ def self.tokenize(input, terminals, options = {}, &block)
# Whitespace between tokens, including comments
# @option options[Integer] :high_water passed to scanner
# @option options[Integer] :low_water passed to scanner
def initialize(input = nil, terminals = nil, options = {})
def initialize(input = nil, terminals = nil, **options)
@options = options.dup
@whitespace = @options[:whitespace]
@terminals = terminals.map do |term|
term.is_a?(Array) ? Terminal.new(*term) : term
if term.is_a?(Array) && term.length ==3
# Last element is options
Terminal.new(term[0], term[1], **term[2])
elsif term.is_a?(Array)
Terminal.new(*term)
else
term
end
end

raise Error, "Terminal patterns not defined" unless @terminals && @terminals.length > 0

@lineno = 1
@scanner = Scanner.new(input, options)
@scanner = Scanner.new(input, **options)
end

##
Expand Down Expand Up @@ -300,7 +307,7 @@ class Terminal
# Cause strings and codepoints to be unescaped.
# @option options [Regexp] :partial_regexp
# A regular expression matching the beginning of this terminal; useful for terminals that match things longer than the scanner low water mark.
def initialize(type, regexp, options = {})
def initialize(type, regexp, **options)
@type, @regexp, @options = type, regexp, options
@partial_regexp = options[:partial_regexp]
@map = options.fetch(:map, {})
Expand Down Expand Up @@ -353,8 +360,8 @@ def unescape(string)
# Scanner instance with access to matched groups
# @param [Hash{Symbol => Object}] options
# @return [Token]
def token(type, value, options = {})
Token.new(type, value, options.merge(lineno: lineno))
def token(type, value, **options)
Token.new(type, value, lineno: lineno, **options)
end

##
Expand Down Expand Up @@ -398,7 +405,7 @@ class Token
# @param [String] value
# @param [Hash{Symbol => Object}] options
# @option options [Integer] :lineno (nil)
def initialize(type, value, options = {})
def initialize(type, value, **options)
@type = type.to_s.to_sym if type
@value = value.to_s
@options = options.dup
Expand Down Expand Up @@ -514,7 +521,7 @@ class Error < StandardError
# @option options [String] :input (nil)
# @option options [String] :token (nil)
# @option options [Integer] :lineno (nil)
def initialize(message, options = {})
def initialize(message, **options)
@input = options[:input]
@token = options[:token]
@lineno = options[:lineno]
Expand Down

0 comments on commit f9dd085

Please sign in to comment.