diff --git a/parse_constants.h b/parse_constants.h index 54670c799..559aad294 100644 --- a/parse_constants.h +++ b/parse_constants.h @@ -77,27 +77,27 @@ enum parse_token_type_t FIRST_PARSE_TOKEN_TYPE = parse_token_type_string } __packed; +/* These must be maintained in sorted order (except for none, which isn't a keyword). This enables us to do binary search. */ enum parse_keyword_t { parse_keyword_none, - parse_keyword_if, - parse_keyword_else, - parse_keyword_for, - parse_keyword_in, - parse_keyword_while, - parse_keyword_begin, - parse_keyword_function, - parse_keyword_switch, - parse_keyword_case, - parse_keyword_end, parse_keyword_and, - parse_keyword_or, - parse_keyword_not, - parse_keyword_command, + parse_keyword_begin, parse_keyword_builtin, + parse_keyword_case, + parse_keyword_command, + parse_keyword_else, + parse_keyword_end, parse_keyword_exec, - - LAST_KEYWORD = parse_keyword_exec + parse_keyword_for, + parse_keyword_function, + parse_keyword_if, + parse_keyword_in, + parse_keyword_not, + parse_keyword_or, + parse_keyword_switch, + parse_keyword_while, + LAST_KEYWORD = parse_keyword_while } __packed; /* Statement decorations. This matches the order of productions in decorated_statement */ diff --git a/parse_tree.cpp b/parse_tree.cpp index 2a0a14a33..85202816c 100644 --- a/parse_tree.cpp +++ b/parse_tree.cpp @@ -236,23 +236,24 @@ static const struct } keyword_map[] = { + /* Note that these must be sorted (except for the first), so that we can do binary search */ KEYWORD_MAP(none), - KEYWORD_MAP(if), - KEYWORD_MAP(else), - KEYWORD_MAP(for), - KEYWORD_MAP(in), - KEYWORD_MAP(while), - KEYWORD_MAP(begin), - KEYWORD_MAP(function), - KEYWORD_MAP(switch), - KEYWORD_MAP(case), - KEYWORD_MAP(end), KEYWORD_MAP(and), - KEYWORD_MAP(or), - KEYWORD_MAP(not), - KEYWORD_MAP(command), + KEYWORD_MAP(begin), KEYWORD_MAP(builtin), - KEYWORD_MAP(exec) + KEYWORD_MAP(case), + KEYWORD_MAP(command), + KEYWORD_MAP(else), + KEYWORD_MAP(end), + KEYWORD_MAP(exec), + KEYWORD_MAP(for), + KEYWORD_MAP(function), + KEYWORD_MAP(if), + KEYWORD_MAP(in), + KEYWORD_MAP(not), + KEYWORD_MAP(or), + KEYWORD_MAP(switch), + KEYWORD_MAP(while) }; wcstring keyword_description(parse_keyword_t k) @@ -1187,11 +1188,23 @@ static parse_keyword_t keyword_for_token(token_type tok, const wchar_t *tok_txt) parse_keyword_t result = parse_keyword_none; if (tok == TOK_STRING) { - for (size_t i=0; i < sizeof keyword_map / sizeof *keyword_map; i++) + /* Binary search on keyword_map. Start at 1 since 0 is keyword_none */ + size_t left = 1, right = sizeof keyword_map / sizeof *keyword_map; + while (left < right) { - if (! wcscmp(keyword_map[i].name, tok_txt)) + size_t mid = left + (right - left)/2; + int cmp = wcscmp(tok_txt, keyword_map[mid].name); + if (cmp < 0) { - result = keyword_map[i].keyword; + right = mid; // tok_txt was smaller than mid + } + else if (cmp > 0) + { + left = mid + 1; // tok_txt was larger than mid + } + else + { + result = keyword_map[mid].keyword; // found it break; } }