lrama 0.1.0 → 0.2.0
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 +4 -4
- data/README.md +13 -2
- data/doc/TODO.md +4 -0
- data/lib/lrama/bitmap.rb +29 -0
- data/lib/lrama/command.rb +19 -4
- data/lib/lrama/context.rb +7 -6
- data/lib/lrama/digraph.rb +53 -0
- data/lib/lrama/output.rb +95 -4
- data/lib/lrama/report.rb +12 -0
- data/lib/lrama/states.rb +99 -391
- data/lib/lrama/states_reporter.rb +310 -0
- data/lib/lrama/version.rb +1 -1
- data/lib/lrama/warning.rb +25 -0
- data/lib/lrama.rb +4 -0
- data/sample/parse.y +58 -0
- data/template/bison/yacc.c +11 -18
- metadata +7 -2
@@ -0,0 +1,310 @@
|
|
1
|
+
module Lrama
|
2
|
+
class StatesReporter
|
3
|
+
include Lrama::Report::Duration
|
4
|
+
|
5
|
+
def initialize(states)
|
6
|
+
@states = states
|
7
|
+
end
|
8
|
+
|
9
|
+
def report(io, **options)
|
10
|
+
report_duration(:report) do
|
11
|
+
_report(io, **options)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def _report(io, grammar: false, states: false, itemsets: false, lookaheads: false, solved: false, verbose: false)
|
18
|
+
# TODO: Unused terms
|
19
|
+
# TODO: Unused rules
|
20
|
+
|
21
|
+
report_conflicts(io)
|
22
|
+
report_grammar(io) if grammar
|
23
|
+
report_states(io, itemsets, lookaheads, solved, verbose)
|
24
|
+
end
|
25
|
+
|
26
|
+
def report_conflicts(io)
|
27
|
+
has_conflict = false
|
28
|
+
|
29
|
+
@states.states.each do |state|
|
30
|
+
messages = []
|
31
|
+
cs = state.conflicts.group_by(&:type)
|
32
|
+
if cs[:shift_reduce]
|
33
|
+
messages << "#{cs[:shift_reduce].count} shift/reduce"
|
34
|
+
end
|
35
|
+
|
36
|
+
if cs[:reduce_reduce]
|
37
|
+
messages << "#{cs[:reduce_reduce].count} reduce/reduce"
|
38
|
+
end
|
39
|
+
|
40
|
+
if !messages.empty?
|
41
|
+
has_conflict = true
|
42
|
+
io << "State #{state.id} conflicts: #{messages.join(', ')}\n"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
if has_conflict
|
47
|
+
io << "\n\n"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def report_grammar(io)
|
52
|
+
io << "Grammar\n"
|
53
|
+
last_lhs = nil
|
54
|
+
|
55
|
+
@states.rules.each do |rule|
|
56
|
+
if rule.rhs.empty?
|
57
|
+
r = "ε"
|
58
|
+
else
|
59
|
+
r = rule.rhs.map(&:display_name).join(" ")
|
60
|
+
end
|
61
|
+
|
62
|
+
if rule.lhs == last_lhs
|
63
|
+
io << sprintf("%5d %s| %s\n", rule.id, " " * rule.lhs.display_name.length, r)
|
64
|
+
else
|
65
|
+
io << "\n"
|
66
|
+
io << sprintf("%5d %s: %s\n", rule.id, rule.lhs.display_name, r)
|
67
|
+
end
|
68
|
+
|
69
|
+
last_lhs = rule.lhs
|
70
|
+
end
|
71
|
+
io << "\n\n"
|
72
|
+
end
|
73
|
+
|
74
|
+
def report_states(io, itemsets, lookaheads, solved, verbose)
|
75
|
+
@states.states.each do |state|
|
76
|
+
# Report State
|
77
|
+
io << "State #{state.id}\n\n"
|
78
|
+
|
79
|
+
# Report item
|
80
|
+
last_lhs = nil
|
81
|
+
list = itemsets ? state.items : state.kernels
|
82
|
+
list.sort_by {|i| [i.rule_id, i.position] }.each do |item|
|
83
|
+
rule = item.rule
|
84
|
+
position = item.position
|
85
|
+
if rule.rhs.empty?
|
86
|
+
r = "ε •"
|
87
|
+
else
|
88
|
+
r = rule.rhs.map(&:display_name).insert(position, "•").join(" ")
|
89
|
+
end
|
90
|
+
if rule.lhs == last_lhs
|
91
|
+
l = " " * rule.lhs.id.s_value.length + "|"
|
92
|
+
else
|
93
|
+
l = rule.lhs.id.s_value + ":"
|
94
|
+
end
|
95
|
+
la = ""
|
96
|
+
if lookaheads && item.end_of_rule?
|
97
|
+
reduce = state.find_reduce_by_item!(item)
|
98
|
+
look_ahead = reduce.selected_look_ahead
|
99
|
+
if !look_ahead.empty?
|
100
|
+
la = " [#{look_ahead.map(&:display_name).join(", ")}]"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
last_lhs = rule.lhs
|
104
|
+
|
105
|
+
io << sprintf("%5i %s %s%s\n", rule.id, l, r, la)
|
106
|
+
end
|
107
|
+
io << "\n"
|
108
|
+
|
109
|
+
|
110
|
+
# Report shifts
|
111
|
+
tmp = state.term_transitions.select do |shift, _|
|
112
|
+
!shift.not_selected
|
113
|
+
end.map do |shift, next_state|
|
114
|
+
[shift.next_sym, next_state.id]
|
115
|
+
end
|
116
|
+
max_len = tmp.map(&:first).map(&:display_name).map(&:length).max
|
117
|
+
tmp.each do |term, state_id|
|
118
|
+
io << " #{term.display_name.ljust(max_len)} shift, and go to state #{state_id}\n"
|
119
|
+
end
|
120
|
+
io << "\n" if !tmp.empty?
|
121
|
+
|
122
|
+
|
123
|
+
# Report error caused by %nonassoc
|
124
|
+
nl = false
|
125
|
+
tmp = state.resolved_conflicts.select do |resolved|
|
126
|
+
resolved.which == :error
|
127
|
+
end.map do |error|
|
128
|
+
error.symbol.display_name
|
129
|
+
end
|
130
|
+
max_len = tmp.map(&:length).max
|
131
|
+
tmp.each do |name|
|
132
|
+
nl = true
|
133
|
+
io << " #{name.ljust(max_len)} error (nonassociative)\n"
|
134
|
+
end
|
135
|
+
io << "\n" if !tmp.empty?
|
136
|
+
|
137
|
+
|
138
|
+
# Report reduces
|
139
|
+
nl = false
|
140
|
+
max_len = state.non_default_reduces.flat_map(&:look_ahead).compact.map(&:display_name).map(&:length).max || 0
|
141
|
+
max_len = [max_len, "$default".length].max if state.default_reduction_rule
|
142
|
+
ary = []
|
143
|
+
|
144
|
+
state.non_default_reduces.each do |reduce|
|
145
|
+
reduce.look_ahead.each do |term|
|
146
|
+
ary << [term, reduce]
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
ary.sort_by do |term, reduce|
|
151
|
+
term.number
|
152
|
+
end.each do |term, reduce|
|
153
|
+
rule = reduce.item.rule
|
154
|
+
io << " #{term.display_name.ljust(max_len)} reduce using rule #{rule.id} (#{rule.lhs.display_name})\n"
|
155
|
+
nl = true
|
156
|
+
end
|
157
|
+
|
158
|
+
if r = state.default_reduction_rule
|
159
|
+
nl = true
|
160
|
+
s = "$default".ljust(max_len)
|
161
|
+
|
162
|
+
if r.initial_rule?
|
163
|
+
io << " #{s} accept\n"
|
164
|
+
else
|
165
|
+
io << " #{s} reduce using rule #{r.id} (#{r.lhs.display_name})\n"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
io << "\n" if nl
|
169
|
+
|
170
|
+
|
171
|
+
# Report nonterminal transitions
|
172
|
+
tmp = []
|
173
|
+
max_len = 0
|
174
|
+
state.nterm_transitions.each do |shift, next_state|
|
175
|
+
nterm = shift.next_sym
|
176
|
+
tmp << [nterm, next_state.id]
|
177
|
+
max_len = [max_len, nterm.id.s_value.length].max
|
178
|
+
end
|
179
|
+
tmp.uniq!
|
180
|
+
tmp.sort_by! do |nterm, state_id|
|
181
|
+
nterm.number
|
182
|
+
end
|
183
|
+
tmp.each do |nterm, state_id|
|
184
|
+
io << " #{nterm.id.s_value.ljust(max_len)} go to state #{state_id}\n"
|
185
|
+
end
|
186
|
+
io << "\n" if !tmp.empty?
|
187
|
+
|
188
|
+
|
189
|
+
if solved
|
190
|
+
# Report conflict resolutions
|
191
|
+
state.resolved_conflicts.each do |resolved|
|
192
|
+
io << " #{resolved.report_message}\n"
|
193
|
+
end
|
194
|
+
io << "\n" if !state.resolved_conflicts.empty?
|
195
|
+
end
|
196
|
+
|
197
|
+
|
198
|
+
if verbose
|
199
|
+
# Report direct_read_sets
|
200
|
+
io << " [Direct Read sets]\n"
|
201
|
+
direct_read_sets = @states.direct_read_sets
|
202
|
+
@states.nterms.each do |nterm|
|
203
|
+
terms = direct_read_sets[[state.id, nterm.token_id]]
|
204
|
+
next if !terms
|
205
|
+
next if terms.empty?
|
206
|
+
|
207
|
+
str = terms.map {|sym| sym.id.s_value }.join(", ")
|
208
|
+
io << " read #{nterm.id.s_value} shift #{str}\n"
|
209
|
+
end
|
210
|
+
io << "\n"
|
211
|
+
|
212
|
+
|
213
|
+
# Reprot reads_relation
|
214
|
+
io << " [Reads Relation]\n"
|
215
|
+
@states.nterms.each do |nterm|
|
216
|
+
a = @states.reads_relation[[state.id, nterm.token_id]]
|
217
|
+
next if !a
|
218
|
+
|
219
|
+
a.each do |state_id2, nterm_id2|
|
220
|
+
n = @states.nterms.find {|n| n.token_id == nterm_id2 }
|
221
|
+
io << " (State #{state_id2}, #{n.id.s_value})\n"
|
222
|
+
end
|
223
|
+
end
|
224
|
+
io << "\n"
|
225
|
+
|
226
|
+
|
227
|
+
# Reprot read_sets
|
228
|
+
io << " [Read sets]\n"
|
229
|
+
read_sets = @states.read_sets
|
230
|
+
@states.nterms.each do |nterm|
|
231
|
+
terms = read_sets[[state.id, nterm.token_id]]
|
232
|
+
next if !terms
|
233
|
+
next if terms.empty?
|
234
|
+
|
235
|
+
terms.each do |sym|
|
236
|
+
io << " #{sym.id.s_value}\n"
|
237
|
+
end
|
238
|
+
end
|
239
|
+
io << "\n"
|
240
|
+
|
241
|
+
|
242
|
+
# Reprot includes_relation
|
243
|
+
io << " [Includes Relation]\n"
|
244
|
+
@states.nterms.each do |nterm|
|
245
|
+
a = @states.includes_relation[[state.id, nterm.token_id]]
|
246
|
+
next if !a
|
247
|
+
|
248
|
+
a.each do |state_id2, nterm_id2|
|
249
|
+
n = @states.nterms.find {|n| n.token_id == nterm_id2 }
|
250
|
+
io << " (State #{state.id}, #{nterm.id.s_value}) -> (State #{state_id2}, #{n.id.s_value})\n"
|
251
|
+
end
|
252
|
+
end
|
253
|
+
io << "\n"
|
254
|
+
|
255
|
+
|
256
|
+
# Report lookback_relation
|
257
|
+
io << " [Lookback Relation]\n"
|
258
|
+
@states.rules.each do |rule|
|
259
|
+
a = @states.lookback_relation[[state.id, rule.id]]
|
260
|
+
next if !a
|
261
|
+
|
262
|
+
a.each do |state_id2, nterm_id2|
|
263
|
+
n = @states.nterms.find {|n| n.token_id == nterm_id2 }
|
264
|
+
io << " (Rule: #{rule.to_s}) -> (State #{state_id2}, #{n.id.s_value})\n"
|
265
|
+
end
|
266
|
+
end
|
267
|
+
io << "\n"
|
268
|
+
|
269
|
+
|
270
|
+
# Reprot follow_sets
|
271
|
+
io << " [Follow sets]\n"
|
272
|
+
follow_sets = @states.follow_sets
|
273
|
+
@states.nterms.each do |nterm|
|
274
|
+
terms = follow_sets[[state.id, nterm.token_id]]
|
275
|
+
|
276
|
+
next if !terms
|
277
|
+
|
278
|
+
terms.each do |sym|
|
279
|
+
io << " #{nterm.id.s_value} -> #{sym.id.s_value}\n"
|
280
|
+
end
|
281
|
+
end
|
282
|
+
io << "\n"
|
283
|
+
|
284
|
+
|
285
|
+
# Report LA
|
286
|
+
io << " [Look-Ahead Sets]\n"
|
287
|
+
tmp = []
|
288
|
+
max_len = 0
|
289
|
+
@states.rules.each do |rule|
|
290
|
+
syms = @states.la[[state.id, rule.id]]
|
291
|
+
next if !syms
|
292
|
+
|
293
|
+
tmp << [rule, syms]
|
294
|
+
max_len = ([max_len] + syms.map {|s| s.id.s_value.length }).max
|
295
|
+
end
|
296
|
+
tmp.each do |rule, syms|
|
297
|
+
syms.each do |sym|
|
298
|
+
io << " #{sym.id.s_value.ljust(max_len)} reduce using rule #{rule.id} (#{rule.lhs.id.s_value})\n"
|
299
|
+
end
|
300
|
+
end
|
301
|
+
io << "\n" if !tmp.empty?
|
302
|
+
end
|
303
|
+
|
304
|
+
|
305
|
+
# End of Report State
|
306
|
+
io << "\n"
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
data/lib/lrama/version.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Lrama
|
2
|
+
class Warning
|
3
|
+
attr_reader :errors, :warns
|
4
|
+
|
5
|
+
def initialize(out = STDERR)
|
6
|
+
@out = out
|
7
|
+
@errors = []
|
8
|
+
@warns = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def error(message)
|
12
|
+
@out << message << "\n"
|
13
|
+
@errors << message
|
14
|
+
end
|
15
|
+
|
16
|
+
def warn(message)
|
17
|
+
@out << message << "\n"
|
18
|
+
@warns << message
|
19
|
+
end
|
20
|
+
|
21
|
+
def has_error?
|
22
|
+
!@errors.empty?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/lrama.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
require "lrama/bitmap"
|
1
2
|
require "lrama/command"
|
2
3
|
require "lrama/context"
|
4
|
+
require "lrama/digraph"
|
3
5
|
require "lrama/grammar"
|
4
6
|
require "lrama/lexer"
|
5
7
|
require "lrama/output"
|
6
8
|
require "lrama/parser"
|
7
9
|
require "lrama/report"
|
8
10
|
require "lrama/states"
|
11
|
+
require "lrama/states_reporter"
|
9
12
|
require "lrama/version"
|
13
|
+
require "lrama/warning"
|
data/sample/parse.y
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
/*
|
2
|
+
* This is comment for this file.
|
3
|
+
*/
|
4
|
+
|
5
|
+
%{
|
6
|
+
// Prologue
|
7
|
+
|
8
|
+
#include "y.tab.h"
|
9
|
+
|
10
|
+
static enum yytokentype yylex(YYSTYPE *lval, YYLTYPE *yylloc);
|
11
|
+
static void yyerror(YYLTYPE *yylloc, const char *msg);
|
12
|
+
|
13
|
+
%}
|
14
|
+
|
15
|
+
%expect 0
|
16
|
+
%define api.pure
|
17
|
+
%define parse.error verbose
|
18
|
+
|
19
|
+
%union {
|
20
|
+
int i;
|
21
|
+
}
|
22
|
+
|
23
|
+
%token <i> number
|
24
|
+
|
25
|
+
%%
|
26
|
+
|
27
|
+
program : expr
|
28
|
+
;
|
29
|
+
|
30
|
+
expr : term '+' expr
|
31
|
+
| term
|
32
|
+
;
|
33
|
+
|
34
|
+
term : factor '*' term
|
35
|
+
| factor
|
36
|
+
;
|
37
|
+
|
38
|
+
factor : number
|
39
|
+
;
|
40
|
+
|
41
|
+
%%
|
42
|
+
|
43
|
+
// Epilogue
|
44
|
+
|
45
|
+
static enum yytokentype
|
46
|
+
yylex(YYSTYPE *lval, YYLTYPE *yylloc)
|
47
|
+
{
|
48
|
+
return 0;
|
49
|
+
}
|
50
|
+
|
51
|
+
static void yyerror(YYLTYPE *yylloc, const char *msg)
|
52
|
+
{
|
53
|
+
(void) msg;
|
54
|
+
}
|
55
|
+
|
56
|
+
int main(int argc, char *argv[])
|
57
|
+
{
|
58
|
+
}
|
data/template/bison/yacc.c
CHANGED
@@ -668,7 +668,7 @@ enum { YYENOMEM = -2 };
|
|
668
668
|
} \
|
669
669
|
else \
|
670
670
|
{ \
|
671
|
-
yyerror (
|
671
|
+
yyerror (<%= output.yyerror_args %>, YY_("syntax error: cannot back up")); \
|
672
672
|
YYERROR; \
|
673
673
|
} \
|
674
674
|
while (0)
|
@@ -802,9 +802,7 @@ yy_symbol_value_print (FILE *yyo,
|
|
802
802
|
yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp<%= output.user_formals %>)
|
803
803
|
{
|
804
804
|
FILE *yyoutput = yyo;
|
805
|
-
|
806
|
-
YY_USE (yylocationp);
|
807
|
-
YY_USE (p);
|
805
|
+
<%= output.parse_param_use("yyoutput", "yylocationp") %>
|
808
806
|
if (!yyvaluep)
|
809
807
|
return;
|
810
808
|
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
|
@@ -1199,9 +1197,7 @@ static void
|
|
1199
1197
|
yydestruct (const char *yymsg,
|
1200
1198
|
yysymbol_kind_t yykind, YYSTYPE *yyvaluep, YYLTYPE *yylocationp<%= output.user_formals %>)
|
1201
1199
|
{
|
1202
|
-
|
1203
|
-
YY_USE (yylocationp);
|
1204
|
-
YY_USE (p);
|
1200
|
+
<%= output.parse_param_use("yyvaluep", "yylocationp") %>
|
1205
1201
|
if (!yymsg)
|
1206
1202
|
yymsg = "Deleting";
|
1207
1203
|
YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp);
|
@@ -1301,10 +1297,7 @@ YYLTYPE yylloc = yyloc_default;
|
|
1301
1297
|
|
1302
1298
|
|
1303
1299
|
<%# b4_user_initial_action -%>
|
1304
|
-
/* User initialization code. */
|
1305
|
-
#line <%= output.grammar.initial_action.line %> "<%= output.grammar_file_path %>"
|
1306
|
-
<%= output.grammar.initial_action.translated_code %>
|
1307
|
-
|
1300
|
+
<%= output.user_initial_action("/* User initialization code. */") %>
|
1308
1301
|
#line [@oline@] [@ofile@]
|
1309
1302
|
|
1310
1303
|
yylsp[0] = yylloc;
|
@@ -1424,7 +1417,7 @@ yybackup:
|
|
1424
1417
|
if (yychar == YYEMPTY)
|
1425
1418
|
{
|
1426
1419
|
YYDPRINTF ((stderr, "Reading a token\n"));
|
1427
|
-
yychar = yylex
|
1420
|
+
yychar = yylex <%= output.yylex_formals %>;
|
1428
1421
|
}
|
1429
1422
|
|
1430
1423
|
if (yychar <= <%= output.eof_symbol.id.s_value %>)
|
@@ -1590,7 +1583,7 @@ yyerrlab:
|
|
1590
1583
|
yysyntax_error_status = YYENOMEM;
|
1591
1584
|
}
|
1592
1585
|
}
|
1593
|
-
yyerror (
|
1586
|
+
yyerror (<%= output.yyerror_args %>, yymsgp);
|
1594
1587
|
if (yysyntax_error_status == YYENOMEM)
|
1595
1588
|
YYNOMEM;
|
1596
1589
|
}
|
@@ -1611,7 +1604,7 @@ yyerrlab:
|
|
1611
1604
|
else
|
1612
1605
|
{
|
1613
1606
|
yydestruct ("Error: discarding",
|
1614
|
-
yytoken, &yylval, &yylloc
|
1607
|
+
yytoken, &yylval, &yylloc<%= output.user_args %>);
|
1615
1608
|
yychar = YYEMPTY;
|
1616
1609
|
}
|
1617
1610
|
}
|
@@ -1667,7 +1660,7 @@ yyerrlab1:
|
|
1667
1660
|
|
1668
1661
|
yyerror_range[1] = *yylsp;
|
1669
1662
|
yydestruct ("Error: popping",
|
1670
|
-
YY_ACCESSING_SYMBOL (yystate), yyvsp, yylsp
|
1663
|
+
YY_ACCESSING_SYMBOL (yystate), yyvsp, yylsp<%= output.user_args %>);
|
1671
1664
|
YYPOPSTACK (1);
|
1672
1665
|
yystate = *yyssp;
|
1673
1666
|
YY_STACK_PRINT (yyss, yyssp);
|
@@ -1708,7 +1701,7 @@ yyabortlab:
|
|
1708
1701
|
| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. |
|
1709
1702
|
`-----------------------------------------------------------*/
|
1710
1703
|
yyexhaustedlab:
|
1711
|
-
yyerror (
|
1704
|
+
yyerror (<%= output.yyerror_args %>, YY_("memory exhausted"));
|
1712
1705
|
yyresult = 2;
|
1713
1706
|
goto yyreturnlab;
|
1714
1707
|
|
@@ -1723,7 +1716,7 @@ yyreturnlab:
|
|
1723
1716
|
user semantic actions for why this is necessary. */
|
1724
1717
|
yytoken = YYTRANSLATE (yychar);
|
1725
1718
|
yydestruct ("Cleanup: discarding lookahead",
|
1726
|
-
yytoken, &yylval, &yylloc
|
1719
|
+
yytoken, &yylval, &yylloc<%= output.user_args %>);
|
1727
1720
|
}
|
1728
1721
|
/* Do not reclaim the symbols of the rule whose action triggered
|
1729
1722
|
this YYABORT or YYACCEPT. */
|
@@ -1732,7 +1725,7 @@ yyreturnlab:
|
|
1732
1725
|
while (yyssp != yyss)
|
1733
1726
|
{
|
1734
1727
|
yydestruct ("Cleanup: popping",
|
1735
|
-
YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, yylsp
|
1728
|
+
YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, yylsp<%= output.user_args %>);
|
1736
1729
|
YYPOPSTACK (1);
|
1737
1730
|
}
|
1738
1731
|
#ifndef yyoverflow
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lrama
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yuichiro Kaneko
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: LALR (1) parser generator written by Ruby
|
14
14
|
email:
|
@@ -29,16 +29,21 @@ files:
|
|
29
29
|
- doc/TODO.md
|
30
30
|
- exe/lrama
|
31
31
|
- lib/lrama.rb
|
32
|
+
- lib/lrama/bitmap.rb
|
32
33
|
- lib/lrama/command.rb
|
33
34
|
- lib/lrama/context.rb
|
35
|
+
- lib/lrama/digraph.rb
|
34
36
|
- lib/lrama/grammar.rb
|
35
37
|
- lib/lrama/lexer.rb
|
36
38
|
- lib/lrama/output.rb
|
37
39
|
- lib/lrama/parser.rb
|
38
40
|
- lib/lrama/report.rb
|
39
41
|
- lib/lrama/states.rb
|
42
|
+
- lib/lrama/states_reporter.rb
|
40
43
|
- lib/lrama/version.rb
|
44
|
+
- lib/lrama/warning.rb
|
41
45
|
- lrama.gemspec
|
46
|
+
- sample/parse.y
|
42
47
|
- template/bison/yacc.c
|
43
48
|
- template/bison/yacc.h
|
44
49
|
homepage: https://github.com/yui-knk/lrama
|