text: import { BTree } from './btree'
  
  export function tokIsKeyword(t :token) :bool {
    return token.keyword_beg < t && t < token.keyword_end
  }
  
  export function hasIntValue(t :token) :bool {
    return t == token.CHAR
  }
  
  export function hasByteValue(t :token) :bool {
    return (
      (token.literal_beg < t && t < token.literal_end) ||
      t == token.COMMENT
    )
  }
  
  // Operator precedences
  export enum prec {
    LOWEST, // = := ! <- ->
    OROR,     // ||
    ANDAND,    // &&
    CMP,    // == != < <= > >=
    ADD,    // + - | ^
    MUL,    // * / % & &^ << >>
  }
  
  export enum token {
    // Special tokens
    ILLEGAL = 0,
    EOF,
    COMMENT,
    DIRECTIVE, // #directive
  
    literal_beg,
    // Identifiers and basic type literals
    // (these tokens stand for classes of literals)
    NAME,    // main
    NAMEAT,  // @foo, @
    literal_num_beg,
    literal_int_beg,
    CHAR,    // 'a'
    INT,     // 12345
    INT_BIN, // 0b1010
    INT_OCT, // 0o6737
    INT_HEX, // 0xBE3f
    literal_int_end,
    FLOAT,   // 123.45
    // RATIO,   // 22/7
    literal_num_end,
    STRING,  // "abc"
    STRING_MULTI, // "ab\nc" — multi-line
    STRING_PIECE, // "a ${...} b" -- the "a " part (" b" is STRING)
    literal_end,
  
    // Delimiters
    delim_beg,
    LPAREN,    // (
    LBRACKET,  // [
    LBRACE,    // {
    COMMA,     // ,
    DOT,       // .
    PERIODS,   // ..
    ELLIPSIS,  // ...
    RPAREN,    // )
    RBRACKET,  // ]
    RBRACE,    // }
    SEMICOLON, // ;
    COLON,     // :
    QUESTION,  // ?
    delim_end,
  
    // Operators
    operator_beg,
  
    // prec.LOWEST
    ASSIGN,         // =
    assignop_beg,
    ADD_ASSIGN,     // +=
    SUB_ASSIGN,     // -=
    MUL_ASSIGN,     // *=
    QUO_ASSIGN,     // /=
    REM_ASSIGN,     // %=
    AND_ASSIGN,     // &=
    OR_ASSIGN,      // |=
    XOR_ASSIGN,     // ^=
    SHL_ASSIGN,     // <<=
    SHR_ASSIGN,     // >>=
    AND_NOT_ASSIGN, // &^=
    assignop_end,
    INC,            // ++
    DEC,            // --
    SET_ASSIGN,     // :=
    NOT,            // !
    ARROWL,         // <-
    ARROWR,         // ->
  
    cmpop_beg,
    // prec.OR
    OROR, // ||
  
    // prec.AND
    ANDAND, // &&
  
    // prec.CMP
    EQL, // ==
    NEQ, // !=
    LSS, // <
    LEQ, // <=
    GTR, // >
    GEQ, // >=
    cmpop_end,
  
    // prec.ADD
    ADD, // +
    SUB, // -
    OR,  // |
    XOR, // ^  "NOT" when unary, "XOR" when binary
  
    // prec.MUL
    MUL,     // *
    QUO,     // /
    REM,     // %
    AND,     // &
    AND_NOT, // &^  equiv to `x & (^y)` (or `x & ~y` in C)
    SHL,     // <<
    SHR,     // >>  (arithmetic when signed, logical when unsigned)
  
    operator_end,
  
    // Keywords
    keyword_beg,
    BREAK,
    //CASE,
    //CHAN,
    //CONST,
    CONTINUE,
    DEFAULT,
    DEFER,
    ELSE,
    ENUM,
    FALLTHROUGH,
    FOR,
    FUN,
    GO,
    //GOTO,
    IF,
    IMPORT,
    INTERFACE,
    IN,
    IS,
    //MAP,
    //PACKAGE,
    //RANGE,
    RETURN,
    SELECT,
    //STRUCT,
    SWITCH,
    SYMBOL,
    TYPE,
    // VAR,
    WHILE,
    keyword_end,
  } // enum T
  
  
  // Keywords
  // When you add, change or remove a keyword, make sure to run gen-btree.js
  // with the changes and update the code below.
  // Keyword token names should be the UPPER-CASE version of the actual keyword
  // name. This convention is used to populate tokenStrings.
  
  
  const tokenStrings = new Map<token, string>([
    [token.NAMEAT, "@"],
  
    [token.ADD, "+"],
    [token.SUB, "-"],
    [token.MUL, "*"],
    [token.QUO, "/"],
    [token.REM, "%"],
  
    [token.AND,     "&"],
    [token.OR,      "|"],
    [token.XOR,     "^"],
    [token.SHL,     "<<"],
    [token.SHR,     ">>"],
    [token.AND_NOT, "&^"],
  
    [token.ADD_ASSIGN, "+="],
    [token.SUB_ASSIGN, "-="],
    [token.MUL_ASSIGN, "*="],
    [token.QUO_ASSIGN, "/="],
    [token.REM_ASSIGN, "%="],
  
    [token.AND_ASSIGN,     "&="],
    [token.OR_ASSIGN,      "|="],
    [token.XOR_ASSIGN,     "^="],
    [token.SHL_ASSIGN,     "<<="],
    [token.SHR_ASSIGN,     ">>="],
    [token.AND_NOT_ASSIGN, "&^="],
  
    [token.ANDAND, "&&"],
    [token.OROR,   "||"],
    [token.ARROWL, "<-"],
    [token.ARROWR, "->"],
    [token.INC,    "++"],
    [token.DEC,    "--"],
  
    [token.EQL,    "=="],
    [token.LSS,    "<"],
    [token.GTR,    ">"],
    [token.ASSIGN, "="],
    [token.NOT,    "!"],
  
    [token.NEQ,        "!="],
    [token.LEQ,        "<="],
    [token.GEQ,        ">="],
    [token.SET_ASSIGN, ":="],
    [token.ELLIPSIS,   "..."],
    [token.PERIODS,    ".."],
  
    [token.LPAREN,   "("],
    [token.LBRACKET, "["],
    [token.LBRACE,   "{"],
    [token.COMMA,    ","],
    [token.DOT,      "."],
  
    [token.RPAREN,    ")"],
    [token.RBRACKET,  "]"],
    [token.RBRACE,    "}"],
    [token.SEMICOLON, ";"],
    [token.COLON,     ":"],
  ]) // tokenStrings
  
  for (let i = token.keyword_beg+1; i < token.keyword_end; ++i) {
    const t = token[i] as string
    tokenStrings.set((token as any)[t] as token, t.toLowerCase())
  }
  
  // tokstr returns a printable version of the token
  //
  export function tokstr(t :token) :string {
    return tokenStrings.get(t) || token[t].toLowerCase()
  }
  
  // BEGIN generated by gen-keywords.js
  const cdat = new Uint8Array([
    103,111,100,101,102,101,114,98,114,101,97,107,99,111,110,116,105,110,117,101
    ,100,101,102,97,117,108,116,101,110,117,109,101,108,115,101,102,97,108,108
    ,116,104,114,111,117,103,104,102,111,114,102,117,110,105,115,105,109,112,111
    ,114,116,105,102,105,110,105,110,116,101,114,102,97,99,101,115,119,105,116
    ,99,104,114,101,116,117,114,110,115,101,108,101,99,116,115,121,109,98,111
    ,108,116,121,112,101,119,104,105,108,101]);
  const keywords = new BTree<token>(
    { k: cdat.subarray(0,2) /*go*/, v: token.GO,
      L:{ k: cdat.subarray(2,7) /*defer*/, v: token.DEFER,
        L:{ k: cdat.subarray(7,12) /*break*/, v: token.BREAK,
          R:{ k: cdat.subarray(12,20) /*continue*/, v: token.CONTINUE,
            R:{ k: cdat.subarray(20,27) /*default*/, v: token.DEFAULT}}},
        R:{ k: cdat.subarray(27,31) /*enum*/, v: token.ENUM,
          L:{ k: cdat.subarray(31,35) /*else*/, v: token.ELSE},
          R:{ k: cdat.subarray(35,46) /*fallthrough*/, v: token.FALLTHROUGH,
            R:{ k: cdat.subarray(46,49) /*for*/, v: token.FOR,
              R:{ k: cdat.subarray(49,52) /*fun*/, v: token.FUN}}}}},
      R:{ k: cdat.subarray(52,54) /*is*/, v: token.IS,
        L:{ k: cdat.subarray(54,60) /*import*/, v: token.IMPORT,
          L:{ k: cdat.subarray(60,62) /*if*/, v: token.IF},
          R:{ k: cdat.subarray(62,64) /*in*/, v: token.IN,
            R:{ k: cdat.subarray(64,73) /*interface*/, v: token.INTERFACE}}},
        R:{ k: cdat.subarray(73,79) /*switch*/, v: token.SWITCH,
          L:{ k: cdat.subarray(79,85) /*return*/, v: token.RETURN,
            R:{ k: cdat.subarray(85,91) /*select*/, v: token.SELECT}},
          R:{ k: cdat.subarray(91,97) /*symbol*/, v: token.SYMBOL,
            R:{ k: cdat.subarray(97,101) /*type*/, v: token.TYPE,
              R:{ k: cdat.subarray(101,106) /*while*/, v: token.WHILE}}}}}}
  )
  // END generated by gen-keywords.js
  
  // lookupKeyword maps an identifier to its keyword token or NAME
  // (if not a keyword).
  //
  export function lookupKeyword(ident :ArrayLike<byte>) :token {
    return keywords.get(ident) || token.NAME
  }
  