lrama 0.5.8 → 0.5.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yaml +6 -1
  3. data/.gitignore +7 -4
  4. data/Gemfile +10 -6
  5. data/README.md +3 -3
  6. data/Rakefile +15 -7
  7. data/Steepfile +15 -1
  8. data/lib/lrama/command.rb +6 -1
  9. data/lib/lrama/context.rb +1 -3
  10. data/lib/lrama/counterexamples/path.rb +0 -46
  11. data/lib/lrama/counterexamples/production_path.rb +17 -0
  12. data/lib/lrama/counterexamples/start_path.rb +21 -0
  13. data/lib/lrama/counterexamples/transition_path.rb +17 -0
  14. data/lib/lrama/counterexamples.rb +3 -0
  15. data/lib/lrama/grammar/code/initial_action_code.rb +28 -0
  16. data/lib/lrama/grammar/code/no_reference_code.rb +24 -0
  17. data/lib/lrama/grammar/code/printer_code.rb +34 -0
  18. data/lib/lrama/grammar/code/rule_action.rb +62 -0
  19. data/lib/lrama/grammar/code.rb +9 -93
  20. data/lib/lrama/grammar/counter.rb +15 -0
  21. data/lib/lrama/grammar/error_token.rb +3 -3
  22. data/lib/lrama/grammar/parameterizing_rules/builder/base.rb +28 -0
  23. data/lib/lrama/grammar/parameterizing_rules/builder/list.rb +20 -0
  24. data/lib/lrama/grammar/parameterizing_rules/builder/nonempty_list.rb +20 -0
  25. data/lib/lrama/grammar/parameterizing_rules/builder/option.rb +20 -0
  26. data/lib/lrama/grammar/parameterizing_rules/builder/separated_list.rb +28 -0
  27. data/lib/lrama/grammar/parameterizing_rules/builder/separated_nonempty_list.rb +27 -0
  28. data/lib/lrama/grammar/parameterizing_rules/builder.rb +43 -0
  29. data/lib/lrama/grammar/percent_code.rb +12 -0
  30. data/lib/lrama/grammar/printer.rb +3 -3
  31. data/lib/lrama/grammar/reference.rb +7 -16
  32. data/lib/lrama/grammar/rule.rb +18 -2
  33. data/lib/lrama/grammar/rule_builder.rb +179 -0
  34. data/lib/lrama/grammar/symbol.rb +2 -2
  35. data/lib/lrama/grammar.rb +132 -302
  36. data/lib/lrama/lexer/location.rb +22 -0
  37. data/lib/lrama/lexer/token/char.rb +8 -0
  38. data/lib/lrama/lexer/token/ident.rb +8 -0
  39. data/lib/lrama/lexer/token/parameterizing.rb +34 -0
  40. data/lib/lrama/lexer/token/tag.rb +12 -0
  41. data/lib/lrama/lexer/token/user_code.rb +64 -0
  42. data/lib/lrama/lexer/token.rb +23 -63
  43. data/lib/lrama/lexer.rb +38 -37
  44. data/lib/lrama/option_parser.rb +2 -1
  45. data/lib/lrama/options.rb +2 -2
  46. data/lib/lrama/output.rb +11 -2
  47. data/lib/lrama/parser.rb +607 -488
  48. data/lib/lrama/report/profile.rb +1 -12
  49. data/lib/lrama/version.rb +1 -1
  50. data/parser.y +177 -96
  51. data/rbs_collection.lock.yaml +17 -1
  52. data/rbs_collection.yaml +1 -0
  53. data/sample/calc.y +3 -1
  54. data/sample/parse.y +5 -1
  55. data/sig/lrama/grammar/code/printer_code.rbs +15 -0
  56. data/sig/lrama/grammar/code.rbs +24 -0
  57. data/sig/lrama/grammar/counter.rbs +11 -0
  58. data/sig/lrama/grammar/parameterizing_rules/builder.rbs +10 -0
  59. data/sig/lrama/grammar/percent_code.rbs +10 -0
  60. data/sig/lrama/grammar/precedence.rbs +11 -0
  61. data/sig/lrama/grammar/printer.rbs +11 -0
  62. data/sig/lrama/grammar/reference.rbs +22 -0
  63. data/sig/lrama/grammar/rule.rbs +13 -0
  64. data/sig/lrama/grammar/rule_builder.rbs +41 -0
  65. data/sig/lrama/grammar.rbs +5 -0
  66. data/sig/lrama/lexer/location.rbs +14 -0
  67. data/sig/lrama/lexer/token/char.rbs +8 -0
  68. data/sig/lrama/lexer/token/ident.rbs +8 -0
  69. data/sig/lrama/lexer/token/parameterizing.rbs +15 -0
  70. data/sig/lrama/lexer/token/tag.rbs +9 -0
  71. data/sig/lrama/lexer/token/user_code.rbs +16 -0
  72. data/sig/lrama/lexer/token.rbs +22 -0
  73. data/sig/stdlib/strscan/string_scanner.rbs +5 -0
  74. data/template/bison/_yacc.h +2 -2
  75. data/template/bison/yacc.c +5 -2
  76. metadata +44 -4
  77. data/lib/lrama/lexer/token/type.rb +0 -8
  78. data/sig/lrama/lexer/token/type.rbs +0 -17
