/
Parser.js
119 lines (106 loc) · 2.56 KB
/
Parser.js
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
var Parser = function(grammar)
{
var toArray = function(args) {
var arr = []
for (var i = 0; i < args.length; i++) arr.push(args[i])
return arr
}
// The Y Combinator
var Y = function (gen) {
return (function(f) {return f(f)})(
function(f) {
return gen(function() {return f(f).apply(null, arguments)})
}
)
}
var Optional = function(func)
{
return function(text, state) {
return func(text, state) || [text, state]
}
}
var EOF = function(text, state) { // matches the end of the text
return (text == "" ? [text, state] : null)
}
var Terminator = function(text, state) { // terminates scanner (possibly in the middle of the text)
return ["", state]
}
var Char = function(alphabet)
{
return function(text, state) {
return ((text.length > 0 && alphabet.indexOf(text.charAt(0)) > -1) ? [text.substr(1), state] : null)
}
}
var NotChar = function(alphabet)
{
return function(text, state) {
return ((text.length > 0 && alphabet.indexOf(text.charAt(0)) == -1) ? [text.substr(1), state] : null)
}
}
var Any = function()
{
var args = toArray(arguments)
return function(text, state) {
var r = null
for each (var arg in args)
{
r = arg(text, state)
if (r)
{
return r
}
}
return null
}
}
var All = function()
{
var args = toArray(arguments)
return function(text, state) {
var r = null
for each (var arg in args)
{
r = arg(text, state)
if (!r) return r
text = r[0]
state = r[1]
}
return [text, state]
}
}
// hook: function(buffer, state) { return state }
var Capture = function(func, hook)
{
return function(text, state)
{
var r = func(text, state)
if (r) {
var t = r[0]
var s = r[1]
return [t, hook(text.substr(0, text.length - t.length), s)]
}
return r
}
}
// hook: function(state1) { return state2 }
var Before = function(func, hook)
{
return function(text, state) {
return func(text, hook(state))
}
}
// hook: function(state1, state2) { return state3 }
var After = function(func, hook)
{
return function(text, state) {
var r = func(text, state)
return r && [r[0], hook(state, r[1])]
}
}
return grammar(All, Any, Capture, Char, NotChar, Optional, Y, EOF, Terminator, Before, After)
}
var Parse = function(parser, text, state)
{
var r = parser(text, state)
return r && r[1]
}