lrama 0.6.9 → 0.6.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yaml +24 -1
  3. data/.gitignore +2 -0
  4. data/Gemfile +6 -3
  5. data/NEWS.md +269 -14
  6. data/README.md +41 -4
  7. data/Rakefile +2 -0
  8. data/Steepfile +9 -17
  9. data/doc/development/compressed_state_table/main.md +635 -0
  10. data/doc/development/compressed_state_table/parse.output +174 -0
  11. data/doc/development/compressed_state_table/parse.y +22 -0
  12. data/doc/development/compressed_state_table/parser.rb +282 -0
  13. data/exe/lrama +1 -0
  14. data/lib/lrama/bitmap.rb +3 -1
  15. data/lib/lrama/command.rb +8 -14
  16. data/lib/lrama/context.rb +11 -9
  17. data/lib/lrama/counterexamples/derivation.rb +8 -5
  18. data/lib/lrama/counterexamples/example.rb +9 -4
  19. data/lib/lrama/counterexamples/path.rb +6 -0
  20. data/lib/lrama/counterexamples/production_path.rb +2 -0
  21. data/lib/lrama/counterexamples/start_path.rb +2 -0
  22. data/lib/lrama/counterexamples/state_item.rb +2 -0
  23. data/lib/lrama/counterexamples/transition_path.rb +2 -0
  24. data/lib/lrama/counterexamples/triple.rb +2 -0
  25. data/lib/lrama/counterexamples.rb +36 -24
  26. data/lib/lrama/diagnostics.rb +36 -0
  27. data/lib/lrama/digraph.rb +2 -0
  28. data/lib/lrama/grammar/auxiliary.rb +2 -0
  29. data/lib/lrama/grammar/binding.rb +12 -1
  30. data/lib/lrama/grammar/code/destructor_code.rb +2 -0
  31. data/lib/lrama/grammar/code/initial_action_code.rb +2 -0
  32. data/lib/lrama/grammar/code/no_reference_code.rb +2 -0
  33. data/lib/lrama/grammar/code/printer_code.rb +2 -0
  34. data/lib/lrama/grammar/code/rule_action.rb +7 -3
  35. data/lib/lrama/grammar/code.rb +7 -5
  36. data/lib/lrama/grammar/counter.rb +2 -0
  37. data/lib/lrama/grammar/destructor.rb +2 -0
  38. data/lib/lrama/grammar/error_token.rb +2 -0
  39. data/lib/lrama/grammar/parameterizing_rule/resolver.rb +7 -1
  40. data/lib/lrama/grammar/parameterizing_rule/rhs.rb +6 -3
  41. data/lib/lrama/grammar/parameterizing_rule/rule.rb +6 -0
  42. data/lib/lrama/grammar/parameterizing_rule.rb +2 -0
  43. data/lib/lrama/grammar/percent_code.rb +2 -0
  44. data/lib/lrama/grammar/precedence.rb +2 -0
  45. data/lib/lrama/grammar/printer.rb +2 -0
  46. data/lib/lrama/grammar/reference.rb +2 -0
  47. data/lib/lrama/grammar/rule.rb +10 -3
  48. data/lib/lrama/grammar/rule_builder.rb +64 -65
  49. data/lib/lrama/grammar/symbol.rb +2 -0
  50. data/lib/lrama/grammar/symbols/resolver.rb +9 -1
  51. data/lib/lrama/grammar/symbols.rb +2 -0
  52. data/lib/lrama/grammar/type.rb +2 -0
  53. data/lib/lrama/grammar/union.rb +2 -0
  54. data/lib/lrama/grammar.rb +53 -32
  55. data/lib/lrama/grammar_validator.rb +37 -0
  56. data/lib/lrama/lexer/grammar_file.rb +2 -0
  57. data/lib/lrama/lexer/location.rb +2 -0
  58. data/lib/lrama/lexer/token/char.rb +2 -0
  59. data/lib/lrama/lexer/token/ident.rb +2 -0
  60. data/lib/lrama/lexer/token/instantiate_rule.rb +2 -0
  61. data/lib/lrama/lexer/token/tag.rb +2 -0
  62. data/lib/lrama/lexer/token/user_code.rb +4 -2
  63. data/lib/lrama/lexer/token.rb +7 -5
  64. data/lib/lrama/lexer.rb +12 -8
  65. data/lib/lrama/{warning.rb → logger.rb} +5 -13
  66. data/lib/lrama/option_parser.rb +58 -33
  67. data/lib/lrama/options.rb +5 -2
  68. data/lib/lrama/output.rb +38 -69
  69. data/lib/lrama/parser.rb +677 -773
  70. data/lib/lrama/report/duration.rb +2 -0
  71. data/lib/lrama/report/profile.rb +2 -0
  72. data/lib/lrama/report.rb +4 -2
  73. data/lib/lrama/state/reduce.rb +4 -2
  74. data/lib/lrama/state/reduce_reduce_conflict.rb +2 -0
  75. data/lib/lrama/state/resolved_conflict.rb +3 -1
  76. data/lib/lrama/state/shift.rb +2 -0
  77. data/lib/lrama/state/shift_reduce_conflict.rb +2 -0
  78. data/lib/lrama/state.rb +7 -5
  79. data/lib/lrama/states/item.rb +5 -3
  80. data/lib/lrama/states.rb +18 -46
  81. data/lib/lrama/states_reporter.rb +60 -19
  82. data/lib/lrama/trace_reporter.rb +30 -0
  83. data/lib/lrama/version.rb +3 -1
  84. data/lib/lrama.rb +22 -17
  85. data/lrama.gemspec +3 -1
  86. data/parser.y +129 -237
  87. data/rbs_collection.lock.yaml +10 -2
  88. data/sig/lrama/counterexamples/derivation.rbs +33 -0
  89. data/sig/lrama/counterexamples/example.rbs +45 -0
  90. data/sig/lrama/counterexamples/path.rbs +21 -0
  91. data/sig/lrama/counterexamples/production_path.rbs +11 -0
  92. data/sig/lrama/counterexamples/start_path.rbs +13 -0
  93. data/sig/lrama/counterexamples/state_item.rbs +10 -0
  94. data/sig/lrama/counterexamples/transition_path.rbs +11 -0
  95. data/sig/lrama/counterexamples/triple.rbs +20 -0
  96. data/sig/lrama/counterexamples.rbs +29 -0
  97. data/sig/lrama/grammar/auxiliary.rbs +10 -0
  98. data/sig/lrama/grammar/binding.rbs +4 -0
  99. data/sig/lrama/grammar/code/destructor_code.rbs +3 -4
  100. data/sig/lrama/grammar/code/initial_action_code.rbs +15 -0
  101. data/sig/lrama/grammar/code/no_reference_code.rbs +15 -0
  102. data/sig/lrama/grammar/code/printer_code.rbs +3 -4
  103. data/sig/lrama/grammar/code/rule_action.rbs +19 -0
  104. data/sig/lrama/grammar/code.rbs +3 -3
  105. data/sig/lrama/grammar/destructor.rbs +3 -1
  106. data/sig/lrama/grammar/error_token.rbs +4 -2
  107. data/sig/lrama/grammar/parameterizing_rule/resolver.rbs +2 -1
  108. data/sig/lrama/grammar/parameterizing_rule/rhs.rbs +1 -1
  109. data/sig/lrama/grammar/precedence.rbs +3 -1
  110. data/sig/lrama/grammar/printer.rbs +3 -1
  111. data/sig/lrama/grammar/rule.rbs +35 -3
  112. data/sig/lrama/grammar/rule_builder.rbs +10 -9
  113. data/sig/lrama/grammar/symbol.rbs +6 -6
  114. data/sig/lrama/grammar/symbols/resolver.rbs +24 -5
  115. data/sig/lrama/grammar/type.rbs +2 -2
  116. data/sig/lrama/grammar/union.rbs +12 -0
  117. data/sig/lrama/grammar.rbs +104 -1
  118. data/sig/lrama/options.rbs +3 -2
  119. data/sig/lrama/state/reduce.rbs +20 -0
  120. data/sig/lrama/state/reduce_reduce_conflict.rbs +13 -0
  121. data/sig/lrama/state/resolved_conflict.rbs +14 -0
  122. data/sig/lrama/state/shift.rbs +14 -0
  123. data/sig/lrama/state/shift_reduce_conflict.rbs +13 -0
  124. data/sig/lrama/state.rbs +79 -0
  125. data/sig/lrama/states/item.rbs +30 -0
  126. data/sig/lrama/states.rbs +101 -0
  127. data/template/bison/yacc.c +24 -19
  128. metadata +32 -6
  129. data/sample/calc.output +0 -263
  130. data/sample/calc.y +0 -101
  131. data/sample/parse.y +0 -59
