lrama 0.6.9 → 0.6.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yaml +19 -0
  3. data/.gitignore +2 -0
  4. data/Gemfile +6 -3
  5. data/NEWS.md +220 -0
  6. data/README.md +41 -4
  7. data/Rakefile +2 -0
  8. data/Steepfile +6 -17
  9. data/exe/lrama +1 -0
  10. data/lib/lrama/bitmap.rb +2 -0
  11. data/lib/lrama/command.rb +8 -14
  12. data/lib/lrama/context.rb +8 -6
  13. data/lib/lrama/counterexamples/derivation.rb +2 -0
  14. data/lib/lrama/counterexamples/example.rb +2 -0
  15. data/lib/lrama/counterexamples/path.rb +2 -0
  16. data/lib/lrama/counterexamples/production_path.rb +2 -0
  17. data/lib/lrama/counterexamples/start_path.rb +2 -0
  18. data/lib/lrama/counterexamples/state_item.rb +2 -0
  19. data/lib/lrama/counterexamples/transition_path.rb +2 -0
  20. data/lib/lrama/counterexamples/triple.rb +2 -0
  21. data/lib/lrama/counterexamples.rb +17 -15
  22. data/lib/lrama/diagnostics.rb +36 -0
  23. data/lib/lrama/digraph.rb +2 -0
  24. data/lib/lrama/grammar/auxiliary.rb +2 -0
  25. data/lib/lrama/grammar/binding.rb +12 -1
  26. data/lib/lrama/grammar/code/destructor_code.rb +2 -0
  27. data/lib/lrama/grammar/code/initial_action_code.rb +2 -0
  28. data/lib/lrama/grammar/code/no_reference_code.rb +2 -0
  29. data/lib/lrama/grammar/code/printer_code.rb +2 -0
  30. data/lib/lrama/grammar/code/rule_action.rb +7 -3
  31. data/lib/lrama/grammar/code.rb +7 -5
  32. data/lib/lrama/grammar/counter.rb +2 -0
  33. data/lib/lrama/grammar/destructor.rb +2 -0
  34. data/lib/lrama/grammar/error_token.rb +2 -0
  35. data/lib/lrama/grammar/parameterizing_rule/resolver.rb +7 -1
  36. data/lib/lrama/grammar/parameterizing_rule/rhs.rb +5 -2
  37. data/lib/lrama/grammar/parameterizing_rule/rule.rb +6 -0
  38. data/lib/lrama/grammar/parameterizing_rule.rb +2 -0
  39. data/lib/lrama/grammar/percent_code.rb +2 -0
  40. data/lib/lrama/grammar/precedence.rb +2 -0
  41. data/lib/lrama/grammar/printer.rb +2 -0
  42. data/lib/lrama/grammar/reference.rb +2 -0
  43. data/lib/lrama/grammar/rule.rb +10 -3
  44. data/lib/lrama/grammar/rule_builder.rb +64 -65
  45. data/lib/lrama/grammar/symbol.rb +2 -0
  46. data/lib/lrama/grammar/symbols/resolver.rb +5 -1
  47. data/lib/lrama/grammar/symbols.rb +2 -0
  48. data/lib/lrama/grammar/type.rb +2 -0
  49. data/lib/lrama/grammar/union.rb +2 -0
  50. data/lib/lrama/grammar.rb +51 -30
  51. data/lib/lrama/grammar_validator.rb +37 -0
  52. data/lib/lrama/lexer/grammar_file.rb +2 -0
  53. data/lib/lrama/lexer/location.rb +2 -0
  54. data/lib/lrama/lexer/token/char.rb +2 -0
  55. data/lib/lrama/lexer/token/ident.rb +2 -0
  56. data/lib/lrama/lexer/token/instantiate_rule.rb +2 -0
  57. data/lib/lrama/lexer/token/tag.rb +2 -0
  58. data/lib/lrama/lexer/token/user_code.rb +3 -1
  59. data/lib/lrama/lexer/token.rb +7 -5
  60. data/lib/lrama/lexer.rb +11 -8
  61. data/lib/lrama/{warning.rb → logger.rb} +5 -13
  62. data/lib/lrama/option_parser.rb +58 -33
  63. data/lib/lrama/options.rb +5 -2
  64. data/lib/lrama/output.rb +38 -69
  65. data/lib/lrama/parser.rb +650 -779
  66. data/lib/lrama/report/duration.rb +2 -0
  67. data/lib/lrama/report/profile.rb +2 -0
  68. data/lib/lrama/report.rb +4 -2
  69. data/lib/lrama/state/reduce.rb +3 -0
  70. data/lib/lrama/state/reduce_reduce_conflict.rb +2 -0
  71. data/lib/lrama/state/resolved_conflict.rb +3 -1
  72. data/lib/lrama/state/shift.rb +2 -0
  73. data/lib/lrama/state/shift_reduce_conflict.rb +2 -0
  74. data/lib/lrama/state.rb +7 -5
  75. data/lib/lrama/states/item.rb +5 -3
  76. data/lib/lrama/states.rb +18 -46
  77. data/lib/lrama/states_reporter.rb +60 -19
  78. data/lib/lrama/trace_reporter.rb +30 -0
  79. data/lib/lrama/version.rb +3 -1
  80. data/lib/lrama.rb +22 -17
  81. data/lrama.gemspec +3 -1
  82. data/parser.y +110 -229
  83. data/sig/lrama/grammar/auxiliary.rbs +10 -0
  84. data/sig/lrama/grammar/binding.rbs +4 -0
  85. data/sig/lrama/grammar/code/destructor_code.rbs +3 -4
  86. data/sig/lrama/grammar/code/initial_action_code.rbs +15 -0
  87. data/sig/lrama/grammar/code/no_reference_code.rbs +15 -0
  88. data/sig/lrama/grammar/code/printer_code.rbs +3 -4
  89. data/sig/lrama/grammar/code/rule_action.rbs +19 -0
  90. data/sig/lrama/grammar/code.rbs +3 -3
  91. data/sig/lrama/grammar/destructor.rbs +3 -1
  92. data/sig/lrama/grammar/error_token.rbs +4 -2
  93. data/sig/lrama/grammar/parameterizing_rule/resolver.rbs +2 -1
  94. data/sig/lrama/grammar/parameterizing_rule/rhs.rbs +1 -1
  95. data/sig/lrama/grammar/precedence.rbs +3 -1
  96. data/sig/lrama/grammar/printer.rbs +3 -1
  97. data/sig/lrama/grammar/rule.rbs +35 -3
  98. data/sig/lrama/grammar/rule_builder.rbs +10 -9
  99. data/sig/lrama/grammar/symbol.rbs +6 -6
  100. data/sig/lrama/grammar/symbols/resolver.rbs +22 -3
  101. data/sig/lrama/grammar/type.rbs +2 -2
  102. data/sig/lrama/grammar/union.rbs +12 -0
  103. data/sig/lrama/grammar.rbs +91 -1
  104. data/sig/lrama/options.rbs +3 -2
  105. data/sig/lrama/state/reduce.rbs +20 -0
  106. data/sig/lrama/state/reduce_reduce_conflict.rbs +13 -0
  107. data/sig/lrama/state/resolved_conflict.rbs +14 -0
  108. data/sig/lrama/state/shift.rbs +14 -0
  109. data/sig/lrama/state/shift_reduce_conflict.rbs +13 -0
  110. data/sig/lrama/states/item.rbs +30 -0
  111. data/template/bison/yacc.c +24 -19
  112. metadata +17 -6
  113. data/sample/calc.output +0 -263
  114. data/sample/calc.y +0 -101
  115. 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
  # Grammar file information not used by States but by Output
