lrama 0.6.4 → 0.6.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ce98751a4b4d20c20addf8eebf2a4eb22150b401abbb994941d73f2b2ef81a09
4
- data.tar.gz: 94b83050b10ec5d01d61093cd2af595e52b3761cc8e86423fa8f30110e44e330
3
+ metadata.gz: 5a24c7fd3c35d08a7e602fe74d4be9987f0415a1dc621ceb02ec4a722b1e16a0
4
+ data.tar.gz: fa3e0819afd1a454c17189c05f4c02260e35a252b09fdc828238f01b7ad3c58e
5
5
  SHA512:
6
- metadata.gz: e9e194703ec0b1657389f289b7c4d9cfd13326b1efe25e656080e5260ef2b7f3d4e93fd3d5d49e0934cfb394bc46b994c167a74c3dd2fb2ed3f3ebaaaf31647d
7
- data.tar.gz: 59e1ed986bbea4ea4a56295d799f6ef5afee24e128fec66bc7ea8184f9bd849aa0807b5995b201e3dda274f6f0f023899a8c287e9a25818dae75c05e5c45cf6a
6
+ metadata.gz: 7a5268674e4e8630a8efad69e82af94202f66da34530fdb87b7bd8d0e4cee93cf3881e1509d441fade31d1886f39e48b43c9f25178511983002a30fe19047266
7
+ data.tar.gz: 54122863a527a29a6279b9ad4c2732a378a138743d5d91e9c611ba9d66c7929f14385ee228b1dde7e20f2a4efc60fe1d9d5046fcb753c828daf64e4d9d465350
data/NEWS.md CHANGED
@@ -1,5 +1,45 @@
1
1
  # NEWS for Lrama
2
2
 
3
+ ## Lrama 0.6.5 (2024-03-25)
4
+
5
+ ### Typed Midrule Actions
6
+
7
+ User can specify the type of mid rule action by tag (`<bar>`) instead of specifying it with in an action.
8
+
9
+ ```
10
+ primary: k_case expr_value terms?
11
+ {
12
+ $<val>$ = p->case_labels;
13
+ p->case_labels = Qnil;
14
+ }
15
+ case_body
16
+ k_end
17
+ {
18
+ ...
19
+ }
20
+ ```
21
+
22
+ can be written as
23
+
24
+ ```
25
+ primary: k_case expr_value terms?
26
+ {
27
+ $$ = p->case_labels;
28
+ p->case_labels = Qnil;
29
+ }<val>
30
+ case_body
31
+ k_end
32
+ {
33
+ ...
34
+ }
35
+ ```
36
+
37
+ `%destructor` for midrule action is invoked only when tag is specified by Typed Midrule Actions.
38
+
39
+ Difference from Bison's Typed Midrule Actions is that tag is postposed in Lrama however it's preposed in Bison.
40
+
41
+ Bison supports this feature from 3.1.
42
+
3
43
  ## Lrama 0.6.4 (2024-03-22)
4
44
 
5
45
  ### Parameterizing rules (preceded, terminated, delimited)
data/lib/lrama/command.rb CHANGED
@@ -47,6 +47,11 @@ module Lrama
47
47
  puts grammar.rules
48
48
  end
49
49
 
50
+ if options.trace_opts && options.trace_opts[:actions]
51
+ puts "Grammar rules with actions:"
52
+ grammar.rules.each { |rule| puts rule.with_actions }
53
+ end
54
+
50
55
  File.open(options.outfile, "w+") do |f|
