diff options
author | Florian Dold <florian.dold@gmail.com> | 2017-05-03 15:35:00 +0200 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2017-05-03 15:35:00 +0200 |
commit | de98e0b232509d5f40c135d540a70e415272ff85 (patch) | |
tree | a79222a5b58484ab3b80d18efcaaa7ccc4769b33 /node_modules/acorn/src/state.js | |
parent | e0c9d480a73fa629c1e4a47d3e721f1d2d345406 (diff) |
node_modules
Diffstat (limited to 'node_modules/acorn/src/state.js')
-rw-r--r-- | node_modules/acorn/src/state.js | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/node_modules/acorn/src/state.js b/node_modules/acorn/src/state.js new file mode 100644 index 000000000..5d9ae7501 --- /dev/null +++ b/node_modules/acorn/src/state.js @@ -0,0 +1,115 @@ +import {reservedWords, keywords} from "./identifier" +import {types as tt} from "./tokentype" +import {lineBreak} from "./whitespace" +import {getOptions} from "./options" + +// Registered plugins +export const plugins = {} + +function keywordRegexp(words) { + return new RegExp("^(" + words.replace(/ /g, "|") + ")$") +} + +export class Parser { + constructor(options, input, startPos) { + this.options = options = getOptions(options) + this.sourceFile = options.sourceFile + this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5]) + let reserved = "" + if (!options.allowReserved) { + for (let v = options.ecmaVersion;; v--) + if (reserved = reservedWords[v]) break + if (options.sourceType == "module") reserved += " await" + } + this.reservedWords = keywordRegexp(reserved) + let reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict + this.reservedWordsStrict = keywordRegexp(reservedStrict) + this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind) + this.input = String(input) + + // Used to signal to callers of `readWord1` whether the word + // contained any escape sequences. This is needed because words with + // escape sequences must not be interpreted as keywords. + this.containsEsc = false + + // Load plugins + this.loadPlugins(options.plugins) + + // Set up token state + + // The current position of the tokenizer in the input. + if (startPos) { + this.pos = startPos + this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1 + this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length + } else { + this.pos = this.lineStart = 0 + this.curLine = 1 + } + + // Properties of the current token: + // Its type + this.type = tt.eof + // For tokens that include more information than their type, the value + this.value = null + // Its start and end offset + this.start = this.end = this.pos + // And, if locations are used, the {line, column} object + // corresponding to those offsets + this.startLoc = this.endLoc = this.curPosition() + + // Position information for the previous token + this.lastTokEndLoc = this.lastTokStartLoc = null + this.lastTokStart = this.lastTokEnd = this.pos + + // The context stack is used to superficially track syntactic + // context to predict whether a regular expression is allowed in a + // given position. + this.context = this.initialContext() + this.exprAllowed = true + + // Figure out if it's a module code. + this.inModule = options.sourceType === "module" + this.strict = this.inModule || this.strictDirective(this.pos) + + // Used to signify the start of a potential arrow function + this.potentialArrowAt = -1 + + // Flags to track whether we are in a function, a generator, an async function. + this.inFunction = this.inGenerator = this.inAsync = false + // Positions to delayed-check that yield/await does not exist in default parameters. + this.yieldPos = this.awaitPos = 0 + // Labels in scope. + this.labels = [] + + // If enabled, skip leading hashbang line. + if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") + this.skipLineComment(2) + + // Scope tracking for duplicate variable names (see scope.js) + this.scopeStack = [] + this.enterFunctionScope() + } + + // DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them + isKeyword(word) { return this.keywords.test(word) } + isReservedWord(word) { return this.reservedWords.test(word) } + + extend(name, f) { + this[name] = f(this[name]) + } + + loadPlugins(pluginConfigs) { + for (let name in pluginConfigs) { + let plugin = plugins[name] + if (!plugin) throw new Error("Plugin '" + name + "' not found") + plugin(this, pluginConfigs[name]) + } + } + + parse() { + let node = this.options.program || this.startNode() + this.nextToken() + return this.parseTopLevel(node) + } +} |