lrama 0.6.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yaml +7 -2
  3. data/NEWS.md +9 -0
  4. data/lib/lrama/command.rb +10 -2
  5. data/lib/lrama/context.rb +2 -2
  6. data/lib/lrama/counterexamples/example.rb +2 -2
  7. data/lib/lrama/grammar/code.rb +1 -1
  8. data/lib/lrama/grammar/parameterizing_rule/resolver.rb +17 -9
  9. data/lib/lrama/grammar/rule.rb +2 -2
  10. data/lib/lrama/grammar/rule_builder.rb +31 -36
  11. data/lib/lrama/grammar/stdlib.y +80 -0
  12. data/lib/lrama/grammar.rb +11 -2
  13. data/lib/lrama/lexer.rb +1 -0
  14. data/lib/lrama/parser.rb +474 -451
  15. data/lib/lrama/states/item.rb +17 -13
  16. data/lib/lrama/states_reporter.rb +8 -10
  17. data/lib/lrama/version.rb +1 -1
  18. data/parser.y +4 -5
  19. data/sig/lrama/grammar/parameterizing_rule/resolver.rbs +1 -0
  20. metadata +3 -16
  21. data/lib/lrama/grammar/parameterizing_rules/builder/base.rb +0 -36
  22. data/lib/lrama/grammar/parameterizing_rules/builder/list.rb +0 -28
  23. data/lib/lrama/grammar/parameterizing_rules/builder/nonempty_list.rb +0 -28
  24. data/lib/lrama/grammar/parameterizing_rules/builder/option.rb +0 -28
  25. data/lib/lrama/grammar/parameterizing_rules/builder/separated_list.rb +0 -39
  26. data/lib/lrama/grammar/parameterizing_rules/builder/separated_nonempty_list.rb +0 -34
  27. data/lib/lrama/grammar/parameterizing_rules/builder.rb +0 -60
  28. data/sig/lrama/grammar/parameterizing_rules/builder/base.rbs +0 -28
  29. data/sig/lrama/grammar/parameterizing_rules/builder/list.rbs +0 -10
  30. data/sig/lrama/grammar/parameterizing_rules/builder/nonempty_list.rbs +0 -10
  31. data/sig/lrama/grammar/parameterizing_rules/builder/option.rbs +0 -10
  32. data/sig/lrama/grammar/parameterizing_rules/builder/separated_list.rbs +0 -13
  33. data/sig/lrama/grammar/parameterizing_rules/builder/separated_nonempty_list.rbs +0 -13
  34. data/sig/lrama/grammar/parameterizing_rules/builder.rbs +0 -24
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 50dc10cc2d790e778dcb6a35b789f146e69157b3c99d5b66059d95c025546ea6
4
- data.tar.gz: cbc16ede0db21b5d22f74c47dfd7a87af2ae20e15f72afc9ea8a79980531861d
3
+ metadata.gz: e4158de45c42ff62eacfb00737261feaa49d8f0cc646004e30da74ba4e2e69c6
4
+ data.tar.gz: 734830227f701e18df2e9e8bc3da55d15f49c890e08530e6ac55ef87ae5f952d
5
5
  SHA512:
6
- metadata.gz: 7567e78e28cb912eb6dae8182827b5c6555924757bffe4fd9db81f79dd117aaf00f0918c90ead79d3567eeee802b90556540141fd5d4083bf5d6013c075cb20c
7
- data.tar.gz: e58f803bc04114bdeb69b74a5e34ab9649241dafb9fe69a62f7d17ea87026411e3f743c54537fa092a9d6cea547a046fc762a78d9daebf92c3184be5502a24c1
6
+ metadata.gz: 52ebbe4d099ae63d73aa995bddc8e966f989a4d00ad3b39634d2abe2448da404dd9bff8f15e0dedd0577716089329c804ef2c4edcadd39ca6ba47f8d293d101d
7
+ data.tar.gz: 72e91c79618071b5850c85335cfe3f1b63ff89f11cd332b0141623a4e2a7e2c2c389dd0db9afe38a5a84b7aa891ac1834fc7a2d6c6eed8f62d87734f6b99cbbf
@@ -87,6 +87,11 @@ jobs:
87
87
  bundler-cache: true
88
88
  - run: bundle install
89
89
 