51
56
  Lrama::Output.new(
52
57
  out: f,
@@ -13,8 +13,12 @@ module Lrama
13
13
  @rules << rule
14
14
  end
15
15
 
16
- def find(token)
17
- select_rules(token).last
16
+ def find_rule(token)
17
+ select_rules(@rules, token).last
18
+ end
19
+
20
+ def find_inline(token)
21
+ @rules.select { |rule| rule.name == token.s_value && rule.is_inline }.last
18
22
  end
19
23
 
20
24
  def created_lhs(lhs_s_value)
@@ -23,8 +27,9 @@ module Lrama
23
27
 
24
28
  private
25
29
 
26
- def select_rules(token)
27
- rules = select_rules_by_name(token.rule_name)
30
+ def select_rules(rules, token)
31
+ rules = select_not_inline_rules(rules)
32
+ rules = select_rules_by_name(rules, token.rule_name)
28
33
  rules = rules.select { |rule| rule.required_parameters_count == token.args_count }
29
34
  if rules.empty?
30
35
  raise "Invalid number of arguments. `#{token.rule_name}`"
@@ -33,8 +38,12 @@ module Lrama
33
38
  end
34
39
  end
35
40
 
36
- def select_rules_by_name(rule_name)
37
- rules = @rules.select { |rule| rule.name == rule_name }
41
+ def select_not_inline_rules(rules)
42
+ rules.select { |rule| !rule.is_inline }
43
+ end
44
+
45
+ def select_rules_by_name(rules, rule_name)
46
+ rules = rules.select { |rule| rule.name == rule_name }
38
47
  if rules.empty?
39
48
  raise "Parameterizing rule does not exist. `#{rule_name}`"
40
49
  else
@@ -2,12 +2,13 @@ module Lrama
2
2
  class Grammar
3
3
  class ParameterizingRule
4
4
  class Rule
5
- attr_reader :name, :parameters, :rhs_list, :required_parameters_count
5
+ attr_reader :name, :parameters, :rhs_list, :required_parameters_count, :is_inline
6
6
 
7
- def initialize(name, parameters, rhs_list)
7
+ def initialize(name, parameters, rhs_list, is_inline: false)
8
8
  @name = name
9
9
  @parameters = parameters
10
10
  @rhs_list = rhs_list
11
+ @is_inline = is_inline
11
12
  @required_parameters_count = parameters.count
12
13
  end
13
14
  end
@@ -19,7 +19,7 @@ module Lrama
19
19
  # TODO: Change this to display_name
20
20
  def to_s
21
21
  l = lhs.id.s_value
22
- r = empty_rule? ? "ε" : rhs.map {|r| r.id.s_value }.join(", ")
22
+ r = empty_rule? ? "ε" : rhs.map {|r| r.id.s_value }.join(" ")
23
23
 
24
24
  "#{l} -> #{r}"
25
25
  end
@@ -32,6 +32,10 @@ module Lrama
32
32
  "#{l}: #{r}"
33
33
  end
34
34
 
35
+ def with_actions
36
+ "#{to_s} {#{token_code&.s_value}}"
37
+ end
38
+
35
39
  # opt_nl: ε <-- empty_rule
36
40
  # | '\n' <-- not empty_rule
37
41
  def empty_rule?
@@ -16,8 +16,13 @@ module Lrama
16
16
  @user_code = nil
17
17
  @precedence_sym = nil
18
18
  @line = nil
19
+ @rules = []
19
20
  @rule_builders_for_parameterizing_rules = []
20
21
  @rule_builders_for_derived_rules = []
22
+ @rule_builders_for_inline_rules = []
23
+ @parameterizing_rules = []
24
+ @inline_rules = []
25
+ @midrule_action_rules = []
21
26
  end
22
27
 
23
28
  def add_rhs(rhs)
@@ -52,12 +57,16 @@ module Lrama
52
57
 
53
58
  def setup_rules(parameterizing_rule_resolver)
54
59
  preprocess_references unless @skip_preprocess_references
55
- process_rhs(parameterizing_rule_resolver)
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
56
65
  build_rules
57
66
  end
58
67
 
59
68
  def rules
60
- @parameterizing_rules + @midrule_action_rules + @rules
69
+ @parameterizing_rules + @inline_rules + @midrule_action_rules + @rules
61
70
  end
62
71
 
63
72
  private
@@ -73,19 +82,25 @@ module Lrama
73
82
  def build_rules
74
83
  tokens = @replaced_rhs
75
84
 
76
- rule = Rule.new(
77
- id: @rule_counter.increment, _lhs: lhs, _rhs: tokens, lhs_tag: lhs_tag, token_code: user_code,
78
- position_in_original_rule_rhs: @position_in_original_rule_rhs, precedence_sym: precedence_sym, lineno: line
79
- )
80
- @rules = [rule]
81
- @parameterizing_rules = @rule_builders_for_parameterizing_rules.map do |rule_builder|
82
- rule_builder.rules
83
- end.flatten
84
- @midrule_action_rules = @rule_builders_for_derived_rules.map do |rule_builder|
85
- rule_builder.rules
86
- end.flatten
87
- @midrule_action_rules.each do |r|
88
- r.original_rule = rule
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
89
104
  end
90
105
  end
91
106
 
@@ -103,7 +118,7 @@ module Lrama
103
118
  when Lrama::Lexer::Token::Ident
104
119
  @replaced_rhs << token
105
120
  when Lrama::Lexer::Token::InstantiateRule
106
- parameterizing_rule = parameterizing_rule_resolver.find(token)
121
+ parameterizing_rule = parameterizing_rule_resolver.find_rule(token)
107
122
  raise "Unexpected token. #{token}" unless parameterizing_rule
108
123
 
109
124
  bindings = Binding.new(parameterizing_rule, token.args)
@@ -115,7 +130,7 @@ module Lrama
115
130
  @replaced_rhs << lhs_token
116
131
  parameterizing_rule_resolver.created_lhs_list << lhs_token
117
132
  parameterizing_rule.rhs_list.each do |r|
118
- rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, lhs_tag: token.lhs_tag, skip_preprocess_references: true)
133
+ rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, lhs_tag: token.lhs_tag)
119
134
  rule_builder.lhs = lhs_token
