【问题标题】:How to disable syntax check in c header file如何在c头文件中禁用语法检查
【发布时间】:2022-01-11 08:16:09
【问题描述】:

我在 cplusplus 中嵌入 Lua 代码;可以这样写

char const *lua_scripts = R"rawstring(

-- lua code

)rawstring";

但是字符串里面的 Lua 代码没有语法高亮,所以我把它分成了 3 个文件: 第一个文件名为head.txt

char const *lua_scripts = R"rawstring(

第二个文件名为body.lua

 -- lua code 

第三个文件名为tail.txt

)rawstring";

然后原来的cpp文件改成

#include "head.txt"
#include "body.lua"
#include "tail.txt"

但是当我编译时,报语法错误,因为编译器在包含之前检查了文件。那么如何禁用编译器检查语法呢?

【问题讨论】:

  • 很确定你不能用打开的引号字符串结束文件。您最好的选择可能是将任何嵌入式代码视为已生成,即使生成有效地执行cat head.txt body.lua tail.txt >some_header.h
  • char const lua_scripts 描述的是单个字符,而不是字符串。
  • 考虑编写一个简单的预构建步骤,从原始源文件构建您的字符串资源。通过这样做,如果您希望字符串“隐藏”在可执行文件中(使用简单的 XOR 链,甚至更复杂的混淆或加密方案),您可以在以后轻松更新程序以混淆字符串。它还避免了使用预编译器的麻烦(最终是徒劳的努力)。
  • 非常接近XY problem。在了解您要解决的问题之前,您正在寻求有关您提出的解决方案的帮助。你有没有想过为什么需要拆分成三个文件?如果您知道为什么仅将 Lua 代码移动到 body.lua 是行不通的,您就会知道为什么您当前的 3 文件方法注定要失败。 (说到这里,您是否有兴趣询问为什么仅将 Lua 代码移动到 body.lua 不起作用?还是您更愿意寻求解决方法?)
  • @paddy 抱歉,打错了。这是char const *lua_scripts

标签: c++ lua


【解决方案1】:

在 C++ 中,程序在预处理之后进行解析。但是将输入划分为词位是在预处理之前完成的。预处理器的输入是令牌流,而不是字符流。

所以一个令牌不能跨越两个输入文件。字符串文字是单个标记。

您也不能将预处理器指令拆分到两个文件中,因此#endif#else 等必须与#if#ifdef 在同一个文件中,并且文件中的最后一行不能以反斜杠结尾。

您可以轻松编写自己的小合并程序,该程序从 C++ 和 Lua 源文件构建 C++ 文件。你甚至可以用 Lua 编写它,它并不复杂。或者您可以使用 M4 宏处理器来实现,它很可能已经安装在您的编译环境中。

【讨论】:

    【解决方案2】:

    编译 C++ 代码时会出现nine phases of translation。第 3 阶段是识别字符串文字的时间。阶段 4 是预处理器。当编译器到达#include 您的文件时,您的原始源文件中的所有字符串文字都已找到并标记为此类。预处理器完成后,您的源文件将不会再进行一次查找更多文字的过程。

    当预处理器引入一个文件时,该文件会经过前四个翻译阶段,然后再插入到您的原始源文件中。这与将头文件直接复制到源文件中的常见简化感知略有不同。标头不是逐个字符的复制,而是逐个标记复制,其中“标记”表示“预处理标记”,包括标识符、运算符和文字等内容。

    实际上,在您尝试让语言元素跨越文件边界之前,简化视图就足够了。特别是,cmets 和字符串文字都不能从一个文件开始并扩展到另一个文件。 (还有其他示例,但将它们发挥作用有点做作。)您尝试让字符串文字在一个文件中开始,扩展到第二个文件,并在第三个文件中结束。这不起作用。

    当预处理器引入head.txt 时,前三个阶段将其分析为五个预处理器标记,后跟一个未终止的原始字符串文字。这就是复制到您的源文件中的内容。请注意,未终止的文字仍然是未终止的文字;它不会变成字面上的寻找结束。

    body.lua 被引入时,它就像任何其他头文件一样被处理。预处理器不关心扩展。文件被引入并受到翻译阶段的影响,就像任何其他#include 一样。第 3 阶段将使用 C++ 语法规则识别以body.lua 开头的字符串文字,但body.lua 的任何部分都不会成为在body.lua 之外开始的字符串文字的一部分。阶段 3,包括字符串文字的识别,单独发生在这个文件上。

    你的方法失败了。


    那么如何禁用编译器检查语法?

    您不能禁用编译器语法检查。这就像问你如何让一个人在不挑选字母和单词的情况下阅读一本书。您已经要求编译器处理您的代码,而第一步是确保代码易于理解,即具有有效的语法。正是这样的问题提醒我们XY problems 和以往一样普遍。

    不过,幸运的是,您确实提到了您的真正问题:“没有语法高亮”。不幸的是,您没有提供有关您的实际问题的足够信息,例如提供语法突出显示的程序。我对以下内容进行了两种不同的语法荧光笔;一个突出显示 Lua 代码为 Lua 代码,另一个没有突出显示。

    R"rawstring(
     -- lua code 
    )rawstring"
    

    如果您愿意忽略第一行和最后一行的突出显示,并且如果您的编辑器成功应用了所需的语法突出显示,则可以将其设为您的 body.lua 文件。那么下面的 C++ 代码应该可以工作了。

    char const *lua_scripts =
    #include "body.lua"
    ;
    

    直到第 7 阶段——在预处理器之后——才能识别语句,因此您可以跨文件拆分语句。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-04
      • 1970-01-01
      • 2012-12-16
      • 1970-01-01
      • 2020-04-27
      • 2023-04-11
      相关资源
      最近更新 更多