@@ -1,18 +1,7 @@
1
1
  module Lrama
2
2
  class Report
3
3
  module Profile
4
- # 1. Wrap target method with Profile.report_profile like below:
5
- #
6
- # Lrama::Report::Profile.report_profile { method }
7
- #
8
- # 2. Run lrama command, for example
9
- #
10
- # $ ./exe/lrama --trace=time spec/fixtures/integration/ruby_3_2_0/parse.tmp.y
11
- #
12
- # 3. Generate html file
13
- #
14
- # $ stackprof --d3-flamegraph tmp/stackprof-cpu-myapp.dump > tmp/flamegraph.html
15
- #
4
+ # See "Profiling Lrama" in README.md for how to use.
16
5
  def self.report_profile
17
6
  require "stackprof"
18
7
 
data/lib/lrama/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Lrama
2
- VERSION = "0.5.8".freeze
2
+ VERSION = "0.5.10".freeze
3
3
  end
data/parser.y CHANGED
@@ -1,6 +1,10 @@
1
1
  class Lrama::Parser
2
+ expect 1
3
+
2
4
  token C_DECLARATION CHARACTER IDENT_COLON IDENTIFIER INTEGER STRING TAG
5
+
3
6
  rule
7
+
4
8
  input: prologue_declarations bison_declarations "%%" grammar epilogue_opt
5
9
 
6
10
  prologue_declarations: # empty
@@ -8,14 +12,12 @@ rule
8
12
 
9
13
  prologue_declaration: "%{"
10
14
  {
11
- @lexer.status = :c_declaration
12
- @lexer.end_symbol = '%}'
15
+ begin_c_declaration("%}")
13
16
  @grammar.prologue_first_lineno = @lexer.line
14
17
  }
15
18
  C_DECLARATION
16
19
  {
17
- @lexer.status = :initial
18
- @lexer.end_symbol = nil
20
+ end_c_declaration
19
21
  }
20
22
  "%}"
