Embedded 基于包结构自动生成代码
我们有不同结构的数据包。它们应该用不同的语言读/写。例如:Embedded 基于包结构自动生成代码,embedded,config,code-generation,packet,Embedded,Config,Code Generation,Packet,我们有不同结构的数据包。它们应该用不同的语言读/写。例如: | ClassId | Data | ClassId = "datapoint" (Data structure): temperature - 1bytes elevation - 2bytes gradient - 1bytes ClassId = "config" (Data structure): frequency - 1bytes deviceId - 3bytes ClassId = "acceler
| ClassId | Data |
ClassId = "datapoint" (Data structure):
temperature - 1bytes
elevation - 2bytes
gradient - 1bytes
ClassId = "config" (Data structure):
frequency - 1bytes
deviceId - 3bytes
ClassId = "accelerometer" (Data structure):
time - 2bytes
x - 2bytes
y - 2bytes
z - 2bytes
我希望有一个配置文件,然后自动生成可以读写数据包的代码(python/c/etc),而不是手动编写基于类解析每个数据包的代码(这很容易出错,也很耗时)。大致如下:
lib.set(packet, "datapoint", {
elevation: 933,
temperature: 18,
gradient: 20
});
lib.get(packet, "datapoint");
=>
{
elevation: 933,
temperature: 18,
gradient: 20
}
谷歌搜索并没有给我带来任何好处。任何指针都会非常有用。您需要一个代码生成系统,它将数据包规范编译成代码来解析/解压数据包 您可以使用语法分析器生成器构建一个特别的语法分析器,并编写特别的代码以按程序遍历语法分析器树并写出相关的代码 或者您可以使用,它将数据包规范视为源代码,并将其转换为目标语言中的源代码。向PTS解释数据包的语法与向解析器生成器解释语法的方式基本相同 但是使用PTS,您可以用表面语法表示法编写转换规则,识别数据包系统语法并将其映射到目标langauge函数语法。这使得编写和维护这样的工具变得更加容易,特别是当数据包语法发生变化,和/或您改变目标语言基础设施以以不同的方式解析数据包时 编辑10/3:OP要求提供一个具体的示例,大概是一个PTS。 我将展示我们的DMS软件再工程工具包的外观(有关DMS的更多信息,请参阅bio) 首先,您需要包语言的(DMS兼容)语法。根据我所看到的,这很简单:
Packets = Packet ;
Packets = Packets Packet ; -- allow a list of packet defintions
Packet = 'ClassID' '=' STRING members ;
members = ;
members = members member ; -- allow list of members
member = IDENTIFIER '-' NATURAL 'bytes' ;
我认为这种语法很幼稚,因为实际上数据包成员可能有不同的类型(可能是字符串、浮点、布尔等);OP的例子只显示了我假设的是N字节的二进制整数。您还需要各种目标语言的语法。我假设你有这些语法(这是完全的假设);让我们暂时使用C。[DMS确实有很多这样的功能]
我们还必须假设传输数据的表示形式。OP提出了一些建议,但我认为他试图暗示生成的代码(“lib.set…”)。
相反,我将假设数据包内容是以二进制字节的形式从流中读取的,只是简单地附加在一起;这使得数据包的大小尽可能小,因此传输时间也很快
所以,现在我们需要指定代码生成器,作为将数据包定义映射到代码的重写规则集
在后台,PTS的重写规则通常如下所示:
if you see *this*, replace it by *that*
所以你实际上是在用另一个结构替换一个结构。它们通常在AST上运行,但为了可读性,使用了表面语法
以下是DMS的源到源重写规则;它们看起来像是对文本进行操作,但实际上它们是对DMS解析器生成的AST进行操作的。
DMS有自己的规则语法,但基本上遵循上述典型样式:
rule rule_name( pattern_variables ):
source_syntax_category -> target_syntax_category =
" this_pattern " -> " that_pattern " ;
源模式和目标模式用*元引号“”括起来;因此,实际的文字引号字符被转义为“\”
对于DMS规则,这始终是数据包表示法的一个片段,这始终是我们选择的目标语言(C)的一个片段.rule head中的模式变量名称是给定的语法类型,只能与AST中的相应类型匹配。在元引号中找到的模式变量写为\variable。元函数可以计算派生结果;它们在模式中被调用为“\function(args)”。有关详细信息,请参阅
source domain Packet; -- the little language we defined
target domain C; -- what we will generate code for
-- you'll write one of these rulesets for each target language
rule top_level(pl: Packets): Packets -> Statements =
" \pl "
-> " ReadPacketType(stream, packet_type);
switch(packet_type) {
\pl
default: Panic(\"unrecognized packet type\");
}" if IsRoot(pl); -- do this once [at root of tree]
rule translate_packet_definitions(p: Packet, pl: packet_list): Packets -> switch_case_list
" \p \pl ";
rule translate_packet_definition(s:STRING, ms: members, pl: Packets): Packets -> switch_case =
" ClassID = \s \m \pl "
-> " case \concatenate\(\"enum_\"\,\string_to_identifier\(\s\)\): {
\string_to_identifier\(\s\)* p=malloc(sizeof(\string_to_identifier\(\s\)));
\m
return p;
}
";
rule translate_members(m: member, ms: members) : members -> Statements
= " \m \ms ";
rule translate_member(i: IDENTIFIER, n: NATURAL) = member -> StatementList =
" \i - \n bytes " ->
" p-> \toCIdentifer\(\i\) = ReadNByteValue(stream,\toCNatural\(\n\)) ; "
这还不完整(特别是,我需要另一组规则来生成数据包类型集的枚举声明),我怀疑这是否正确,但它提供了规则的味道。有了这些规则,OP的示例输入将生成以下C代码:
ReadPacketType(stream, packet_type);
switch(packet_type) {
case enum_datapoint: {
datapoint* p=malloc(sizeof(datapoint));
p->temperature=ReadNByteValue(stream,1);
p->elevation=ReadNByteValue(stream,2);
p->gradient=ReadNByteValue(stream,2);
return p;
}
case enum_config: {
config* p=malloc(sizeof(config));
p->frequency=ReadNByteValue(stream,1);
p->deviceId=ReadNByteValue(stream,3);
return p;
}
case enum_accelerometer: {
accelerometer* p=malloc(sizeof(accelerometer));
p-time>=ReadNByteValue(stream,2);
p->x=ReadNByteValue(stream,2);
p->y=ReadNByteValue(stream,2);
p->z=ReadNByteValue(stream,2);
return p;
}
default: Panic(\"unrecognized packet type\");
}
向下投票人:我不认为你会有礼貌地解释你的理由。答案是真实的和有用的。请你根据问题中的例子结构给出一个具体的例子好吗?