lrama 0.6.8 → 0.6.10
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 +19 -0
- data/.gitignore +2 -0
- data/Gemfile +6 -3
- data/NEWS.md +220 -0
- data/README.md +41 -4
- data/Rakefile +2 -0
- data/Steepfile +6 -17
- data/exe/lrama +1 -0
- data/lib/lrama/bitmap.rb +2 -0
- data/lib/lrama/command.rb +8 -14
- data/lib/lrama/context.rb +8 -6
- data/lib/lrama/counterexamples/derivation.rb +2 -0
- data/lib/lrama/counterexamples/example.rb +2 -0
- data/lib/lrama/counterexamples/path.rb +2 -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 +17 -15
- 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 +25 -0
- data/lib/lrama/grammar/parameterizing_rule/rule.rb +9 -2
- 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 +65 -66
- data/lib/lrama/grammar/symbol.rb +2 -0
- data/lib/lrama/grammar/symbols/resolver.rb +5 -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 +51 -30
- 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 +3 -1
- data/lib/lrama/lexer/token.rb +7 -5
- data/lib/lrama/lexer.rb +11 -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 +650 -779
- 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 +3 -0
- 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 +111 -230
- 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 +2 -1
- data/sig/lrama/grammar/parameterizing_rule/rule.rbs +2 -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 +22 -3
- data/sig/lrama/grammar/type.rbs +2 -2
- data/sig/lrama/grammar/union.rbs +12 -0
- data/sig/lrama/grammar.rbs +91 -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/states/item.rbs +30 -0
- data/template/bison/yacc.c +24 -19
- metadata +17 -6
- data/sample/calc.output +0 -263
- data/sample/calc.y +0 -101
- data/sample/parse.y +0 -59
@@ -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
|
@@ -9,6 +11,29 @@ module Lrama
|
|
9
11
|
@user_code = nil
|
10
12
|
@precedence_sym = nil
|
11
13
|
end
|
14
|
+
|
15
|
+
def resolve_user_code(bindings)
|
16
|
+
return unless user_code
|
17
|
+
|
18
|
+
resolved = Lexer::Token::UserCode.new(s_value: user_code.s_value, location: user_code.location)
|
19
|
+
var_to_arg = {}
|
20
|
+
symbols.each do |sym|
|
21
|
+
resolved_sym = bindings.resolve_symbol(sym)
|
22
|
+
if resolved_sym != sym
|
23
|
+
var_to_arg[sym.s_value] = resolved_sym.s_value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
var_to_arg.each do |var, arg|
|
28
|
+
resolved.references.each do |ref|
|
29
|
+
if ref.name == var
|
30
|
+
ref.name = arg
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
return resolved
|
36
|
+
end
|
12
37
|
end
|
13
38
|
end
|
14
39
|
end
|
@@ -1,16 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Lrama
|
2
4
|
class Grammar
|
3
5
|
class ParameterizingRule
|
4
6
|
class Rule
|
5
|
-
attr_reader :name, :parameters, :rhs_list, :required_parameters_count, :is_inline
|
7
|
+
attr_reader :name, :parameters, :rhs_list, :required_parameters_count, :tag, :is_inline
|
6
8
|
|
7
|
-
def initialize(name, parameters, rhs_list, is_inline: false)
|
9
|
+
def initialize(name, parameters, rhs_list, tag: nil, is_inline: false)
|
8
10
|
@name = name
|
9
11
|
@parameters = parameters
|
10
12
|
@rhs_list = rhs_list
|
13
|
+
@tag = tag
|
11
14
|
@is_inline = is_inline
|
12
15
|
@required_parameters_count = parameters.count
|
13
16
|
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
"#{@name}(#{@parameters.map(&:s_value).join(', ')})"
|
20
|
+
end
|
14
21
|
end
|
15
22
|
end
|
16
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
|
@@ -1,12 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Lrama
|
2
4
|
class Grammar
|
3
5
|
class RuleBuilder
|
4
6
|
attr_accessor :lhs, :line
|
5
7
|
attr_reader :lhs_tag, :rhs, :user_code, :precedence_sym
|
6
8
|
|
7
|
-
def initialize(rule_counter, midrule_action_counter, position_in_original_rule_rhs = nil, lhs_tag: nil, skip_preprocess_references: false)
|
9
|
+
def initialize(rule_counter, midrule_action_counter, parameterizing_rule_resolver, position_in_original_rule_rhs = nil, lhs_tag: nil, skip_preprocess_references: false)
|
8
10
|
@rule_counter = rule_counter
|
9
11
|
@midrule_action_counter = midrule_action_counter
|
12
|
+
@parameterizing_rule_resolver = parameterizing_rule_resolver
|
10
13
|
@position_in_original_rule_rhs = position_in_original_rule_rhs
|
11
14
|
@skip_preprocess_references = skip_preprocess_references
|
12
15
|
|
@@ -19,16 +22,12 @@ module Lrama
|
|
19
22
|
@rules = []
|
20
23
|
@rule_builders_for_parameterizing_rules = []
|
21
24
|
@rule_builders_for_derived_rules = []
|
22
|
-
@rule_builders_for_inline_rules = []
|
23
25
|
@parameterizing_rules = []
|
24
|
-
@inline_rules = []
|
25
26
|
@midrule_action_rules = []
|
26
27
|
end
|
27
28
|
|
28
29
|
def add_rhs(rhs)
|
29
|
-
|
30
|
-
@line = rhs.line
|
31
|
-
end
|
30
|
+
@line ||= rhs.line
|
32
31
|
|
33
32
|
flush_user_code
|
34
33
|
|
@@ -36,9 +35,7 @@ module Lrama
|
|
36
35
|
end
|
37
36
|
|
38
37
|
def user_code=(user_code)
|
39
|
-
|
40
|
-
@line = user_code&.line
|
41
|
-
end
|
38
|
+
@line ||= user_code&.line
|
42
39
|
|
43
40
|
flush_user_code
|
44
41
|
|
@@ -55,18 +52,41 @@ module Lrama
|
|
55
52
|
freeze_rhs
|
56
53
|
end
|
57
54
|
|
58
|
-
def setup_rules
|
55
|
+
def setup_rules
|
59
56
|
preprocess_references unless @skip_preprocess_references
|
60
|
-
|
61
|
-
resolve_inline(parameterizing_rule_resolver)
|
62
|
-
else
|
63
|
-
process_rhs(parameterizing_rule_resolver)
|
64
|
-
end
|
57
|
+
process_rhs
|
65
58
|
build_rules
|
66
59
|
end
|
67
60
|
|
68
61
|
def rules
|
69
|
-
@parameterizing_rules + @
|
62
|
+
@parameterizing_rules + @midrule_action_rules + @rules
|
63
|
+
end
|
64
|
+
|
65
|
+
def has_inline_rules?
|
66
|
+
rhs.any? { |token| @parameterizing_rule_resolver.find_inline(token) }
|
67
|
+
end
|
68
|
+
|
69
|
+
def resolve_inline_rules
|
70
|
+
resolved_builders = []
|
71
|
+
rhs.each_with_index do |token, i|
|
72
|
+
if (inline_rule = @parameterizing_rule_resolver.find_inline(token))
|
73
|
+
inline_rule.rhs_list.each do |inline_rhs|
|
74
|
+
rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, @parameterizing_rule_resolver, lhs_tag: lhs_tag)
|
75
|
+
if token.is_a?(Lexer::Token::InstantiateRule)
|
76
|
+
resolve_inline_rhs(rule_builder, inline_rhs, i, Binding.new(inline_rule, token.args))
|
77
|
+
else
|
78
|
+
resolve_inline_rhs(rule_builder, inline_rhs, i)
|
79
|
+
end
|
80
|
+
rule_builder.lhs = lhs
|
81
|
+
rule_builder.line = line
|
82
|
+
rule_builder.precedence_sym = precedence_sym
|
83
|
+
rule_builder.user_code = replace_inline_user_code(inline_rhs, i)
|
84
|
+
resolved_builders << rule_builder
|
85
|
+
end
|
86
|
+
break
|
87
|
+
end
|
88
|
+
end
|
89
|
+
resolved_builders
|
70
90
|
end
|
71
91
|
|
72
92
|
private
|
@@ -82,31 +102,25 @@ module Lrama
|
|
82
102
|
def build_rules
|
83
103
|
tokens = @replaced_rhs
|
84
104
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
r.original_rule = rule
|
99
|
-
end
|
100
|
-
else
|
101
|
-
@inline_rules = @rule_builders_for_inline_rules.map do |rule_builder|
|
102
|
-
rule_builder.rules
|
103
|
-
end.flatten
|
105
|
+
rule = Rule.new(
|
106
|
+
id: @rule_counter.increment, _lhs: lhs, _rhs: tokens, lhs_tag: lhs_tag, token_code: user_code,
|
107
|
+
position_in_original_rule_rhs: @position_in_original_rule_rhs, precedence_sym: precedence_sym, lineno: line
|
108
|
+
)
|
109
|
+
@rules = [rule]
|
110
|
+
@parameterizing_rules = @rule_builders_for_parameterizing_rules.map do |rule_builder|
|
111
|
+
rule_builder.rules
|
112
|
+
end.flatten
|
113
|
+
@midrule_action_rules = @rule_builders_for_derived_rules.map do |rule_builder|
|
114
|
+
rule_builder.rules
|
115
|
+
end.flatten
|
116
|
+
@midrule_action_rules.each do |r|
|
117
|
+
r.original_rule = rule
|
104
118
|
end
|
105
119
|
end
|
106
120
|
|
107
121
|
# rhs is a mixture of variety type of tokens like `Ident`, `InstantiateRule`, `UserCode` and so on.
|
108
122
|
# `#process_rhs` replaces some kind of tokens to `Ident` so that all `@replaced_rhs` are `Ident` or `Char`.
|
109
|
-
def process_rhs
|
123
|
+
def process_rhs
|
110
124
|
return if @replaced_rhs
|
111
125
|
|
112
126
|
@replaced_rhs = []
|
@@ -118,26 +132,26 @@ module Lrama
|
|
118
132
|
when Lrama::Lexer::Token::Ident
|
119
133
|
@replaced_rhs << token
|
120
134
|
when Lrama::Lexer::Token::InstantiateRule
|
121
|
-
parameterizing_rule = parameterizing_rule_resolver.find_rule(token)
|
135
|
+
parameterizing_rule = @parameterizing_rule_resolver.find_rule(token)
|
122
136
|
raise "Unexpected token. #{token}" unless parameterizing_rule
|
123
137
|
|
124
138
|
bindings = Binding.new(parameterizing_rule, token.args)
|
125
139
|
lhs_s_value = lhs_s_value(token, bindings)
|
126
|
-
if (created_lhs = parameterizing_rule_resolver.created_lhs(lhs_s_value))
|
140
|
+
if (created_lhs = @parameterizing_rule_resolver.created_lhs(lhs_s_value))
|
127
141
|
@replaced_rhs << created_lhs
|
128
142
|
else
|
129
143
|
lhs_token = Lrama::Lexer::Token::Ident.new(s_value: lhs_s_value, location: token.location)
|
130
144
|
@replaced_rhs << lhs_token
|
131
|
-
parameterizing_rule_resolver.created_lhs_list << lhs_token
|
145
|
+
@parameterizing_rule_resolver.created_lhs_list << lhs_token
|
132
146
|
parameterizing_rule.rhs_list.each do |r|
|
133
|
-
rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, lhs_tag: token.lhs_tag)
|
147
|
+
rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, @parameterizing_rule_resolver, lhs_tag: token.lhs_tag || parameterizing_rule.tag)
|
134
148
|
rule_builder.lhs = lhs_token
|
135
149
|
r.symbols.each { |sym| rule_builder.add_rhs(bindings.resolve_symbol(sym)) }
|
136
150
|
rule_builder.line = line
|
137
151
|
rule_builder.precedence_sym = r.precedence_sym
|
138
|
-
rule_builder.user_code = r.
|
152
|
+
rule_builder.user_code = r.resolve_user_code(bindings)
|
139
153
|
rule_builder.complete_input
|
140
|
-
rule_builder.setup_rules
|
154
|
+
rule_builder.setup_rules
|
141
155
|
@rule_builders_for_parameterizing_rules << rule_builder
|
142
156
|
end
|
143
157
|
end
|
@@ -147,11 +161,11 @@ module Lrama
|
|
147
161
|
new_token = Lrama::Lexer::Token::Ident.new(s_value: prefix + @midrule_action_counter.increment.to_s)
|
148
162
|
@replaced_rhs << new_token
|
149
163
|
|
150
|
-
rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, i, lhs_tag: tag, skip_preprocess_references: true)
|
164
|
+
rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, @parameterizing_rule_resolver, i, lhs_tag: tag, skip_preprocess_references: true)
|
151
165
|
rule_builder.lhs = new_token
|
152
166
|
rule_builder.user_code = token
|
153
167
|
rule_builder.complete_input
|
154
|
-
rule_builder.setup_rules
|
168
|
+
rule_builder.setup_rules
|
155
169
|
|
156
170
|
@rule_builders_for_derived_rules << rule_builder
|
157
171
|
else
|
@@ -172,27 +186,10 @@ module Lrama
|
|
172
186
|
"#{token.rule_name}_#{s_values.join('_')}"
|
173
187
|
end
|
174
188
|
|
175
|
-
def
|
176
|
-
rhs.each_with_index do |token, i|
|
177
|
-
if inline_rule = parameterizing_rule_resolver.find_inline(token)
|
178
|
-
inline_rule.rhs_list.each_with_index do |inline_rhs|
|
179
|
-
rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, lhs_tag: lhs_tag, skip_preprocess_references: true)
|
180
|
-
resolve_inline_rhs(rule_builder, inline_rhs, i)
|
181
|
-
rule_builder.lhs = lhs
|
182
|
-
rule_builder.line = line
|
183
|
-
rule_builder.user_code = replace_inline_user_code(inline_rhs, i)
|
184
|
-
rule_builder.complete_input
|
185
|
-
rule_builder.setup_rules(parameterizing_rule_resolver)
|
186
|
-
@rule_builders_for_inline_rules << rule_builder
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
def resolve_inline_rhs(rule_builder, inline_rhs, index)
|
189
|
+
def resolve_inline_rhs(rule_builder, inline_rhs, index, bindings = nil)
|
193
190
|
rhs.each_with_index do |token, i|
|
194
191
|
if index == i
|
195
|
-
inline_rhs.symbols.each { |sym| rule_builder.add_rhs(sym) }
|
192
|
+
inline_rhs.symbols.each { |sym| rule_builder.add_rhs(bindings.nil? ? sym : bindings.resolve_symbol(sym)) }
|
196
193
|
else
|
197
194
|
rule_builder.add_rhs(token)
|
198
195
|
end
|
@@ -204,6 +201,11 @@ module Lrama
|
|
204
201
|
return user_code if user_code.nil?
|
205
202
|
|
206
203
|
code = user_code.s_value.gsub(/\$#{index + 1}/, inline_rhs.user_code.s_value)
|
204
|
+
user_code.references.each do |ref|
|
205
|
+
next if ref.index.nil? || ref.index <= index # nil is a case for `$$`
|
206
|
+
code = code.gsub(/\$#{ref.index}/, "$#{ref.index + (inline_rhs.symbols.count-1)}")
|
207
|
+
code = code.gsub(/@#{ref.index}/, "@#{ref.index + (inline_rhs.symbols.count-1)}")
|
208
|
+
end
|
207
209
|
Lrama::Lexer::Token::UserCode.new(s_value: code, location: user_code.location)
|
208
210
|
end
|
209
211
|
|
@@ -238,9 +240,6 @@ module Lrama
|
|
238
240
|
end
|
239
241
|
|
240
242
|
if ref.number
|
241
|
-
# TODO: When Inlining is implemented, for example, if `$1` is expanded to multiple RHS tokens,
|
242
|
-
# `$2` needs to access `$2 + n` to actually access it. So, after the Inlining implementation,
|
243
|
-
# it needs resolves from number to index.
|
244
243
|
ref.index = ref.number
|
245
244
|
end
|
246
245
|
|
data/lib/lrama/grammar/symbol.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Lrama
|
2
4
|
class Grammar
|
3
5
|
class Symbols
|
@@ -42,7 +44,9 @@ module Lrama
|
|
42
44
|
end
|
43
45
|
|
44
46
|
def add_nterm(id:, alias_name: nil, tag: nil)
|
45
|
-
|
47
|
+
if (sym = find_symbol_by_id(id))
|
48
|
+
return sym
|
49
|
+
end
|
46
50
|
|
47
51
|
@symbols = nil
|
48
52
|
nterm = Symbol.new(
|
data/lib/lrama/grammar/type.rb
CHANGED