lrama 0.5.0 → 0.5.2

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: 0a8a1b04a3e761af04029af3e3b74aaaf4fe9a9e2741205f430264ee3399f66c
4
- data.tar.gz: a97ec2c2b2007f3bad6cbe5d1b37baa87d520cc3025e82403a9d8a70cddccc8a
3
+ metadata.gz: 26bcef726eebf61de01200b02250b2aef91ca957df43db5d72e99ae30e320f4e
4
+ data.tar.gz: 751b62d184806c0cff319bffc4990ad0de9dd143accafdf6bdf1652eb02512b7
5
5
  SHA512:
6
- metadata.gz: 820bce06aefc235c02995cc957f9e0d9b2e8d588ce7748225896f0d63c319135068da39977be860815276c360a66e3dd6c2132802aa30e3292d706bc6ae7ef9d
7
- data.tar.gz: d5c4ec405196bca888c78bf8a16cc9aef47da0f9943d7eee2bf9033c104f9a07fcb07c4cb6aabb3bb49f0e3665bf37932e2206cd9acad925702c30c7124210fb
6
+ metadata.gz: 02001b5b137d023c4f5ce48c1d9284ce90c5aad2ec269d7ef7a17e6ffa65be9e553e213400fc63d8256c0209908fc4b314de261993442af4a25772449453fbeb
7
+ data.tar.gz: 76a9f6bac19c0dcbdc6f9e2834d3c437f9fc5eb999d1b45d20362d52a94c9dc74bca3411b681993e28f388374df7f9b8ea7d0f534e53399efb8cc24112f75ea4
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: 'github-actions'
4
+ directory: '/'
5
+ schedule:
6
+ interval: 'weekly'
@@ -22,6 +22,21 @@ jobs:
22
22
  bundler-cache: true
23
23
  - run: bundle install
24
24
  - run: bundle exec rspec
25
+ steep-check:
26
+ runs-on: ubuntu-20.04
27
+ strategy:
28
+ fail-fast: false
29
+ matrix:
30
+ ruby: ['head']
31
+ steps:
32
+ - uses: actions/checkout@v3
33
+ - uses: ruby/setup-ruby@v1
34
+ with:
35
+ ruby-version: ${{ matrix.ruby }}
36
+ bundler-cache: true
37
+ - run: bundle install
38
+ - run: bundle exec rbs collection install
39
+ - run: bundle exec steep check
25
40
  test-ruby:
26
41
  runs-on: ubuntu-20.04
27
42
  strategy:
@@ -43,9 +58,7 @@ jobs:
43
58
  - run: mkdir -p tool/lrama
44
59
  working-directory: ../ruby
45
60
  - name: Copy Lrama to ruby/tool
46
- run: cp -r exe lib ../ruby/tool/lrama
47
- # TODO: Consider how to manage changes on ruby/ruby master and ruby/lrama
48
- # run: cp -r exe lib template ../ruby/tool/lrama
61
+ run: cp -r exe lib template ../ruby/tool/lrama
49
62
  working-directory:
50
63
  - run: tree tool/lrama
51
64
  working-directory: ../ruby
@@ -70,5 +83,5 @@ jobs:
70
83
  - run: sudo apt-get --purge remove bison
71
84
  - run: ../autogen.sh
72
85
  - run: ../configure -C --disable-install-doc
73
- - run: make YACC=$(readlink -f $(pwd)/../tool/lrama/exe/lrama)
86
+ - run: make
74
87
  - run: make test-all
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ /.gem_rbs_collection/
1
2
  /tmp
2
3
  .irbrc
3
4
  /Gemfile.lock
data/Gemfile CHANGED
@@ -6,3 +6,5 @@ gem "rspec"
6
6
  gem "pry"
7
7
  gem "stackprof"
8
8
  gem "rake"
9
+ gem "rbs", require: false
10
+ gem "steep", require: false
data/README.md CHANGED
@@ -21,9 +21,11 @@ $ gem install lrama
21
21
  From source codes,
22
22
 
23
23
  ```shell
24
+ $ cd "$(lrama root)"
25
+ $ bundle install
24
26
  $ bundle exec rake install
25
- $ lrama --version
26
- 0.1.0
27
+ $ bundle exec lrama --version
28
+ 0.5.0
27
29
  ```
28
30
 
29
31
  ## Usage
@@ -33,11 +35,36 @@ $ lrama --version
33
35
  $ lrama -d sample/parse.y
