-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathlex.js
52 lines (40 loc) · 1.3 KB
/
lex.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
var R = require('ramda');
var tokenMatches = [
{ type: 'space', match: /^\s+/ },
{ type: 'literal', match: /^(\d*\.\d+|\d+)/ },
{ type: 'name', match: /^[a-zA-Z_]\w*/ },
{ type: 'paren', match: /^[\(\)]/ },
{ type: 'operator', match: /^[\+\-%\*\/\^<>]/ }
];
var mkToken = function(token, value, repr) {
return {
type: 'token',
token: token,
value: value,
repr: repr || value
};
};
var checkToken = function(token, checks) {
checks = checks || {};
return !!token && token.type === 'token' &&
(token.token === checks.token || !checks.token) &&
(token.value === checks.value || !checks.value);
};
var chomp = function(str) {
var matcher = R.find(R.where({ match: function(re) { return re.test(str); } }), tokenMatches);
var token = matcher ?
mkToken(matcher.type, str.match(matcher.match)[0]) :
mkToken(null, str[0]);
return { token: token, leftover: str.slice(token.value.length) };
};
var chompReduce = function(str) {
function reducer(initial, leftover) {
if (!leftover) { return initial; } // nothing more to eat!
var result = chomp(leftover);
return reducer(R.append(result.token, initial), result.leftover);
}
return reducer([], str);
};
chompReduce.token = mkToken;
chompReduce.check = checkToken;
module.exports = chompReduce;