21
23
  {
@@ -34,86 +36,97 @@ rule
34
36
  | "%lex-param" params
35
37
  {
36
38
  val[1].each {|token|
37
- token.references = []
38
- @grammar.lex_param = @grammar.build_code(:lex_param, token).token_code.s_value
39
+ @grammar.lex_param = Grammar::Code::NoReferenceCode.new(type: :lex_param, token_code: token).token_code.s_value
39
40
  }
40
41
  }
41
42
  | "%parse-param" params
42
43
  {
43
44
  val[1].each {|token|
44
- token.references = []
45
- @grammar.parse_param = @grammar.build_code(:parse_param, token).token_code.s_value
45
+ @grammar.parse_param = Grammar::Code::NoReferenceCode.new(type: :parse_param, token_code: token).token_code.s_value
46
46
  }
47
47
  }
48
+ | "%code" IDENTIFIER "{"
49
+ {
50
+ begin_c_declaration("}")
51
+ }
52
+ C_DECLARATION
53
+ {
54
+ end_c_declaration
55
+ }
56
+ "}"
57
+ {
58
+ @grammar.add_percent_code(id: val[1], code: val[4])
59
+ }
48
60
  | "%initial-action" "{"
49
61
  {
50
- @lexer.status = :c_declaration
51
- @lexer.end_symbol = '}'
62
+ begin_c_declaration("}")
52
63
  }
53
64
  C_DECLARATION
54
65
  {
55
- @lexer.status = :initial
56
- @lexer.end_symbol = nil
66
+ end_c_declaration
57
67
  }
58
68
  "}"
59
69
  {
60
- @grammar.initial_action = @grammar.build_code(:initial_action, val[3])
70
+ @grammar.initial_action = Grammar::Code::InitialActionCode.new(type: :initial_action, token_code: val[3])
61
71
  }
62
72
  | ";"
63
73
 
64
74
  grammar_declaration: "%union" "{"
65
75
  {
66
- @lexer.status = :c_declaration
67
- @lexer.end_symbol = '}'
76
+ begin_c_declaration("}")
68
77
  }
69
78
  C_DECLARATION
70
79
  {
71
- @lexer.status = :initial
72
- @lexer.end_symbol = nil
80
+ end_c_declaration
73
81
  }
74
82
  "}"
75
83
  {
76
- @grammar.set_union(@grammar.build_code(:union, val[3]), val[3].line)
84
+ @grammar.set_union(
85
+ Grammar::Code::NoReferenceCode.new(type: :union, token_code: val[3]),
86
+ val[3].line
87
+ )
77
88
  }
78
89
  | symbol_declaration
79
90
  | "%destructor" "{"
80
91
  {
81
- @lexer.status = :c_declaration
82
- @lexer.end_symbol = '}'
92
+ begin_c_declaration("}")
83
93
  }
84
94
  C_DECLARATION
85
95
  {
86
- @lexer.status = :initial
87
- @lexer.end_symbol = nil
96
+ end_c_declaration
88
97
  }
89
- "}" generic_symlist
98
+ "}" generic_symlist
90
99
  | "%printer" "{"
91
100
  {
92
- @lexer.status = :c_declaration
93
- @lexer.end_symbol = '}'
101
+ begin_c_declaration("}")
94
102
  }
95
103
  C_DECLARATION
96
104
  {
97
- @lexer.status = :initial
98
- @lexer.end_symbol = nil
105
+ end_c_declaration
99
106
  }
100
107
  "}" generic_symlist
101
108
  {
102
- @grammar.add_printer(ident_or_tags: val[6], code: @grammar.build_code(:printer, val[3]), lineno: val[3].line)
109
+ @grammar.add_printer(
110
+ ident_or_tags: val[6],
111
+ token_code: val[3],
112
+ lineno: val[3].line
113
+ )
103
114
  }
104
115
  | "%error-token" "{"
105
116
  {
106
- @lexer.status = :c_declaration
107
- @lexer.end_symbol = '}'
117
+ begin_c_declaration("}")
108
118
  }
109
119
  C_DECLARATION
110
120
  {
111
- @lexer.status = :initial
112
- @lexer.end_symbol = nil
121
+ end_c_declaration
113
122
  }
114
123
  "}" generic_symlist
115
124
  {
116
- @grammar.add_error_token(ident_or_tags: val[6], code: @grammar.build_code(:error_token, val[3]), lineno: val[3].line)
125
+ @grammar.add_error_token(
126
+ ident_or_tags: val[6],
127
+ token_code: val[3],
128
+ lineno: val[3].line
129
+ )
117
130
  }
118
131
 
119
132
  symbol_declaration: "%token" token_declarations
@@ -217,13 +230,11 @@ rule
217
230
 
218
231
  params: params "{"
219
232
  {
220
- @lexer.status = :c_declaration
221
- @lexer.end_symbol = '}'
233
+ begin_c_declaration("}")
222
234
  }
223
235
  C_DECLARATION
224
236
  {
225
- @lexer.status = :initial
226
- @lexer.end_symbol = nil
237
+ end_c_declaration
227
238
  }
228
239
  "}"
229
240
  {
@@ -231,13 +242,11 @@ rule
231
242
  }
232
243
  | "{"
233
244
  {
234
- @lexer.status = :c_declaration
235
- @lexer.end_symbol = '}'
245
+ begin_c_declaration("}")
236
246
  }
237
247
  C_DECLARATION
238
248
  {
239
- @lexer.status = :initial
240
- @lexer.end_symbol = nil
249
+ end_c_declaration
241
250
  }
242
251
  "}"
243
252
  {
@@ -252,9 +261,9 @@ rule
252
261
  {
253
262
  result = [{tag: val[0], tokens: val[1]}]
254
263
  }
255
- | token_declarations_for_precedence token_declaration_list_for_precedence
264
+ | token_declarations_for_precedence TAG token_declaration_list_for_precedence
256
265
  {
257
- result = val[0].append({tag: nil, tokens: val[1]})
266
+ result = val[0].append({tag: val[1], tokens: val[2]})
258
267
  }
259
268
 
260
269
  token_declaration_list_for_precedence: token_declaration_for_precedence { result = [val[0]] }
@@ -262,8 +271,8 @@ rule
262
271
 
263
272
  token_declaration_for_precedence: id
264
273
 
265
- id: IDENTIFIER { raise "Ident after %prec" if @prec_seen }
266
- | CHARACTER { raise "Char after %prec" if @prec_seen }
274
+ id: IDENTIFIER { on_action_error("ident after %prec", val[0]) if @prec_seen }
275
+ | CHARACTER { on_action_error("char after %prec", val[0]) if @prec_seen }
267
276
 
268
277
  grammar: rules_or_grammar_declaration
269
278
  | grammar rules_or_grammar_declaration
@@ -274,81 +283,104 @@ rule
274
283
  rules: id_colon named_ref_opt ":" rhs_list
275
284
  {
276
285
  lhs = val[0]
277
- lhs.alias = val[1]
278
- val[3].each {|hash|
279
- @grammar.add_rule(lhs: lhs, rhs: hash[:rhs], lineno: hash[:lineno])
280
- }
286
+ lhs.alias_name = val[1]
287
+ val[3].each do |builder|
288
+ builder.lhs = lhs
289
+ builder.complete_input
290
+ @grammar.add_rule_builder(builder)
291
+ end
281
292
  }
282
293
 
283
294
  rhs_list: rhs
284
295
  {
285
- result = [{rhs: val[0], lineno: val[0].first&.line || @lexer.line - 1}]
296
+ builder = val[0]
297
+ if !builder.line
298
+ builder.line = @lexer.line - 1
299
+ end
300
+ result = [builder]
286
301
  }
287
302
  | rhs_list "|" rhs
288
303
  {
289
- result = val[0].append({rhs: val[2], lineno: val[2].first&.line || @lexer.line - 1})
304
+ builder = val[2]
305
+ if !builder.line
306
+ builder.line = @lexer.line - 1
307
+ end
308
+ result = val[0].append(builder)
290
309
  }
291
310
  | rhs_list ";"
292
311
 
293
312
  rhs: /* empty */
294
313
  {
295
- result = []
296
- @prec_seen = false
297
- @code_after_prec = false
314
+ reset_precs
315
+ result = Grammar::RuleBuilder.new(@rule_counter, @midrule_action_counter)
316
+ }
317
+ | "%empty"
318
+ {
319
+ reset_precs
320
+ result = Grammar::RuleBuilder.new(@rule_counter, @midrule_action_counter)
298
321
  }
299
322
  | rhs symbol named_ref_opt
300
323
  {
301
324
  token = val[1]
302
- token.alias = val[2]
303
- result = val[0].append(token)
325
+ token.alias_name = val[2]
326
+ builder = val[0]
327
+ builder.add_rhs(token)
328
+ result = builder
304
329
  }
305
- | rhs "{"
330
+ | rhs IDENTIFIER parameterizing_suffix
306
331
  {
307
- if @prec_seen
308
- raise "Multiple User_code after %prec" if @code_after_prec
309
- @code_after_prec = true
310
- end
311
- @lexer.status = :c_declaration
312
- @lexer.end_symbol = '}'
332
+ token = Lrama::Lexer::Token::Parameterizing.new(s_value: val[2], location: @lexer.location, args: [val[1]])
333
+ builder = val[0]
334
+ builder.add_rhs(token)
335
+ result = builder
313
336
  }
314
- C_DECLARATION
337
+ | rhs IDENTIFIER "(" symbol ")"
315
338
  {
316
- @lexer.status = :initial
317
- @lexer.end_symbol = nil
339
+ token = Lrama::Lexer::Token::Parameterizing.new(s_value: val[1].s_value, location: @lexer.location, args: [val[3]])
340
+ builder = val[0]
341
+ builder.add_rhs(token)
342
+ result = builder
318
343
  }
319
- "}" named_ref_opt
320
- {
321
- token = val[3]
322
- token.alias = val[6]
323
- result = val[0].append(token)
324
- }
325
- | "{"
344
+ | rhs IDENTIFIER "(" symbol "," symbol ")"
345
+ {
346
+ token = Lrama::Lexer::Token::Parameterizing.new(s_value: val[1].s_value, location: @lexer.location, args: [val[3], val[5]])
347
+ builder = val[0]
348
+ builder.add_rhs(token)
349
+ result = builder
350
+ }
351
+ | rhs "{"
326
352
  {
327
353
  if @prec_seen
328
- raise "Multiple User_code after %prec" if @code_after_prec
354
+ on_action_error("multiple User_code after %prec", val[0]) if @code_after_prec
329
355
  @code_after_prec = true
330
356
  end
331
- @lexer.status = :c_declaration
332
- @lexer.end_symbol = '}'
357
+ begin_c_declaration("}")
333
358
  }
334
359
  C_DECLARATION
335
360
  {
336
- @lexer.status = :initial
337
- @lexer.end_symbol = nil
361
+ end_c_declaration
338
362
  }
339
363
  "}" named_ref_opt
340
364
  {
341
- token = val[2]
342
- token.alias = val[5]
343
- result = [token]
365
+ token = val[3]
366
+ token.alias_name = val[6]
367
+ builder = val[0]
368
+ builder.user_code = token
369
+ result = builder
344
370
  }
345
371
  | rhs "%prec" symbol
346
372
  {
347
373
  sym = @grammar.find_symbol_by_id!(val[2])
348
- result = val[0].append(sym)
349
374
  @prec_seen = true
375
+ builder = val[0]
376
+ builder.precedence_sym = sym
377
+ result = builder
350
378
  }
351
379
 
380
+ parameterizing_suffix: "?"
381
+ | "+"
382
+ | "*"
383
+
352
384
  named_ref_opt: # empty
353
385
  | '[' IDENTIFIER ']' { result = val[1].s_value }
354
386
 
@@ -357,14 +389,12 @@ rule
357
389
  epilogue_opt: # empty
358
390
  | "%%"
359
391
  {
360
- @lexer.status = :c_declaration
361
- @lexer.end_symbol = '\Z'
392
+ begin_c_declaration('\Z')
362
393
  @grammar.epilogue_first_lineno = @lexer.line + 1
363
394
  }
364
395
  C_DECLARATION
365
396
  {
366
- @lexer.status = :initial
367
- @lexer.end_symbol = nil
397
+ end_c_declaration
368
398
  @grammar.epilogue = val[2].s_value
369
399
  }
370
400
 
@@ -381,28 +411,29 @@ rule
381
411
  generic_symlist_item: symbol
382
412
  | TAG
383
413
 
384
- string_as_id: STRING { result = Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Ident, s_value: val[0]) }
414
+ string_as_id: STRING { result = Lrama::Lexer::Token::Ident.new(s_value: val[0]) }
385
415
  end
386
416
 
387
417
  ---- inner
388
418
 
389
419
  include Lrama::Report::Duration
390
420
 
391
- def initialize(text, path)
421
+ def initialize(text, path, debug = false)
392
422
  @text = text
393
423
  @path = path
424
+ @yydebug = debug
425
+ @rule_counter = Lrama::Grammar::Counter.new(0)
426
+ @midrule_action_counter = Lrama::Grammar::Counter.new(1)
394
427
  end
395
428
 
396
429
  def parse
397
430
  report_duration(:parse) do
398
431
  @lexer = Lrama::Lexer.new(@text)
399
- @grammar = Lrama::Grammar.new
432
+ @grammar = Lrama::Grammar.new(@rule_counter)
400
433
  @precedence_number = 0
434
+ reset_precs
401
435
  do_parse
402
- @grammar.extract_references
403
436
  @grammar.prepare
404
- @grammar.compute_nullable
405
- @grammar.compute_first_set
406
437
  @grammar.validate!
407
438
  @grammar
408
439
  end
@@ -413,10 +444,60 @@ def next_token
413
444
  end
414
445
 
415
446
  def on_error(error_token_id, error_value, value_stack)
416
- source = @text.split("\n")[error_value.line - 1]
447
+ if error_value.is_a?(Lrama::Lexer::Token)
448
+ line = error_value.first_line
449
+ first_column = error_value.first_column
450
+ last_column = error_value.last_column
451
+ value = "'#{error_value.s_value}'"
452
+ else
453
+ line = @lexer.line
454
+ first_column = @lexer.head_column
455
+ last_column = @lexer.column
456
+ value = error_value.inspect
457
+ end
458
+
417
459
  raise ParseError, <<~ERROR
418
- #{@path}:#{@lexer.line}:#{@lexer.column}: parse error on value #{error_value.inspect} (#{token_to_str(error_token_id) || '?'})
419
- #{source}
420
- #{' ' * @lexer.column}^
460
+ #{@path}:#{line}:#{first_column}: parse error on value #{value} (#{token_to_str(error_token_id) || '?'})
461
+ #{@text.split("\n")[line - 1]}
462
+ #{carrets(first_column, last_column)}
421
463
  ERROR
422
464
  end
465
+
466
+ def on_action_error(error_message, error_value)
467
+ if error_value.is_a?(Lrama::Lexer::Token)
468
+ line = error_value.first_line
469
+ first_column = error_value.first_column
470
+ last_column = error_value.last_column
471
+ else
472
+ line = @lexer.line
473
+ first_column = @lexer.head_column
474
+ last_column = @lexer.column
475
+ end
476
+
477
+ raise ParseError, <<~ERROR
478
+ #{@path}:#{line}: #{error_message}
479
+ #{@text.split("\n")[line - 1]}
480
+ #{carrets(first_column, last_column)}
481
+ ERROR
482
+ end
483
+
484
+ private
485
+
486
+ def reset_precs
487
+ @prec_seen = false
488
+ @code_after_prec = false
489
+ end
490
+
491
+ def begin_c_declaration(end_symbol)
492
+ @lexer.status = :c_declaration
493
+ @lexer.end_symbol = end_symbol
494
+ end
495
+
496
+ def end_c_declaration
497
+ @lexer.status = :initial
498
+ @lexer.end_symbol = nil
499
+ end
500
+
501
+ def carrets(first_column, last_column)
502
+ ' ' * (first_column + 1) + '^' * (last_column - first_column)
503
+ end
@@ -2,7 +2,7 @@
2
2
  sources:
3
3
  - type: git
4
4
  name: ruby/gem_rbs_collection
5
- revision: 95ad664324500c9eec78569b45da98c65a27a511
5
+ revision: 25286c51a19927f28623aee3cd36655f902399ba
6
6
  remote: https://github.com/ruby/gem_rbs_collection.git
7
7
  repo_dir: gems
8
8
  path: ".gem_rbs_collection"
@@ -11,6 +11,22 @@ gems:
11
11
  version: '0'
12
12
  source:
13
13
  type: stdlib
14
+ - name: fileutils
15
+ version: '0'
16
+ source:
17
+ type: stdlib
18
+ - name: forwardable
19
+ version: '0'
20
+ source:
21
+ type: stdlib
22
+ - name: rake
23
+ version: '13.0'
24
+ source:
25
+ type: git
26
+ name: ruby/gem_rbs_collection
27
+ revision: 2de2d4535caba275f3b8533684aab110d921f553
28
+ remote: https://github.com/ruby/gem_rbs_collection.git
29
+ repo_dir: gems
14
30
  - name: stackprof
15
31
  version: '0.2'
16
32
  source:
data/rbs_collection.yaml CHANGED
@@ -20,3 +20,4 @@ gems:
20
20
  # It's unnecessary if you don't use rbs as a library.
21
21
  - name: rbs
22
22
  ignore: true
23
+ - name: forwardable
data/sample/calc.y CHANGED
@@ -15,10 +15,12 @@
15
15
  #include <stdio.h>
16
16
  #include <stdlib.h>
17
17
  #include <ctype.h>
18
+ %}
18
19
 