@@ -0,0 +1,174 @@
1
+ Symbol
2
+
3
+ -2 EMPTY
4
+ 0 "end of file"
5
+ 1 error
6
+ 2 "invalid token" (undef)
7
+ 3 LF
8
+ 4 NUM
9
+ 5 '+'
10
+ 6 '*'
11
+ 7 '('
12
+ 8 ')'
13
+ 9 $accept # Start of nonterminal
14
+ 10 program
15
+ 11 expr
16
+
17
+
18
+ Grammar
19
+
20
+ 0 $accept: program "end of file"
21
+
22
+ 1 program: ε
23
+ 2 | expr LF
24
+
25
+ 3 expr: NUM
26
+ 4 | expr '+' expr
27
+ 5 | expr '*' expr
28
+ 6 | '(' expr ')'
29
+
30
+
31
+ State 0
32
+
33
+ 0 $accept: • program "end of file"
34
+ 1 program: ε • ["end of file"]
35
+ 2 | • expr LF
36
+ 3 expr: • NUM
37
+ 4 | • expr '+' expr
38
+ 5 | • expr '*' expr
39
+ 6 | • '(' expr ')'
40
+
41
+ NUM shift, and go to state 1
42
+ '(' shift, and go to state 2
43
+
44
+ $default reduce using rule 1 (program)
45
+
46
+ program go to state 3
47
+ expr go to state 4
48
+
49
+
50
+ State 1
51
+
52
+ 3 expr: NUM •
53
+
54
+ $default reduce using rule 3 (expr)
55
+
56
+
57
+ State 2
58
+
59
+ 3 expr: • NUM
60
+ 4 | • expr '+' expr
61
+ 5 | • expr '*' expr
62
+ 6 | • '(' expr ')'
63
+ 6 | '(' • expr ')'
64
+
65
+ NUM shift, and go to state 1
66
+ '(' shift, and go to state 2
67
+
68
+ expr go to state 5
69
+
70
+
71
+ State 3
72
+
73
+ 0 $accept: program • "end of file"
74
+
75
+ "end of file" shift, and go to state 6
76
+
77
+
78
+ State 4
79
+
80
+ 2 program: expr • LF
81
+ 4 expr: expr • '+' expr
82
+ 5 | expr • '*' expr
83
+
84
+ LF shift, and go to state 7
85
+ '+' shift, and go to state 8
86
+ '*' shift, and go to state 9
87
+
88
+
89
+ State 5
90
+
91
+ 4 expr: expr • '+' expr
92
+ 5 | expr • '*' expr
93
+ 6 | '(' expr • ')'
94
+
95
+ '+' shift, and go to state 8
96
+ '*' shift, and go to state 9
97
+ ')' shift, and go to state 10
98
+
99
+
100
+ State 6
101
+
102
+ 0 $accept: program "end of file" •
103
+
104
+ $default accept
105
+
106
+
107
+ State 7
108
+
109
+ 2 program: expr LF •
110
+
111
+ $default reduce using rule 2 (program)
112
+
113
+
114
+ State 8
115
+
116
+ 3 expr: • NUM
117
+ 4 | • expr '+' expr
118
+ 4 | expr '+' • expr
119
+ 5 | • expr '*' expr
120
+ 6 | • '(' expr ')'
121
+
122
+ NUM shift, and go to state 1
123
+ '(' shift, and go to state 2
124
+
125
+ expr go to state 11
126
+
127
+
128
+ State 9
129
+
130
+ 3 expr: • NUM
131
+ 4 | • expr '+' expr
132
+ 5 | • expr '*' expr
133
+ 5 | expr '*' • expr
134
+ 6 | • '(' expr ')'
135
+
136
+ NUM shift, and go to state 1
137
+ '(' shift, and go to state 2
138
+
139
+ expr go to state 12
140
+
141
+
142
+ State 10
143
+
144
+ 6 expr: '(' expr ')' •
145
+
146
+ $default reduce using rule 6 (expr)
147
+
148
+
149
+ State 11
150
+
151
+ 4 expr: expr • '+' expr
152
+ 4 | expr '+' expr • [LF, '+', ')']
153
+ 5 | expr • '*' expr
154
+
155
+ '*' shift, and go to state 9
156
+
157
+ $default reduce using rule 4 (expr)
158
+
159
+ Conflict between rule 4 and token '+' resolved as reduce (%left '+').
160
+ Conflict between rule 4 and token '*' resolved as shift ('+' < '*').
161
+
162
+
163
+ State 12
164
+
165
+ 4 expr: expr • '+' expr
166
+ 5 | expr • '*' expr
167
+ 5 | expr '*' expr • [LF, '+', '*', ')']
168
+
169
+ $default reduce using rule 5 (expr)
170
+
171
+ Conflict between rule 5 and token '+' resolved as reduce ('+' < '*').
172
+ Conflict between rule 5 and token '*' resolved as reduce (%left '*').
173
+
174
+
@@ -0,0 +1,22 @@
1
+ %union {
2
+ int val;
3
+ }
4
+ %token LF
5
+ %token <val> NUM
6
+ %type <val> expr
7
+ %left '+'
8
+ %left '*'
9
+
10
+ %%
11
+
12
+ program : /* empty */
13
+ | expr LF { printf("=> %d\n", $1); }
14
+ ;
15
+
16
+ expr : NUM
17
+ | expr '+' expr { $$ = $1 + $3; }
18
+ | expr '*' expr { $$ = $1 * $3; }
19
+ | '(' expr ')' { $$ = $2; }
20
+ ;
21
+
22
+ %%
@@ -0,0 +1,282 @@
1
+ class Parser
2
+ YYNTOKENS = 9
3
+ YYLAST = 13
4
+ YYTABLE_NINF = -1
5
+ YYTABLE = [ 5, 6, 7, 9, 8, 9, 11, 12, 8, 9, 1, 10, 0, 2]
6
+ YYCHECK = [ 2, 0, 3, 6, 5, 6, 8, 9, 5, 6, 4, 8, -1, 7]
7
+
8
+ YYPACT_NINF = -4
9
+ YYPACT = [ 6, -4, 6, 1, -1, 3, -4, -4, 6, 6, -4, -3, -4]
10
+ YYPGOTO = [ -4, -4, -2]
11
+
12
+ YYDEFACT = [ 2, 4, 0, 0, 0, 0, 1, 3, 0, 0, 7, 5, 6]
13
+ YYDEFGOTO = [ 0, 3, 4]
14
+
15
+ YYR1 = [ 0, 9, 10, 10, 11, 11, 11, 11]
16
+ YYR2 = [ 0, 2, 0, 2, 1, 3, 3, 3]
17
+
18
+ YYFINAL = 6
19
+
20
+ # Symbols
21
+ SYM_EMPTY = -2
22
+ SYM_EOF = 0 # "end of file"
23
+ SYM_ERROR = 1 # error
24
+ SYM_UNDEF = 2 # Invalid Token
25
+ SYM_LF = 3 # LF
26
+ SYM_NUM = 4 # NUM
27
+ SYM_PLUS = 5 # '+'
28
+ SYM_ASTER = 6 # '*'
29
+ SYM_LPAREN = 7 # '('
30
+ SYM_RPAREN = 8 # ')'
31
+ # Start of nonterminal
32
+ SYM_ACCEPT = 9 # $accept
33
+ SYM_PROGRAM = 10 # program
34
+ SYM_EXPR = 11 # expr
35
+
36
+ def initialize(debug = false)
37
+ @debug = debug
38
+ end
39
+
40
+ def parse(lexer)
41
+ state = 0
42
+ stack = []
43
+ yytoken = SYM_EMPTY
44
+ parser_action = :push_state
45
+ next_state = nil
46
+ rule = nil
47
+
48
+ while true
49
+ _parser_action = parser_action
50
+ parser_action = nil
51
+
52
+ case _parser_action
53
+ when :syntax_error
54
+ debug_print("Entering :syntax_error")
55
+
56
+ return 1
57
+ when :accept
58
+ debug_print("Entering :accept")
59
+
60
+ return 0
61
+ when :push_state
62
+ # Precondition: `state` is set to new state
63
+ debug_print("Entering :push_state")
64
+
65
+ debug_print("Push state #{state}")
66
+ stack.push(state)
67
+ debug_print("Current stack #{stack}")
68
+
69
+ if state == YYFINAL
70
+ parser_action = :accept
71
+ next
72
+ end
73
+
74
+ parser_action = :decide_parser_action
75
+ next
76
+ when :decide_parser_action
77
+ debug_print("Entering :decide_parser_action")
78
+
79
+ offset = yypact[state]
80
+ if offset == YYPACT_NINF
81
+ parser_action = :yydefault
82
+ next
83
+ end
84
+
85
+ # Ensure next token
86
+ if yytoken == SYM_EMPTY
87
+ debug_print("Reading a token")
88
+
89
+ yytoken = lexer.next_token
90
+ end
91
+
92
+ case yytoken
93
+ when SYM_EOF
94
+ debug_print("Now at end of input.")
95
+ when SYM_ERROR
96
+ parser_action = :syntax_error
97
+ next
98
+ else
99
+ debug_print("Next token is #{yytoken}")
100
+ end
101
+
102
+ idx = offset + yytoken
103
+ if idx < 0 || YYLAST < idx
104
+ debug_print("Decide next parser action as :yydefault")
105
+
106
+ parser_action = :yydefault
107
+ next
108
+ end
109
+ if yycheck[idx] != yytoken
110
+ debug_print("Decide next parser action as :yydefault")
111
+
112
+ parser_action = :yydefault
113
+ next
114
+ end
115
+
116
+ action = yytable[idx]
117
+ if action == YYTABLE_NINF
118
+ parser_action = :syntax_error
119
+ next
120
+ end
121
+ if action > 0
122
+ # Shift
123
+ debug_print("Decide next parser action as :yyshift")
124
+
125
+ next_state = action
126
+ parser_action = :yyshift
127
+ next
128
+ else
129
+ # Reduce
130
+ debug_print("Decide next parser action as :yyreduce")
131
+
132
+ rule = -action
133
+ parser_action = :yyreduce
134
+ next
135
+ end
136
+ when :yyshift
137
+ # Precondition: `next_state` is set
138
+ debug_print("Entering :yyshift")
139
+ raise "next_state is not set" unless next_state
140
+
141
+ yytoken = SYM_EMPTY
142
+ state = next_state
143
+ next_state = nil
144
+ parser_action = :push_state
145
+ next
146
+ when :yydefault
147
+ debug_print("Entering :yydefault")
148
+
149
+ rule = yydefact[state]
150
+ if rule == 0
151
+ parser_action = :syntax_error
152
+ next
153
+ end
154
+
155
+ parser_action = :yyreduce
156
+ next
157
+ when :yyreduce
158
+ # Precondition: `rule`, used for reduce, is set
159
+ debug_print("Entering :yyreduce")
160
+ raise "rule is not set" unless rule
161
+
162
+ rhs_length = yyr2[rule]
163
+ lhs_nterm = yyr1[rule]
164
+ lhs_nterm_id = lhs_nterm - YYNTOKENS
165
+
166
+ text = "Execute action for Rule (#{rule}) "
167
+ case rule
168
+ when 1
169
+ text << "$accept: program \"end of file\""
170
+ when 2
171
+ text << "program: ε"
172
+ when 3
173
+ text << "program: expr LF"
174
+ when 4
175
+ text << "expr: NUM"
176
+ when 5
177
+ text << "expr: expr '+' expr"
178
+ when 6
179
+ text << "expr: expr '*' expr"
180
+ when 7
181
+ text << "expr: '(' expr ')'"
182
+ end
183
+ debug_print(text)
184
+
185
+ debug_print("Pop #{rhs_length} elements")
186
+ debug_print("Stack before pop: #{stack}")
187
+ stack.pop(rhs_length)
188
+ debug_print("Stack after pop: #{stack}")
189
+ state = stack[-1]
190
+
191
+ # "Shift" LHS nonterminal
192
+ offset = yypgoto[lhs_nterm_id]
193
+ if offset == YYPACT_NINF
194
+ state = yydefgoto[lhs_nterm_id]
195
+ else
196
+ idx = offset + state
197
+ if idx < 0 || YYLAST < idx
198
+ state = yydefgoto[lhs_nterm_id]
199
+ elsif yycheck[idx] != state
200
+ state = yydefgoto[lhs_nterm_id]
201
+ else
202
+ state = yytable[idx]
203
+ end
204
+ end
205
+
206
+ rule = nil
207
+ parser_action = :push_state
208
+ next
209
+ else
210
+ raise "Unknown parser_action: #{parser_action}"
211
+ end
212
+ end
213
+ end
214
+
215
+ private
216
+
217
+ def debug_print(str)
218
+ if @debug
219
+ $stderr.puts str
220
+ end
221
+ end
222
+
223
+ def yytable
224
+ YYTABLE
225
+ end
226
+
227
+ def yycheck
228
+ YYCHECK
229
+ end
230
+
231
+ def yypact
232
+ YYPACT
233
+ end
234
+
235
+ def yypgoto
236
+ YYPGOTO
237
+ end
238
+
239
+ def yydefact
240
+ YYDEFACT
241
+ end
242
+
243
+ def yydefgoto
244
+ YYDEFGOTO
245
+ end
246
+
247
+ def yyr1
248
+ YYR1
249
+ end
250
+
251
+ def yyr2
252
+ YYR2
253
+ end
254
+ end
255
+
256
+ class Lexer
257
+ def initialize(tokens)
258
+ @tokens = tokens
259
+ @index = 0
260
+ end
261
+
262
+ def next_token
263
+ if @tokens.length > @index
264
+ token = @tokens[@index]
265
+ @index += 1
266
+ return token
267
+ else
268
+ return Parser::SYM_EOF
269
+ end
270
+ end
271
+ end
272
+
273
+ lexer = Lexer.new([
274
+ # 1 + 2 + 3 LF
275
+ Parser::SYM_NUM,
276
+ Parser::SYM_PLUS,
277
+ Parser::SYM_NUM,
278
+ Parser::SYM_PLUS,
279
+ Parser::SYM_NUM,
280
+ Parser::SYM_LF,
281
+ ])
282
+ Parser.new(debug: true).parse(lexer)
data/exe/lrama CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  $LOAD_PATH << File.join(__dir__, "../lib")
4
5
  require "lrama"
