Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80555 views
1
import {tokTypes as tt, Token, isNewLine, SourceLocation, getLineInfo, lineBreakG} from ".."
2
import {LooseParser} from "./state"
3
4
const lp = LooseParser.prototype
5
6
function isSpace(ch) {
7
return (ch < 14 && ch > 8) || ch === 32 || ch === 160 || isNewLine(ch)
8
}
9
10
lp.next = function() {
11
this.last = this.tok
12
if (this.ahead.length)
13
this.tok = this.ahead.shift()
14
else
15
this.tok = this.readToken()
16
17
if (this.tok.start >= this.nextLineStart) {
18
while (this.tok.start >= this.nextLineStart) {
19
this.curLineStart = this.nextLineStart
20
this.nextLineStart = this.lineEnd(this.curLineStart) + 1
21
}
22
this.curIndent = this.indentationAfter(this.curLineStart)
23
}
24
}
25
26
lp.readToken = function() {
27
for (;;) {
28
try {
29
this.toks.next()
30
if (this.toks.type === tt.dot &&
31
this.input.substr(this.toks.end, 1) === "." &&
32
this.options.ecmaVersion >= 6) {
33
this.toks.end++
34
this.toks.type = tt.ellipsis
35
}
36
return new Token(this.toks)
37
} catch(e) {
38
if (!(e instanceof SyntaxError)) throw e
39
40
// Try to skip some text, based on the error message, and then continue
41
let msg = e.message, pos = e.raisedAt, replace = true
42
if (/unterminated/i.test(msg)) {
43
pos = this.lineEnd(e.pos + 1)
44
if (/string/.test(msg)) {
45
replace = {start: e.pos, end: pos, type: tt.string, value: this.input.slice(e.pos + 1, pos)}
46
} else if (/regular expr/i.test(msg)) {
47
let re = this.input.slice(e.pos, pos)
48
try { re = new RegExp(re) } catch(e) {}
49
replace = {start: e.pos, end: pos, type: tt.regexp, value: re}
50
} else if (/template/.test(msg)) {
51
replace = {start: e.pos, end: pos,
52
type: tt.template,
53
value: this.input.slice(e.pos, pos)}
54
} else {
55
replace = false
56
}
57
} else if (/invalid (unicode|regexp|number)|expecting unicode|octal literal|is reserved|directly after number|expected number in radix/i.test(msg)) {
58
while (pos < this.input.length && !isSpace(this.input.charCodeAt(pos))) ++pos
59
} else if (/character escape|expected hexadecimal/i.test(msg)) {
60
while (pos < this.input.length) {
61
let ch = this.input.charCodeAt(pos++)
62
if (ch === 34 || ch === 39 || isNewLine(ch)) break
63
}
64
} else if (/unexpected character/i.test(msg)) {
65
pos++
66
replace = false
67
} else if (/regular expression/i.test(msg)) {
68
replace = true
69
} else {
70
throw e
71
}
72
this.resetTo(pos)
73
if (replace === true) replace = {start: pos, end: pos, type: tt.name, value: "✖"}
74
if (replace) {
75
if (this.options.locations)
76
replace.loc = new SourceLocation(
77
this.toks,
78
getLineInfo(this.input, replace.start),
79
getLineInfo(this.input, replace.end))
80
return replace
81
}
82
}
83
}
84
}
85
86
lp.resetTo = function(pos) {
87
this.toks.pos = pos
88
let ch = this.input.charAt(pos - 1)
89
this.toks.exprAllowed = !ch || /[\[\{\(,;:?\/*=+\-~!|&%^<>]/.test(ch) ||
90
/[enwfd]/.test(ch) &&
91
/\b(keywords|case|else|return|throw|new|in|(instance|type)of|delete|void)$/.test(this.input.slice(pos - 10, pos))
92
93
if (this.options.locations) {
94
this.toks.curLine = 1
95
this.toks.lineStart = lineBreakG.lastIndex = 0
96
let match
97
while ((match = lineBreakG.exec(this.input)) && match.index < pos) {
98
++this.toks.curLine
99
this.toks.lineStart = match.index + match[0].length
100
}
101
}
102
}
103
104
lp.lookAhead = function(n) {
105
while (n > this.ahead.length)
106
this.ahead.push(this.readToken())
107
return this.ahead[n - 1]
108
}
109
110