lrama 0.6.4 → 0.6.6

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