data/lib/lrama/bitmap.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lrama
2
4
  module Bitmap
3
5
  def self.from_array(ary)
@@ -11,7 +13,7 @@ module Lrama
11
13
  end
12
14
 
13
15
  def self.to_array(int)
14
- a = []
16
+ a = [] #: Array[Integer]
15
17
  i = 0
16
18
 
17
19
  while int > 0 do
data/lib/lrama/command.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lrama
2
4
  class Command
3
5
  LRAMA_LIB = File.realpath(File.join(File.dirname(__FILE__)))
@@ -14,7 +16,6 @@ module Lrama
14
16
 
15
17
  Report::Duration.enable if options.trace_opts[:time]
16
18
 
17
- warning = Lrama::Warning.new
18
19
  text = options.y.read
19
20
  options.y.close if options.y != STDIN
20
21
  begin
@@ -31,7 +32,7 @@ module Lrama
31
32
  message = message.gsub(/.+/, "\e[1m\\&\e[m") if Exception.to_tty?
32
33
  abort message
33
34
  end
34
- states = Lrama::States.new(grammar, warning, trace_state: (options.trace_opts[:automaton] || options.trace_opts[:closure]))
35
+ states = Lrama::States.new(grammar, trace_state: (options.trace_opts[:automaton] || options.trace_opts[:closure]))
35
36
  states.compute
