如何在 xtext DSL 中嵌入C++代码
How to embed C++ code in a xtext DSL?
Xtext/ANTLR中处理C++代码块的正确方法是什么?
我们正在为DSL编写一个基于Xtext的eclipse插件,该插件支持在明确定义的范围(主要是serial { /* ... */ }
块)中添加C++函数级代码,如下所示:
module m {
chare c {
entry void foo() {
serial {
// C++ code block
}
}
}
}
有关更全面的示例,请参阅此处。然后将其移交给外部工具来处理进一步的编译/链接步骤,因此我们不会从 eclipse 生成任何代码。
这里的问题是如何处理这些C++代码块,特别是考虑到它们可能包含自己的大括号。这与如何在 Xtext DSL 中包含 Java 代码块非常相似?但就目前而言,我们满足于忽略该块(即没有内容辅助或语法突出显示并不理想,但可以接受。
在我们基于 bison/flex 的工具中,这是通过在解析器和词法分析器之间共享一个变量来完成的,该变量在某些语法规则中切换"C++解析模式",使词法分析器返回除相关分隔符(例如大括号)之外的所有内容的 CPROGRAM 标记。自然翻译似乎有一个自定义的ANTLR词法分析器,它使用语义谓词来达到相同的效果,例如
RULE_NON_BRACES: {in_braces}? ~('{' | '}')+;
作为第一个词法规则,但我找不到如何从 Xtext 语法中访问该全局变量,因为似乎没有像 bison 那样的"规则操作"概念。还有其他非"串行"语法上下文需要C++代码,因此解析器和词法分析器之间需要一些协调。
您的问题似乎更侧重于 DSL 词法分析器如何避免迷失在C++代码中。 基本答案是您需要匹配括号(例如,确保它们正确嵌套)。
我不知道你如何定义一个Xtext/ANTLR词汇规则来做到这一点;我认为有一种丑陋的方法可以下拉到过程代码中并开始逐个读取字符。 这可能会有一些并发症;您的参数匹配逻辑可能不得不担心C++代码中的各种类型的引用。 例如
{ // this } isn't a match
和
{ char x[]="} this isnt a match { either" }
其他C++字符串引号可能会使这更加难以看到。 对于这样使用的C++宏,您将怎么做?
{
#define rcb }
{ rcb
}
您可能需要制定一些关于如何在嵌入式C++代码中处理 } 的特殊规则,并且您的逐字符扫描必须知道此规则。
与其让事情变得复杂,我认为你应该做的是在C++中选择一个非常不可能的角色序列作为你的终止,例如,
][[
我相信除了字符串或评论之外,不能出现在C++中,或者
}}}
并简单地使用它。 根本不需要匹配括号。 在几乎所有情况下,都不必触摸C++;在极少数情况下,当它恰好包含该序列时,只需进行简单的编辑(插入空格或换行符)即可修复它。 现在您的词法分析器规则很简单,可以使用标准词法分析器表示(我认为)。
如果你这样做,我建议你选择一个相应的开场序列来介绍C++代码,只是为了提醒读者需要一个有趣的序列,例如,
serial {{{ <C++code> }}}
或
serial ]][ <C++code> ][[
有了这个约定,即使是我丑陋的宏示例也很容易:
serial {{{
{
#define rcb }
{ rcb
}
}}}
PS:这个有趣的记谱技巧被称为"域(记谱法)转义"。 这个问题发生在每个系统中(是的,在野外不是那么多,但我有一个:)这允许人们混合多个符号。 顺序因语言/系统而异,具体取决于口味。
如果你真的无法改变语法并且需要依赖匹配的大括号,那么你需要在Java中重新实现基于flex的解决方案(例如使用jflex)并使Xtext使用该词法分析器。我在这篇博文中简要介绍了这一点。它还包含一个指向示例代码的指针,其中我在 Xtext 中使用了基于 jflex 的词法分析器。
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 代码在main()中运行,但在函数中出现错误
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- 编译包含字符串的代码时遇到问题
- 我在c++代码中生成了一个运行时#3异常
- 如何在linux终端中同时编译和运行c++代码
- 为cl.exe(Visual Studio代码)指定命令行C++版本
- 在Linux for Windows上编译C++代码时出错
- 我的字符计数代码计算错误.为什么
- 孤立代码块在结构中引发异常
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 此代码是否违反一个定义规则
- 为什么我的代码在输出中增加了93天
- 我的简单if-else语句是如何无法访问的代码
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 为什么在这个代码结束循环中没有得到结束
- 在c代码之间共享数据的最佳方式
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值