lrama 0.6.9 → 0.6.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yaml +24 -1
- data/.gitignore +2 -0
- data/Gemfile +6 -3
- data/NEWS.md +269 -14
- data/README.md +41 -4
- data/Rakefile +2 -0
- data/Steepfile +9 -17
- 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/exe/lrama +1 -0
- data/lib/lrama/bitmap.rb +3 -1
- data/lib/lrama/command.rb +8 -14
- data/lib/lrama/context.rb +11 -9
- data/lib/lrama/counterexamples/derivation.rb +8 -5
- data/lib/lrama/counterexamples/example.rb +9 -4
- data/lib/lrama/counterexamples/path.rb +6 -0
- data/lib/lrama/counterexamples/production_path.rb +2 -0
- data/lib/lrama/counterexamples/start_path.rb +2 -0
- data/lib/lrama/counterexamples/state_item.rb +2 -0
- data/lib/lrama/counterexamples/transition_path.rb +2 -0
- data/lib/lrama/counterexamples/triple.rb +2 -0
- data/lib/lrama/counterexamples.rb +36 -24
- data/lib/lrama/diagnostics.rb +36 -0
- data/lib/lrama/digraph.rb +2 -0
- data/lib/lrama/grammar/auxiliary.rb +2 -0
- data/lib/lrama/grammar/binding.rb +12 -1
- data/lib/lrama/grammar/code/destructor_code.rb +2 -0
- data/lib/lrama/grammar/code/initial_action_code.rb +2 -0
- data/lib/lrama/grammar/code/no_reference_code.rb +2 -0
- data/lib/lrama/grammar/code/printer_code.rb +2 -0
- data/lib/lrama/grammar/code/rule_action.rb +7 -3
- data/lib/lrama/grammar/code.rb +7 -5
- data/lib/lrama/grammar/counter.rb +2 -0
- data/lib/lrama/grammar/destructor.rb +2 -0
- data/lib/lrama/grammar/error_token.rb +2 -0
- data/lib/lrama/grammar/parameterizing_rule/resolver.rb +7 -1
- data/lib/lrama/grammar/parameterizing_rule/rhs.rb +6 -3
- data/lib/lrama/grammar/parameterizing_rule/rule.rb +6 -0
- data/lib/lrama/grammar/parameterizing_rule.rb +2 -0
- data/lib/lrama/grammar/percent_code.rb +2 -0
- data/lib/lrama/grammar/precedence.rb +2 -0
- data/lib/lrama/grammar/printer.rb +2 -0
- data/lib/lrama/grammar/reference.rb +2 -0
- data/lib/lrama/grammar/rule.rb +10 -3
- data/lib/lrama/grammar/rule_builder.rb +64 -65
- data/lib/lrama/grammar/symbol.rb +2 -0
- data/lib/lrama/grammar/symbols/resolver.rb +9 -1
- data/lib/lrama/grammar/symbols.rb +2 -0
- data/lib/lrama/grammar/type.rb +2 -0
- data/lib/lrama/grammar/union.rb +2 -0
- data/lib/lrama/grammar.rb +53 -32
- data/lib/lrama/grammar_validator.rb +37 -0
- data/lib/lrama/lexer/grammar_file.rb +2 -0
- data/lib/lrama/lexer/location.rb +2 -0
- data/lib/lrama/lexer/token/char.rb +2 -0
- data/lib/lrama/lexer/token/ident.rb +2 -0
- data/lib/lrama/lexer/token/instantiate_rule.rb +2 -0
- data/lib/lrama/lexer/token/tag.rb +2 -0
- data/lib/lrama/lexer/token/user_code.rb +4 -2
- data/lib/lrama/lexer/token.rb +7 -5
- data/lib/lrama/lexer.rb +12 -8
- data/lib/lrama/{warning.rb → logger.rb} +5 -13
- data/lib/lrama/option_parser.rb +58 -33
- data/lib/lrama/options.rb +5 -2
- data/lib/lrama/output.rb +38 -69
- data/lib/lrama/parser.rb +677 -773
- data/lib/lrama/report/duration.rb +2 -0
- data/lib/lrama/report/profile.rb +2 -0
- data/lib/lrama/report.rb +4 -2
- data/lib/lrama/state/reduce.rb +4 -2
- data/lib/lrama/state/reduce_reduce_conflict.rb +2 -0
- data/lib/lrama/state/resolved_conflict.rb +3 -1
- data/lib/lrama/state/shift.rb +2 -0
- data/lib/lrama/state/shift_reduce_conflict.rb +2 -0
- data/lib/lrama/state.rb +7 -5
- data/lib/lrama/states/item.rb +5 -3
- data/lib/lrama/states.rb +18 -46
- data/lib/lrama/states_reporter.rb +60 -19
- data/lib/lrama/trace_reporter.rb +30 -0
- data/lib/lrama/version.rb +3 -1
- data/lib/lrama.rb +22 -17
- data/lrama.gemspec +3 -1
- data/parser.y +129 -237
- data/rbs_collection.lock.yaml +10 -2
- 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/auxiliary.rbs +10 -0
- data/sig/lrama/grammar/binding.rbs +4 -0
- data/sig/lrama/grammar/code/destructor_code.rbs +3 -4
- data/sig/lrama/grammar/code/initial_action_code.rbs +15 -0
- data/sig/lrama/grammar/code/no_reference_code.rbs +15 -0
- data/sig/lrama/grammar/code/printer_code.rbs +3 -4
- data/sig/lrama/grammar/code/rule_action.rbs +19 -0
- data/sig/lrama/grammar/code.rbs +3 -3
- data/sig/lrama/grammar/destructor.rbs +3 -1
- data/sig/lrama/grammar/error_token.rbs +4 -2
- data/sig/lrama/grammar/parameterizing_rule/resolver.rbs +2 -1
- data/sig/lrama/grammar/parameterizing_rule/rhs.rbs +1 -1
- data/sig/lrama/grammar/precedence.rbs +3 -1
- data/sig/lrama/grammar/printer.rbs +3 -1
- data/sig/lrama/grammar/rule.rbs +35 -3
- data/sig/lrama/grammar/rule_builder.rbs +10 -9
- data/sig/lrama/grammar/symbol.rbs +6 -6
- data/sig/lrama/grammar/symbols/resolver.rbs +24 -5
- data/sig/lrama/grammar/type.rbs +2 -2
- data/sig/lrama/grammar/union.rbs +12 -0
- data/sig/lrama/grammar.rbs +104 -1
- data/sig/lrama/options.rbs +3 -2
- data/sig/lrama/state/reduce.rbs +20 -0
- data/sig/lrama/state/reduce_reduce_conflict.rbs +13 -0
- data/sig/lrama/state/resolved_conflict.rbs +14 -0
- data/sig/lrama/state/shift.rbs +14 -0
- data/sig/lrama/state/shift_reduce_conflict.rbs +13 -0
- data/sig/lrama/state.rbs +79 -0
- data/sig/lrama/states/item.rbs +30 -0
- data/sig/lrama/states.rbs +101 -0
- data/template/bison/yacc.c +24 -19
- metadata +32 -6
- data/sample/calc.output +0 -263
- data/sample/calc.y +0 -101
- 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
data/lib/lrama/bitmap.rb
CHANGED
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,
|
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
|
-
|
46
|
-
|
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
|
-
|
69
|
-
|
70
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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 &&
|
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
|
-
|
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
|
-
|
53
|
-
|
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
|
-
|
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)
|