Skip to content

Commit 1121f1d

Browse files
authored
Runtime: Implemement set_parser_trace (#1308)
1 parent 1f3ecf6 commit 1121f1d

File tree

4 files changed

+159
-24
lines changed

4 files changed

+159
-24
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
* Runtime: Implement buffer for in_channels
2121
* Runtime: add support for unix_opendir, unix_readdir, unix_closedir, win_findfirst, win_findnext, win_findclose
2222
* Runtime: Dont use require when target-env is browser
23+
* Runtime: Implements Parsing.set_trace (#1308)
2324
* Test: track external used in the stdlib and unix
2425

2526
## Bug fixes

compiler/tests-jsoo/gh_1307.ml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ let test content =
1010
print_endline "failure"
1111

1212
let%expect_test "parsing" =
13-
let (_ : bool) = Parsing.set_trace false in
13+
(* use [Parsing.set_trace true] once https://github.com/janestreet/ppx_expect/issues/43 is fixed *)
14+
let (old : bool) = Parsing.set_trace false in
1415
test "a";
1516
[%expect {|
1617
input: "a"
@@ -25,4 +26,6 @@ let%expect_test "parsing" =
2526
[%expect {|
2627
input: "aaa"
2728
Stdlib.Parsing.Parse_error
28-
failure |}]
29+
failure |}];
30+
let (_ : bool) = Parsing.set_trace old in
31+
()

compiler/tests-jsoo/test_parsing.ml

Lines changed: 87 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,93 @@ let parse s =
2929
with Calc_lexer.Eof -> print_endline "EOF"
3030

3131
let%expect_test "parsing" =
32-
let (old : bool) = Parsing.set_trace false in
33-
parse "1+2*3";
34-
[%expect {|
35-
EOF |}];
36-
parse "(1+2)*3";
37-
[%expect {|
38-
EOF |}];
39-
parse "-10-1";
40-
[%expect {|
41-
EOF |}];
42-
parse "63/2*-3";
43-
[%expect {|
44-
EOF |}];
45-
let (_ : bool) = Parsing.set_trace old in
32+
(* Uncomment once https://github.com/janestreet/ppx_expect/issues/43 is fixed.
33+
{[
34+
let (old : bool) = Parsing.set_trace true in
35+
parse "1+2*3";
36+
[%expect
37+
{|
38+
State 0: shift to state 1
39+
State 1: read token INT(1)
40+
State 1: shift to state 3
41+
State 3: reduce by rule 2
42+
State 7: read token PLUS
43+
State 7: shift to state 10
44+
State 10: read token INT(2)
45+
State 10: shift to state 3
46+
State 3: reduce by rule 2
47+
State 16: read token TIMES
48+
State 16: shift to state 12
49+
State 12: read token INT(3)
50+
State 12: shift to state 3
51+
State 3: reduce by rule 2
52+
State 18: reduce by rule 6
53+
EOF |}];
54+
parse "(1+2)*3";
55+
[%expect
56+
{|
57+
State 0: shift to state 1
58+
State 1: read token LPAREN
59+
State 1: shift to state 5
60+
State 5: read token INT(1)
61+
State 5: shift to state 3
62+
State 3: reduce by rule 2
63+
State 9: read token PLUS
64+
State 9: shift to state 10
65+
State 10: read token INT(2)
66+
State 10: shift to state 3
67+
State 3: reduce by rule 2
68+
State 16: read token RPAREN
69+
State 16: reduce by rule 4
70+
State 9: shift to state 15
71+
State 15: reduce by rule 3
72+
State 7: read token TIMES
73+
State 7: shift to state 12
74+
State 12: read token INT(3)
75+
State 12: shift to state 3
76+
State 3: reduce by rule 2
77+
State 18: reduce by rule 6
78+
EOF |}];
79+
parse "-10-1";
80+
[%expect
81+
{|
82+
State 0: shift to state 1
83+
State 1: read token MINUS
84+
State 1: shift to state 4
85+
State 4: read token INT(10)
86+
State 4: shift to state 3
87+
State 3: reduce by rule 2
88+
State 8: reduce by rule 8
89+
State 7: read token MINUS
90+
State 7: shift to state 11
91+
State 11: read token INT(1)
92+
State 11: shift to state 3
93+
State 3: reduce by rule 2
94+
EOF |}];
95+
parse "63/2*-3";
96+
[%expect
97+
{|
98+
State 0: shift to state 1
99+
State 1: read token INT(63)
100+
State 1: shift to state 3
101+
State 3: reduce by rule 2
102+
State 7: read token DIV
103+
State 7: shift to state 13
104+
State 13: read token INT(2)
105+
State 13: shift to state 3
106+
State 3: reduce by rule 2
107+
State 19: reduce by rule 7
108+
State 7: read token TIMES
109+
State 7: shift to state 12
110+
State 12: read token MINUS
111+
State 12: shift to state 4
112+
State 4: read token INT(3)
113+
State 4: shift to state 3
114+
State 3: reduce by rule 2
115+
State 8: reduce by rule 8
116+
State 18: reduce by rule 6
117+
EOF |}];
118+
let (_ : bool) = Parsing.set_trace old in ]} *)
46119
parse "1+2*3";
47120
[%expect {| EOF |}];
48121
parse "(1+2)*3";

runtime/parsing.js

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,13 @@
1717

1818
/* The pushdown automata */
1919

20+
//Provides: caml_parser_trace
21+
var caml_parser_trace = 0;
22+
2023
//Provides: caml_parse_engine
21-
//Requires: caml_lex_array
24+
//Requires: caml_lex_array, caml_parser_trace,caml_jsstring_of_string
25+
//Requires: caml_ml_output, caml_ml_string_length, caml_string_of_jsbytes
26+
//Requires: caml_jsbytes_of_string, MlBytes
2227
function caml_parse_engine(tables, env, cmd, arg)
2328
{
2429
var ERRCODE = 256;
@@ -73,8 +78,42 @@ function caml_parse_engine(tables, env, cmd, arg)
7378
var tbl_table = 12;
7479
var tbl_check = 13;
7580
// var _tbl_error_function = 14;
76-
// var _tbl_names_const = 15;
77-
// var _tbl_names_block = 16;
81+
var tbl_names_const = 15;
82+
var tbl_names_block = 16;
83+
84+
85+
function log(x) {
86+
var s = caml_string_of_jsbytes(x + "\n");
87+
caml_ml_output(2, s, 0, caml_ml_string_length(s));
88+
}
89+
90+
function token_name(names, number)
91+
{
92+
var str = caml_jsstring_of_string(names);
93+
if (str[0] == '\x00')
94+
return "<unknown token>";
95+
return str.split('\x00')[number];
96+
}
97+
98+
function print_token(state, tok)
99+
{
100+
var token, kind;
101+
if (tok instanceof Array) {
102+
token = token_name(tables[tbl_names_block], tok[0]);
103+
if (typeof tok[1] == "number")
104+
kind = "" + tok[1];
105+
else if (typeof tok[1] == "string")
106+
kind = tok[1]
107+
else if (tok[1] instanceof MlBytes)
108+
kind = caml_jsbytes_of_string(tok[1])
109+
else
110+
kind = "_"
111+
log("State " + state + ": read token " + token + "(" + kind + ")");
112+
} else {
113+
token = token_name(tables[tbl_names_const], tok);
114+
log("State " + state + ": read token " + token);
115+
}
116+
}
78117

79118
if (!tables.dgoto) {
80119
tables.defred = caml_lex_array (tables[tbl_defred]);
@@ -118,6 +157,7 @@ function caml_parse_engine(tables, env, cmd, arg)
118157
env[env_curr_char] = tables[tbl_transl_const][arg + 1];
119158
env[env_lval] = 0;
120159
}
160+
if (caml_parser_trace) print_token (state, arg);
121161
// Fall through
122162

123163
case 7://testshift:
@@ -149,16 +189,26 @@ function caml_parse_engine(tables, env, cmd, arg)
149189
n2 = n1 + ERRCODE;
150190
if (n1 != 0 && n2 >= 0 && n2 <= tables[tbl_tablesize] &&
151191
tables.check[n2] == ERRCODE) {
192+
if (caml_parser_trace)
193+
log("Recovering in state " + state1);
152194
cmd = shift_recover; break next;
153195
} else {
154-
if (sp <= env[env_stackbase]) return RAISE_PARSE_ERROR;
196+
if (caml_parser_trace)
197+
log("Discarding state " + state1);
198+
if (sp <= env[env_stackbase]) {
199+
if (caml_parser_trace)
200+
log("No more states to discard");
201+
return RAISE_PARSE_ERROR;
202+
}
155203
/* The ML code raises Parse_error */
156204
sp--;
157205
}
158206
}
159207
} else {
160-
if (env[env_curr_char] == 0) return RAISE_PARSE_ERROR;
161-
/* The ML code raises Parse_error */
208+
if (env[env_curr_char] == 0)
209+
return RAISE_PARSE_ERROR; /* The ML code raises Parse_error */
210+
if (caml_parser_trace)
211+
log("Discarding last token read");
162212
env[env_curr_char] = -1;
163213
cmd = loop; break;
164214
}
@@ -168,6 +218,8 @@ function caml_parse_engine(tables, env, cmd, arg)
168218
if (errflag > 0) errflag--;
169219
// Fall through
170220
case 9://shift_recover:
221+
if (caml_parser_trace)
222+
log("State " + state + ": shift to state " + tables.table[n2]);
171223
state = tables.table[n2];
172224
sp++;
173225
if (sp >= env[env_stacksize]) {
@@ -185,6 +237,8 @@ function caml_parse_engine(tables, env, cmd, arg)
185237
break;
186238

187239
case 10://reduce:
240+
if (caml_parser_trace)
241+
log("State " + state + ": reduce by rule " + n);
188242
var m = tables.len[n];
189243
env[env_asp] = sp;
190244
env[env_rule_number] = n;
@@ -232,5 +286,9 @@ function caml_parse_engine(tables, env, cmd, arg)
232286
}
233287

234288
//Provides: caml_set_parser_trace const
235-
//Dummy function!
236-
function caml_set_parser_trace() { return 0; }
289+
//Requires: caml_parser_trace
290+
function caml_set_parser_trace(bool) {
291+
var oldflag = caml_parser_trace;
292+
caml_parser_trace = bool;
293+
return oldflag;
294+
}

0 commit comments

Comments
 (0)