lrama 0.6.9 → 0.6.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yaml +24 -1
- data/.gitignore +2 -0
- data/Gemfile +6 -3
- data/NEWS.md +269 -14
- data/README.md +41 -4
- data/Rakefile +2 -0
- data/Steepfile +9 -17
- data/doc/development/compressed_state_table/main.md +635 -0
- data/doc/development/compressed_state_table/parse.output +174 -0
- data/doc/development/compressed_state_table/parse.y +22 -0
- data/doc/development/compressed_state_table/parser.rb +282 -0
- data/exe/lrama +1 -0
- data/lib/lrama/bitmap.rb +3 -1
- data/lib/lrama/command.rb +8 -14
- data/lib/lrama/context.rb +11 -9
- data/lib/lrama/counterexamples/derivation.rb +8 -5
- data/lib/lrama/counterexamples/example.rb +9 -4
- data/lib/lrama/counterexamples/path.rb +6 -0
- data/lib/lrama/counterexamples/production_path.rb +2 -0
- data/lib/lrama/counterexamples/start_path.rb +2 -0
- data/lib/lrama/counterexamples/state_item.rb +2 -0
- data/lib/lrama/counterexamples/transition_path.rb +2 -0
- data/lib/lrama/counterexamples/triple.rb +2 -0
- data/lib/lrama/counterexamples.rb +36 -24
- data/lib/lrama/diagnostics.rb +36 -0
- data/lib/lrama/digraph.rb +2 -0
- data/lib/lrama/grammar/auxiliary.rb +2 -0
- data/lib/lrama/grammar/binding.rb +12 -1
- data/lib/lrama/grammar/code/destructor_code.rb +2 -0
- data/lib/lrama/grammar/code/initial_action_code.rb +2 -0
- data/lib/lrama/grammar/code/no_reference_code.rb +2 -0
- data/lib/lrama/grammar/code/printer_code.rb +2 -0
- data/lib/lrama/grammar/code/rule_action.rb +7 -3
- data/lib/lrama/grammar/code.rb +7 -5
- data/lib/lrama/grammar/counter.rb +2 -0
- data/lib/lrama/grammar/destructor.rb +2 -0
- data/lib/lrama/grammar/error_token.rb +2 -0
- data/lib/lrama/grammar/parameterizing_rule/resolver.rb +7 -1
- data/lib/lrama/grammar/parameterizing_rule/rhs.rb +6 -3
- data/lib/lrama/grammar/parameterizing_rule/rule.rb +6 -0
- data/lib/lrama/grammar/parameterizing_rule.rb +2 -0
- data/lib/lrama/grammar/percent_code.rb +2 -0
- data/lib/lrama/grammar/precedence.rb +2 -0
- data/lib/lrama/grammar/printer.rb +2 -0
- data/lib/lrama/grammar/reference.rb +2 -0
- data/lib/lrama/grammar/rule.rb +10 -3
- data/lib/lrama/grammar/rule_builder.rb +64 -65
- data/lib/lrama/grammar/symbol.rb +2 -0
- data/lib/lrama/grammar/symbols/resolver.rb +9 -1
- data/lib/lrama/grammar/symbols.rb +2 -0
- data/lib/lrama/grammar/type.rb +2 -0
- data/lib/lrama/grammar/union.rb +2 -0
- data/lib/lrama/grammar.rb +53 -32
- data/lib/lrama/grammar_validator.rb +37 -0
- data/lib/lrama/lexer/grammar_file.rb +2 -0
- data/lib/lrama/lexer/location.rb +2 -0
- data/lib/lrama/lexer/token/char.rb +2 -0
- data/lib/lrama/lexer/token/ident.rb +2 -0
- data/lib/lrama/lexer/token/instantiate_rule.rb +2 -0
- data/lib/lrama/lexer/token/tag.rb +2 -0
- data/lib/lrama/lexer/token/user_code.rb +4 -2
- data/lib/lrama/lexer/token.rb +7 -5
- data/lib/lrama/lexer.rb +12 -8
- data/lib/lrama/{warning.rb → logger.rb} +5 -13
- data/lib/lrama/option_parser.rb +58 -33
- data/lib/lrama/options.rb +5 -2
- data/lib/lrama/output.rb +38 -69
- data/lib/lrama/parser.rb +677 -773
- data/lib/lrama/report/duration.rb +2 -0
- data/lib/lrama/report/profile.rb +2 -0
- data/lib/lrama/report.rb +4 -2
- data/lib/lrama/state/reduce.rb +4 -2
- data/lib/lrama/state/reduce_reduce_conflict.rb +2 -0
- data/lib/lrama/state/resolved_conflict.rb +3 -1
- data/lib/lrama/state/shift.rb +2 -0
- data/lib/lrama/state/shift_reduce_conflict.rb +2 -0
- data/lib/lrama/state.rb +7 -5
- data/lib/lrama/states/item.rb +5 -3
- data/lib/lrama/states.rb +18 -46
- data/lib/lrama/states_reporter.rb +60 -19
- data/lib/lrama/trace_reporter.rb +30 -0
- data/lib/lrama/version.rb +3 -1
- data/lib/lrama.rb +22 -17
- data/lrama.gemspec +3 -1
- data/parser.y +129 -237
- data/rbs_collection.lock.yaml +10 -2
- data/sig/lrama/counterexamples/derivation.rbs +33 -0
- data/sig/lrama/counterexamples/example.rbs +45 -0
- data/sig/lrama/counterexamples/path.rbs +21 -0
- data/sig/lrama/counterexamples/production_path.rbs +11 -0
- data/sig/lrama/counterexamples/start_path.rbs +13 -0
- data/sig/lrama/counterexamples/state_item.rbs +10 -0
- data/sig/lrama/counterexamples/transition_path.rbs +11 -0
- data/sig/lrama/counterexamples/triple.rbs +20 -0
- data/sig/lrama/counterexamples.rbs +29 -0
- data/sig/lrama/grammar/auxiliary.rbs +10 -0
- data/sig/lrama/grammar/binding.rbs +4 -0
- data/sig/lrama/grammar/code/destructor_code.rbs +3 -4
- data/sig/lrama/grammar/code/initial_action_code.rbs +15 -0
- data/sig/lrama/grammar/code/no_reference_code.rbs +15 -0
- data/sig/lrama/grammar/code/printer_code.rbs +3 -4
- data/sig/lrama/grammar/code/rule_action.rbs +19 -0
- data/sig/lrama/grammar/code.rbs +3 -3
- data/sig/lrama/grammar/destructor.rbs +3 -1
- data/sig/lrama/grammar/error_token.rbs +4 -2
- data/sig/lrama/grammar/parameterizing_rule/resolver.rbs +2 -1
- data/sig/lrama/grammar/parameterizing_rule/rhs.rbs +1 -1
- data/sig/lrama/grammar/precedence.rbs +3 -1
- data/sig/lrama/grammar/printer.rbs +3 -1
- data/sig/lrama/grammar/rule.rbs +35 -3
- data/sig/lrama/grammar/rule_builder.rbs +10 -9
- data/sig/lrama/grammar/symbol.rbs +6 -6
- data/sig/lrama/grammar/symbols/resolver.rbs +24 -5
- data/sig/lrama/grammar/type.rbs +2 -2
- data/sig/lrama/grammar/union.rbs +12 -0
- data/sig/lrama/grammar.rbs +104 -1
- data/sig/lrama/options.rbs +3 -2
- data/sig/lrama/state/reduce.rbs +20 -0
- data/sig/lrama/state/reduce_reduce_conflict.rbs +13 -0
- data/sig/lrama/state/resolved_conflict.rbs +14 -0
- data/sig/lrama/state/shift.rbs +14 -0
- data/sig/lrama/state/shift_reduce_conflict.rbs +13 -0
- data/sig/lrama/state.rbs +79 -0
- data/sig/lrama/states/item.rbs +30 -0
- data/sig/lrama/states.rbs +101 -0
- data/template/bison/yacc.c +24 -19
- metadata +32 -6
- data/sample/calc.output +0 -263
- data/sample/calc.y +0 -101
- data/sample/parse.y +0 -59
@@ -1,13 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "set"
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
require_relative "counterexamples/derivation"
|
6
|
+
require_relative "counterexamples/example"
|
7
|
+
require_relative "counterexamples/path"
|
8
|
+
require_relative "counterexamples/production_path"
|
9
|
+
require_relative "counterexamples/start_path"
|
10
|
+
require_relative "counterexamples/state_item"
|
11
|
+
require_relative "counterexamples/transition_path"
|
12
|
+
require_relative "counterexamples/triple"
|
11
13
|
|
12
14
|
module Lrama
|
13
15
|
# See: https://www.cs.cornell.edu/andru/papers/cupex/cupex.pdf
|
@@ -30,8 +32,10 @@ module Lrama
|
|
30
32
|
conflict_state.conflicts.flat_map do |conflict|
|
31
33
|
case conflict.type
|
32
34
|
when :shift_reduce
|
35
|
+
# @type var conflict: State::ShiftReduceConflict
|
33
36
|
shift_reduce_example(conflict_state, conflict)
|
34
37
|
when :reduce_reduce
|
38
|
+
# @type var conflict: State::ReduceReduceConflict
|
35
39
|
reduce_reduce_examples(conflict_state, conflict)
|
36
40
|
end
|
37
41
|
end.compact
|
@@ -46,7 +50,7 @@ module Lrama
|
|
46
50
|
@reverse_transitions = {}
|
47
51
|
|
48
52
|
@states.states.each do |src_state|
|
49
|
-
trans = {}
|
53
|
+
trans = {} #: Hash[Grammar::Symbol, State]
|
50
54
|
|
51
55
|
src_state.transitions.each do |shift, next_state|
|
52
56
|
trans[shift.next_sym] = next_state
|
@@ -64,6 +68,7 @@ module Lrama
|
|
64
68
|
|
65
69
|
@transitions[[src_state_item, sym]] = dest_state_item
|
66
70
|
|
71
|
+
# @type var key: [StateItem, Grammar::Symbol]
|
67
72
|
key = [dest_state_item, sym]
|
68
73
|
@reverse_transitions[key] ||= Set.new
|
69
74
|
@reverse_transitions[key] << src_state_item
|
@@ -80,7 +85,7 @@ module Lrama
|
|
80
85
|
|
81
86
|
@states.states.each do |state|
|
82
87
|
# LHS => Set(Item)
|
83
|
-
h = {}
|
88
|
+
h = {} #: Hash[Grammar::Symbol, Set[States::Item]]
|
84
89
|
|
85
90
|
state.closure.each do |item|
|
86
91
|
sym = item.lhs
|
@@ -95,6 +100,7 @@ module Lrama
|
|
95
100
|
|
96
101
|
sym = item.next_sym
|
97
102
|
state_item = StateItem.new(state, item)
|
103
|
+
# @type var key: [State, Grammar::Symbol]
|
98
104
|
key = [state, sym]
|
99
105
|
|
100
106
|
@productions[state_item] = h[sym]
|
@@ -107,6 +113,7 @@ module Lrama
|
|
107
113
|
|
108
114
|
def shift_reduce_example(conflict_state, conflict)
|
109
115
|
conflict_symbol = conflict.symbols.first
|
116
|
+
# @type var shift_conflict_item: ::Lrama::States::Item
|
110
117
|
shift_conflict_item = conflict_state.items.find { |item| item.next_sym == conflict_symbol }
|
111
118
|
path2 = shortest_path(conflict_state, conflict.reduce.item, conflict_symbol)
|
112
119
|
path1 = find_shift_conflict_shortest_path(path2, conflict_state, shift_conflict_item)
|
@@ -151,12 +158,14 @@ module Lrama
|
|
151
158
|
prev_state_item = prev_path&.to
|
152
159
|
|
153
160
|
if target_state_item == state_item || target_state_item.item.start_item?
|
154
|
-
result.concat(
|
161
|
+
result.concat(
|
162
|
+
reversed_reduce_path[_j..-1] #: Array[StartPath|TransitionPath|ProductionPath]
|
163
|
+
.map(&:to))
|
155
164
|
break
|
156
165
|
end
|
157
166
|
|
158
167
|
if target_state_item.item.beginning_of_rule?
|
159
|
-
queue = []
|
168
|
+
queue = [] #: Array[Array[StateItem]]
|
160
169
|
queue << [target_state_item]
|
161
170
|
|
162
171
|
# Find reverse production
|
@@ -171,10 +180,18 @@ module Lrama
|
|
171
180
|
break
|
172
181
|
end
|
173
182
|
|
174
|
-
if
|
183
|
+
if si.item.beginning_of_rule?
|
184
|
+
# @type var key: [State, Grammar::Symbol]
|
185
|
+
key = [si.state, si.item.lhs]
|
186
|
+
@reverse_productions[key].each do |item|
|
187
|
+
state_item = StateItem.new(si.state, item)
|
188
|
+
queue << (sis + [state_item])
|
189
|
+
end
|
190
|
+
else
|
191
|
+
# @type var key: [StateItem, Grammar::Symbol]
|
175
192
|
key = [si, si.item.previous_sym]
|
176
193
|
@reverse_transitions[key].each do |prev_target_state_item|
|
177
|
-
next if prev_target_state_item.state != prev_state_item
|
194
|
+
next if prev_target_state_item.state != prev_state_item&.state
|
178
195
|
sis.shift
|
179
196
|
result.concat(sis)
|
180
197
|
result << prev_target_state_item
|
@@ -183,19 +200,14 @@ module Lrama
|
|
183
200
|
queue.clear
|
184
201
|
break
|
185
202
|
end
|
186
|
-
else
|
187
|
-
key = [si.state, si.item.lhs]
|
188
|
-
@reverse_productions[key].each do |item|
|
189
|
-
state_item = StateItem.new(si.state, item)
|
190
|
-
queue << (sis + [state_item])
|
191
|
-
end
|
192
203
|
end
|
193
204
|
end
|
194
205
|
else
|
195
206
|
# Find reverse transition
|
207
|
+
# @type var key: [StateItem, Grammar::Symbol]
|
196
208
|
key = [target_state_item, target_state_item.item.previous_sym]
|
197
209
|
@reverse_transitions[key].each do |prev_target_state_item|
|
198
|
-
next if prev_target_state_item.state != prev_state_item
|
210
|
+
next if prev_target_state_item.state != prev_state_item&.state
|
199
211
|
result << prev_target_state_item
|
200
212
|
target_state_item = prev_target_state_item
|
201
213
|
i = j
|
@@ -222,9 +234,9 @@ module Lrama
|
|
222
234
|
|
223
235
|
def shortest_path(conflict_state, conflict_reduce_item, conflict_term)
|
224
236
|
# queue: is an array of [Triple, [Path]]
|
225
|
-
queue = []
|
226
|
-
visited = {}
|
227
|
-
start_state = @states.states.first
|
237
|
+
queue = [] #: Array[[Triple, Array[StartPath|TransitionPath|ProductionPath]]]
|
238
|
+
visited = {} #: Hash[Triple, true]
|
239
|
+
start_state = @states.states.first #: Lrama::State
|
228
240
|
raise "BUG: Start state should be just one kernel." if start_state.kernels.count != 1
|
229
241
|
|
230
242
|
start = Triple.new(start_state, start_state.kernels.first, Set.new([@states.eof_symbol]))
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lrama
|
4
|
+
class Diagnostics
|
5
|
+
def initialize(grammar, states, logger)
|
6
|
+
@grammar = grammar
|
7
|
+
@states = states
|
8
|
+
@logger = logger
|
9
|
+
end
|
10
|
+
|
11
|
+
def run(diagnostic)
|
12
|
+
if diagnostic
|
13
|
+
diagnose_conflict
|
14
|
+
diagnose_parameterizing_redefined
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def diagnose_conflict
|
21
|
+
if @states.sr_conflicts_count != 0
|
22
|
+
@logger.warn("shift/reduce conflicts: #{@states.sr_conflicts_count} found")
|
23
|
+
end
|
24
|
+
|
25
|
+
if @states.rr_conflicts_count != 0
|
26
|
+
@logger.warn("reduce/reduce conflicts: #{@states.rr_conflicts_count} found")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def diagnose_parameterizing_redefined
|
31
|
+
@grammar.parameterizing_rule_resolver.redefined_rules.each do |rule|
|
32
|
+
@logger.warn("parameterizing rule redefined: #{rule}")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/lrama/digraph.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Lrama
|
2
4
|
class Grammar
|
3
5
|
class Binding
|
@@ -16,8 +18,17 @@ module Lrama
|
|
16
18
|
resolved_args = symbol.args.map { |arg| resolve_symbol(arg) }
|
17
19
|
Lrama::Lexer::Token::InstantiateRule.new(s_value: symbol.s_value, location: symbol.location, args: resolved_args, lhs_tag: symbol.lhs_tag)
|
18
20
|
else
|
19
|
-
|
21
|
+
parameter_to_arg(symbol) || symbol
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def parameter_to_arg(symbol)
|
28
|
+
if (arg = @parameter_to_arg[symbol.s_value].dup)
|
29
|
+
arg.alias_name = symbol.alias_name
|
20
30
|
end
|
31
|
+
arg
|
21
32
|
end
|
22
33
|
end
|
23
34
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Lrama
|
2
4
|
class Grammar
|
3
5
|
class Code
|
@@ -41,6 +43,7 @@ module Lrama
|
|
41
43
|
when ref.type == :dollar && ref.name == "$" # $$
|
42
44
|
tag = ref.ex_tag || lhs.tag
|
43
45
|
raise_tag_not_found_error(ref) unless tag
|
46
|
+
# @type var tag: Lexer::Token::Tag
|
44
47
|
"(yyval.#{tag.member})"
|
45
48
|
when ref.type == :at && ref.name == "$" # @$
|
46
49
|
"(yyloc)"
|
@@ -50,6 +53,7 @@ module Lrama
|
|
50
53
|
i = -position_in_rhs + ref.index
|
51
54
|
tag = ref.ex_tag || rhs[ref.index - 1].tag
|
52
55
|
raise_tag_not_found_error(ref) unless tag
|
56
|
+
# @type var tag: Lexer::Token::Tag
|
53
57
|
"(yyvsp[#{i}].#{tag.member})"
|
54
58
|
when ref.type == :at # @n
|
55
59
|
i = -position_in_rhs + ref.index
|
@@ -69,18 +73,18 @@ module Lrama
|
|
69
73
|
@rule.position_in_original_rule_rhs || @rule.rhs.count
|
70
74
|
end
|
71
75
|
|
72
|
-
# If this is midrule action, RHS is
|
76
|
+
# If this is midrule action, RHS is an RHS of the original rule.
|
73
77
|
def rhs
|
74
78
|
(@rule.original_rule || @rule).rhs
|
75
79
|
end
|
76
80
|
|
77
|
-
# Unlike `rhs`, LHS is always
|
81
|
+
# Unlike `rhs`, LHS is always an LHS of the rule.
|
78
82
|
def lhs
|
79
83
|
@rule.lhs
|
80
84
|
end
|
81
85
|
|
82
86
|
def raise_tag_not_found_error(ref)
|
83
|
-
raise "Tag is not specified for '$#{ref.value}' in '#{@rule}'"
|
87
|
+
raise "Tag is not specified for '$#{ref.value}' in '#{@rule.display_name}'"
|
84
88
|
end
|
85
89
|
end
|
86
90
|
end
|
data/lib/lrama/grammar/code.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "forwardable"
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
require_relative "code/destructor_code"
|
5
|
+
require_relative "code/initial_action_code"
|
6
|
+
require_relative "code/no_reference_code"
|
7
|
+
require_relative "code/printer_code"
|
8
|
+
require_relative "code/rule_action"
|
7
9
|
|
8
10
|
module Lrama
|
9
11
|
class Grammar
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Lrama
|
2
4
|
class Grammar
|
3
5
|
class ParameterizingRule
|
@@ -18,13 +20,17 @@ module Lrama
|
|
18
20
|
end
|
19
21
|
|
20
22
|
def find_inline(token)
|
21
|
-
@rules.
|
23
|
+
@rules.reverse.find { |rule| rule.name == token.s_value && rule.is_inline }
|
22
24
|
end
|
23
25
|
|
24
26
|
def created_lhs(lhs_s_value)
|
25
27
|
@created_lhs_list.reverse.find { |created_lhs| created_lhs.s_value == lhs_s_value }
|
26
28
|
end
|
27
29
|
|
30
|
+
def redefined_rules
|
31
|
+
@rules.select { |rule| @rules.count { |r| r.name == rule.name && r.required_parameters_count == rule.required_parameters_count } > 1 }
|
32
|
+
end
|
33
|
+
|
28
34
|
private
|
29
35
|
|
30
36
|
def select_rules(rules, token)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Lrama
|
2
4
|
class Grammar
|
3
5
|
class ParameterizingRule
|
@@ -13,7 +15,8 @@ module Lrama
|
|
13
15
|
def resolve_user_code(bindings)
|
14
16
|
return unless user_code
|
15
17
|
|
16
|
-
|
18
|
+
resolved = Lexer::Token::UserCode.new(s_value: user_code.s_value, location: user_code.location)
|
19
|
+
var_to_arg = {} #: Hash[String, String]
|
17
20
|
symbols.each do |sym|
|
18
21
|
resolved_sym = bindings.resolve_symbol(sym)
|
19
22
|
if resolved_sym != sym
|
@@ -22,14 +25,14 @@ module Lrama
|
|
22
25
|
end
|
23
26
|
|
24
27
|
var_to_arg.each do |var, arg|
|
25
|
-
|
28
|
+
resolved.references.each do |ref|
|
26
29
|
if ref.name == var
|
27
30
|
ref.name = arg
|
28
31
|
end
|
29
32
|
end
|
30
33
|
end
|
31
34
|
|
32
|
-
return
|
35
|
+
return resolved
|
33
36
|
end
|
34
37
|
end
|
35
38
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Lrama
|
2
4
|
class Grammar
|
3
5
|
class ParameterizingRule
|
@@ -12,6 +14,10 @@ module Lrama
|
|
12
14
|
@is_inline = is_inline
|
13
15
|
@required_parameters_count = parameters.count
|
14
16
|
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
"#{@name}(#{@parameters.map(&:s_value).join(', ')})"
|
20
|
+
end
|
15
21
|
end
|
16
22
|
end
|
17
23
|
end
|
data/lib/lrama/grammar/rule.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Lrama
|
2
4
|
class Grammar
|
3
5
|
# _rhs holds original RHS element. Use rhs to refer to Symbol.
|
@@ -16,8 +18,7 @@ module Lrama
|
|
16
18
|
self.lineno == other.lineno
|
17
19
|
end
|
18
20
|
|
19
|
-
|
20
|
-
def to_s
|
21
|
+
def display_name
|
21
22
|
l = lhs.id.s_value
|
22
23
|
r = empty_rule? ? "ε" : rhs.map {|r| r.id.s_value }.join(" ")
|
23
24
|
|
@@ -33,7 +34,7 @@ module Lrama
|
|
33
34
|
end
|
34
35
|
|
35
36
|
def with_actions
|
36
|
-
"#{
|
37
|
+
"#{display_name} {#{token_code&.s_value}}"
|
37
38
|
end
|
38
39
|
|
39
40
|
# opt_nl: ε <-- empty_rule
|
@@ -55,6 +56,12 @@ module Lrama
|
|
55
56
|
|
56
57
|
Code::RuleAction.new(type: :rule_action, token_code: token_code, rule: self).translated_code
|
57
58
|
end
|
59
|
+
|
60
|
+
def contains_at_reference?
|
61
|
+
return false unless token_code
|
62
|
+
|
63
|
+
token_code.references.any? {|r| r.type == :at }
|
64
|
+
end
|
58
65
|
end
|
59
66
|
end
|
60
67
|
end
|