90
+ # Copy from https://github.com/ruby/ruby/blob/cb9a47f2acd6e373ef868b890a9d07da6f565dd4/.github/workflows/check_misc.yml#L31
91
+ - name: Check if C-sources are US-ASCII
92
+ run: |
93
+ grep -r -n --include='*.[chyS]' --include='*.asm' $'[^\t-~]' -- . && exit 1 || :
94
+
90
95
  # Copy from https://github.com/ruby/ruby/blob/089227e94823542acfdafa68541d330eee42ffea/.github/workflows/check_misc.yml#L27
91
96
  - name: Check for trailing spaces
92
97
  run: |
@@ -120,8 +125,8 @@ jobs:
120
125
  fail-fast: false
121
126
  matrix:
122
127
  # '3.0' is the oldest living ruby version
123
- # '2.5' is for BASERUBY
124
- baseruby: ['head', '3.0', '2.5']
128
+ # '2.7' is for BASERUBY
129
+ baseruby: ['head', '3.0', '2.7']
125
130
  ruby_branch: ['master']
126
131
  defaults:
127
132
  run:
data/NEWS.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # NEWS for Lrama
2
2
 
3
+ ## Lrama 0.6.2 (2024-01-27)
4
+
5
+ ### %no-stdlib directive
6
+
7
+ If `%no-stdlib` directive is set, Lrama doesn't load Lrama standard library for
8
+ parameterizing rules, stdlib.y.
9
+
10
+ https://github.com/ruby/lrama/pull/344
11
+
3
12
  ## Lrama 0.6.1 (2024-01-13)
4
13
 
5
14
  ### Nested parameterizing rules
data/lib/lrama/command.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  module Lrama
2
2
  class Command
3
+ LRAMA_LIB = File.realpath(File.join(File.dirname(__FILE__)))
4
+ STDLIB_FILE_PATH = File.join(LRAMA_LIB, 'grammar', 'stdlib.y')
5
+
3
6
  def run(argv)
4
7
  begin
5
8
  options = OptionParser.new.parse(argv)
@@ -14,9 +17,14 @@ module Lrama
14
17
  warning = Lrama::Warning.new
15
18
  text = options.y.read
16
19
  options.y.close if options.y != STDIN
17
- parser = Lrama::Parser.new(text, options.grammar_file, options.debug)
18
20
  begin
19
- grammar = parser.parse
21
+ grammar = Lrama::Parser.new(text, options.grammar_file, options.debug).parse
22
+ unless grammar.no_stdlib
23
+ stdlib_grammar = Lrama::Parser.new(File.read(STDLIB_FILE_PATH), STDLIB_FILE_PATH, options.debug).parse
24
+ grammar.insert_before_parameterizing_rules(stdlib_grammar.parameterizing_rules)
25
+ end
26
+ grammar.prepare
27
+ grammar.validate!
20
28
  rescue => e
21
29
  raise e if options.debug
22
30
  message = e.message
data/lib/lrama/context.rb CHANGED
@@ -41,7 +41,7 @@ module Lrama
41
41
  def yyfinal
42
42
  @states.states.find do |state|
43
43
  state.items.find do |item|
44
- item.rule.lhs.accept_symbol? && item.end_of_rule?
44
+ item.lhs.accept_symbol? && item.end_of_rule?
45
45
  end
46
46
  end.id
47
47
  end
@@ -221,7 +221,7 @@ module Lrama
221
221
 
222
222
  if state.reduces.map(&:selected_look_ahead).any? {|la| !la.empty? }
223
223
  # Iterate reduces with reverse order so that first rule is used.
224
- state.reduces.reverse.each do |reduce|
224
+ state.reduces.reverse_each do |reduce|
225
225
  reduce.look_ahead.each do |term|
226
226
  actions[term.number] = rule_id_to_action_number(reduce.rule.id)
227
227
  end
@@ -40,7 +40,7 @@ module Lrama
40
40
  current = :production
41
41
  lookahead_sym = paths.last.to.item.end_of_rule? ? @conflict_symbol : nil
42
42
 
43
- paths.reverse.each do |path|
43
+ paths.reverse_each do |path|
44
44
  item = path.to.item
45
45
 
46
46
  case current
@@ -97,7 +97,7 @@ module Lrama
97
97
  if next_sym == sym