36
37
  context = Lrama::Context.new(states)
37
38
 
@@ -42,15 +43,8 @@ module Lrama
42
43
  end
43
44
  end
44
45
 
45
- if options.trace_opts && options.trace_opts[:rules]
46
- puts "Grammar rules:"
47
- puts grammar.rules
48
- end
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
46
+ reporter = Lrama::TraceReporter.new(grammar)
47
+ reporter.report(**options.trace_opts)
54
48
 
55
49
  File.open(options.outfile, "w+") do |f|
56
50
  Lrama::Output.new(
@@ -65,9 +59,9 @@ module Lrama
65
59
  ).render
66
60
  end
67
61
 
68
- if warning.has_error?
69
- exit false
70
- end
62
+ logger = Lrama::Logger.new
63
+ exit false unless Lrama::GrammarValidator.new(grammar, states, logger).valid?
64
+ Lrama::Diagnostics.new(grammar, states, logger).run(options.diagnostic)
71
65
  end
72
66
  end
73
67
  end
data/lib/lrama/context.rb CHANGED
@@ -1,4 +1,6 @@
1
- require "lrama/report/duration"
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "report/duration"
2
4
 
3
5
  module Lrama
4
6
  # This is passed to a template
@@ -253,7 +255,7 @@ module Lrama
253
255
 
