且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

是Boost跳过解析器的正确方法吗?

更新时间: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;
}



LIVE DEMO



这是一个演示程序,它使用您的问题的示例输入将它绑定在一起:



Live on Coliru

  //#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