20
+ %code provides {
19
21
  static int yylex(YYSTYPE *val, YYLTYPE *loc);
20
22
  static int yyerror(YYLTYPE *loc, const char *str);
21
- %}
23
+ }
22
24
 
23
25
  %union {
24
26
  int val;
data/sample/parse.y CHANGED
@@ -4,10 +4,14 @@
4
4
 
5
5
  %{
6
6
  // Prologue
7
+ %}
8
+
9
+ %code provides {
10
+
7
11
  static enum yytokentype yylex(YYSTYPE *lval, YYLTYPE *yylloc);
8
12
  static void yyerror(YYLTYPE *yylloc, const char *msg);
9
13
 
10
- %}
14
+ }
11
15
 
12
16
  %expect 0
13
17
  %define api.pure
@@ -0,0 +1,15 @@
1
+ module Lrama
2
+ class Grammar
3
+ class Code
4
+ class PrinterCode < Code
5
+ @tag: untyped
6
+ def initialize: (?type: untyped, ?token_code: untyped, ?tag: untyped) -> void
7
+
8
+ private
9
+
10
+ # ref: Lrama::Grammar::Code.token_code.references
11
+ def reference_to_c: (untyped ref) -> untyped
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,24 @@
1
+ module Lrama
2
+ class Grammar
3
+ class Code
4
+ extend Forwardable
5
+
6
+ attr_accessor type: untyped
7
+ attr_accessor token_code: untyped
8
+
9
+ # delegated
10
+ def s_value: -> String
11
+ def line: -> Integer
12
+ def column: -> untyped
13
+ def references: -> untyped
14
+
15
+ def initialize: (?type: untyped, ?token_code: untyped) -> void
16
+
17
+ def translated_code: () -> String
18
+
19
+ private
20
+
21
+ def reference_to_c: (untyped ref) -> untyped
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,11 @@
1
+ module Lrama
2
+ class Grammar
3
+ class Counter
4
+ @number: Integer
5
+
6
+ def initialize: (Integer number) -> void
7
+
8
+ def increment: () -> Integer
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ module Lrama
2
+ class Grammar
3
+ class ParameterizingRules
4
+ class Builder
5
+ def initialize: (Lexer::Token token, Counter rule_counter, Lexer::Token lhs, Lexer::Token::UserCode? user_code, Lexer::Token? precedence_sym, Integer? line) -> void
6
+ def build: () -> Array[Rule]
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Lrama
2
+ class Grammar
3
+ class PercentCode
4
+ attr_reader id: Lexer::Token::Ident
5
+ attr_reader code: Lexer::Token::UserCode
6
+
7
+ def initialize: (Lexer::Token::Ident id, Lexer::Token::UserCode code) -> void
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ module Lrama
2
+ class Grammar
3
+ class Precedence
4
+ include Comparable
5
+ attr_accessor type: Symbol
6
+ attr_accessor precedence: Integer
7
+
8
+ def <=>: (Precedence other) -> Integer
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Lrama
2
+ class Grammar
3
+ class Printer
4
+ attr_accessor ident_or_tags: Array[Lexer::Token::Ident|Lexer::Token::Tag]
5
+ attr_accessor token_code: Grammar::Code
6
+ attr_accessor lineno: Integer
7
+
8
+ def translated_code: (Lexer::Token member) -> String
9
+ end
10
+ end
11
+ end