254
256
  # If no default_reduction_rule, default behavior is an
255
257
  # error then replace ErrorActionNumber with zero.
256
- if !state.default_reduction_rule
258
+ unless state.default_reduction_rule
257
259
  actions.map! do |e|
258
260
  if e == ErrorActionNumber
259
261
  0
@@ -301,10 +303,7 @@ module Lrama
301
303
  end
302
304
 
303
305
  @states.nterms.each do |nterm|
304
- if !(states = nterm_to_next_states[nterm])
305
- default_goto = 0
306
- not_default_gotos = []
307
- else
306
+ if (states = nterm_to_next_states[nterm])
308
307
  default_state = states.map(&:last).group_by {|s| s }.max_by {|_, v| v.count }.first
309
308
  default_goto = default_state.id
310
309
  not_default_gotos = []
@@ -312,6 +311,9 @@ module Lrama
312
311
  next if to_state.id == default_goto
313
312
  not_default_gotos << [from_state.id, to_state.id]
314
313
  end
314
+ else
315
+ default_goto = 0
316
+ not_default_gotos = []
315
317
  end
316
318
 
317
319
  k = nterm_number_to_sequence_number(nterm.number)
@@ -403,7 +405,7 @@ module Lrama
403
405
  @check = []
404
406
  # Key is froms_and_tos, value is index position