@@ -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
- @parameter_to_arg[symbol.s_value] || symbol
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lrama
2
4
  class Grammar
3
5
  class Code
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lrama
2
4
  class Grammar
3
5
  class Code
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lrama
2
4
  class Grammar
3
5
  class Code
@@ -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 a RHS of the original rule.
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 a LHS of the rule.
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
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "forwardable"
2
- require "lrama/grammar/code/destructor_code"
3
- require "lrama/grammar/code/initial_action_code"
4
- require "lrama/grammar/code/no_reference_code"
5
- require "lrama/grammar/code/printer_code"
6
- require "lrama/grammar/code/rule_action"
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 Counter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lrama
2
4
  class Grammar
3
5
  class Destructor < Struct.new(:ident_or_tags, :token_code, :lineno, keyword_init: true)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lrama
2
4
  class Grammar
3
5
  class ErrorToken < Struct.new(:ident_or_tags, :token_code, :lineno, keyword_init: true)
@@ -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.select { |rule| rule.name == token.s_value && rule.is_inline }.last
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,6 +15,7 @@ module Lrama
13
15
  def resolve_user_code(bindings)
14
16
  return unless user_code
15
17
 
18
+ resolved = Lexer::Token::UserCode.new(s_value: user_code.s_value, location: user_code.location)
16
19
  var_to_arg = {}
