private static @string String(this jsCtx i) { if (i >= jsCtx(len(_jsCtx_index) - 1L)) { return("jsCtx(" + strconv.FormatInt(int64(i), 10L) + ")"); } return(_jsCtx_name[_jsCtx_index[i].._jsCtx_index[i + 1L]]);
// nextJSCtx returns the context that determines whether a slash after the // given run of tokens starts a regular expression instead of a division // operator: / or /=. // // This assumes that the token run does not include any string tokens, comment // tokens, regular expression literal tokens, or division operators. // // This fails on some valid but nonsensical JavaScript programs like // "x = ++/foo/i" which is quite different than "x++/foo/i", but is not known to // fail on any known useful programs. It is based on the draft // JavaScript 2.0 lexical grammar and requires one token of lookbehind: // https://www.mozilla.org/js/language/js20-2000-07/rationale/syntax.html private static jsCtx nextJSCtx(slice<byte> s, jsCtx preceding) { s = bytes.TrimRight(s, "\t\n\f\r \u2028\u2029"); if (len(s) == 0L) { return preceding; } { var c = s[len(s) - 1L]; var n = len(s); switch (c) { case '+': // ++ and -- are not regexp preceders, but + and - are whether // they are used as infix or prefix operators. case '-': // ++ and -- are not regexp preceders, but + and - are whether // they are used as infix or prefix operators. var start = n - 1L; // Count the number of adjacent dashes or pluses. while (start > 0L && s[start - 1L] == c) { start--; } if ((n - start) & 1L == 1L) { // Reached for trailing minus signs since "---" is the // same as "-- -". return jsCtxRegexp; } return jsCtxDivOp; break; case '.': // Handle "42." if (n != 1L && '0' <= s[n - 2L] && s[n - 2L] <= '9') { return jsCtxDivOp; } return jsCtxRegexp; // Suffixes for all punctuators from section 7.7 of the language spec // that only end binary operators not handled above. break; case ',': case '<': case '>': case '=': case '*': case '%': case '&': case '|': case '^': case '?': return jsCtxRegexp; // Suffixes for all punctuators from section 7.7 of the language spec // that are prefix operators not handled above. break; case '!': case '~': return jsCtxRegexp; // Matches all the punctuators from section 7.7 of the language spec // that are open brackets not handled above. break; case '(': case '[': return jsCtxRegexp; // Matches all the punctuators from section 7.7 of the language spec // that precede expression starts. break; case ':': case ';': case '{': return jsCtxRegexp; // CAVEAT: the close punctuators ('}', ']', ')') precede div ops and // are handled in the default except for '}' which can precede a // division op as in // ({ valueOf: function () { return 42 } } / 2 // which is valid, but, in practice, developers don't divide object // literals, so our heuristic works well for code like // function () { ... } /foo/.test(x) && sideEffect(); // The ')' punctuator can precede a regular expression as in // if (b) /foo/.test(x) && ... // but this is much less likely than // (a + b) / c break; case '}': return jsCtxRegexp; break; default: // Look for an IdentifierName and see if it is a keyword that // can precede a regular expression. var j = n; while (j > 0L && isJSIdentPart(rune(s[j - 1L]))) { j--; } if (regexpPrecederKeywords[string(s[j..])])
public context(state state = default, delim delim = default, urlPart urlPart = default, jsCtx jsCtx = default, attr attr = default, element element = default, ref ptr <Error> err = default) { this.state = state; this.delim = delim; this.urlPart = urlPart; this.jsCtx = jsCtx; this.attr = attr; this.element = element; this.err = err; }