98
98
  derivation = nil
99
99
 
100
- sis.reverse.each do |si|
100
+ sis.reverse_each do |si|
101
101
  derivation = Derivation.new(si.item, derivation)
102
102
  end
103
103
 
@@ -28,7 +28,7 @@ module Lrama
28
28
  def translated_code
29
29
  t_code = s_value.dup
30
30
 
31
- references.reverse.each do |ref|
31
+ references.reverse_each do |ref|
32
32
  first_column = ref.first_column
33
33
  last_column = ref.last_column
34
34
 
@@ -2,7 +2,7 @@ module Lrama
2
2
  class Grammar
3
3
  class ParameterizingRule
4
4
  class Resolver
5
- attr_accessor :created_lhs_list
5
+ attr_accessor :rules, :created_lhs_list
6
6
 
7
7
  def initialize
8
8
  @rules = []
@@ -13,24 +13,32 @@ module Lrama
13
13
  @rules << rule
14
14
  end
15
15
 
16
- def defined?(token)
17
- !select_rules(token).empty?
18
- end
19
-
20
16
  def find(token)
21
17
  select_rules(token).last
22
18
  end
23
19
 
24
20
  def created_lhs(lhs_s_value)
25
- @created_lhs_list.select { |created_lhs| created_lhs.s_value == lhs_s_value }.last
21
+ @created_lhs_list.reverse.find { |created_lhs| created_lhs.s_value == lhs_s_value }
26
22
  end
27
23
 
28
24
  private
29
25
 
30
26
  def select_rules(token)
31
- @rules.select do |rule|
32
- rule.name == token.rule_name &&
33
- rule.required_parameters_count == token.args_count
27
+ rules = select_rules_by_name(token.rule_name)
28
+ rules = rules.select { |rule| rule.required_parameters_count == token.args_count }
29
+ if rules.empty?
30
+ raise "Invalid number of arguments. `#{token.rule_name}`"
31
+ else
32
+ rules
33
+ end
34
+ end
35
+
36
+ def select_rules_by_name(rule_name)
37
+ rules = @rules.select { |rule| rule.name == rule_name }
38
+ if rules.empty?
39
+ raise "Parameterizing rule does not exist. `#{rule_name}`"
40
+ else
41
+ rules
34
42
  end
35
43
  end
36
44
  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 = rhs.empty? ? "ε" : 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
@@ -27,7 +27,7 @@ module Lrama
27
27
  # Used by #user_actions
28
28
  def as_comment
29
29
  l = lhs.id.s_value
30
- r = rhs.empty? ? "%empty" : rhs.map(&:display_name).join(" ")
30
+ r = empty_rule? ? "%empty" : rhs.map(&:display_name).join(" ")
31
31
 
32
32
  "#{l}: #{r}"
33
33
  end
@@ -1,5 +1,3 @@
1
- require 'lrama/grammar/parameterizing_rules/builder'
2
-
3
1
  module Lrama
4
2
  class Grammar
5
3
  class RuleBuilder
@@ -59,7 +57,7 @@ module Lrama
59
57
  end
60
58
 
61
59
  def rules
62
- @parameterizing_rules + @old_parameterizing_rules + @midrule_action_rules + @rules
60
+ @parameterizing_rules + @midrule_action_rules + @rules
63
61
  end
64
62
 
65
63
  private
@@ -97,7 +95,6 @@ module Lrama
97
95
  return if @replaced_rhs
98
96
 
99
97
  @replaced_rhs = []
100
- @old_parameterizing_rules = []
101
98
 
102
99
  rhs.each_with_index do |token, i|
103
100
  case token
@@ -106,35 +103,28 @@ module Lrama
106
103
  when Lrama::Lexer::Token::Ident
107
104
  @replaced_rhs << token
108
105
  when Lrama::Lexer::Token::InstantiateRule
