【问题标题】:Most Efficient way to 'look up' Keywords“查找”关键字的最有效方法
【发布时间】:2010-09-21 04:18:27
【问题描述】:

好的,所以我正在编写一个函数作为词法分析器的一部分,用于“查找”或搜索与关键字匹配的内容。我的词法分析器捕获了所有明显的标记,例如单字符和多字符运算符 (+ - * / > < = == etc)(cmets 和空格也已经被取出),所以我在收集了一个只有字母数字字符(包括下划线)的流之后调用了一个函数string,则此字符串需要作为已知关键字或标识符进行匹配。

所以我想知道如何识别它?我知道我基本上需要将它与某个列表或数组或所有内置关键字中的某些内容进行比较,如果它匹配一个返回匹配它的相应枚举值;否则,如果不匹配,则它必须是函数或变量标识符。那么我应该如何寻找匹配项呢?我在某处读到所谓的二叉搜索树是一种有效的方法,或者使用哈希表,问题是我从来没有使用过,所以我不确定它是否是正确的方法。我可以使用 MySQL 数据库吗?

【问题讨论】:

标签: c++ search performance lexer


【解决方案1】:

如果您的关键字集是固定的,则可以为 O(1) 查找构建 perfect hash。查看gperfcmph

【讨论】:

  • 您仍然会与非关键字发生哈希冲突,所以我认为这并不比其他方法更有效。它也不是 O(1),确实复杂性不取决于关键字的数量,而是取决于每个关键字的长度。
  • 查找后的验证是字符串比较,但这不太可能是影响性能的重要因素。由于散列是完美的,没有散列冲突惩罚,输入要么匹配散列槽,要么不匹配,不需要额外的搜索。
  • 完美的哈希函数实际上对编译器词法分析器没有那么有用;最好计算单个哈希并将其用于各种每个范围哈希表中的关键字查找和符号查找。您可以通过增加关键字哈希表的大小来廉价地保证关键字查找没有冲突,或者更好的是,在添加任何其他内容之前将关键字添加到全局哈希表,因此您只需要一次查找即可解析关键字和符号。或者考虑将所有标识(包括关键字)放在一个全局哈希表中,以便在编译器的其他地方进行超便宜的指针比较。
  • 关键字需要在全局变量或任何其他标识符之前找到,但否则我同意,这可能是我在尝试基于完美散列的任何其他优化之前会做的事情。我怀疑这很少值得。
【解决方案2】:

std::map 的任何实现都可能就足够了。

【讨论】:

  • 或者 std::tr1::unordered_map 如果你的编译器支持它,最新的 VC++ 和 GCC 都支持。 :)
【解决方案3】:

这是针对一种语言,具有一组永不改变且数量不多的特定关键字?

如果是这样,您使用什么可能并不重要。你会有更大的鱼来炸。

但是,由于列表不会改变,因此很难击败像这样的硬编码搜索:

// search on first letter
switch(s[0]){
  case 'a':
    // search on 2nd letter, etc.
    break;
  case 'b':
    // search on 2nd letter, etc.
    break;
  ........
  case '_':
    // search on 2nd letter, etc.
    break;
}

【讨论】:

    【解决方案4】:

    "trie" 肯定是最有效的方法。

    【讨论】:

      【解决方案5】:

      对于单字符关键字,查找表将是完美的。对于多字符(特别是如果长度不同):哈希表。如果您需要性能,您甚至可以使用源代码生成来创建哈希表(使用能够或不忽略大小写的简单哈希函数,具体取决于您的语法)。

      所以我会用 LUT 和哈希表来实现它:首先你用 LUT 检查第一个字符(如果它是一个简单的运算符,它将以非字母数字值开头),如果不是找到了,检查哈希表。

      【讨论】:

        猜你喜欢
        • 2014-03-02
        • 2018-05-23
        • 2021-02-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-17
        • 2016-02-11
        • 1970-01-01
        相关资源
        最近更新 更多