34
36
  ```
35
37
 
38
+ ```shell
39
+ # "calc", "calc.c", and "calc.h" are generated
40
+ $ lrama -d sample/calc.y -o calc.c && gcc -Wall calc.c -o calc && ./calc
41
+ Enter the formula:
42
+ 1
43
+ => 1
44
+ 1+2*3
45
+ => 7
46
+ (1+2)*3
47
+ => 9
48
+ ```
49
+
50
+ ## Versions and Branches
51
+
52
+ ### v0_4 (`lrama_0_4` branch)
53
+
54
+ This branch generates "parse.c" compatible with Bison 3.8.2 for ruby 3.0, 3.1, 3.2. The first version migrated to ruby is ["0.4.0"](https://github.com/ruby/ruby/pull/7798) therefore keep this branch for Bison compatible branch.
55
+
36
56
  ## Build Ruby
37
57
 
38
58
  1. Install Lrama
39
59
  2. Run `make YACC=lrama`
40
60
 
61
+ ## Release flow
62
+
63
+ 1. Update `Lrama::VERSION`
64
+ 2. Release as a gem by `rake release`
65
+ 3. Update Lrama in ruby/ruby by `cp -r LEGAL.md MIT exe lib ruby/tool/lrama`
66
+ 4. Create new release on [GitHub](https://github.com/ruby/lrama/releases)
67
+
41
68
  ## License
42
69
 
43
70
  See LEGAL.md file.
data/Steepfile ADDED
@@ -0,0 +1,9 @@
1
+ # D = Steep::Diagnostic
2
+ #
3
+ target :lib do
4
+ signature "sig"
5
+
6
+ check "lib/lrama/bitmap.rb"
7
+ check "lib/lrama/report.rb"
8
+ check "lib/lrama/warning.rb"
9
+ end
data/lib/lrama/grammar.rb CHANGED
@@ -155,18 +155,18 @@ module Lrama
155
155
  last_column = ref.last_column
156
156
 
157
157
  case
158
- when ref.number == "$" && ref.type == :dollar # $$
158
+ when ref.value == "$" && ref.type == :dollar # $$
159
159
  # Omit "<>"
160
160
  member = tag.s_value[1..-2]
161
161
  str = "((*yyvaluep).#{member})"
162
- when ref.number == "$" && ref.type == :at # @$
162
+ when ref.value == "$" && ref.type == :at # @$
163
163
  str = "(*yylocationp)"
164
164
  when ref.type == :dollar # $n
165
- raise "$#{ref.number} can not be used in %printer."
165
+ raise "$#{ref.value} can not be used in %printer."
166
166
  when ref.type == :at # @n
167
- raise "@#{ref.number} can not be used in %printer."
167
+ raise "@#{ref.value} can not be used in %printer."
168
168
  else
169
- raise "Unexpected. #{code}, #{ref}"
169
+ raise "Unexpected. #{self}, #{ref}"
170
170
  end
171
171
 
172
172
  t_code[first_column..last_column] = str
@@ -190,22 +190,22 @@ module Lrama
190
190
  last_column = ref.last_column
191
191
 
192
192
  case
193
- when ref.number == "$" && ref.type == :dollar # $$
193
+ when ref.value == "$" && ref.type == :dollar # $$
194
194
  # Omit "<>"
195
195
  member = ref.tag.s_value[1..-2]
196
196
  str = "(yyval.#{member})"
197
- when ref.number == "$" && ref.type == :at # @$
197
+ when ref.value == "$" && ref.type == :at # @$
198
198
  str = "(yyloc)"
199
199
  when ref.type == :dollar # $n
200
- i = -ref.position_in_rhs + ref.number
200
+ i = -ref.position_in_rhs + ref.value
201
201
  # Omit "<>"
202
202
  member = ref.tag.s_value[1..-2]
203
203
  str = "(yyvsp[#{i}].#{member})"
204
204
  when ref.type == :at # @n
205
- i = -ref.position_in_rhs + ref.number
205
+ i = -ref.position_in_rhs + ref.value
206
206
  str = "(yylsp[#{i}])"
207
207
  else
208
- raise "Unexpected. #{code}, #{ref}"
208
+ raise "Unexpected. #{self}, #{ref}"
209
209
  end
210
210
 
211
211
  t_code[first_column..last_column] = str
@@ -226,16 +226,16 @@ module Lrama
226
226
  last_column = ref.last_column
227
227
 
228
228
  case
229
- when ref.number == "$" && ref.type == :dollar # $$
229
+ when ref.value == "$" && ref.type == :dollar # $$
230
230
  str = "yylval"
231
- when ref.number == "$" && ref.type == :at # @$
231
+ when ref.value == "$" && ref.type == :at # @$
232
232
  str = "yylloc"
233
233
  when ref.type == :dollar # $n
234
- raise "$#{ref.number} can not be used in initial_action."
234
+ raise "$#{ref.value} can not be used in initial_action."
235
235
  when ref.type == :at # @n
236
- raise "@#{ref.number} can not be used in initial_action."
236
+ raise "@#{ref.value} can not be used in initial_action."
237
237
  else
238
- raise "Unexpected. #{code}, #{ref}"
238
+ raise "Unexpected. #{self}, #{ref}"
239
239
  end
240
240
 
241
241
  t_code[first_column..last_column] = str
@@ -247,7 +247,7 @@ module Lrama
247
247
 
248
248
  # type: :dollar or :at
249
249
  # ex_tag: "$<tag>1" (Optional)
250
- Reference = Struct.new(:type, :number, :ex_tag, :first_column, :last_column, :referring_symbol, :position_in_rhs, keyword_init: true) do
250
+ Reference = Struct.new(:type, :value, :ex_tag, :first_column, :last_column, :referring_symbol, :position_in_rhs, keyword_init: true) do
251
251
  def tag
252
252
  if ex_tag
253
253
  ex_tag
@@ -382,8 +382,8 @@ module Lrama
382
382
  end
383
383
 
384
384
  def build_references(token_code)
385
- token_code.references.map! do |type, number, tag, first_column, last_column|
386
- Reference.new(type: type, number: number, ex_tag: tag, first_column: first_column, last_column: last_column)
385
+ token_code.references.map! do |type, value, tag, first_column, last_column|
386
+ Reference.new(type: type, value: value, ex_tag: tag, first_column: first_column, last_column: last_column)
387
387
  end
388
388
 
389
389
  token_code
@@ -627,15 +627,23 @@ module Lrama
627
627
  ref.position_in_rhs = i - 1
628
628
  next if ref.type == :at
629
629
  # $$, $n, @$, @n can be used in any actions
630
- number = ref.number
631
630
 
632
- if number == "$"
631
+ if ref.value == "$"
633
632
  # TODO: Should be postponed after middle actions are extracted?
634
633
  ref.referring_symbol = lhs
635
- else
636
- raise "Can not refer following component. #{number} >= #{i}. #{token}" if number >= i
637
- rhs1[number - 1].referred = true
638
- ref.referring_symbol = rhs1[number - 1]
634
+ elsif ref.value.is_a?(Integer)
635
+ raise "Can not refer following component. #{ref.value} >= #{i}. #{token}" if ref.value >= i
636
+ rhs1[ref.value - 1].referred = true
637
+ ref.referring_symbol = rhs1[ref.value - 1]
638
+ elsif ref.value.is_a?(String)
639
+ target_tokens = ([lhs] + rhs1 + [code]).compact.first(i)
640
+ referring_symbol_candidate = target_tokens.filter {|token| token.referred_by?(ref.value) }
641
+ raise "Referring symbol `#{ref.value}` is duplicated. #{token}" if referring_symbol_candidate.size >= 2
642
+ raise "Referring symbol `#{ref.value}` is not found. #{token}" if referring_symbol_candidate.count == 0
643
+
644
+ referring_symbol = referring_symbol_candidate.first
645
+ referring_symbol.referred = true
646
+ ref.referring_symbol = referring_symbol
639
647
  end
