UNPKG

tenko

Version:

A "pixel perfect" 100% spec compliant ES2021 JavaScript parser written in JS.

136 lines (129 loc) 4.54 kB
// All constants in this file will be extrapolated and unconditionally inlined in a build without scope tracking // (Make sure to only make primitives `const`, use `let` for anything else. Even if it's a constant value otherwise.) import {ASSERT} from "./utils.mjs"; let __$flag_lf = 0; // This name is hardcoded in the build script... const LF_NO_FLAGS = 0; const LF_CAN_NEW_DOT_TARGET = 1 << ++__$flag_lf; // current scope is inside at least one regular (non-arrow) function const LF_FOR_REGEX = 1 << ++__$flag_lf; const LF_IN_ASYNC = 1 << ++__$flag_lf; const LF_IN_CONSTRUCTOR = 1 << ++__$flag_lf; // inside a class constructor (not a regular function) that is not static const LF_IN_FOR_LHS = 1 << ++__$flag_lf; // inside the initial part of a for-header, prevents `in` being parsed as an operator, hint for checks when destructuring pattern as lhs const LF_IN_FUNC_ARGS = 1 << ++__$flag_lf; // throws for await expression const LF_IN_GENERATOR = 1 << ++__$flag_lf; const LF_IN_GLOBAL = 1 << ++__$flag_lf; // unset whenever you go into any kind of function (for return) const LF_IN_ITERATION = 1 << ++__$flag_lf; // inside a loop (tells you whether break/continue is valid) const LF_IN_SWITCH = 1 << ++__$flag_lf; // inside a switch (tells you whether break is valid) const LF_IN_TEMPLATE = 1 << ++__$flag_lf; const LF_NO_ASI = 1 << ++__$flag_lf; // can you asi if you must? used for async. LF_IN_TEMPLATE also implies this flag! const LF_STRICT_MODE = 1 << ++__$flag_lf; const LF_SUPER_CALL = 1 << ++__$flag_lf; // can call `super()` const LF_SUPER_PROP = 1 << ++__$flag_lf; // can read `super.foo` (there are cases where you can doo this but not `super()`) const LF_NOT_KEYWORD = 1 << ++__$flag_lf; // skip keyword check for next ident parse (like member expression property) const LF_CHAINING = 1 << ++__$flag_lf; // Currently in an optional chain. If we encounter `?.` do not add another `ChainExpression` node. ASSERT(__$flag_lf < 32, 'cannot use more than 32 flags'); // start of the first statement without knowing strict mode status: // - div means regular expression // - closing curly means closing curly (not template body/tail) // - sloppy mode until proven otherwise const INITIAL_LEXER_FLAGS = LF_FOR_REGEX | LF_IN_GLOBAL; // not sure about global, that may change depending on options{$? function L(flags) { let bak = flags; let s = []; if (!flags) { s.push('LF_NO_FLAGS'); } if (flags & LF_STRICT_MODE) { flags ^= LF_STRICT_MODE; s.push('LF_STRICT_MODE'); } if (flags & LF_FOR_REGEX) { flags ^= LF_FOR_REGEX; s.push('LF_FOR_REGEX'); } if (flags & LF_IN_TEMPLATE) { flags ^= LF_IN_TEMPLATE; s.push('LF_IN_TEMPLATE'); } if (flags & LF_IN_ASYNC) { flags ^= LF_IN_ASYNC; s.push('LF_IN_ASYNC'); } if (flags & LF_IN_GENERATOR) { flags ^= LF_IN_GENERATOR; s.push('LF_IN_GENERATOR'); } if (flags & LF_IN_CONSTRUCTOR) { flags ^= LF_IN_CONSTRUCTOR; s.push('LF_IN_CONSTRUCTOR'); } if (flags & LF_IN_FUNC_ARGS) { flags ^= LF_IN_FUNC_ARGS; s.push('LF_IN_FUNC_ARGS'); } if (flags & LF_IN_GLOBAL) { flags ^= LF_IN_GLOBAL; s.push('LF_IN_GLOBAL'); } if (flags & LF_IN_ITERATION) { flags ^= LF_IN_ITERATION; s.push('LF_IN_ITERATION'); } if (flags & LF_IN_SWITCH) { flags ^= LF_IN_SWITCH; s.push('LF_IN_SWITCH'); } if (flags & LF_CAN_NEW_DOT_TARGET) { flags ^= LF_CAN_NEW_DOT_TARGET; s.push('LF_CAN_NEW_DOT_TARGET'); } if (flags & LF_IN_FOR_LHS) { flags ^= LF_IN_FOR_LHS; s.push('LF_IN_FOR_LHS'); } if (flags & LF_NO_ASI) { flags ^= LF_NO_ASI; s.push('LF_NO_ASI'); } if (flags & LF_SUPER_CALL) { flags ^= LF_SUPER_CALL; s.push('LF_SUPER_CALL'); } if (flags & LF_SUPER_PROP) { flags ^= LF_SUPER_PROP; s.push('LF_SUPER_PROP'); } if (flags & LF_NOT_KEYWORD) { flags ^= LF_NOT_KEYWORD; s.push('LF_NOT_KEYWORD'); } if (flags & LF_CHAINING) { flags ^= LF_CHAINING; s.push('LF_CHAIING'); } if (flags) { throw new Error('UNKNOWN_FLAGS: ' + flags.toString(2) + ' (was: ' + bak.toString(2) + '), so far: [' + s.join('|') + ']'); } return 'L:' + s.join('|'); } export { INITIAL_LEXER_FLAGS, LF_NO_FLAGS, LF_CAN_NEW_DOT_TARGET, LF_FOR_REGEX, LF_IN_ASYNC, LF_IN_CONSTRUCTOR, LF_IN_FOR_LHS, LF_IN_FUNC_ARGS, LF_IN_GENERATOR, LF_IN_GLOBAL, LF_IN_ITERATION, LF_IN_SWITCH, LF_IN_TEMPLATE, LF_NO_ASI, LF_STRICT_MODE, LF_SUPER_CALL, LF_SUPER_PROP, LF_NOT_KEYWORD, LF_CHAINING, L, };