更新时间:2023-02-16 17:45:03
建议你只想在顶层规则使用船长。
您不使用星号的船长,因为您可以使用星号 不要要忽略它们。如果他们被忽略,你的规则不能对他们采取行动。
此外,内部规则不应该使用空格跳过简单的原因,空格和换行符是有效的字段数据
因此,所有这些的结果是:
value = *(ascii :: char _(\x20-\x7e\r\\\
) - '*')>> '*';
field = ascii :: graph>>值;
start = STX>>值>> * field>> ETX>> xmit_checksum;
这些规则将用各自的skippers声明:
qi :: uint_parser< uint16_t,16,4,4> xmit_checksum;
qi :: rule< It,ascii :: space_type>开始;
qi :: rule< It>字段,值; // no skippers - they are lexemes
:在规则中拆分您的语法。
您的样品不必要地混合分析和打印的职责。
我建议不要在这里使用语义操作( Boost Spirit:语义
$ b>
struct JEDEC {
std :: string caption;
struct field {
char id;
std :: string value;
};
std :: vector< field>字段;
uint16_t checksum;
};
并在规则中声明:
qi :: rule< It,ast :: JEDEC(),ascii :: space_type>开始;
qi :: rule< It,ast :: JEDEC :: field()>领域;
qi :: rule< It,std :: string()>值;
qi :: uint_parser< uint16_t,16,4,4> xmit_checksum;
现在,您的语法无需更改,您可以使用以下命令打印所需的输出: / p>
inline static std :: ostream& operator<<(std :: ostream& os,JEDEC const& jedec){
os< 开始:< jedec.caption<< \\\
;
for(auto& f:jedec.fields)
os<< f.id<< :<< f.value<< \\\
;
auto saved = os.rdstate();
os<< End:<< std :: hex<< std :: setw(4)<< std :: setfill('0')<< jedec.checksum;
os.setstate(saved);
return os;
}
这是一个演示程序,它使用您的问题的示例输入将它绑定在一起:
//#define BOOST_SPIRIT_DEBUG
#include< boost / fusion / adapted / struct.hpp>
#include< boost / spirit / include / qi.hpp>
#include< iomanip>
命名空间qi = boost :: spirit :: qi;
namespace ascii = qi :: ascii;
namespace ast {
struct JEDEC {
std :: string caption;
struct field {
char id;
std :: string value;
};
std :: vector< field>字段;
uint16_t checksum;
};
inline static std :: ostream& operator<<(std :: ostream& os,JEDEC const& jedec){
os< 开始:< jedec.caption<< \\\
;
for(auto& f:jedec.fields)
os<< f.id<< :<< f.value<< \\\
;
auto saved = os.rdstate();
os<< End:<< std :: hex<< std :: setw(4)<< std :: setfill('0')<< std :: uppercase<< jedec.checksum;
os.setstate(saved);
return os;
}
}
BOOST_FUSION_ADAPT_STRUCT(ast :: JEDEC :: field,
(char,id)(std :: string,value))
BOOST_FUSION_ADAPT_STRUCT(ast :: JEDEC,
(std :: string,caption)
(std :: vector< ast :: JEDEC :: field> fields)
(uint16_t,checksum))
template< typename it>
struct JedecGrammar:qi :: grammar< It,ast :: JEDEC(),ascii :: space_type>
{
JedecGrammar():JedecGrammar :: base_type(start){
const char STX ='\x02';
const char ETX ='\x03';
value = *(ascii :: char _(\x20-\x7e\r\\\
) - '*')>> '*';
field = ascii :: graph>>值;
start = STX>>值>> * field>> ETX>> xmit_checksum;
BOOST_SPIRIT_DEBUG_NODES((start)(field)(value))
}
private:
qi :: rule< It,ast :: JEDEC :: space_type>开始;
qi :: rule< It,ast :: JEDEC :: field()>领域;
qi :: rule< It,std :: string()>值;
qi :: uint_parser< uint16_t,16,4,4> xmit_checksum
};
int main(){
typedef boost :: spirit :: istream_iterator It;
首先(std :: cin>> std :: noskipws),last;
JedecGrammar< it> G;
ast :: JEDEC jedec;
bool ok = phrase_parse(first,last,g,ascii :: space,jedec);
if(ok)
{
std :: cout< parse success\\\
;
std :: cout<<杰德克
}
else
std :: cout<< 解析失败\\\
;
if(first!= last)
std :: cout<< 剩余输入未解析:'< std :: string(first,last)<< '\\\
;
}
输出:
开始:John Doe生成的JEDEC文件
D:M SIGNETICS(PHILIPS)
D:D GAL16R8
Q:P20
Q: V0
G:0
F:0
L:00000 1110101111100110111101101110111100111111
C:DEAD
结束:BEEF