Skip to content

support Ruby 2.4's frozen string literals (on master) #81

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions bin/racc
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,10 @@ def main
profiler.report
rescue Racc::CompileError, Errno::ENOENT, Errno::EPERM => err
raise if $DEBUG
lineno = err.message.slice!(/\A\d+:/).to_s
message = err.message.dup # string may be frozen literal
lineno = message.slice!(/\A\d+:/).to_s
location = lineno.empty? ? bright("#{input}:") : bright("#{input}:#{lineno}")
$stderr.puts "#{red('Error: ')}#{location} #{err.message.strip}"
$stderr.puts "#{red('Error: ')}#{location} #{message.strip}"
exit 1
end
end
Expand Down
18 changes: 9 additions & 9 deletions lib/racc/color.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,43 +23,43 @@ def self.without_color
def bright(text)
return text unless Color.enabled?
text = text.gsub(/\e\[.*?m[^\e]*\e\[0m/, "\e[0m\\0\e[1m")
"\e[1m#{text}\e[0m"
String.new "\e[1m#{text}\e[0m"
end

def red(text)
return text unless Color.enabled?
"\e[31m#{text}\e[0m"
String.new "\e[31m#{text}\e[0m"
end

def green(text)
return text unless Color.enabled?
"\e[32m#{text}\e[0m"
String.new "\e[32m#{text}\e[0m"
end

def violet(text)
return text unless Color.enabled?
"\e[1;35m#{text}\e[0m"
String.new "\e[1;35m#{text}\e[0m"
end

# Syntax highlighting for various types of symbols...
def nonterminal(text)
return text unless Color.enabled?
"\e[1;34m#{text}\e[0m" # blue
String.new "\e[1;34m#{text}\e[0m" # blue
end

def terminal(text)
return text unless Color.enabled?
"\e[1;36m\e[4m#{text}\e[0m" # cyan, with underline
String.new "\e[1;36m\e[4m#{text}\e[0m" # cyan, with underline
end

def string(text)
return text unless Color.enabled?
"\e[1;33m#{text}\e[0m" # bright yellow
String.new "\e[1;33m#{text}\e[0m" # bright yellow
end

def explicit_prec(text)
return text unless Color.enabled?
"\e[1;31m#{text}\e[0m" # bright reddish orange
String.new "\e[1;31m#{text}\e[0m" # bright reddish orange
end
end
end
end
16 changes: 8 additions & 8 deletions lib/racc/grammar.rb
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ def check_terminals
locations = undeclared.flat_map(&:locate).map(&:rule).uniq
raise CompileError, "terminal#{'s' unless undeclared.one?} " \
"#{Racc.to_sentence(undeclared)} #{undeclared.one? ? 'was' : 'were'} " \
"not declared in a 'token' block:\n" <<
"not declared in a 'token' block:\n" +
Source::SparseLines.render(locations.map(&:source))
end

Expand All @@ -308,15 +308,15 @@ def check_terminals
raise CompileError, "token#{'s' unless wrongly_declared.one?} " \
"#{Racc.to_sentence(wrongly_declared)} were declared in a 'token'" \
" block, but #{wrongly_declared.one? ? 'it also has' : 'they also have'}" \
" derivation rules:\n" << Source::SparseLines.render(bad_rules.map(&:source))
" derivation rules:\n" + Source::SparseLines.render(bad_rules.map(&:source))
end
end

bad_strings = @symbols.select { |s| s.string_symbol? && s.nonterminal? }
unless bad_strings.empty?
bad_rules = bad_strings.flat_map(&:heads).map(&:rule)
raise CompileError, 'you may not create derivation rules for a ' \
"string literal:\n" << Source::SparseLines.render(bad_rules.map(&:source))
"string literal:\n" + Source::SparseLines.render(bad_rules.map(&:source))
end

bad_prec = @symbols.select { |s| s.assoc && s.nonterminal? }
Expand All @@ -325,7 +325,7 @@ def check_terminals
raise CompileError, "token#{'s' unless bad_prec.one?} " \
"#{Racc.to_sentence(bad_prec)} appeared in a prechigh/preclow " \
"block, but #{bad_prec.one? ? 'it is not a' : 'they are not'} " \
"terminal#{'s' unless bad_prec.one?}:\n" <<
"terminal#{'s' unless bad_prec.one?}:\n" +
Source::SparseLines.render(bad_rules.map(&:source))
end

Expand All @@ -335,7 +335,7 @@ def check_terminals
unless bad_prec.empty?
raise CompileError, "The following rule#{'s' unless bad_prec.one?} " \
"use#{'s' if bad_prec.one?} nonterminals for explicit precedence, " \
"which is not allowed:\n" <<
"which is not allowed:\n" +
Source::SparseLines.render(bad_prec.map(&:source))
end
end
Expand All @@ -344,13 +344,13 @@ def check_rules
@rules.group_by(&:target).each_value do |same_lhs|
same_lhs.group_by { |r| r.symbols.reject(&:hidden?) }.each_value do |same_rhs|
next unless same_rhs.size > 1
raise CompileError, "The following rules are duplicates:\n" <<
raise CompileError, "The following rules are duplicates:\n" +
Source::SparseLines.render(same_rhs.map(&:source))
end
end

unless @error.heads.empty?
raise CompileError, "You cannot create rules for the error symbol:\n" <<
raise CompileError, "You cannot create rules for the error symbol:\n" +
Source::SparseLines.render(@error.heads.map { |ptr| ptr.rule.source} )
end
end
Expand Down Expand Up @@ -568,7 +568,7 @@ def following
end

def to_s
result = "#{@rule.target} : "
result = String.new "#{@rule.target} : "
if @index > 0
result << "#{preceding.reject(&:hidden?).map(&:to_s).join(' ')} ."
else
Expand Down
2 changes: 1 addition & 1 deletion lib/racc/source.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def spiffy
highlights.sort_by!(&:from)

raw = text
cooked = ''
cooked = String.new
offset = 0

highlights.each do |hilite|
Expand Down
2 changes: 1 addition & 1 deletion lib/racc/state_transition_table.rb
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def add_entry(all, array, chkval, ptr_array)
end

def mkmapexp(arr)
map = ''
map = String.new
maxdup = RE_DUP_MAX

arr.chunk(&:nil?).each do |is_nil, items|
Expand Down
16 changes: 8 additions & 8 deletions lib/racc/warning.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def initialize(type, title, details = nil)
end

def to_s
msg = violet('Warning: ') << bright(title)
msg = violet('Warning: ') + bright(title)
msg << "\n" << details if details
msg
end
Expand Down Expand Up @@ -104,7 +104,7 @@ def title
def details
"Its derivation rule#{'s all' unless @sym.heads.one?} contain" \
"#{'s' if @sym.heads.one?} #{'an ' if @sym.heads.one?}infinite loop" \
"#{'s' unless @sym.heads.one?}:\n" <<
"#{'s' unless @sym.heads.one?}:\n" +
@sym.heads.map { |ptr| ptr.rule.to_s }.join("\n")
end

Expand Down Expand Up @@ -175,7 +175,7 @@ def details

"When the next token is #{connective}#{Racc.to_sentence(tokens, 'or')}" \
", it is overridden by #{rules.one? ? 'this' : 'these'} " \
"higher-precedence rule#{'s' unless rules.one?}:\n" <<
"higher-precedence rule#{'s' unless rules.one?}:\n" +
Source::SparseLines.render(rules.map(&:source))
end.join("\n\n")
end
Expand All @@ -196,15 +196,15 @@ def initialize(conflict, grammar, verbose)
end

def title
"Shift/reduce conflict on #{@sym}," <<
"Shift/reduce conflict on #{@sym}," +
(@path.reject(&:hidden?).empty? ?
' at the beginning of the parse.' :
' after the following input:')
end

def details
if @path.reject(&:hidden?).empty?
result = ''
result = String.new
else
result = @path.reject(&:hidden?).map(&:to_s).join(' ') << "\n"
end
Expand Down Expand Up @@ -253,15 +253,15 @@ def initialize(conflict, grammar, verbose)
end

def title
"Reduce/reduce conflict on #{@sym}," <<
"Reduce/reduce conflict on #{@sym}," +
(@path.reject(&:hidden?).empty? ?
' at the beginning of the parse.' :
' after the following input:')
end

def details
if @path.reject(&:hidden?).empty?
result = ''
result = String.new
else
result = @path.reject(&:hidden?).map(&:to_s).join(' ') << "\n"
end
Expand Down Expand Up @@ -300,4 +300,4 @@ def type
end
end
end
end
end
10 changes: 10 additions & 0 deletions test/run_tests.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
#!/usr/bin/env bash

set -eux

test_frozen_strings=$(ruby -e 'puts (RUBY_ENGINE == "ruby" && RUBY_VERSION > "2.4")')

if [[ $test_frozen_strings == "true" ]] ; then
echo "NOTE: enabling frozen string literals"
rvm install rubygems 2.6.12 --force # because of an issue in rubygems 2.7 with ruby 2.5 and frozen string literals
export RUBYOPT="--enable-frozen-string-literal --debug=frozen-string-literal"
fi

bundle exec rake test
bundle exec rake test_pure
4 changes: 2 additions & 2 deletions test/test_scanner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ class TestScanner < TestCase
define_method("test_scan_#{File.basename(testfile)}".to_sym) do
original = File.read(testfile)
# wrap the Ruby source code in an action block
wrapped = "class Test\nrule\na : '*' {" << original << "\n}"
wrapped = "class Test\nrule\na : '*' {" + original + "\n}"
file = Source::Buffer.new(testfile, wrapped)
scanner = Racc::GrammarFileScanner.new(file)

rebuilt = ''
rebuilt = String.new
scanner.yylex do |token|
break if token.nil?
rebuilt << token[1][0].text if token[0] == :ACTION
Expand Down