lrama 0.6.9 → 0.6.10

Sign up to get free protection for your applications and to get access to all the features.
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)