640
648
  end
641
649
  end
@@ -716,7 +724,7 @@ module Lrama
716
724
  # If id is Token::Char, it uses ASCII code
717
725
  if sym.term? && sym.token_id.nil?
718
726
  if sym.id.type == Token::Char
719
- # Igonre ' on the both sides
727
+ # Ignore ' on the both sides
720
728
  case sym.id.s_value[1..-2]
721
729
  when "\\b"
722
730
  sym.token_id = 8
@@ -844,7 +852,7 @@ module Lrama
844
852
 
845
853
  return if invalid.empty?
846
854
 
847
- raise "Symbol number is dupulicated. #{invalid}"
855
+ raise "Symbol number is duplicated. #{invalid}"
848
856
  end
849
857
  end
850
858
  end
data/lib/lrama/lexer.rb CHANGED
@@ -7,7 +7,7 @@ module Lrama
7
7
  include Lrama::Report::Duration
8
8
 
9
9
  # s_value is semantic value
10
- Token = Struct.new(:type, :s_value, keyword_init: true) do
10
+ Token = Struct.new(:type, :s_value, :alias, keyword_init: true) do
11
11
  Type = Struct.new(:id, :name, keyword_init: true)
12
12
 
13
13
  attr_accessor :line, :column, :referred
@@ -18,6 +18,31 @@ module Lrama
18
18
  "#{super} line: #{line}, column: #{column}"
