lrama 0.1.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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/lexer.rb +1 -1
- data/lib/lrama/output.rb +95 -4
- data/lib/lrama/report.rb +12 -0
- data/lib/lrama/states.rb +100 -392
- 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.1
|
4
|
+
version: 0.2.1
|
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
|