Skip to content

Commit f319629

Browse files
committed
Fix unused variable warning in no_result_var mode with EBNF operators
1 parent e1e6e76 commit f319629

2 files changed

Lines changed: 125 additions & 3 deletions

File tree

lib/racc/grammarfileparser.rb

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ def _add_many_rule(prev)
295295
return target if target
296296
target = _gen_target_name("many", prev)
297297
@many_rule_registry[prev.to_s] = target
298-
src = SourceText.new("result = val[1] ? val[1].unshift(val[0]) : val", @filename, @scanner.lineno + 1)
298+
src = SourceText.new(_many_action_code, @filename, @scanner.lineno + 1)
299299
act = UserAction.source_text(src)
300300
@grammar.add Rule.new(target, [], act)
301301
@grammar.add Rule.new(target, [prev, target], act)
@@ -308,13 +308,25 @@ def _add_many1_rule(prev)
308308
return target if target
309309
target = _gen_target_name("many1", prev)
310310
@many1_rule_registry[prev.to_s] = target
311-
src = SourceText.new("result = val[1] ? val[1].unshift(val[0]) : val", @filename, @scanner.lineno + 1)
311+
src = SourceText.new(_many_action_code, @filename, @scanner.lineno + 1)
312312
act = UserAction.source_text(src)
313313
@grammar.add Rule.new(target, [prev], act)
314314
@grammar.add Rule.new(target, [prev, target], act)
315315
target
316316
end
317317

318+
def _action_code(expression)
319+
@result.params.result_var? ? "result = #{expression}" : expression
320+
end
321+
322+
def _many_action_code
323+
_action_code("val[1] ? val[1].unshift(val[0]) : val")
324+
end
325+
326+
def _group_action_code
327+
_action_code("val")
328+
end
329+
318330
def _add_group_rule(enum)
319331
target = @grammar.intern("-temp-group", true)
320332
rules, _ = _add_rule_block(target, enum)
@@ -323,7 +335,7 @@ def _add_group_rule(enum)
323335
unless target = @group_rule_registry[target_name]
324336
target = @grammar.intern("-group@#{target_name}", true)
325337
@group_rule_registry[target_name] = target
326-
src = SourceText.new("result = val", @filename, @scanner.lineno + 1)
338+
src = SourceText.new(_group_action_code, @filename, @scanner.lineno + 1)
327339
act = UserAction.source_text(src)
328340
rules.each do |syms, sprec|
329341
rule = Rule.new(target, syms, act)

test/test_grammar_file_parser.rb

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,115 @@ def test_parse
1111
parser = Racc::GrammarFileParser.new(debug_flags)
1212
parser.parse(File.read(file), File.basename(file))
1313
end
14+
15+
def parse_grammar(grammar_source)
16+
debug_flags = Racc::DebugFlags.parse_option_string('')
17+
parser = Racc::GrammarFileParser.new(debug_flags)
18+
parser.parse(grammar_source, 'test.y')
19+
end
20+
21+
def test_no_result_var_with_many_operator
22+
grammar_source = <<~GRAMMAR
23+
class TestParser
24+
options no_result_var
25+
26+
rule
27+
root
28+
: 'a' 'b'*
29+
GRAMMAR
30+
31+
result = parse_grammar(grammar_source)
32+
33+
assert_equal false, result.params.result_var?
34+
35+
actions = result.grammar.each_rule.filter_map { |rule| rule.action.source&.text }
36+
actions.each do |action|
37+
refute_match(/\Aresult\s*=/, action, "Action should not start with 'result =' when no_result_var is set")
38+
end
39+
end
40+
41+
def test_no_result_var_with_many1_operator
42+
grammar_source = <<~GRAMMAR
43+
class TestParser
44+
options no_result_var
45+
46+
rule
47+
root
48+
: 'a' 'b'+
49+
GRAMMAR
50+
51+
result = parse_grammar(grammar_source)
52+
53+
assert_equal false, result.params.result_var?
54+
55+
actions = result.grammar.each_rule.filter_map { |rule| rule.action.source&.text }
56+
actions.each do |action|
57+
refute_match(/\Aresult\s*=/, action, "Action should not start with 'result =' when no_result_var is set")
58+
end
59+
end
60+
61+
def test_no_result_var_with_group_operator
62+
grammar_source = <<~GRAMMAR
63+
class TestParser
64+
options no_result_var
65+
66+
rule
67+
root
68+
: ('a' | 'b')
69+
GRAMMAR
70+
71+
result = parse_grammar(grammar_source)
72+
73+
assert_equal false, result.params.result_var?
74+
75+
actions = result.grammar.each_rule.filter_map { |rule| rule.action.source&.text }
76+
actions.each do |action|
77+
refute_match(/\Aresult\s*=/, action, "Action should not start with 'result =' when no_result_var is set")
78+
end
79+
end
80+
81+
def test_result_var_with_many_operator
82+
grammar_source = <<~GRAMMAR
83+
class TestParser
84+
85+
rule
86+
root
87+
: 'a' 'b'*
88+
GRAMMAR
89+
90+
result = parse_grammar(grammar_source)
91+
92+
assert_equal true, result.params.result_var?
93+
94+
actions = result.grammar.each_rule.filter_map { |rule| rule.action.source&.text }.reject(&:empty?)
95+
assert actions.any? { |action| action.match?(/\Aresult\s*=/) }, "Action should start with 'result =' when result_var is enabled"
96+
end
97+
98+
def test_no_result_var_no_warnings
99+
grammar_file = Tempfile.new(['test_no_result_var', '.y'])
100+
grammar_file.write(<<~GRAMMAR)
101+
class TestParser
102+
options no_result_var
103+
104+
rule
105+
root
106+
: 'a' 'b'*
107+
| 'c' 'd'+
108+
| ('e' | 'f')
109+
GRAMMAR
110+
grammar_file.close
111+
112+
output_file = Tempfile.new(['test_no_result_var', '.rb'])
113+
output_file.close
114+
115+
system("ruby", "-I#{LIB_DIR}", "-S", RACC, "-o", output_file.path, grammar_file.path)
116+
assert $?.success?, "racc command failed"
117+
118+
warnings = `ruby -W #{output_file.path} 2>&1`
119+
assert_equal "", warnings, "Expected no warnings but got: #{warnings}"
120+
ensure
121+
grammar_file&.unlink
122+
output_file&.unlink
123+
end
14124
end
15125
end

0 commit comments

Comments
 (0)