19
19
  end
20
20
 
21
+ def referred_by?(string)
22
+ [self.s_value, self.alias].include?(string)
23
+ end
24
+
25
+ def ==(other)
26
+ self.class == other.class && self.type == other.type && self.s_value == other.s_value
27
+ end
28
+
29
+ def numberize_references(lhs, rhs)
30
+ self.references.map! {|ref|
31
+ ref_name = ref[1]
32
+ if ref_name.is_a?(String) && ref_name != '$'
33
+ value =
34
+ if lhs.referred_by?(ref_name)
35
+ '$'
36
+ else
37
+ rhs.find_index {|token| token.referred_by?(ref_name) } + 1
38
+ end
39
+ [ref[0], value, ref[2], ref[3], ref[4]]
40
+ else
41
+ ref
42
+ end
43
+ }
44
+ end
45
+
21
46
  @i = 0
22
47
  @types = []
23
48
 
@@ -47,6 +72,7 @@ module Lrama
47
72
  define_type(:Number) # 0
48
73
  define_type(:Ident_Colon) # k_if:, k_if : (spaces can be there)
49
74
  define_type(:Ident) # api.pure, tNUMBER
75
+ define_type(:Named_Ref) # [foo]
50
76
  define_type(:Semicolon) # ;
51
77
  define_type(:Bar) # |
52
78
  define_type(:String) # "str"
@@ -166,10 +192,15 @@ module Lrama
166
192
  tokens << create_token(Token::Number, Integer(ss[0]), line, ss.pos - column)
167
193
  when ss.scan(/(<[a-zA-Z0-9_]+>)/)
168
194
  tokens << create_token(Token::Tag, ss[0], line, ss.pos - column)
195
+ when ss.scan(/([a-zA-Z_.][-a-zA-Z0-9_.]*)\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]\s*:/)
196
+ tokens << create_token(Token::Ident_Colon, ss[1], line, ss.pos - column)
197
+ tokens << create_token(Token::Named_Ref, ss[2], line, ss.pos - column)
169
198
  when ss.scan(/([a-zA-Z_.][-a-zA-Z0-9_.]*)\s*:/)
170
199
  tokens << create_token(Token::Ident_Colon, ss[1], line, ss.pos - column)
171
200
  when ss.scan(/([a-zA-Z_.][-a-zA-Z0-9_.]*)/)
172
201
  tokens << create_token(Token::Ident, ss[0], line, ss.pos - column)
202
+ when ss.scan(/\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]/)
203
+ tokens << create_token(Token::Named_Ref, ss[1], line, ss.pos - column)
173
204
  when ss.scan(/%expect/)
174
205
  tokens << create_token(Token::P_expect, ss[0], line, ss.pos - column)
175
206
  when ss.scan(/%define/)
@@ -206,6 +237,8 @@ module Lrama
206
237
  when ss.scan(/\/\*/)
207
238
  # TODO: Need to keep comment?
208
239
  line = lex_comment(ss, line, lines, "")