109
- if parameterizing_rule_resolver.defined?(token)
110
- parameterizing_rule = parameterizing_rule_resolver.find(token)
111
- raise "Unexpected token. #{token}" unless parameterizing_rule
112
-
113
- bindings = Binding.new(parameterizing_rule, token.args)
114
- lhs_s_value = lhs_s_value(token, bindings)
115
- if (created_lhs = parameterizing_rule_resolver.created_lhs(lhs_s_value))
116
- @replaced_rhs << created_lhs
117
- else
118
- lhs_token = Lrama::Lexer::Token::Ident.new(s_value: lhs_s_value, location: token.location)
119
- @replaced_rhs << lhs_token
120
- parameterizing_rule_resolver.created_lhs_list << lhs_token
121
- parameterizing_rule.rhs_list.each do |r|
122
- rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, i, lhs_tag: token.lhs_tag, skip_preprocess_references: true)
123
- rule_builder.lhs = lhs_token
124
- r.symbols.each { |sym| rule_builder.add_rhs(bindings.resolve_symbol(sym)) }
125
- rule_builder.line = line
126
- rule_builder.user_code = r.user_code
127
- rule_builder.precedence_sym = r.precedence_sym
128
- rule_builder.complete_input
129
- rule_builder.setup_rules(parameterizing_rule_resolver)
130
- @rule_builders_for_parameterizing_rules << rule_builder
131
- end
132
- end
106
+ parameterizing_rule = parameterizing_rule_resolver.find(token)
107
+ raise "Unexpected token. #{token}" unless parameterizing_rule
108
+
109
+ bindings = Binding.new(parameterizing_rule, token.args)
110
+ lhs_s_value = lhs_s_value(token, bindings)
111
+ if (created_lhs = parameterizing_rule_resolver.created_lhs(lhs_s_value))
112
+ @replaced_rhs << created_lhs
133
113
  else
134
- # TODO: Delete when the standard library will defined as a grammar file.
135
- parameterizing_rule = ParameterizingRules::Builder.new(token, @rule_counter, token.lhs_tag, user_code, precedence_sym, line)
136
- @old_parameterizing_rules = @old_parameterizing_rules + parameterizing_rule.build
137
- @replaced_rhs << parameterizing_rule.build_token
114
+ lhs_token = Lrama::Lexer::Token::Ident.new(s_value: lhs_s_value, location: token.location)
115
+ @replaced_rhs << lhs_token
116
+ parameterizing_rule_resolver.created_lhs_list << lhs_token
117
+ parameterizing_rule.rhs_list.each do |r|
118
+ rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, i, lhs_tag: token.lhs_tag, skip_preprocess_references: true)
119
+ rule_builder.lhs = lhs_token
120
+ r.symbols.each { |sym| rule_builder.add_rhs(bindings.resolve_symbol(sym)) }
121
+ rule_builder.line = line
122
+ rule_builder.user_code = r.user_code
123
+ rule_builder.precedence_sym = r.precedence_sym
124
+ rule_builder.complete_input
125
+ rule_builder.setup_rules(parameterizing_rule_resolver)
126
+ @rule_builders_for_parameterizing_rules << rule_builder
127
+ end
138
128
  end
139
129
  when Lrama::Lexer::Token::UserCode
140
130
  prefix = token.referred ? "@" : "$@"
@@ -173,11 +163,12 @@ module Lrama
173
163
 
174
164
  token.references.each do |ref|
175
165
  ref_name = ref.name
176
- if ref_name && ref_name != '$'
177
- if lhs.referred_by?(ref_name)
166
+
167
+ if ref_name
168
+ if ref_name == '$'
178
169
  ref.name = '$'
179
170
  else
180
- candidates = rhs.each_with_index.select {|token, i| token.referred_by?(ref_name) }
171
+ candidates = ([lhs] + rhs).each_with_index.select {|token, _i| token.referred_by?(ref_name) }
181
172
 
182
173
  if candidates.size >= 2
183
174
  token.invalid_ref(ref, "Referring symbol `#{ref_name}` is duplicated.")
@@ -187,7 +178,11 @@ module Lrama
187
178
  token.invalid_ref(ref, "Referring symbol `#{ref_name}` is not found.")
188
179
  end
189
180
 
190
- ref.index = referring_symbol[1] + 1
181
+ if referring_symbol[1] == 0 # Refers to LHS
182
+ ref.name = '$'
183
+ else
184
+ ref.index = referring_symbol[1]
185
+ end
191
186
  end
192
187
  end
193
188
 
