Repository navigation
Expand file tree
/
Copy pathCalculatorLexer.js
More file actions
103 lines (86 loc) · 2.03 KB
/
Copy pathCalculatorLexer.js
File metadata and controls
103 lines (86 loc) · 2.03 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
var EOF = -1;
function CalculatorLexer(input) {
this.input = input;
this.c = input[0];
this.p = 0;
}
CalculatorLexer.prototype.tokenize = function () {
var tokens = [];
for (var t = this.nextToken(); t !== EOF; t = this.nextToken()) {
tokens.push(t)
}
return tokens;
}
CalculatorLexer.prototype.nextToken = function () {
while (this.c !== EOF) {
if (/\s/.test(this.c)) {
this.consume(); continue;
} else if (['(', ')', '+', '/', ',', '='].indexOf(this.c) > -1) {
return this.symbol();
} else if (this.c === '*') {
this.consume();
if (this.c === '*') {
this.consume();
return '**';
} else {
return '*';
}
} else if (this.c === '-') {
if (this.isNumber(this.input[this.p + 1])) {
// this is a negative number
return this.number();
} else {
return '-';
}
} else if (this.isNumber(this.c)) {
return this.number();
} else if (this.isCharacter(this.c)) {
return this.functionOrVariableName();
} else {
throw 'Illegal: ' + this.c;
}
}
return EOF;
}
CalculatorLexer.prototype.isCharacter = function (c) {
return /^[a-z]$/.test(c);
}
CalculatorLexer.prototype.isNumber = function (d) {
return /^[0-9.]$/.test(d);
}
CalculatorLexer.prototype.symbol = function () {
var c = this.c;
this.consume();
return c;
}
CalculatorLexer.prototype.number = function () {
var result = [];
// allow negatives at the front only
if (this.c === '-') {
result.push('-');
this.consume();
}
do {
result.push(this.c);
this.consume();
} while (this.c === '.' || this.isNumber(this.c));
var numStr = result.join('');
if (/^.*\..*\..*$/.test(numStr)) {
throw 'Invalid number: ' + numStr;
}
return numStr;
}
CalculatorLexer.prototype.functionOrVariableName = function () {
var result = [];
do {
result.push(this.c);
this.consume();
} while (this.isCharacter(this.c));
return result.join('');
}
CalculatorLexer.prototype.consume = function () {
this.p++;
if (this.p < this.input.length) { this.c = this.input[this.p]; }
else { this.c = EOF; }
}
module.exports = CalculatorLexer;