240
+ when ss.scan(/\/\//)
241
+ line = lex_line_comment(ss, line, "")
209
242
  when ss.scan(/'(.)'/)
210
243
  tokens << create_token(Token::Char, ss[0], line, ss.pos - column)
211
244
  when ss.scan(/'\\(.)'/) # '\\', '\t'
@@ -218,7 +251,7 @@ module Lrama
218
251
  l = line - lines.first[1]
219
252
  split = ss.string.split("\n")
220
253
  col = ss.pos - split[0...l].join("\n").length
221
- raise "Parse error (unknow token): #{split[l]} \"#{ss.string[ss.pos]}\" (#{line}: #{col})"
254
+ raise "Parse error (unknown token): #{split[l]} \"#{ss.string[ss.pos]}\" (#{line}: #{col})"
222
255
  end
223
256
  end
224
257
  end
@@ -255,6 +288,9 @@ module Lrama
255
288
  when ss.scan(/\$(<[a-zA-Z0-9_]+>)?(\d+)/) # $1, $2, $<long>1
256
289
  tag = ss[1] ? create_token(Token::Tag, ss[1], line, str.length) : nil
257
290
  references << [:dollar, Integer(ss[2]), tag, str.length, str.length + ss[0].length - 1]
291
+ when ss.scan(/\$(<[a-zA-Z0-9_]+>)?([a-zA-Z_.][-a-zA-Z0-9_.]*)/) # $foo, $expr, $<long>program
292
+ tag = ss[1] ? create_token(Token::Tag, ss[1], line, str.length) : nil
293
+ references << [:dollar, ss[2], tag, str.length, str.length + ss[0].length - 1]
258
294
  when ss.scan(/@\$/) # @$
259
295
  references << [:at, "$", nil, str.length, str.length + ss[0].length - 1]
260
296
  when ss.scan(/@(\d)+/) # @1
@@ -276,6 +312,9 @@ module Lrama
276
312
  when ss.scan(/\/\*/)
277
313
  str << ss[0]
278
314
  line = lex_comment(ss, line, lines, str)
315
+ when ss.scan(/\/\//)
316
+ str << ss[0]
317
+ line = lex_line_comment(ss, line, str)
279
318
  else
280
319
  # noop, just consume char
281
320
  str << ss.getch
@@ -314,8 +353,6 @@ module Lrama
314
353
  raise "Parse error (quote mismatch): #{ss.string.split("\n")[l]} \"#{ss.string[ss.pos]}\" (#{line}: #{ss.pos})"
315
354
  end
316
355
 
317
- # TODO: Need to handle // style comment
318
- #
319
356
  # /* */ style comment
320
357
  def lex_comment(ss, line, lines, str)
321
358
  while !ss.eos? do
@@ -337,6 +374,23 @@ module Lrama
337
374
  raise "Parse error (comment mismatch): #{ss.string.split("\n")[l]} \"#{ss.string[ss.pos]}\" (#{line}: #{ss.pos})"
338
375
  end
339
376
 
377
+ # // style comment
378
+ def lex_line_comment(ss, line, str)
379
+ while !ss.eos? do
380
+ case
381
+ when ss.scan(/\n/)
382
+ return line + 1
383
+ else
384
+ str << ss.getch
385
+ next
386
+ end
387
+
388
+ str << ss[0]
389
+ end
390
+
391
+ line # Reach to end of input
392
+ end
393
+
340
394
  def lex_grammar_rules_tokens
341
395
  lex_common(@grammar_rules, @grammar_rules_tokens)
342
396
  end
@@ -0,0 +1,59 @@
1
+ module Lrama
2
+ class Parser
3
+ class TokenScanner
4
+ def initialize(tokens)
5
+ @tokens = tokens
6
+ @index = 0
7
+ end
8
+
9
+ def current_token
10
+ @tokens[@index]
11
+ end
12
+
13
+ def current_type
14
+ current_token && current_token.type
15
+ end
16
+
17
+ def previous_token
18
+ @tokens[@index - 1]
19
+ end
20
+
21
+ def next
22
+ token = current_token
23
+ @index += 1
24
+ return token
25
+ end
26
+
27
+ def consume(*token_types)
28
+ if token_types.include?(current_type)
29
+ token = current_token
30
+ self.next
31
+ return token
32
+ end
33
+
34
+ return nil
35
+ end
36
+
37
+ def consume!(*token_types)
38
+ consume(*token_types) || (raise "#{token_types} is expected but #{current_type}. #{current_token}")
39
+ end
40
+
41
+ def consume_multi(*token_types)
42
+ a = []
43
+
44
+ while token_types.include?(current_type)
45
+ a << current_token
46
+ self.next
47
+ end
48
+
49
+ raise "No token is consumed. #{token_types}" if a.empty?
50
+
51
+ return a
52
+ end
53
+
54
+ def eots?
55
+ current_token.nil?
56
+ end
57
+ end
58
+ end
59
+ end
data/lib/lrama/parser.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "lrama/report"
2
+ require "lrama/parser/token_scanner"
2
3
 
3
4
  module Lrama
4
5
  # Parser for parse.y, generates a grammar
@@ -7,58 +8,6 @@ module Lrama
7
8
 
8
9
  T = Lrama::Lexer::Token
9
10
 
10
- class TokenScanner
11
- def initialize(tokens)
12
- @tokens = tokens
13
- @index = 0
14
- end
15
-
16
- def current_token
17
- @tokens[@index]
18
- end
19
-
20
- def current_type
21
- current_token && current_token.type
22
- end
23
-
24
- def next
25
- token = current_token
26
- @index += 1
27
- return token
28
- end
29
-
30
- def consume(*token_types)
31
- if token_types.include?(current_type)
32
- token = current_token
33
- self.next
34
- return token
35
- end
36
-
37
- return nil
38
- end
39
-
40
- def consume!(*token_types)
41
- consume(*token_types) || (raise "#{token_types} is expected but #{current_type}. #{current_token}")
42
- end
43
-
44
- def consume_multi(*token_types)
45
- a = []
46
-
47
- while token_types.include?(current_type)
48
- a << current_token
49
- self.next
50
- end
51
-
52
- raise "No token is consumed. #{token_types}" if a.empty?
53
-
54
- return a
55
- end
56
-
57
- def eots?
58
- current_token.nil?
59
- end
60
- end
61
-
62
11
  def initialize(text)
63
12
  @text = text
64
13
  end
@@ -226,8 +175,11 @@ module Lrama
226
175
  # LHS
227
176
  lhs = ts.consume!(T::Ident_Colon) # class:
228
177
  lhs.type = T::Ident
178
+ if named_ref = ts.consume(T::Named_Ref)
179
+ lhs.alias = named_ref.s_value
180
+ end
229
181
 
230
- rhs = parse_grammar_rule_rhs(ts, grammar)
182
+ rhs = parse_grammar_rule_rhs(ts, grammar, lhs)
231
183
 
232
184
  grammar.add_rule(lhs: lhs, rhs: rhs, lineno: rhs.first ? rhs.first.line : lhs.line)
233
185
 
@@ -237,7 +189,7 @@ module Lrama
237
189
  # |
238
190
  bar_lineno = ts.current_token.line
239
191
  ts.next
240
- rhs = parse_grammar_rule_rhs(ts, grammar)
192
+ rhs = parse_grammar_rule_rhs(ts, grammar, lhs)
241
193
  grammar.add_rule(lhs: lhs, rhs: rhs, lineno: rhs.first ? rhs.first.line : bar_lineno)
242
194
  when T::Semicolon
243
195
  # ;
@@ -256,13 +208,13 @@ module Lrama
256
208
  end
257
209
  end
258
210
 
259
- def parse_grammar_rule_rhs(ts, grammar)
211
+ def parse_grammar_rule_rhs(ts, grammar, lhs)
260
212
  a = []
261
213
  prec_seen = false
262
214
  code_after_prec = false
263
215
 
264
216
  while true do
265
- # TODO: Srting can be here
217
+ # TODO: String can be here
266
218
  case ts.current_type
267
219
  when T::Ident
268
220
  # keyword_class
@@ -295,9 +247,13 @@ module Lrama
295
247
  end
296
248
 
297
249
  code = ts.current_token
250
+ code.numberize_references(lhs, a)
298
251
  grammar.build_references(code)
299
252
  a << code
300
253
  ts.next
254
+ when T::Named_Ref
255
+ ts.previous_token.alias = ts.current_token.s_value
256
+ ts.next
301
257
  when T::Bar
302
258
  # |
303
259
  break
@@ -0,0 +1,35 @@
1
+ module Lrama
2
+ class State
3
+ class Reduce
4
+ # https://www.gnu.org/software/bison/manual/html_node/Default-Reductions.html
5
+ attr_reader :item, :look_ahead, :not_selected_symbols
6
+ attr_accessor :default_reduction
7
+
8
+ def initialize(item)
9
+ @item = item
10
+ @look_ahead = nil
11
+ @not_selected_symbols = []
12
+ end
13
+
14
+ def rule
15
+ @item.rule
16
+ end
17
+
18
+ def look_ahead=(look_ahead)
19
+ @look_ahead = look_ahead.freeze
20
+ end
21
+
22
+ def add_not_selected_symbol(sym)
23
+ @not_selected_symbols << sym
24
+ end
25
+
26
+ def selected_look_ahead
27
+ if @look_ahead
28
+ @look_ahead - @not_selected_symbols
29
+ else
30
+ []
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,13 @@
1
+ module Lrama
2
+ class State
3
+ class Shift
4
+ attr_reader :next_sym, :next_items
5
+ attr_accessor :not_selected
6
+
7
+ def initialize(next_sym, next_items)
8
+ @next_sym = next_sym
9
+ @next_items = next_items
10
+ end
11
+ end
12
+ end
13
+ end