-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathParserCombinators.js
More file actions
117 lines (102 loc) · 3.13 KB
/
ParserCombinators.js
File metadata and controls
117 lines (102 loc) · 3.13 KB
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
// Messing around with Parser-Combinators
// Based on: http://theorangeduck.com/page/you-could-have-invented-parser-combinators
// Parser: a function accepting strings as input and returning some structure as output.
// Combinator: Combines values in various ways to build up more complex values.
var current = 0;
function inputRead(input) {
console.log("Read: ", input[current]);
return input[current];
}
function inputAdvance(input, step) {
current++;
console.log("Advancing: ", step);
}
var failure = void 0;
// Parser function that looks for a specific character and returns
// either the matching character or failure.
function lit(c) {
console.log("Looking for: ", c);
return (function(input) {
var r = inputRead(input);
if (r === c) {
inputAdvance(input, 1);
return c;
} else {
return failure;
}
});
}
//var parser = lit("a");
//var result = parser(input);
//console.log("Result: ", result);
// Returns a function that returns true if either input function is true
function or(parserA, parserB) {
return (function (input) {
var resultA = parserA(input);
if (resultA != failure) { return resultA; }
var resultB = parserB(input);
if (resultB != failure) { return resultB; }
return failure;
});
}
//var parserAB = or(lit('a'), lit('b'));
//var resultAB = parserAB(input);
//console.log("resultAB: ", resultAB);
// Returns a function that returns the concatination of the results
// if all the functions pass. If any function fails then the input
// is reset and failure is returned.
function and(parserA, parserB) {
return (function(input) {
var before = current;
var resultA = parserA(input);
if (resultA == failure) {
current = before;
return failure;
}
var resultB = parserB(input);
if (resultB == failure) {
current = before;
return failure;
}
return [resultA, resultB];
});
}
//var input = [ 'a', 'b' ];
//var parserAAndB = and(lit('a'), lit('b'));
//var resultAAndB = parserAAndB(input);
//console.log("ResultAAndB: ", resultAAndB);
//var input = [ 'c', 'd' ];
//var parserAAndB = or(and(lit('a'), lit('b')), and(lit('c'),lit('d')));
//var resultAAndB = parserAAndB(input);
//console.log("ResultAAndB: ", resultAAndB);
// Returns a function that runs a parsing function and applies f to its results.
function apply(f, parser) {
return (function (input) {
var result = parser(input);
if (result == failure) {
return failure;
} else {
return f(result);
}
});
}
//function toInt(chars) {
// var result = [];
// for (var i = 0; i < chars.length; i++) {
// result.push(chars[i].charCodeAt());
// }
// return result;
//}
function toInt(char) {
return char.charCodeAt(0);
}
function litToInt(c) {
return apply(toInt, lit(c));
}
var parser = or(
and(litToInt('a'), litToInt('b')),
and(litToInt('c'), litToInt('d'))
);
var input = [ 'a', 'b' ];
var result = parser(input);
console.log("result: ", result);