-
Notifications
You must be signed in to change notification settings - Fork 11
/
test.html
121 lines (109 loc) · 4.46 KB
/
test.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<html><head>
<title>test page for metacircular PEG compiler-compiler</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="style.css" />
<script src="bootstrap.js"></script>
<script type="text/javascript">
function $(id) { return document.getElementById(id) }
window.onload = function() {
$('debug_output').value = all_rules;
window.parse_sentence = parse_sentence;
}
function timeit(thunk) {
var start, end;
start = new Date();
thunk();
end = new Date();
$('debug_output').value = '' + (end.getTime() - start.getTime()) + ' ms';
}
function compile(output_id) {
var output;
timeit(function() { output = parse_sentence($('grammar').value, 0).val; });
$(output_id).value = output;
eval(output);
window.parse_sentence = parse_sentence;
}
</script>
</head><body>
<h1>test page for metacircular PEG compiler-compiler</h1>
<h2>debug output</h2>
<textarea id="debug_output" cols="80" rows="24"></textarea>
<h2>input grammar</h2>
<textarea id="grammar" cols="80" rows="66">
sp <- ' ' / '\n' / '\t'.
_ <- sp _ / .
rule <- n: name _ '<-'_ body: choice '.'_ ->
(["function parse_", n, "(input, pos) {\n",
' var state = { pos: pos };\n',
' var stack = [];\n',
body,
' return state;\n',
"}\n"].join(''))
.
sentence <- _ r: rule g: sentence -> (r + "\n" + g)
/ _ r: rule -> (r + "\n"
+ 'function parse_char(input, pos) {\n'
+ ' if (pos >= input.length) return null;\n'
+ ' return { pos: pos + 1, val: input.charAt(pos) };\n'
+ '}\n'
+ 'function literal(input, pos, string) {\n'
+ ' if (input.substr(pos, string.length) === string) {\n'
+ ' return { pos: pos + string.length, val: string };\n'
+ ' } else return null;\n'
+ '}\n'
+ "if (typeof exports !== 'undefined')\n"
+ " exports.parse_sentence = parse_sentence;\n"
).
meta <- '!' / '\'' / '<-' / '/' / '.' / '(' / ')' / ':' / '->'.
name <- c: namechar n: name -> (c + n) / namechar.
namechar <- !meta !sp char.
term <- labeled / nonterminal / string / negation / parenthesized.
nonterminal <- n: name _ ->
([' state = parse_', n, '(input, state.pos);\n'].join(''))
.
labeled <- label: name _ ':'_ value: term ->
([value, ' if (state) var ', label, ' = state.val;\n'].join(''))
.
sequence <- foo: term bar: sequence ->
([foo, ' if (state) {\n', bar, ' }\n'].join(''))
/ result_expression / -> ('').
string <- '\'' s: stringcontents '\''_ ->
([" state = literal(input, state.pos, '", s, "');\n"].join(''))
.
stringcontents <- !'\\' !'\'' c: char s: stringcontents -> (c + s)
/ b: '\\' c: char s: stringcontents -> (b + c + s)
/ -> ('').
choice <- a: sequence '/'_ b: choice ->
([' stack.push(state);\n',
a,
' if (!state) {\n',
' state = stack.pop();\n',
b,
' } else stack.pop();\n'].join(''))
/ sequence.
negation <- '!'_ t: term ->
([' stack.push(state);\n',
t,
' if (state) {\n',
' stack.pop();\n',
' state = null;\n',
' } else state = stack.pop();\n'].join(''))
.
result_expression <- '->'_ result: expr _ ->
([' if (state) state.val = ', result, ';\n'].join(''))
.
expr <- '('_ e: exprcontents ')' -> ('(' + e + ')').
exprcontents <- c: (!'(' !')' char / expr) e: exprcontents -> (c + e)
/ -> ('').
parenthesized <- '('_ body: choice ')'_ -> (body).
</textarea>
<h2>output compiler, first stage</h2>
<a href="javascript:compile('output1')">go</a><br />
<textarea id="output1" rows="10" cols="80"></textarea>
<h2>output compiler, second stage</h2>
<a href="javascript:compile('output2')">go</a><br />
<textarea id="output2" rows="10" cols="80"></textarea>
<h2>output compiler, third stage</h2>
<a href="javascript:compile('output3')">go</a><br />
<textarea id="output3" rows="10" cols="80"></textarea>
</body></html>