【问题标题】:How to add a custom keyword to be treated as "class" in clang format?如何添加自定义关键字以在 clang 格式中被视为“类”?
【发布时间】:2019-09-30 16:30:06
【问题描述】:

我想使用clang-format 来格式化规范代码 (<file>.sc)

Specc 有一些预定义的关键字,它们的格式可以与 class 在 C++ 中的格式相同:

  • behavior
  • interface

我可以在.clang-format 文件中实现这一点吗?

带有behavior关键字的输入文件:

#include <stdio.h>

behavior Main(void)
{
        int main(void)
        {
        printf("Hello World!\n");
        return(0);
        }
};

clang-format -style=Mozilla hello.sc的输出

#include <stdio.h>

behavior Main(void) { int main(void) { printf("Hello World!\n");
return (0);
}
}
;

如果我使用关键字class 而不是behavior,这就是我得到的输出,这就是我想要的:

#include <stdio.h>

class Main(void) {
  int main(void) {
    printf("Hello World!\n");
    return (0);
  }
};

TLDR: 我希望 clang-format 处理来自 specc 的关键字 behavior,因为它处理关键字 class

注意,我只想格式化文件。我不打算用 C/C++ 编译器编译它。

【问题讨论】:

  • @Jarod42 能否详细说明如何使用MACRO
  • @ChrisTurner,语言 SpecC 是 C 的超集,behavior 是 specc 编译器可以理解的关键字。我想用clang-format来对待关键字behavior,就像它对待关键字class一样。
  • 所以你想要的是clang看到“行为”并理解“类”。 IE。您实际上并不想要任何功能差异,任何含义差异,只允许写“行为”并表示“类”?
  • 您可以围绕clang-format 编写一个简短的脚本,在其前后调用sedbehavior 替换为class(反之亦然)。
  • 好的。我还没有真正意识到您根本没有尝试编译它,只是漂亮地打印它。我还担心您的seding 可能会无意中更改注释或变量名中的classbehaviour 一词的其他实例。最好将behaviour 更改为class /*AS behaviour*/,然后只将class /*AS behaviour*/ 更改回behaviour

标签: c++ c clang-format


【解决方案1】:

您是否考虑过将 SpecC 支持开发/贡献到 clang 格式作为一流的语言?

由于它主要是一种 C 风格的语言,我认为添加它不会那么难。

我最近开始努力添加 C# 支持(我猜这可能更糟),并且在格式化方面遇到了类似的问题,我希望关键字在 C# 和 C++ 中的行为不同(公共是其中之一)

例如,一种机制是将关键字转换为其他关键字类型(或 Token 类型),然后可以用于稍后为不同语言设置不同的代码格式。

在此示例中,我将“行为”标记转换为认为它们是“类”

bool FormatTokenLexer::tryMergeSpeccCBehavior() {
  if (Tokens.size() < 1)
    return false;
  auto &Identifier = *(Tokens.end() - 1);
  if (!Identifier->is(tok::identifier))
    return false;

  if ((Identifier->TokenText == "behavior"))
    Identifier->Tok.setKind(tok::kw_class);
  return true;
}

虽然我无法让您的确切示例起作用,但 (main(void)) 似乎使 clang-format 令人困惑

仅通过此更改(并在 Lexing 期间调用它),我就能够让 clang-format 认为“行为”关键字是“类”关键字,而不仅仅是返回类型(我认为它是这样认为的)是的)

这意味着当它看到行为时,它会应用任何正在寻找类的格式规则,这将倾向于做更多正确的事情。

您需要更多的管道以允许某些 SpecC 特定规则,但这不会超出可能性范围。

$ clang-format -style=Mozilla hello.sc
#include <stdio.h>

behavior Main
{
  int main(void)
  {
    printf("Hello World!\n");
    return (0);
  }
};

behavior B(in int p1, out int p2)
{

  int a, b;

  int f(int x) { return (x * x); }

  void main(void)
  {
    a = p1;
    b = f(a);
    p2 = b;
  }
};

LLVM 对他们允许的内容有相当高的标准,但我猜如果这是一种标准语言并且有很大的兴趣并且有人愿意支持它,你至少可以要求他们考虑它(特别是如果有人提供了补丁),或者你总是可以“简单地 fork LLVM”并添加它。

只是一个想法

【讨论】:

  • 感谢您的建议。我希望你可以在配置文件中做类似的事情,但这是我试图找到的答案。当我发现更多困扰我的格式问题时,我会考虑扩展它。
  • 您知道 Clang 中的新关键字还需要添加哪些其他内容吗?在将关键字添加到 TokenKinds.tdAttr.td 之后,我收到关于关键字是未定义函数的错误。
【解决方案2】:

正如@Jason 在对我的问题的评论中所建议的那样,我可以使用sed 来替换关键字。因此,我最终做的是将以下命令包装在一个 shell 脚本中:

sed "s/behavior/class/g" <file>.sc | clang-format -style=Mozilla | sed "s/class/behavior/g" > <file>.sc

【讨论】:

  • 覆盖您正在读取的同一文件是不安全的。最佳做法是写入一个临时文件,然后mv 完成后将副本覆盖在原始文件之上。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多