17
20
  symbols.each do |sym|
18
21
  resolved_sym = bindings.resolve_symbol(sym)
@@ -22,14 +25,14 @@ module Lrama
22
25
  end
23
26
 
24
27
  var_to_arg.each do |var, arg|
25
- user_code.references.each do |ref|
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 user_code
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'parameterizing_rule/resolver'
2
4
  require_relative 'parameterizing_rule/rhs'
3
5
  require_relative 'parameterizing_rule/rule'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lrama
2
4
  class Grammar
3
5
  class PercentCode
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lrama
2
4
  class Grammar
3
5
  class Precedence < Struct.new(:type, :precedence, keyword_init: true)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lrama
2
4
  class Grammar
3
5
  class Printer < Struct.new(:ident_or_tags, :token_code, :lineno, keyword_init: true)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lrama
2
4
  class Grammar
3
5
  # type: :dollar or :at
@@ -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
- # TODO: Change this to display_name
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
- "#{to_s} {#{token_code&.s_value}}"
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
- if !@line
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
- if !@line
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(parameterizing_rule_resolver)
55
+ def setup_rules
59
56
  preprocess_references unless @skip_preprocess_references
60
- if rhs.any? { |token| parameterizing_rule_resolver.find_inline(token) }
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 + @inline_rules + @midrule_action_rules + @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
- if tokens
86
- rule = Rule.new(
87
- id: @rule_counter.increment, _lhs: lhs, _rhs: tokens, lhs_tag: lhs_tag, token_code: user_code,
88
- position_in_original_rule_rhs: @position_in_original_rule_rhs, precedence_sym: precedence_sym, lineno: line
89
- )
90
- @rules = [rule]
91
- @parameterizing_rules = @rule_builders_for_parameterizing_rules.map do |rule_builder|
92
- rule_builder.rules
93
- end.flatten
94
- @midrule_action_rules = @rule_builders_for_derived_rules.map do |rule_builder|
95
- rule_builder.rules
96
- end.flatten
97
- @midrule_action_rules.each do |r|
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(parameterizing_rule_resolver)
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 || parameterizing_rule.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
152
  rule_builder.user_code = r.resolve_user_code(bindings)
139
153
  rule_builder.complete_input
140
- rule_builder.setup_rules(parameterizing_rule_resolver)
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(parameterizing_rule_resolver)
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 resolve_inline(parameterizing_rule_resolver)
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
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Symbol is both of nterm and term
2
4
  # `number` is both for nterm and term
3
5
  # `token_id` is tokentype for term, internal sequence number for nterm
@@ -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
- return if find_symbol_by_id(id)
47
+ if (sym = find_symbol_by_id(id))
48
+ return sym
49
+ end
46
50
 
47
51
  @symbols = nil
48
52
  nterm = Symbol.new(
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "symbols/resolver"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lrama
2
4
  class Grammar
3
5
  class Type
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lrama
2
4
  class Grammar
3
5
  class Union < Struct.new(:code, :lineno, keyword_init: true)