-
Notifications
You must be signed in to change notification settings - Fork 0
/
token.js
101 lines (81 loc) · 2.11 KB
/
token.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
var Position = require("./position");
// Token Constructor
function Token(type, position) {
this.type = type;
this["is" + type] = true;
this.position = position || Position("???", "???");
// These will be assigned later
this.index = 0;
this.tokenArray = [];
}
Token.eof = function () {
return new Token("End of File", null)
.set("string", "End of File");
}
Token.indent = function (str, position) {
return new Token("Indent", position)
.set("width", str.length);
}
Token.identifier = tokenCreator("Identifier");
Token.comment = tokenCreator("Comment");
Token.punctuation = tokenCreator("Punctuation");
Token.number = valueTokenCreator("Number");
Token.string = valueTokenCreator("String");
Token.regex = valueTokenCreator("Regex");
Token.boolean = valueTokenCreator("Boolean");
function tokenCreator(type) {
return function (str, position) {
return new Token(type, position)
.set("string", str);
}
}
function valueTokenCreator(type) {
return function (str, position) {
return new Token(type, position)
.set("string", str)
.set("value", evalMultiline(str));
}
}
Token.prototype = {
is: function (candidate) {
return this.string === candidate;
},
isNot: function (candidate) {
return this.string !== candidate;
},
move: function (distance) {
var newIndex = this.index + distance;
// ensure new index is within the bounds of the token array
newIndex = Math.min(newIndex, this.tokenArray.length - 1);
newIndex = Math.max(newIndex, 0);
return this.tokenArray[newIndex];
},
next: function () {
return this.move(1);
},
previous: function () {
return this.move(-1);
},
set: function (property, value) {
this[property] = value;
return this;
},
error: function (message) {
this.position.error(message);
},
};
Token.prototype.toString = Token.prototype.inspect = function () {
// show width for indents
return this.type +
"(" +
("width" in this ? this.width : this.string) +
")" +
" at line " +
this.position.line +
", column " +
this.position.column;
}
function evalMultiline(str) {
return eval(str.replace(/\r\n|\r|\n/g, "\\n"));
}
module.exports = Token;