405
407
  pushed = {}
406
- userd_res = {}
408
+ used_res = {}
407
409
  lowzero = 0
408
410
  high = 0
409
411
 
@@ -428,7 +430,7 @@ module Lrama
428
430
  end
429
431
  end
430
432
 
431
- if ok && userd_res[res]
433
+ if ok && used_res[res]
432
434
  ok = false
433
435
  end
434
436
 
@@ -456,7 +458,7 @@ module Lrama
456
458
 
457
459
  @base[state_id] = res
458
460
  pushed[froms_and_tos] = res
459
- userd_res[res] = true
461
+ used_res[res] = true
460
462
  end
461
463
 
462
464
  @yylast = high
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lrama
2
4
  class Counterexamples
3
5
  class Derivation
@@ -16,7 +18,7 @@ module Lrama
16
18
  alias :inspect :to_s
17
19
 
18
20
  def render_strings_for_report
19
- result = []
21
+ result = [] #: Array[String]
20
22
  _render_for_report(self, 0, result, 0)
21
23
  result.map(&:rstrip)
22
24
  end
@@ -42,18 +44,19 @@ module Lrama
42
44
  str << "#{item.next_sym.display_name}"
43
45
  length = _render_for_report(derivation.left, len, strings, index + 1)
44
46
  # I want String#ljust!
