-
Notifications
You must be signed in to change notification settings - Fork 0
/
clex.js
96 lines (73 loc) · 2.17 KB
/
clex.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
class Token{
constructor(kind, val, line){
this.kind = kind;
this.value = val;
this.line = line
}
}
export class Lexer{
constructor(data){
this.buf = data
this.pos = 0
this.line = 1
}
// toks is a dict of tokens like or ('id', 'foo') or ...
toks = {
'lbrace': /^(\{)/,
'rbrace': /^(\})/,
'lparen': /^(\()/,
'rparen': /^(\))/,
'lbrack': /^(\[)/,
'rbrack': /^(\])/,
'semicolon': /^(;)/,
'colon':/^(:)/,
'comma': /^(,)/,
'qmark':/^(\?)/,
'integer': /^(\d+)/,
'id': /^([a-zA-Z0-9][\w_]*)/,
'le' : /^(<=)/,
'ge' : /^(>=)/,
'lt' : /^(<)/,
'gt' : /^(>)/,
'equal': /^(==)/,
'assignment': /^(=)/,
'ne': /^(!=)/,
'and':/^(&&)/,
'or': /^(\|\|)/,
'minus': /^(-)/,
'plus': /^(\+)/,
'mul': /^(\*)/,
'div': /^(\/)/,
'mod': /^(%)/,
'not': /^(~)/,
'negation': /^(!)/,
'newline': /^(\n)+/,
'space': /^([ ]+)/
}
keywords = ['int', 'return', 'if', 'else', 'for', 'break', 'continue']
next(){
if (this.pos >= this.buf.length){
return null
}
for(let k in this.toks){
let match = this.toks[k].exec(this.buf.slice(this.pos, ))
if (match) {
// update pos // return tok // update line num
this.pos += match[1].length
if(k == 'newline'){
this.line += match[1].length
return this.next()
}
else if(k == 'space'){
return this.next()
}
if (this.keywords.includes(match[1])){
return new Token("keyword", match[1], this.line)
}
return new Token(k, match[1],this.line)
}
}
console.log('ERROR. NO TOKEN MATCHED')
process.exit(1)
}
}