120
135
  r.symbols.each { |sym| rule_builder.add_rhs(bindings.resolve_symbol(sym)) }
121
136
  rule_builder.line = line
@@ -128,10 +143,11 @@ module Lrama
128
143
  end
129
144
  when Lrama::Lexer::Token::UserCode
130
145
  prefix = token.referred ? "@" : "$@"
146
+ tag = token.tag || lhs_tag
131
147
  new_token = Lrama::Lexer::Token::Ident.new(s_value: prefix + @midrule_action_counter.increment.to_s)
132
148
  @replaced_rhs << new_token
133
149
 
134
- rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, i, lhs_tag: lhs_tag, skip_preprocess_references: true)
150
+ rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, i, lhs_tag: tag, skip_preprocess_references: true)
135
151
  rule_builder.lhs = new_token
136
152
  rule_builder.user_code = token
137
153
  rule_builder.complete_input
@@ -156,6 +172,41 @@ module Lrama
156
172
  "#{token.rule_name}_#{s_values.join('_')}"
157
173
  end
158
174
 
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)
193
+ rhs.each_with_index do |token, i|
194
+ if index == i
195
+ inline_rhs.symbols.each { |sym| rule_builder.add_rhs(sym) }
196
+ else
197
+ rule_builder.add_rhs(token)
198
+ end
199
+ end
200
+ end
201
+
202
+ def replace_inline_user_code(inline_rhs, index)
203
+ return user_code if inline_rhs.user_code.nil?
204
+ return user_code if user_code.nil?
205
+
206
+ code = user_code.s_value.gsub(/\$#{index + 1}/, inline_rhs.user_code.s_value)
207
+ Lrama::Lexer::Token::UserCode.new(s_value: code, location: user_code.location)
208
+ end
209
+
159
210
  def numberize_references
160
211
  # Bison n'th component is 1-origin
161
212
  (rhs + [user_code]).compact.each.with_index(1) do |token, i|
@@ -1,11 +1,21 @@
1
1
  module Lrama
2
2
  class Lexer
3
3
  class GrammarFile
4
+ class Text < String
5
+ def inspect
6
+ length <= 50 ? super : "#{self[0..47]}...".inspect
7
+ end
8
+ end
9
+
4
10
  attr_reader :path, :text
5
11
 
6
12
  def initialize(path, text)
7
13
  @path = path
8
- @text = text.freeze
14
+ @text = Text.new(text).freeze
15
+ end
16
+
17
+ def inspect
18
+ "<#{self.class}: @path=#{path}, @text=#{text.inspect}>"
9
19
  end
10
20
 
11
21
  def ==(other)
@@ -4,6 +4,8 @@ module Lrama
4
4
  class Lexer
5
5
  class Token
6
6
  class UserCode < Token
7
+ attr_accessor :tag
8
+
7
9
  def references
8
10
  @references ||= _references
9
11
  end
data/lib/lrama/lexer.rb CHANGED
@@ -37,6 +37,7 @@ module Lrama
37
37
  %code
38
38
  %rule
39
39
  %no-stdlib
40
+ %inline
40
41
  )
41
42
 
42
43
  def initialize(grammar_file)
@@ -119,8 +119,9 @@ module Lrama
119
119
 
120
120
  VALID_TRACES = %w[
121
121
  none locations scan parse automaton bitsets
122
- closure grammar rules resource sets muscles tools
123
- m4-early m4 skeleton time ielr cex all
122
+ closure grammar rules actions resource
123
+ sets muscles tools m4-early m4 skeleton time
124
+ ielr cex all
124
125
  ]
125
126
 
126
127
  def validate_trace(trace)