45
- str << " " * (length - str.length)
47
+ str << " " * (length - str.length) if length > str.length
46
48
  else
47
49
  str << " • #{item.symbols_after_dot.map(&:display_name).join(" ")} "
48
50
  return str.length
49
51
  end
50
52
 
51
53
  if derivation.right&.left
52
- length = _render_for_report(derivation.right.left, str.length, strings, index + 1)
53
- str << "#{item.symbols_after_dot[1..-1].map(&:display_name).join(" ")} "
54
+ left = derivation.right&.left #: Derivation
55
+ length = _render_for_report(left, str.length, strings, index + 1)
56
+ str << "#{item.symbols_after_dot[1..-1].map(&:display_name).join(" ")} " # steep:ignore
54
57
  str << " " * (length - str.length) if length > str.length
55
58
  elsif item.next_next_sym
56
- str << "#{item.symbols_after_dot[1..-1].map(&:display_name).join(" ")} "
59
+ str << "#{item.symbols_after_dot[1..-1].map(&:display_name).join(" ")} " # steep:ignore
57
60
  end
58
61
 
59
62
  return str.length
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lrama
2
4
  class Counterexamples
3
5
  class Example
@@ -36,9 +38,10 @@ module Lrama
36
38
  private
37
39
 
38
40
  def _derivations(paths)
