github.com/team-ide/go-dialect@v1.9.20/vitess/sqlparser/keywords.go (about)

     1  /*
     2  Copyright 2021 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package sqlparser
    18  
    19  import (
    20  	"fmt"
    21  	"strings"
    22  )
    23  
    24  type keyword struct {
    25  	name string
    26  	id   int
    27  }
    28  
    29  func (k *keyword) match(input []byte) bool {
    30  	if len(input) != len(k.name) {
    31  		return false
    32  	}
    33  	for i, c := range input {
    34  		if 'A' <= c && c <= 'Z' {
    35  			c += 'a' - 'A'
    36  		}
    37  		if k.name[i] != c {
    38  			return false
    39  		}
    40  	}
    41  	return true
    42  }
    43  
    44  func (k *keyword) matchStr(input string) bool {
    45  	return keywordASCIIMatch(input, k.name)
    46  }
    47  
    48  func keywordASCIIMatch(input string, expected string) bool {
    49  	if len(input) != len(expected) {
    50  		return false
    51  	}
    52  	for i := 0; i < len(input); i++ {
    53  		c := input[i]
    54  		if 'A' <= c && c <= 'Z' {
    55  			c += 'a' - 'A'
    56  		}
    57  		if expected[i] != c {
    58  			return false
    59  		}
    60  	}
    61  	return true
    62  }
    63  
    64  // keywords is a table of mysql keywords that fall into two categories:
    65  // 1) keywords considered reserved by MySQL
    66  // 2) keywords for us to handle specially in sql.y
    67  //
    68  // Those marked as UNUSED are likely reserved keywords. We add them here so that
    69  // when rewriting queries we can properly backtick quote them so they don't cause issues
    70  //
    71  // NOTE: If you add new keywords, add them also to the reserved_keywords or
    72  // non_reserved_keywords grammar in sql.y -- this will allow the keyword to be used
    73  // in identifiers. See the docs for each grammar to determine which one to put it into.
    74  var keywords = []keyword{
    75  	{"_armscii8", UNDERSCORE_ARMSCII8},
    76  	{"_ascii", UNDERSCORE_ASCII},
    77  	{"_big5", UNDERSCORE_BIG5},
    78  	{"_binary", UNDERSCORE_BINARY},
    79  	{"_cp1250", UNDERSCORE_CP1250},
    80  	{"_cp1251", UNDERSCORE_CP1251},
    81  	{"_cp1256", UNDERSCORE_CP1256},
    82  	{"_cp1257", UNDERSCORE_CP1257},
    83  	{"_cp850", UNDERSCORE_CP850},
    84  	{"_cp852", UNDERSCORE_CP852},
    85  	{"_cp866", UNDERSCORE_CP866},
    86  	{"_cp932", UNDERSCORE_CP932},
    87  	{"_dec8", UNDERSCORE_DEC8},
    88  	{"_eucjpms", UNDERSCORE_EUCJPMS},
    89  	{"_euckr", UNDERSCORE_EUCKR},
    90  	{"_gb18030", UNDERSCORE_GB18030},
    91  	{"_gb2312", UNDERSCORE_GB2312},
    92  	{"_gbk", UNDERSCORE_GBK},
    93  	{"_geostd8", UNDERSCORE_GEOSTD8},
    94  	{"_greek", UNDERSCORE_GREEK},
    95  	{"_hebrew", UNDERSCORE_HEBREW},
    96  	{"_hp8", UNDERSCORE_HP8},
    97  	{"_keybcs2", UNDERSCORE_KEYBCS2},
    98  	{"_koi8r", UNDERSCORE_KOI8R},
    99  	{"_koi8u", UNDERSCORE_KOI8U},
   100  	{"_latin1", UNDERSCORE_LATIN1},
   101  	{"_latin2", UNDERSCORE_LATIN2},
   102  	{"_latin5", UNDERSCORE_LATIN5},
   103  	{"_latin7", UNDERSCORE_LATIN7},
   104  	{"_macce", UNDERSCORE_MACCE},
   105  	{"_macroman", UNDERSCORE_MACROMAN},
   106  	{"_sjis", UNDERSCORE_SJIS},
   107  	{"_swe7", UNDERSCORE_SWE7},
   108  	{"_tis620", UNDERSCORE_TIS620},
   109  	{"_ucs2", UNDERSCORE_UCS2},
   110  	{"_ujis", UNDERSCORE_UJIS},
   111  	{"_utf16", UNDERSCORE_UTF16},
   112  	{"_utf16le", UNDERSCORE_UTF16LE},
   113  	{"_utf32", UNDERSCORE_UTF32},
   114  	{"_utf8", UNDERSCORE_UTF8},
   115  	{"_utf8mb4", UNDERSCORE_UTF8MB4},
   116  	{"accessible", UNUSED},
   117  	{"action", ACTION},
   118  	{"add", ADD},
   119  	{"after", AFTER},
   120  	{"against", AGAINST},
   121  	{"algorithm", ALGORITHM},
   122  	{"all", ALL},
   123  	{"alter", ALTER},
   124  	{"always", ALWAYS},
   125  	{"analyze", ANALYZE},
   126  	{"and", AND},
   127  	{"as", AS},
   128  	{"asc", ASC},
   129  	{"asensitive", UNUSED},
   130  	{"auto_increment", AUTO_INCREMENT},
   131  	{"avg_row_length", AVG_ROW_LENGTH},
   132  	{"before", UNUSED},
   133  	{"begin", BEGIN},
   134  	{"between", BETWEEN},
   135  	{"bigint", BIGINT},
   136  	{"binary", BINARY},
   137  	{"bit", BIT},
   138  	{"blob", BLOB},
   139  	{"bool", BOOL},
   140  	{"boolean", BOOLEAN},
   141  	{"both", UNUSED},
   142  	{"by", BY},
   143  	{"call", CALL},
   144  	{"cancel", CANCEL},
   145  	{"cascade", CASCADE},
   146  	{"cascaded", CASCADED},
   147  	{"case", CASE},
   148  	{"cast", CAST},
   149  	{"channel", CHANNEL},
   150  	{"change", CHANGE},
   151  	{"char", CHAR},
   152  	{"character", CHARACTER},
   153  	{"charset", CHARSET},
   154  	{"check", CHECK},
   155  	{"checksum", CHECKSUM},
   156  	{"cleanup", CLEANUP},
   157  	{"coalesce", COALESCE},
   158  	{"code", CODE},
   159  	{"collate", COLLATE},
   160  	{"collation", COLLATION},
   161  	{"column", COLUMN},
   162  	{"columns", COLUMNS},
   163  	{"comment", COMMENT_KEYWORD},
   164  	{"committed", COMMITTED},
   165  	{"commit", COMMIT},
   166  	{"compact", COMPACT},
   167  	{"complete", COMPLETE},
   168  	{"compressed", COMPRESSED},
   169  	{"compression", COMPRESSION},
   170  	{"condition", UNUSED},
   171  	{"connection", CONNECTION},
   172  	{"constraint", CONSTRAINT},
   173  	{"continue", UNUSED},
   174  	{"convert", CONVERT},
   175  	{"copy", COPY},
   176  	{"cume_dist", UNUSED},
   177  	{"substr", SUBSTRING},
   178  	{"subpartition", SUBPARTITION},
   179  	{"subpartitions", SUBPARTITIONS},
   180  	{"substring", SUBSTRING},
   181  	{"create", CREATE},
   182  	{"cross", CROSS},
   183  	{"csv", CSV},
   184  	{"current_date", CURRENT_DATE},
   185  	{"current_time", CURRENT_TIME},
   186  	{"current_timestamp", CURRENT_TIMESTAMP},
   187  	{"current_user", CURRENT_USER},
   188  	{"cursor", UNUSED},
   189  	{"data", DATA},
   190  	{"database", DATABASE},
   191  	{"databases", DATABASES},
   192  	{"day", DAY},
   193  	{"day_hour", DAY_HOUR},
   194  	{"day_microsecond", DAY_MICROSECOND},
   195  	{"day_minute", DAY_MINUTE},
   196  	{"day_second", DAY_SECOND},
   197  	{"date", DATE},
   198  	{"datetime", DATETIME},
   199  	{"dec", UNUSED},
   200  	{"decimal", DECIMAL_TYPE},
   201  	{"declare", UNUSED},
   202  	{"default", DEFAULT},
   203  	{"definer", DEFINER},
   204  	{"delay_key_write", DELAY_KEY_WRITE},
   205  	{"delayed", UNUSED},
   206  	{"delete", DELETE},
   207  	{"dense_rank", UNUSED},
   208  	{"desc", DESC},
   209  	{"describe", DESCRIBE},
   210  	{"deterministic", UNUSED},
   211  	{"directory", DIRECTORY},
   212  	{"disable", DISABLE},
   213  	{"discard", DISCARD},
   214  	{"disk", DISK},
   215  	{"distinct", DISTINCT},
   216  	{"distinctrow", DISTINCTROW},
   217  	{"div", DIV},
   218  	{"double", DOUBLE},
   219  	{"do", DO},
   220  	{"drop", DROP},
   221  	{"dumpfile", DUMPFILE},
   222  	{"duplicate", DUPLICATE},
   223  	{"dynamic", DYNAMIC},
   224  	{"each", UNUSED},
   225  	{"else", ELSE},
   226  	{"elseif", UNUSED},
   227  	{"empty", UNUSED},
   228  	{"enable", ENABLE},
   229  	{"enclosed", ENCLOSED},
   230  	{"encryption", ENCRYPTION},
   231  	{"end", END},
   232  	{"enforced", ENFORCED},
   233  	{"engine", ENGINE},
   234  	{"engines", ENGINES},
   235  	{"enum", ENUM},
   236  	{"error", ERROR},
   237  	{"escape", ESCAPE},
   238  	{"escaped", ESCAPED},
   239  	{"event", EVENT},
   240  	{"exchange", EXCHANGE},
   241  	{"exclusive", EXCLUSIVE},
   242  	{"exists", EXISTS},
   243  	{"exit", UNUSED},
   244  	{"explain", EXPLAIN},
   245  	{"expansion", EXPANSION},
   246  	{"export", EXPORT},
   247  	{"extended", EXTENDED},
   248  	{"extract", EXTRACT},
   249  	{"false", FALSE},
   250  	{"fetch", UNUSED},
   251  	{"fields", FIELDS},
   252  	{"first", FIRST},
   253  	{"first_value", UNUSED},
   254  	{"fixed", FIXED},
   255  	{"float", FLOAT_TYPE},
   256  	{"float4", UNUSED},
   257  	{"float8", UNUSED},
   258  	{"flush", FLUSH},
   259  	{"for", FOR},
   260  	{"force", FORCE},
   261  	{"foreign", FOREIGN},
   262  	{"format", FORMAT},
   263  	{"from", FROM},
   264  	{"full", FULL},
   265  	{"fulltext", FULLTEXT},
   266  	{"function", FUNCTION},
   267  	{"general", GENERAL},
   268  	{"generated", GENERATED},
   269  	{"geometry", GEOMETRY},
   270  	{"geometrycollection", GEOMETRYCOLLECTION},
   271  	{"get", UNUSED},
   272  	{"global", GLOBAL},
   273  	{"gtid_executed", GTID_EXECUTED},
   274  	{"grant", UNUSED},
   275  	{"group", GROUP},
   276  	{"grouping", UNUSED},
   277  	{"groups", UNUSED},
   278  	{"group_concat", GROUP_CONCAT},
   279  	{"hash", HASH},
   280  	{"having", HAVING},
   281  	{"header", HEADER},
   282  	{"high_priority", UNUSED},
   283  	{"hosts", HOSTS},
   284  	{"hour", HOUR},
   285  	{"hour_microsecond", HOUR_MICROSECOND},
   286  	{"hour_minute", HOUR_MINUTE},
   287  	{"hour_second", HOUR_SECOND},
   288  	{"if", IF},
   289  	{"ignore", IGNORE},
   290  	{"import", IMPORT},
   291  	{"in", IN},
   292  	{"index", INDEX},
   293  	{"indexes", INDEXES},
   294  	{"infile", UNUSED},
   295  	{"inout", UNUSED},
   296  	{"inner", INNER},
   297  	{"inplace", INPLACE},
   298  	{"insensitive", UNUSED},
   299  	{"insert", INSERT},
   300  	{"insert_method", INSERT_METHOD},
   301  	{"int", INT},
   302  	{"int1", UNUSED},
   303  	{"int2", UNUSED},
   304  	{"int3", UNUSED},
   305  	{"int4", UNUSED},
   306  	{"int8", UNUSED},
   307  	{"integer", INTEGER},
   308  	{"interval", INTERVAL},
   309  	{"into", INTO},
   310  	{"io_after_gtids", UNUSED},
   311  	{"is", IS},
   312  	{"isolation", ISOLATION},
   313  	{"iterate", UNUSED},
   314  	{"invoker", INVOKER},
   315  	{"join", JOIN},
   316  	{"json", JSON},
   317  	{"json_table", UNUSED},
   318  	{"key", KEY},
   319  	{"keys", KEYS},
   320  	{"keyspaces", KEYSPACES},
   321  	{"key_block_size", KEY_BLOCK_SIZE},
   322  	{"kill", UNUSED},
   323  	{"lag", UNUSED},
   324  	{"language", LANGUAGE},
   325  	{"last", LAST},
   326  	{"last_value", UNUSED},
   327  	{"last_insert_id", LAST_INSERT_ID},
   328  	{"lateral", UNUSED},
   329  	{"lead", UNUSED},
   330  	{"leading", UNUSED},
   331  	{"leave", UNUSED},
   332  	{"left", LEFT},
   333  	{"less", LESS},
   334  	{"level", LEVEL},
   335  	{"like", LIKE},
   336  	{"limit", LIMIT},
   337  	{"linear", LINEAR},
   338  	{"lines", LINES},
   339  	{"linestring", LINESTRING},
   340  	{"list", LIST},
   341  	{"load", LOAD},
   342  	{"local", LOCAL},
   343  	{"localtime", LOCALTIME},
   344  	{"localtimestamp", LOCALTIMESTAMP},
   345  	{"lock", LOCK},
   346  	{"logs", LOGS},
   347  	{"long", UNUSED},
   348  	{"longblob", LONGBLOB},
   349  	{"longtext", LONGTEXT},
   350  	{"loop", UNUSED},
   351  	{"low_priority", LOW_PRIORITY},
   352  	{"manifest", MANIFEST},
   353  	{"master_bind", UNUSED},
   354  	{"match", MATCH},
   355  	{"max_rows", MAX_ROWS},
   356  	{"maxvalue", MAXVALUE},
   357  	{"mediumblob", MEDIUMBLOB},
   358  	{"mediumint", MEDIUMINT},
   359  	{"mediumtext", MEDIUMTEXT},
   360  	{"memory", MEMORY},
   361  	{"member", MEMBER},
   362  	{"merge", MERGE},
   363  	{"microsecond", MICROSECOND},
   364  	{"middleint", UNUSED},
   365  	{"min_rows", MIN_ROWS},
   366  	{"minute", MINUTE},
   367  	{"minute_microsecond", MINUTE_MICROSECOND},
   368  	{"minute_second", MINUTE_SECOND},
   369  	{"mod", MOD},
   370  	{"mode", MODE},
   371  	{"modify", MODIFY},
   372  	{"modifies", UNUSED},
   373  	{"multilinestring", MULTILINESTRING},
   374  	{"multipoint", MULTIPOINT},
   375  	{"multipolygon", MULTIPOLYGON},
   376  	{"month", MONTH},
   377  	{"name", NAME},
   378  	{"names", NAMES},
   379  	{"natural", NATURAL},
   380  	{"nchar", NCHAR},
   381  	{"next", NEXT},
   382  	{"no", NO},
   383  	{"none", NONE},
   384  	{"not", NOT},
   385  	{"now", NOW},
   386  	{"no_write_to_binlog", NO_WRITE_TO_BINLOG},
   387  	{"nth_value", UNUSED},
   388  	{"ntile", UNUSED},
   389  	{"null", NULL},
   390  	{"numeric", NUMERIC},
   391  	{"of", UNUSED},
   392  	{"off", OFF},
   393  	{"offset", OFFSET},
   394  	{"on", ON},
   395  	{"only", ONLY},
   396  	{"open", OPEN},
   397  	{"optimize", OPTIMIZE},
   398  	{"optimizer_costs", OPTIMIZER_COSTS},
   399  	{"option", OPTION},
   400  	{"optionally", OPTIONALLY},
   401  	{"or", OR},
   402  	{"order", ORDER},
   403  	{"out", UNUSED},
   404  	{"outer", OUTER},
   405  	{"outfile", OUTFILE},
   406  	{"over", UNUSED},
   407  	{"overwrite", OVERWRITE},
   408  	{"pack_keys", PACK_KEYS},
   409  	{"parser", PARSER},
   410  	{"partition", PARTITION},
   411  	{"partitions", PARTITIONS},
   412  	{"partitioning", PARTITIONING},
   413  	{"password", PASSWORD},
   414  	{"percent_rank", UNUSED},
   415  	{"plugins", PLUGINS},
   416  	{"point", POINT},
   417  	{"polygon", POLYGON},
   418  	{"precision", UNUSED},
   419  	{"primary", PRIMARY},
   420  	{"privileges", PRIVILEGES},
   421  	{"processlist", PROCESSLIST},
   422  	{"procedure", PROCEDURE},
   423  	{"query", QUERY},
   424  	{"range", RANGE},
   425  	{"quarter", QUARTER},
   426  	{"rank", UNUSED},
   427  	{"read", READ},
   428  	{"reads", UNUSED},
   429  	{"read_write", UNUSED},
   430  	{"real", REAL},
   431  	{"rebuild", REBUILD},
   432  	{"recursive", RECURSIVE},
   433  	{"redundant", REDUNDANT},
   434  	{"references", REFERENCES},
   435  	{"regexp", REGEXP},
   436  	{"relay", RELAY},
   437  	{"release", RELEASE},
   438  	{"remove", REMOVE},
   439  	{"rename", RENAME},
   440  	{"reorganize", REORGANIZE},
   441  	{"repair", REPAIR},
   442  	{"repeat", UNUSED},
   443  	{"repeatable", REPEATABLE},
   444  	{"replace", REPLACE},
   445  	{"require", UNUSED},
   446  	{"resignal", UNUSED},
   447  	{"restrict", RESTRICT},
   448  	{"return", UNUSED},
   449  	{"retry", RETRY},
   450  	{"revert", REVERT},
   451  	{"revoke", UNUSED},
   452  	{"right", RIGHT},
   453  	{"rlike", REGEXP},
   454  	{"rollback", ROLLBACK},
   455  	{"row", UNUSED},
   456  	{"row_format", ROW_FORMAT},
   457  	{"row_number", UNUSED},
   458  	{"rows", UNUSED},
   459  	{"s3", S3},
   460  	{"savepoint", SAVEPOINT},
   461  	{"schema", SCHEMA},
   462  	{"schemas", SCHEMAS},
   463  	{"second", SECOND},
   464  	{"second_microsecond", SECOND_MICROSECOND},
   465  	{"security", SECURITY},
   466  	{"select", SELECT},
   467  	{"sensitive", UNUSED},
   468  	{"separator", SEPARATOR},
   469  	{"sequence", SEQUENCE},
   470  	{"serializable", SERIALIZABLE},
   471  	{"session", SESSION},
   472  	{"set", SET},
   473  	{"share", SHARE},
   474  	{"shared", SHARED},
   475  	{"show", SHOW},
   476  	{"signal", UNUSED},
   477  	{"signed", SIGNED},
   478  	{"slow", SLOW},
   479  	{"smallint", SMALLINT},
   480  	{"spatial", SPATIAL},
   481  	{"specific", UNUSED},
   482  	{"sql", SQL},
   483  	{"sqlexception", UNUSED},
   484  	{"sqlstate", UNUSED},
   485  	{"sqlwarning", UNUSED},
   486  	{"sql_big_result", UNUSED},
   487  	{"sql_cache", SQL_CACHE},
   488  	{"sql_calc_found_rows", SQL_CALC_FOUND_ROWS},
   489  	{"sql_no_cache", SQL_NO_CACHE},
   490  	{"sql_small_result", UNUSED},
   491  	{"ssl", UNUSED},
   492  	{"start", START},
   493  	{"starting", STARTING},
   494  	{"stats_auto_recalc", STATS_AUTO_RECALC},
   495  	{"stats_persistent", STATS_PERSISTENT},
   496  	{"stats_sample_pages", STATS_SAMPLE_PAGES},
   497  	{"status", STATUS},
   498  	{"storage", STORAGE},
   499  	{"stored", STORED},
   500  	{"straight_join", STRAIGHT_JOIN},
   501  	{"stream", STREAM},
   502  	{"system", UNUSED},
   503  	{"table", TABLE},
   504  	{"tables", TABLES},
   505  	{"tablespace", TABLESPACE},
   506  	{"temporary", TEMPORARY},
   507  	{"temptable", TEMPTABLE},
   508  	{"terminated", TERMINATED},
   509  	{"text", TEXT},
   510  	{"than", THAN},
   511  	{"then", THEN},
   512  	{"time", TIME},
   513  	{"timestamp", TIMESTAMP},
   514  	{"timestampadd", TIMESTAMPADD},
   515  	{"timestampdiff", TIMESTAMPDIFF},
   516  	{"tinyblob", TINYBLOB},
   517  	{"tinyint", TINYINT},
   518  	{"tinytext", TINYTEXT},
   519  	{"to", TO},
   520  	{"trailing", UNUSED},
   521  	{"transaction", TRANSACTION},
   522  	{"tree", TREE},
   523  	{"traditional", TRADITIONAL},
   524  	{"trigger", TRIGGER},
   525  	{"triggers", TRIGGERS},
   526  	{"true", TRUE},
   527  	{"truncate", TRUNCATE},
   528  	{"uncommitted", UNCOMMITTED},
   529  	{"undefined", UNDEFINED},
   530  	{"undo", UNUSED},
   531  	{"union", UNION},
   532  	{"unique", UNIQUE},
   533  	{"unlock", UNLOCK},
   534  	{"unsigned", UNSIGNED},
   535  	{"update", UPDATE},
   536  	{"upgrade", UPGRADE},
   537  	{"usage", UNUSED},
   538  	{"use", USE},
   539  	{"user", USER},
   540  	{"user_resources", USER_RESOURCES},
   541  	{"using", USING},
   542  	{"utc_date", UTC_DATE},
   543  	{"utc_time", UTC_TIME},
   544  	{"utc_timestamp", UTC_TIMESTAMP},
   545  	{"validation", VALIDATION},
   546  	{"values", VALUES},
   547  	{"variables", VARIABLES},
   548  	{"varbinary", VARBINARY},
   549  	{"varchar", VARCHAR},
   550  	{"varcharacter", UNUSED},
   551  	{"varying", UNUSED},
   552  	{"vgtid_executed", VGTID_EXECUTED},
   553  	{"virtual", VIRTUAL},
   554  	{"vindex", VINDEX},
   555  	{"vindexes", VINDEXES},
   556  	{"view", VIEW},
   557  	{"vitess", VITESS},
   558  	{"vitess_keyspaces", VITESS_KEYSPACES},
   559  	{"vitess_metadata", VITESS_METADATA},
   560  	{"vitess_migration", VITESS_MIGRATION},
   561  	{"vitess_migrations", VITESS_MIGRATIONS},
   562  	{"vitess_replication_status", VITESS_REPLICATION_STATUS},
   563  	{"vitess_shards", VITESS_SHARDS},
   564  	{"vitess_tablets", VITESS_TABLETS},
   565  	{"vschema", VSCHEMA},
   566  	{"vstream", VSTREAM},
   567  	{"warnings", WARNINGS},
   568  	{"when", WHEN},
   569  	{"where", WHERE},
   570  	{"while", UNUSED},
   571  	{"window", UNUSED},
   572  	{"with", WITH},
   573  	{"without", WITHOUT},
   574  	{"work", WORK},
   575  	{"write", WRITE},
   576  	{"xor", XOR},
   577  	{"year", YEAR},
   578  	{"year_month", YEAR_MONTH},
   579  	{"zerofill", ZEROFILL},
   580  }
   581  
   582  // keywordStrings contains the reverse mapping of token to keyword strings
   583  var keywordStrings = map[int]string{}
   584  
   585  // keywordLookupTable is a perfect hash map that maps **case insensitive** keyword names to their ids
   586  var keywordLookupTable *caseInsensitiveTable
   587  
   588  type caseInsensitiveTable struct {
   589  	h map[uint64]keyword
   590  }
   591  
   592  func buildCaseInsensitiveTable(keywords []keyword) *caseInsensitiveTable {
   593  	table := &caseInsensitiveTable{
   594  		h: make(map[uint64]keyword, len(keywords)),
   595  	}
   596  
   597  	for _, kw := range keywords {
   598  		hash := fnv1aIstr(offset64, kw.name)
   599  		if _, exists := table.h[hash]; exists {
   600  			panic("collision in caseInsensitiveTable")
   601  		}
   602  		table.h[hash] = kw
   603  	}
   604  	return table
   605  }
   606  
   607  func (cit *caseInsensitiveTable) LookupString(name string) (int, bool) {
   608  	hash := fnv1aIstr(offset64, name)
   609  	if candidate, ok := cit.h[hash]; ok {
   610  		return candidate.id, candidate.matchStr(name)
   611  	}
   612  	return 0, false
   613  }
   614  
   615  func (cit *caseInsensitiveTable) Lookup(name []byte) (int, bool) {
   616  	hash := fnv1aI(offset64, name)
   617  	if candidate, ok := cit.h[hash]; ok {
   618  		return candidate.id, candidate.match(name)
   619  	}
   620  	return 0, false
   621  }
   622  
   623  func init() {
   624  	for _, kw := range keywords {
   625  		if kw.id == UNUSED {
   626  			continue
   627  		}
   628  		if kw.name != strings.ToLower(kw.name) {
   629  			panic(fmt.Sprintf("keyword %q must be lowercase in table", kw.name))
   630  		}
   631  		keywordStrings[kw.id] = kw.name
   632  	}
   633  
   634  	keywordLookupTable = buildCaseInsensitiveTable(keywords)
   635  }
   636  
   637  // KeywordString returns the string corresponding to the given keyword
   638  func KeywordString(id int) string {
   639  	str, ok := keywordStrings[id]
   640  	if !ok {
   641  		return ""
   642  	}
   643  	return str
   644  }
   645  
   646  const offset64 = uint64(14695981039346656037)
   647  const prime64 = uint64(1099511628211)
   648  
   649  func fnv1aI(h uint64, s []byte) uint64 {
   650  	for _, c := range s {
   651  		if 'A' <= c && c <= 'Z' {
   652  			c += 'a' - 'A'
   653  		}
   654  		h = (h ^ uint64(c)) * prime64
   655  	}
   656  	return h
   657  }
   658  
   659  func fnv1aIstr(h uint64, s string) uint64 {
   660  	for i := 0; i < len(s); i++ {
   661  		c := s[i]
   662  		if 'A' <= c && c <= 'Z' {
   663  			c += 'a' - 'A'
   664  		}
   665  		h = (h ^ uint64(c)) * prime64
   666  	}
   667  	return h
   668  }