我不明白为什么错误(不兼容的操作数类型)发生在我的c++代码

bhmjp9jg  于 2023-08-09  发布在  其他
关注(0)|答案(1)|浏览(106)

我用c++写了一段代码来分析JavaScript代码的词法。下面是相应的函数。作为参考,Kind是一个包含各种lex的枚举类,函数toKind的定义在函数analyzeLexeme的下面。

auto analyzeLexeme(std::wstring & source_code) -> std::vector<Token> {
    using std::__1::wregex;
    using std::regex_search;
    using std::vector;
    using std::wsmatch;
    using std::wstring;
    using std::string;
    using std::tuple;
    using std::map;

    wsmatch matched;
    Kind    result_kind;

    map<string, bool> context  = { { "in_tmplt", false }, };
    auto              result   = vector<Token>();
    auto              reSearch = [&source_code, &matched] (const wregex & re) {
        return regex_search(source_code, matched, re);
    };

    source_code += L'\0';

    for (; source_code[0]; source_code = matched.suffix()) {
        if (reSearch(kReWhiteSpace)) continue;

        result.push_back({(
                reSearch(kReNumLiteral)                             ? [] { return Kind::NumberLiteral; }                       :
                reSearch(kReStrLiteral)                             ? [] { return Kind::StringLiteral; }                       :
                reSearch(kReTmpltHdLiteral) && !context["in_tmplt"] ?
                    [&] {
                        context["in_tmplt"] = true;
                        return Kind::TemplateHeadLiteral;
                    }                                                                                                          :
                reSearch(kReTmpltTlLiteral) && context["in_tmplt"]  ?
                    [&] {
                        context["in_tmplt"] = false;
                        return Kind::TemplateTailLiteral;
                    }                                                                                                          :
                reSearch(kReTmpltMdLiteral) && context["in_tmplt"]   ? [] { return Kind::TemplateMiddleLiteral; }              :
                reSearch(kReTmpltLiteral)                            ? [] { return Kind::TemplateLiteral; }                    :
                reSearch(kReIdentifierKyword)                        ? [&] { return toKind(matched.str(), Kind::Identifier); } :
                reSearch(kReOperatorBracket)                         ? [&] { return toKind(matched.str()); }                   :
                [] { return Kind::Unknown; }
            )(),
            matched.str(),
        });

        if (result.back().kind == Kind::Unknown) {
            std::wcerr << L"[ERR] : Unknown Token : " << source_code.substr(0, 40) << std::endl;
            // fwprintf(stderr, L"[ERR] : Unknown Token : %s", source_code.substr(0, 40).c_str());
            exit(1);
        }
    }

    return result;
}

个字符
此处发生错误(reSearch(kReOperatorBracket) ? [&] { return toKind(matched.str()); })。原因是error: incompatible operand types ('(lambda at ~/projects/lexer.cc:69:72)' and '(lambda at ~/projects/lexer.cc:70:17)')
我不明白,因为toKind的返回类型是Kind,所以lambda函数([&] { return toKind(matched.str()))必须返回Kind值,而lambda函数([] { return Kind::Unknown; })也别无选择,只能返回Kind类型的值。
一开始我以为g++不能解释我的代码(在python中,有时候如果我写了不该写的行,解释器就不能解释它)。但是,经过多次尝试,我发现这也不是主要原因。
另外,如果代码被编译,我会运行gdb来调试它,但我也不能这样做,因为这是编译过程的问题。

mgdq6dx1

mgdq6dx11#

由于在三进制操作中使用lambda表达式作为操作数,因此需要将这些lambda表达式 Package 在std::function中。
正如您所看到的,所有lambda表达式都有自己独特的类型,而不是std::function。如果你想让一个表达式返回一种类型或另一种类型,你需要某种类型的擦除。
但是,你似乎在现场调用了函数,在表达式中一行。考虑到这一点,您还可以删除所有单语句lambda表达式,并在三进制中调用多语句。
如果你当场给他们打电话,情况会是这样的:

result.push_back({
  (
    reSearch(kReNumLiteral)
      ? Kind::NumberLiteral
      : reSearch(kReStrLiteral)
        ? Kind::StringLiteral
        : reSearch(kReTmpltHdLiteral) && !context["in_tmplt"]
          ? [&] {
            context["in_tmplt"] = true;
            return Kind::TemplateHeadLiteral;
          }() // here!
          : reSearch(kReTmpltTlLiteral) && context["in_tmplt"]
            ? [&] {
              context["in_tmplt"] = false;
              return Kind::TemplateTailLiteral;
            }() // here again, lambda called.
            : reSearch(kReTmpltMdLiteral) && context["in_tmplt"]
              ? Kind::TemplateMiddleLiteral
              : reSearch(kReTmpltLiteral)
                ? Kind::TemplateLiteral;
                : reSearch(kReIdentifierKyword)
                  ? toKind(matched.str(), Kind::Identifier)
                  : reSearch(kReOperatorBracket)
                    ? toKind(matched.str())
                    : Kind::Unknown
  ),
  matched.str(),
});

字符串
下面是将它们全部 Package 在类型擦除 Package 器(如std::function)中的情况:

result.push_back({
  (
    reSearch(kReNumLiteral)
      ? std::function{[]{ return Kind::NumberLiteral; }}
      : reSearch(kReStrLiteral)
        ? std::function{[]{ return Kind::StringLiteral; }}
        : reSearch(kReTmpltHdLiteral) && !context["in_tmplt"]
          ? std::function{[&] {
            context["in_tmplt"] = true;
            return Kind::TemplateHeadLiteral;
          }}
          : reSearch(kReTmpltTlLiteral) && context["in_tmplt"]
            ? std::function{[&] {
              context["in_tmplt"] = false;
              return Kind::TemplateTailLiteral;
            }}
            : reSearch(kReTmpltMdLiteral) && context["in_tmplt"]
              ? std::function{[]{ return Kind::TemplateMiddleLiteral; }}
              : reSearch(kReTmpltLiteral)
                ? std::function{[]{ return Kind::TemplateLiteral; }}
                : reSearch(kReIdentifierKyword)
                  ? std::function{[]{ return toKind(matched.str(), Kind::Identifier); }}
                  : reSearch(kReOperatorBracket)
                    ? std::function{[]{ return toKind(matched.str()); }}
                    : std::function{[]{ return Kind::Unknown; }}
  )(), // call the std::function that wraps a lambda
  matched.str(),
});

相关问题