lrama 0.6.10 → 0.7.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/.github/workflows/gh-pages.yml +46 -0
- data/.github/workflows/test.yaml +40 -8
- data/.gitignore +1 -0
- data/.rdoc_options +2 -0
- data/Gemfile +4 -2
- data/NEWS.md +125 -30
- data/README.md +44 -15
- data/Rakefile +13 -1
- data/Steepfile +5 -0
- data/doc/Index.md +58 -0
- data/doc/development/compressed_state_table/main.md +635 -0
- data/doc/development/compressed_state_table/parse.output +174 -0
- data/doc/development/compressed_state_table/parse.y +22 -0
- data/doc/development/compressed_state_table/parser.rb +282 -0
- data/lib/lrama/bitmap.rb +4 -1
- data/lib/lrama/command.rb +2 -1
- data/lib/lrama/context.rb +3 -3
- data/lib/lrama/counterexamples/derivation.rb +6 -5
- data/lib/lrama/counterexamples/example.rb +7 -4
- data/lib/lrama/counterexamples/path.rb +4 -0
- data/lib/lrama/counterexamples.rb +19 -9
- data/lib/lrama/digraph.rb +30 -0
- data/lib/lrama/grammar/binding.rb +47 -15
- data/lib/lrama/grammar/parameterizing_rule/rhs.rb +1 -1
- data/lib/lrama/grammar/rule.rb +8 -0
- data/lib/lrama/grammar/rule_builder.rb +4 -16
- data/lib/lrama/grammar/symbols/resolver.rb +4 -0
- data/lib/lrama/grammar.rb +10 -5
- data/lib/lrama/lexer/grammar_file.rb +8 -1
- data/lib/lrama/lexer/location.rb +17 -1
- data/lib/lrama/lexer/token/char.rb +1 -0
- data/lib/lrama/lexer/token/ident.rb +1 -0
- data/lib/lrama/lexer/token/instantiate_rule.rb +6 -1
- data/lib/lrama/lexer/token/tag.rb +3 -1
- data/lib/lrama/lexer/token/user_code.rb +6 -2
- data/lib/lrama/lexer/token.rb +14 -2
- data/lib/lrama/lexer.rb +5 -5
- data/lib/lrama/logger.rb +4 -0
- data/lib/lrama/option_parser.rb +10 -8
- data/lib/lrama/options.rb +2 -1
- data/lib/lrama/parser.rb +529 -490
- data/lib/lrama/state/reduce.rb +2 -3
- data/lib/lrama/state.rb +288 -1
- data/lib/lrama/states/item.rb +8 -0
- data/lib/lrama/states.rb +69 -2
- data/lib/lrama/trace_reporter.rb +17 -2
- data/lib/lrama/version.rb +1 -1
- data/lrama.gemspec +1 -1
- data/parser.y +42 -30
- data/rbs_collection.lock.yaml +10 -2
- data/sig/generated/lrama/bitmap.rbs +11 -0
- data/sig/generated/lrama/digraph.rbs +39 -0
- data/sig/generated/lrama/grammar/binding.rbs +34 -0
- data/sig/generated/lrama/lexer/grammar_file.rbs +28 -0
- data/sig/generated/lrama/lexer/location.rbs +52 -0
- data/sig/{lrama → generated/lrama}/lexer/token/char.rbs +2 -0
- data/sig/{lrama → generated/lrama}/lexer/token/ident.rbs +2 -0
- data/sig/{lrama → generated/lrama}/lexer/token/instantiate_rule.rbs +8 -0
- data/sig/{lrama → generated/lrama}/lexer/token/tag.rbs +3 -0
- data/sig/{lrama → generated/lrama}/lexer/token/user_code.rbs +6 -1
- data/sig/{lrama → generated/lrama}/lexer/token.rbs +26 -3
- data/sig/generated/lrama/logger.rbs +14 -0
- data/sig/generated/lrama/trace_reporter.rbs +25 -0
- data/sig/lrama/counterexamples/derivation.rbs +33 -0
- data/sig/lrama/counterexamples/example.rbs +45 -0
- data/sig/lrama/counterexamples/path.rbs +21 -0
- data/sig/lrama/counterexamples/production_path.rbs +11 -0
- data/sig/lrama/counterexamples/start_path.rbs +13 -0
- data/sig/lrama/counterexamples/state_item.rbs +10 -0
- data/sig/lrama/counterexamples/transition_path.rbs +11 -0
- data/sig/lrama/counterexamples/triple.rbs +20 -0
- data/sig/lrama/counterexamples.rbs +29 -0
- data/sig/lrama/grammar/rule_builder.rbs +0 -1
- data/sig/lrama/grammar/symbol.rbs +1 -1
- data/sig/lrama/grammar/symbols/resolver.rbs +3 -3
- data/sig/lrama/grammar.rbs +13 -0
- data/sig/lrama/options.rbs +1 -0
- data/sig/lrama/state/reduce_reduce_conflict.rbs +2 -2
- data/sig/lrama/state.rbs +79 -0
- data/sig/lrama/states.rbs +101 -0
- metadata +34 -14
- data/sig/lrama/bitmap.rbs +0 -7
- data/sig/lrama/digraph.rbs +0 -23
- data/sig/lrama/grammar/binding.rbs +0 -19
- data/sig/lrama/lexer/grammar_file.rbs +0 -17
- data/sig/lrama/lexer/location.rbs +0 -26
@@ -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/lib/lrama/bitmap.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
# rbs_inline: enabled
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Lrama
|
4
5
|
module Bitmap
|
6
|
+
# @rbs (Array[Integer] ary) -> Integer
|
5
7
|
def self.from_array(ary)
|
6
8
|
bit = 0
|
7
9
|
|
@@ -12,8 +14,9 @@ module Lrama
|
|
12
14
|
bit
|
13
15
|
end
|
14
16
|
|
17
|
+
# @rbs (Integer int) -> Array[Integer]
|
15
18
|
def self.to_array(int)
|
16
|
-
a = []
|
19
|
+
a = [] #: Array[Integer]
|
17
20
|
i = 0
|
18
21
|
|
19
22
|
while int > 0 do
|
data/lib/lrama/command.rb
CHANGED
@@ -19,7 +19,7 @@ module Lrama
|
|
19
19
|
text = options.y.read
|
20
20
|
options.y.close if options.y != STDIN
|
21
21
|
begin
|
22
|
-
grammar = Lrama::Parser.new(text, options.grammar_file, options.debug).parse
|
22
|
+
grammar = Lrama::Parser.new(text, options.grammar_file, options.debug, options.define).parse
|
23
23
|
unless grammar.no_stdlib
|
24
24
|
stdlib_grammar = Lrama::Parser.new(File.read(STDLIB_FILE_PATH), STDLIB_FILE_PATH, options.debug).parse
|
25
25
|
grammar.insert_before_parameterizing_rules(stdlib_grammar.parameterizing_rules)
|
@@ -34,6 +34,7 @@ module Lrama
|
|
34
34
|
end
|
35
35
|
states = Lrama::States.new(grammar, trace_state: (options.trace_opts[:automaton] || options.trace_opts[:closure]))
|
36
36
|
states.compute
|
37
|
+
states.compute_ielr if grammar.ielr_defined?
|
37
38
|
context = Lrama::Context.new(states)
|
38
39
|
|
39
40
|
if options.report_file
|
data/lib/lrama/context.rb
CHANGED
@@ -405,7 +405,7 @@ module Lrama
|
|
405
405
|
@check = []
|
406
406
|
# Key is froms_and_tos, value is index position
|
407
407
|
pushed = {}
|
408
|
-
|
408
|
+
used_res = {}
|
409
409
|
lowzero = 0
|
410
410
|
high = 0
|
411
411
|
|
@@ -430,7 +430,7 @@ module Lrama
|
|
430
430
|
end
|
431
431
|
end
|
432
432
|
|
433
|
-
if ok &&
|
433
|
+
if ok && used_res[res]
|
434
434
|
ok = false
|
435
435
|
end
|
436
436
|
|
@@ -458,7 +458,7 @@ module Lrama
|
|
458
458
|
|
459
459
|
@base[state_id] = res
|
460
460
|
pushed[froms_and_tos] = res
|
461
|
-
|
461
|
+
used_res[res] = true
|
462
462
|
end
|
463
463
|
|
464
464
|
@yylast = high
|
@@ -18,7 +18,7 @@ module Lrama
|
|
18
18
|
alias :inspect :to_s
|
19
19
|
|
20
20
|
def render_strings_for_report
|
21
|
-
result = []
|
21
|
+
result = [] #: Array[String]
|
22
22
|
_render_for_report(self, 0, result, 0)
|
23
23
|
result.map(&:rstrip)
|
24
24
|
end
|
@@ -44,18 +44,19 @@ module Lrama
|
|
44
44
|
str << "#{item.next_sym.display_name}"
|
45
45
|
length = _render_for_report(derivation.left, len, strings, index + 1)
|
46
46
|
# I want String#ljust!
|
47
|
-
str << " " * (length - str.length)
|
47
|
+
str << " " * (length - str.length) if length > str.length
|
48
48
|
else
|
49
49
|
str << " • #{item.symbols_after_dot.map(&:display_name).join(" ")} "
|
50
50
|
return str.length
|
51
51
|
end
|
52
52
|
|
53
53
|
if derivation.right&.left
|
54
|
-
|
55
|
-
|
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
|
56
57
|
str << " " * (length - str.length) if length > str.length
|
57
58
|
elsif item.next_next_sym
|
58
|
-
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
|
59
60
|
end
|
60
61
|
|
61
62
|
return str.length
|
@@ -38,9 +38,10 @@ module Lrama
|
|
38
38
|
private
|
39
39
|
|
40
40
|
def _derivations(paths)
|
41
|
-
derivation = nil
|
41
|
+
derivation = nil #: Derivation
|
42
42
|
current = :production
|
43
|
-
|
43
|
+
last_path = paths.last #: Path
|
44
|
+
lookahead_sym = last_path.to.item.end_of_rule? ? @conflict_symbol : nil
|
44
45
|
|
45
46
|
paths.reverse_each do |path|
|
46
47
|
item = path.to.item
|
@@ -57,12 +58,14 @@ module Lrama
|
|
57
58
|
when ProductionPath
|
58
59
|
derivation = Derivation.new(item, derivation)
|
59
60
|
current = :production
|
61
|
+
else
|
62
|
+
raise "Unexpected. #{path}"
|
60
63
|
end
|
61
64
|
|
62
65
|
if lookahead_sym && item.next_next_sym && item.next_next_sym.first_set.include?(lookahead_sym)
|
63
66
|
state_item = @counterexamples.transitions[[path.to, item.next_sym]]
|
64
67
|
derivation2 = find_derivation_for_symbol(state_item, lookahead_sym)
|
65
|
-
derivation.right = derivation2
|
68
|
+
derivation.right = derivation2 # steep:ignore
|
66
69
|
lookahead_sym = nil
|
67
70
|
end
|
68
71
|
|
@@ -89,7 +92,7 @@ module Lrama
|
|
89
92
|
end
|
90
93
|
|
91
94
|
def find_derivation_for_symbol(state_item, sym)
|
92
|
-
queue = []
|
95
|
+
queue = [] #: Array[Array[StateItem]]
|
93
96
|
queue << [state_item]
|
94
97
|
|
95
98
|
while (sis = queue.shift)
|