我想解析以下结构(为简单起见,我仅显示其中一半,但其余结构与所示结构相同):
*Point, name=1, mission=mission2, inherit_point=bla
*Sn
22,-22.5
22,22.5
22,22.5
22,22.5
22,22.5
22,22.5
*Material
22.55,22.55,22.55
22.55,22.55,22.55
*Kt
1
*Output
sequiv_fat, sequiv_propa
*End Point
每个部分(以*开头)将被解析为一个结构。主要部分Point将包含子部分Sn,Material和Output。它还将具有属性名称,任务和Inherited_point。
Sn部分将被解析为
struct Sn {
std::string name // "Sn"
std::map<int,double> data;
}
材料成
struct material {
std::string name // "material"
std::vector<double> data;
}
千吨
struct Kt {
std::string name; // "kt"
int value;
}
输出
struct Output {
std::string name; //"output"
std::vector<std::string> data;
}
为了解析本节,我以经过修改的Boost Spirit为例。
我有一个很大的部分要分析,我正在考虑将语法规则分成几个单独的类。我的想法是为要解析的每个子节制定一个规则,并为解析Point节制定一条主要规则。
每个sub rule
将被解析为其相应的结构。
要做到这一点,我需要将词法分析器传递给每个“子规则”,但我不知道这样做。
这是我所做的。
从语法定义中可以看到,规则Assigment_Rule2在单独的文件中定义,但是我不知道如何将词法分析器传递给该规则。而且它不会编译。
#define BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT
#define BOOST_SPIRIT_DEBUG
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/qi_real.hpp>
#include <boost/spirit/include/qi_eol.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include "example.hpp"
using namespace boost::spirit;
using boost::phoenix::val;
///////////////////////////////////////////////////////////////////////////////
// class definition
///////////////////////////////////////////////////////////////////////////////
namespace client {
namespace qi = boost::spirit::qi;
struct point
{
std::string name;
std::string name2;
std::string mission;
std::string parent_point;
};
}
BOOST_FUSION_ADAPT_STRUCT(client::point,
(std::string, name),
(std::string, name2),
(std::string, mission),
(std::string, parent_point)
)
namespace client {
///////////////////////////////////////////////////////////////////////////////
// Token id definitions
///////////////////////////////////////////////////////////////////////////////
enum token_ids
{
ID_CONSTANT = 1000,
ID_START_POINT,
ID_END_POINT,
ID_SN,
ID_MATERIAL,
ID_IDENTIFIER,
ID_INTEGER,
ID_FLOAT
};
///////////////////////////////////////////////////////////////////////////////
// Token definitions
///////////////////////////////////////////////////////////////////////////////
template <typename Lexer>
struct example6_tokens : lex::lexer<Lexer>
{
example6_tokens()
{
// define the tokens to match
identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
constant = "[0-9]+";
float_value = "-?\\d+(\\.\\d+)?";
this->self = lex::token_def<>('(') | ')' | '=' | ',' | '*';
this->self.add
(constant, ID_CONSTANT)
("Point", ID_START_POINT)
("End Point", ID_END_POINT)
("Sn", ID_SN)
("Material", ID_MATERIAL)
(identifier, ID_IDENTIFIER)
(float_value, ID_FLOAT)
;
this->self("WS")
= lex::token_def<>("[ \\t\\n]+")
| "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/"
;
}
lex::token_def<std::string> identifier;
lex::token_def<unsigned int> constant;
lex::token_def<double> float_value;
};
}
///////////////////////////////////////////////////////////////////////////////
// Grammar definition
///////////////////////////////////////////////////////////////////////////////
namespace client {
template <typename Iterator, typename Lexer>
struct example6_grammar
: qi::grammar<Iterator, point(), qi::in_state_skipper<Lexer> >
{
template <typename TokenDef>
example6_grammar(TokenDef const& tok)
: example6_grammar::base_type(start)
{
using boost::spirit::_val;
using boost::spirit::qi::eol;
using qi::on_error;
using qi::fail;
using qi::debug;
start
= '*'
>> token(ID_START_POINT)
>> ','
>> assignment2
>> ','
>> assignment2
>> ','
>> assignment2
>> *statement
>> '*'
>> token(ID_END_POINT)
;
statement
= sn_stmt
| material_stmt
;
assignment
= tok.identifier >> '=' >> expression
;
sn_stmt = ('*' >> token(ID_SN) >> +pair)
[
std::cout << val("sn statement to: ")
<< _1 << "\n"
]
;
material_stmt = ('*' >> token(ID_MATERIAL) >> +list)
[
std::cout << val("material statement to: ")
<< _1 << "\n"
]
;
list = token(ID_FLOAT) % ',';
pair
= token(ID_CONSTANT) >> ',' >> token(ID_FLOAT)
;
expression
= tok.identifier[_val = _1]
| tok.constant[_val = _1]
;
sn_stmt.name("sn_stmt");
material_stmt.name("material_stmt");
debug(sn_stmt);
debug(material_stmt);
}
typedef boost::variant<unsigned int, std::string> expression_type;
qi::rule<Iterator, point(), qi::in_state_skipper<Lexer> > start;
qi::rule<Iterator, qi::in_state_skipper<Lexer> > statement, material_stmt, pair, list, assignment;
qi::rule<Iterator, qi::in_state_skipper<Lexer>> sn_stmt;
qi::rule<Iterator, expression_type(), qi::in_state_skipper<Lexer> > expression;
Assigment_Rule2<Iterator> assignment2;
};
}
///////////////////////////////////////////////////////////////////////////////
int main()
{
typedef std::string::iterator base_iterator_type;
typedef lex::lexertl::token<
base_iterator_type, boost::mpl::vector<unsigned int, std::string, double>
> token_type;
typedef lex::lexertl::lexer<token_type> lexer_type;
typedef client::example6_tokens<lexer_type> example6_tokens;
typedef example6_tokens::iterator_type iterator_type;
typedef client::example6_grammar<iterator_type, example6_tokens::lexer_def> example6_grammar;
example6_tokens tokens; // Our lexer
example6_grammar calc(tokens); // Our parser
std::string str(read_from_file("ReadMe.txt"));
std::string::iterator it = str.begin();
iterator_type iter = tokens.begin(it, str.end());
iterator_type end = tokens.end();
std::string ws("WS");
client::point my_point;
bool r = qi::phrase_parse(iter, end, calc, qi::in_state(ws)[tokens.self], my_point);
if (r && iter == end)
{
std::cout << "-------------------------\n";
std::cout << "Parsing succeeded\n";
std::cout << "-------------------------\n";
}
else
{
std::cout << "-------------------------\n";
std::cout << "Parsing failed\n";
std::cout << "-------------------------\n";
}
std::cout << "Bye... :-) \n\n";
return 0;
}
BasicRules.hpp文件
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/qi_real.hpp>
#include <boost/spirit/include/qi_eol.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi_char_.hpp>
#include <boost/spirit/include/qi_lexeme.hpp>
using namespace boost::spirit;
using boost::phoenix::val;
namespace client {
template <typename Iterator>
struct Assigment_Rule2
: qi::grammar<Iterator, std::string()>
{
Assigment_Rule2()
: Assigment_Rule2::base_type(start)
{
using boost::spirit::double_;
using boost::spirit::lexeme;
using boost::spirit::ascii::char_;
start = ( "2">> '=' >> "2" )
[
_val = _2
]
;
}
qi::rule<Iterator, std::string()> start;
};
}
如果有人能给我一些想法和一些起点,我将不胜感激。 谢谢。