@@ -0,0 +1,80 @@
1
+ /**********************************************************************
2
+
3
+ stdlib.y
4
+
5
+ This is lrama's standard library. It provides a number of
6
+ parameterizing rule definitions, such as options and lists,
7
+ that should be useful in a number of situations.
8
+
9
+ **********************************************************************/
10
+
11
+ /*
12
+ * program: option(number)
13
+ *
14
+ * =>
15
+ *
16
+ * program: option_number
17
+ * option_number: %empty
18
+ * option_number: number
19
+ */
20
+ %rule option(X): /* empty */
21
+ | X
22
+ ;
23
+
24
+ /*
25
+ * program: list(number)
26
+ *
27
+ * =>
28
+ *
29
+ * program: list_number
30
+ * list_number: %empty
31
+ * list_number: list_number number
32
+ */
33
+ %rule list(X): /* empty */
34
+ | list(X) X
35
+ ;
36
+
37
+ /*
38
+ * program: nonempty_list(number)
39
+ *
40
+ * =>
41
+ *
42
+ * program: nonempty_list_number
43
+ * nonempty_list_number: number
44
+ * nonempty_list_number: nonempty_list_number number
45
+ */
46
+ %rule nonempty_list(X): X
47
+ | nonempty_list(X) X
48
+ ;
49
+
50
+ /*
51
+ * program: separated_nonempty_list(comma, number)
52
+ *
53
+ * =>
54
+ *
55
+ * program: separated_nonempty_list_comma_number
56
+ * separated_nonempty_list_comma_number: number
57
+ * separated_nonempty_list_comma_number: separated_nonempty_list_comma_number comma number
58
+ */
59
+ %rule separated_nonempty_list(separator, X): X
60
+ | separated_nonempty_list(separator, X) separator X
61
+ ;
62
+
63
+ /*
64
+ * program: separated_list(comma, number)
65
+ *
66
+ * =>
67
+ *
68
+ * program: separated_list_comma_number
69
+ * separated_list_comma_number: option_separated_nonempty_list_comma_number
70
+ * option_separated_nonempty_list_comma_number: %empty
71
+ * option_separated_nonempty_list_comma_number: separated_nonempty_list_comma_number
72
+ * separated_nonempty_list_comma_number: number
73
+ * separated_nonempty_list_comma_number: comma separated_nonempty_list_comma_number number
74
+ */
75
+ %rule separated_list(separator, X): option(separated_nonempty_list(separator, X))
76
+ ;
77
+
78
+ %%
79
+
80
+ %union{};
data/lib/lrama/grammar.rb CHANGED
@@ -24,7 +24,7 @@ module Lrama
24
24
  :lex_param, :parse_param, :initial_action,
25
25
  :symbols, :types,
26
26
  :rules, :rule_builders,
27
- :sym_to_rules
27
+ :sym_to_rules, :no_stdlib
28
28
 
29
29
  def initialize(rule_counter)
30
30
  @rule_counter = rule_counter
@@ -45,6 +45,7 @@ module Lrama
45
45
  @undef_symbol = nil
46
46
  @accept_symbol = nil
47
47
  @aux = Auxiliary.new
48
+ @no_stdlib = false
48
49
 
49
50
  append_special_symbols
50
51
  end
@@ -136,6 +137,14 @@ module Lrama
136
137
  @parameterizing_rule_resolver.add_parameterizing_rule(rule)
137
138
  end
138
139
 
140
+ def parameterizing_rules
141
+ @parameterizing_rule_resolver.rules
142
+ end
143
+
144
+ def insert_before_parameterizing_rules(rules)
145
+ @parameterizing_rule_resolver.rules = rules + @parameterizing_rule_resolver.rules
146
+ end
147
+
139
148
  def prologue_first_lineno=(prologue_first_lineno)
140
149
  @aux.prologue_first_lineno = prologue_first_lineno
141
150
  end
@@ -234,7 +243,7 @@ module Lrama
234
243
  def compute_nullable
235
244
  @rules.each do |rule|
236
245
  case
237
- when rule.rhs.empty?
246
+ when rule.empty_rule?
238
247
  rule.nullable = true
239
248
  when rule.rhs.any?(&:term)
240
249
  rule.nullable = false
data/lib/lrama/lexer.rb CHANGED
@@ -29,6 +29,7 @@ module Lrama
29
29
  %empty
30
30
  %code
31
31
  %rule
32
+ %no-stdlib
32
33
  )
33
34
 
34
35
  def initialize(grammar_file)