diff --git a/bin/racc b/bin/racc
index 4507d049..5c6b046b 100755
--- a/bin/racc
+++ b/bin/racc
@@ -19,6 +19,7 @@ def main
make_executable = false
rubypath = nil
embed_runtime = false
+ frozen_strings = false
debug_flags = Racc::DebugFlags.new
line_convert = true
line_convert_all = false
@@ -57,6 +58,9 @@ def main
parser.on('-E', '--embedded', "Embeds Racc runtime in output.") {
embed_runtime = true
}
+ parser.on('-F', '--frozen', "Add frozen_string_literals: true.") {
+ frozen_strings = true
+ }
parser.on('--line-convert-all', 'Converts line numbers of user codes.') {
line_convert_all = true
}
@@ -162,6 +166,7 @@ def main
params.convert_line = line_convert
params.convert_line_all = line_convert_all
params.embed_runtime = embed_runtime
+ params.frozen_strings = frozen_strings
profiler.section('generation') {
generator = Racc::ParserFileGenerator.new(states, params)
generator.generate_parser_file(output || make_filename(input, '.tab.rb'))
diff --git a/doc/ja/command.ja.html b/doc/ja/command.ja.html
index f7223076..52eccfd4 100644
--- a/doc/ja/command.ja.html
+++ b/doc/ja/command.ja.html
@@ -6,6 +6,7 @@
Raccコマンドリファレンス
[-Ofilename] [--log-file=filename]
[-g] [--debug]
[-E] [--embedded]
+ [-F] [--frozen]
[-l] [--no-line-convert]
[-c] [--line-convert-all]
[-a] [--no-omit-actions]
@@ -50,6 +51,10 @@ Raccコマンドリファレンス
ランタイムルーチンをすべて含んだコードを生成します。
つまり、このオプションをつけて生成したコードは Ruby さえあれば動きます。
+-F, --frozen
+
+Add frozen_string_literals: true.
+
-C, --check-only
(文法ファイルの) 文法のチェックだけをして終了します。
diff --git a/lib/racc/parser.rb b/lib/racc/parser.rb
index 9ad8f104..20f04fb6 100644
--- a/lib/racc/parser.rb
+++ b/lib/racc/parser.rb
@@ -57,6 +57,8 @@ class ParseError < StandardError; end
# use this '-g' option and set @yydebug true in parser class.
# [-E, --embedded]
# Output parser which doesn't need runtime files (racc/parser.rb).
+# [-F, --frozen]
+# Output parser which declares frozen_string_literals: true
# [-C, --check-only]
# Check syntax of racc grammar file and quit.
# [-S, --output-status]
diff --git a/lib/racc/parserfilegenerator.rb b/lib/racc/parserfilegenerator.rb
index 236ff27d..e6ea53d1 100644
--- a/lib/racc/parserfilegenerator.rb
+++ b/lib/racc/parserfilegenerator.rb
@@ -45,6 +45,7 @@ def #{name}=(b)
bool_attr :convert_line
bool_attr :convert_line_all
bool_attr :embed_runtime
+ bool_attr :frozen_strings
bool_attr :make_executable
attr_accessor :interpreter
@@ -64,6 +65,7 @@ def initialize
self.convert_line = true
self.convert_line_all = false
self.embed_runtime = false
+ self.frozen_strings = false
self.make_executable = false
self.interpreter = nil
end
@@ -122,6 +124,7 @@ def shebang(path)
end
def notice
+ line %q[# frozen_string_literal: true] if @params.frozen_strings?
line %q[#]
line %q[# DO NOT MODIFY!!!!]
line %Q[# This file is automatically generated by Racc #{Racc::Version}]
diff --git a/test/assets/frozen.y b/test/assets/frozen.y
new file mode 100644
index 00000000..c2640f33
--- /dev/null
+++ b/test/assets/frozen.y
@@ -0,0 +1,47 @@
+class Journey::Parser
+
+token SLASH LITERAL SYMBOL LPAREN RPAREN DOT STAR OR
+
+rule
+ expressions
+ : expressions expression { result = Cat.new(val.first, val.last) }
+ | expression { result = val.first }
+ | or
+ ;
+ expression
+ : terminal
+ | group
+ | star
+ ;
+ group
+ : LPAREN expressions RPAREN { result = Group.new(val[1]) }
+ ;
+ or
+ : expressions OR expression { result = Or.new([val.first, val.last]) }
+ ;
+ star
+ : STAR { result = Star.new(Symbol.new(val.last)) }
+ ;
+ terminal
+ : symbol
+ | literal
+ | slash
+ | dot
+ ;
+ slash
+ : SLASH { result = Slash.new('/') }
+ ;
+ symbol
+ : SYMBOL { result = Symbol.new(val.first) }
+ ;
+ literal
+ : LITERAL { result = Literal.new(val.first) }
+ dot
+ : DOT { result = Dot.new(val.first) }
+ ;
+
+end
+
+---- header
+
+require 'journey/parser_extras'
diff --git a/test/regress/frozen b/test/regress/frozen
new file mode 100644
index 00000000..b8d69c82
--- /dev/null
+++ b/test/regress/frozen
@@ -0,0 +1,225 @@
+# frozen_string_literal: true
+#
+# DO NOT MODIFY!!!!
+# This file is automatically generated by Racc 1.5.2
+# from Racc grammar file "".
+#
+
+require 'racc/parser.rb'
+
+
+require 'journey/parser_extras'
+module Journey
+ class Parser < Racc::Parser
+##### State transition tables begin ###
+
+racc_action_table = [
+ 17, 21, 13, 15, 14, 7, nil, 16, 8, 19,
+ 13, 15, 14, 7, 23, 16, 8, 19, 13, 15,
+ 14, 7, nil, 16, 8, 13, 15, 14, 7, nil,
+ 16, 8, 13, 15, 14, 7, nil, 16, 8 ]
+
+racc_action_check = [
+ 1, 17, 1, 1, 1, 1, nil, 1, 1, 1,
+ 20, 20, 20, 20, 20, 20, 20, 20, 0, 0,
+ 0, 0, nil, 0, 0, 7, 7, 7, 7, nil,
+ 7, 7, 19, 19, 19, 19, nil, 19, 19 ]
+
+racc_action_pointer = [
+ 16, 0, nil, nil, nil, nil, nil, 23, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, 1, nil, 30,
+ 8, nil, nil, nil ]
+
+racc_action_default = [
+ -18, -18, -2, -3, -4, -5, -6, -18, -9, -10,
+ -11, -12, -13, -14, -15, -16, -17, -18, -1, -18,
+ -18, 24, -8, -7 ]
+
+racc_goto_table = [
+ 18, 1, nil, nil, nil, nil, nil, nil, 20, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, 22, 18 ]
+
+racc_goto_check = [
+ 2, 1, nil, nil, nil, nil, nil, nil, 1, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, 2, 2 ]
+
+racc_goto_pointer = [
+ nil, 1, -1, nil, nil, nil, nil, nil, nil, nil,
+ nil ]
+
+racc_goto_default = [
+ nil, nil, 2, 3, 4, 5, 6, 9, 10, 11,
+ 12 ]
+
+racc_reduce_table = [
+ 0, 0, :racc_error,
+ 2, 11, :_reduce_1,
+ 1, 11, :_reduce_2,
+ 1, 11, :_reduce_none,
+ 1, 12, :_reduce_none,
+ 1, 12, :_reduce_none,
+ 1, 12, :_reduce_none,
+ 3, 15, :_reduce_7,
+ 3, 13, :_reduce_8,
+ 1, 16, :_reduce_9,
+ 1, 14, :_reduce_none,
+ 1, 14, :_reduce_none,
+ 1, 14, :_reduce_none,
+ 1, 14, :_reduce_none,
+ 1, 19, :_reduce_14,
+ 1, 17, :_reduce_15,
+ 1, 18, :_reduce_16,
+ 1, 20, :_reduce_17 ]
+
+racc_reduce_n = 18
+
+racc_shift_n = 24
+
+racc_token_table = {
+ false => 0,
+ :error => 1,
+ :SLASH => 2,
+ :LITERAL => 3,
+ :SYMBOL => 4,
+ :LPAREN => 5,
+ :RPAREN => 6,
+ :DOT => 7,
+ :STAR => 8,
+ :OR => 9 }
+
+racc_nt_base = 10
+
+racc_use_result_var = true
+
+Racc_arg = [
+ racc_action_table,
+ racc_action_check,
+ racc_action_default,
+ racc_action_pointer,
+ racc_goto_table,
+ racc_goto_check,
+ racc_goto_default,
+ racc_goto_pointer,
+ racc_nt_base,
+ racc_reduce_table,
+ racc_token_table,
+ racc_shift_n,
+ racc_reduce_n,
+ racc_use_result_var ]
+Ractor.make_shareable(Racc_arg) if defined?(Ractor)
+
+Racc_token_to_s_table = [
+ "$end",
+ "error",
+ "SLASH",
+ "LITERAL",
+ "SYMBOL",
+ "LPAREN",
+ "RPAREN",
+ "DOT",
+ "STAR",
+ "OR",
+ "$start",
+ "expressions",
+ "expression",
+ "or",
+ "terminal",
+ "group",
+ "star",
+ "symbol",
+ "literal",
+ "slash",
+ "dot" ]
+Ractor.make_shareable(Racc_token_to_s_table) if defined?(Ractor)
+
+Racc_debug_parser = false
+
+##### State transition tables end #####
+
+# reduce 0 omitted
+
+module_eval(<<'.,.,', 'frozen.y', 6)
+ def _reduce_1(val, _values, result)
+ result = Cat.new(val.first, val.last)
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'frozen.y', 7)
+ def _reduce_2(val, _values, result)
+ result = val.first
+ result
+ end
+.,.,
+
+# reduce 3 omitted
+
+# reduce 4 omitted
+
+# reduce 5 omitted
+
+# reduce 6 omitted
+
+module_eval(<<'.,.,', 'frozen.y', 16)
+ def _reduce_7(val, _values, result)
+ result = Group.new(val[1])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'frozen.y', 19)
+ def _reduce_8(val, _values, result)
+ result = Or.new([val.first, val.last])
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'frozen.y', 22)
+ def _reduce_9(val, _values, result)
+ result = Star.new(Symbol.new(val.last))
+ result
+ end
+.,.,
+
+# reduce 10 omitted
+
+# reduce 11 omitted
+
+# reduce 12 omitted
+
+# reduce 13 omitted
+
+module_eval(<<'.,.,', 'frozen.y', 31)
+ def _reduce_14(val, _values, result)
+ result = Slash.new('/')
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'frozen.y', 34)
+ def _reduce_15(val, _values, result)
+ result = Symbol.new(val.first)
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'frozen.y', 37)
+ def _reduce_16(val, _values, result)
+ result = Literal.new(val.first)
+ result
+ end
+.,.,
+
+module_eval(<<'.,.,', 'frozen.y', 39)
+ def _reduce_17(val, _values, result)
+ result = Dot.new(val.first)
+ result
+ end
+.,.,
+
+def _reduce_none(val, _values, result)
+ val[0]
+end
+
+ end # class Parser
+end # module Journey
diff --git a/test/test_racc_command.rb b/test/test_racc_command.rb
index 9d2b566b..f8f3856e 100644
--- a/test/test_racc_command.rb
+++ b/test/test_racc_command.rb
@@ -199,6 +199,14 @@ def test_journey
assert_output_unchanged 'journey.y'
end
+ # .y file from journey gem, but with --frozen
+
+ def test_frozen
+ assert_compile 'frozen.y', '--frozen'
+ assert_debugfile 'frozen.y', []
+ assert_output_unchanged 'frozen.y'
+ end
+
# .y file from nokogiri gem
def test_nokogiri_css