39
- derivation = nil
41
+ derivation = nil #: Derivation
40
42
  current = :production
41
- lookahead_sym = paths.last.to.item.end_of_rule? ? @conflict_symbol : nil
43
+ last_path = paths.last #: Path
44
+ lookahead_sym = last_path.to.item.end_of_rule? ? @conflict_symbol : nil
42
45
 
43
46
  paths.reverse_each do |path|
44
47
  item = path.to.item
@@ -55,12 +58,14 @@ module Lrama
55
58
  when ProductionPath
56
59
  derivation = Derivation.new(item, derivation)
57
60
  current = :production
61
+ else
62
+ raise "Unexpected. #{path}"
58
63
  end
59
64
 
60
65
  if lookahead_sym && item.next_next_sym && item.next_next_sym.first_set.include?(lookahead_sym)
61
66
  state_item = @counterexamples.transitions[[path.to, item.next_sym]]
62
67
  derivation2 = find_derivation_for_symbol(state_item, lookahead_sym)
63
- derivation.right = derivation2
68
+ derivation.right = derivation2 # steep:ignore
64
69
  lookahead_sym = nil
65
70
  end
66
71
 
@@ -87,7 +92,7 @@ module Lrama
87
92
  end
88
93
 
89
94
  def find_derivation_for_symbol(state_item, sym)
90
- queue = []
95
+ queue = [] #: Array[Array[StateItem]]
91
96
  queue << [state_item]
92
97
 
93
98
  while (sis = queue.shift)