Skip to content

Commit cd0f85b

Browse files
committed
Allow terminal symbols to be used anywhere in the grammar rules
Fixes: #182
1 parent bab5a21 commit cd0f85b

File tree

4 files changed

+158
-4
lines changed

4 files changed

+158
-4
lines changed

lib/racc/grammarfileparser.rb

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ def parse(src, filename = '-', lineno = 1)
200200
@grammar = Grammar.new
201201
@result = Result.new(@grammar)
202202
@embedded_action_seq = 0
203+
@current_rule_target = nil
203204
yyparse @scanner, :yylex
204205
parse_user_code
205206
@result.grammar.init
@@ -228,11 +229,21 @@ def location
228229
end
229230

230231
def add_rule_block(list)
231-
target = list.shift
232-
case target
233-
when OrMark, OptionMark, ManyMark, Many1Mark, GroupStartMark, GroupEndMark, UserAction, Prec
234-
raise CompileError, "#{target.lineno}: unexpected symbol #{target.name}"
232+
if !list.empty? && list[0].is_a?(OrMark)
233+
list.shift
234+
target = @current_rule_target
235+
if target.nil?
236+
raise CompileError, "#{location()}: no target for rule continuation"
237+
end
238+
else
239+
target = list.shift
240+
case target
241+
when OrMark, OptionMark, ManyMark, Many1Mark, GroupStartMark, GroupEndMark, UserAction, Prec
242+
raise CompileError, "#{target.lineno}: unexpected symbol #{target.name}"
243+
end
244+
@current_rule_target = target
235245
end
246+
236247
enum = list.each.with_index
237248
_, sym, idx = _add_rule_block(target, enum)
238249
if idx

test/assets/term.y

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class Parse
2+
rule
3+
target : term
4+
{ p 'target:term' }
5+
term : :TERM1
6+
{ p 'term:TERM1' }
7+
| :TERM2
8+
{ p 'term:TERM2'}
9+
| term :TERM3
10+
{ p 'term:TERM3' }
11+
end

test/regress/term

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#
2+
# DO NOT MODIFY!!!!
3+
# This file is automatically generated by Racc 1.8.1
4+
# from Racc grammar file "term.y".
5+
#
6+
7+
require 'racc/parser.rb'
8+
class Parse < Racc::Parser
9+
##### State transition tables begin ###
10+
11+
racc_action_table = [
12+
3, 4, 5, 6, 7 ]
13+
14+
racc_action_check = [
15+
0, 0, 0, 1, 6 ]
16+
17+
racc_action_pointer = [
18+
-2, 3, nil, nil, nil, nil, 4, nil ]
19+
20+
racc_action_default = [
21+
-4, -6, -1, -2, -3, -5, -6, 8 ]
22+
23+
racc_goto_table = [
24+
1, 2 ]
25+
26+
racc_goto_check = [
27+
1, 2 ]
28+
29+
racc_goto_pointer = [
30+
nil, 0, 1 ]
31+
32+
racc_goto_default = [
33+
nil, nil, nil ]
34+
35+
racc_reduce_table = [
36+
0, 0, :racc_error,
37+
1, 6, :_reduce_1,
38+
1, 7, :_reduce_2,
39+
1, 7, :_reduce_3,
40+
0, 7, :_reduce_none,
41+
1, 7, :_reduce_5 ]
42+
43+
racc_reduce_n = 6
44+
45+
racc_shift_n = 8
46+
47+
racc_token_table = {
48+
false => 0,
49+
:error => 1,
50+
:TERM1 => 2,
51+
:TERM2 => 3,
52+
:TERM3 => 4 }
53+
54+
racc_nt_base = 5
55+
56+
racc_use_result_var = true
57+
58+
Racc_arg = [
59+
racc_action_table,
60+
racc_action_check,
61+
racc_action_default,
62+
racc_action_pointer,
63+
racc_goto_table,
64+
racc_goto_check,
65+
racc_goto_default,
66+
racc_goto_pointer,
67+
racc_nt_base,
68+
racc_reduce_table,
69+
racc_token_table,
70+
racc_shift_n,
71+
racc_reduce_n,
72+
racc_use_result_var ]
73+
Ractor.make_shareable(Racc_arg) if defined?(Ractor)
74+
75+
Racc_token_to_s_table = [
76+
"$end",
77+
"error",
78+
"TERM1",
79+
"TERM2",
80+
"TERM3",
81+
"$start",
82+
"target",
83+
"term" ]
84+
Ractor.make_shareable(Racc_token_to_s_table) if defined?(Ractor)
85+
86+
Racc_debug_parser = false
87+
88+
##### State transition tables end #####
89+
90+
# reduce 0 omitted
91+
92+
module_eval(<<'.,.,', 'term.y', 3)
93+
def _reduce_1(val, _values, result)
94+
p 'target:term'
95+
result
96+
end
97+
.,.,
98+
99+
module_eval(<<'.,.,', 'term.y', 5)
100+
def _reduce_2(val, _values, result)
101+
p 'term:TERM1'
102+
result
103+
end
104+
.,.,
105+
106+
module_eval(<<'.,.,', 'term.y', 7)
107+
def _reduce_3(val, _values, result)
108+
p 'term:TERM2'
109+
result
110+
end
111+
.,.,
112+
113+
# reduce 4 omitted
114+
115+
module_eval(<<'.,.,', 'term.y', 9)
116+
def _reduce_5(val, _values, result)
117+
p 'term:TERM3'
118+
result
119+
end
120+
.,.,
121+
122+
def _reduce_none(val, _values, result)
123+
val[0]
124+
end
125+
126+
end # class Parse

test/test_racc_command.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,5 +374,11 @@ def test_group
374374
assert_debugfile 'group.y', [0, 0, 0, 0]
375375
assert_output_unchanged 'group.y'
376376
end
377+
378+
def test_term
379+
assert_compile 'term.y'
380+
assert_debugfile 'term.y', [0, 0, 0, 0]
381+
assert_output_unchanged 'term.y'
382+
end
377383
end
378384
end

0 commit comments

Comments
 (0)