2010-06-14 53 views
0

我有問題得到一個小精神/ qi語法編譯。構建堆棧跟蹤的fugly足夠多到沒有任何意義,我(儘管有些assertion_failed我可以在那裏看到,但沒有帶來多大的信息)建立錯誤與助推精神語法(助推器1.43和g + + 4.4.1)

輸入語法標題:

inputGrammar.h

#include <boost/config/warning_disable.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix_core.hpp> 
#include <boost/spirit/include/phoenix_operator.hpp> 
#include <boost/spirit/include/phoenix_fusion.hpp> 
#include <boost/spirit/include/phoenix_stl.hpp> 
#include <boost/fusion/include/adapt_struct.hpp> 
#include <boost/variant/recursive_variant.hpp> 
#include <boost/foreach.hpp> 

#include <iostream> 
#include <fstream> 
#include <string> 
#include <vector> 

namespace sp = boost::spirit; 
namespace qi = boost::spirit::qi; 
using namespace boost::spirit::ascii; 
//using namespace boost::spirit::arg_names; 

namespace fusion = boost::fusion; 
namespace phoenix = boost::phoenix; 

using phoenix::at_c; 
using phoenix::push_back; 


template< typename Iterator , typename ExpressionAST > 
struct InputGrammar : qi::grammar<Iterator, ExpressionAST(), space_type> { 

    InputGrammar() : InputGrammar::base_type(block) { 
     tag = sp::lexeme[+(alpha)  [sp::_val += sp::_1]];//[+(char_ - '<')  [_val += _1]]; 

     block = sp::lit("block") [ at_c<0>(sp::_val) = sp::_1] 
       >> "(" >> *instruction[ push_back(at_c<1>(sp::_val) , sp::_1) ] 
       >> ")"; 

     command = tag [ at_c<0>(sp::_val) = sp::_1] 
           >> "(" >> *instruction [ push_back(at_c<1>(sp::_val) , sp::_1)] 
           >> ")"; 

     instruction = (command | tag) [sp::_val = sp::_1]; 
    } 
    qi::rule< Iterator , std::string() , space_type > tag; 
    qi::rule< Iterator , ExpressionAST() , space_type > block; 
    qi::rule< Iterator , ExpressionAST() , space_type > function_def; 
    qi::rule< Iterator , ExpressionAST() , space_type > command; 
    qi::rule< Iterator , ExpressionAST() , space_type > instruction; 
}; 

的測試版本程序: 我看來構建失敗的齊:: phrase_parse,我使用升壓1.43和g ++ 4.4.1

#include <iostream> 
#include <string> 
#include <vector> 
using namespace std; 

//my grammar 
#include <InputGrammar.h> 

struct MockExpressionNode { 
    std::string name; 
    std::vector<MockExpressionNode> operands; 

    typedef std::vector<MockExpressionNode>::iterator iterator; 
    typedef std::vector<MockExpressionNode>::const_iterator const_iterator; 

    iterator begin() { return operands.begin(); } 
    const_iterator begin() const { return operands.begin(); } 
    iterator end() { return operands.end(); } 
    const_iterator end() const { return operands.end(); } 

    bool is_leaf() const { 
     return (operands.begin() == operands.end()); 
    } 
}; 


BOOST_FUSION_ADAPT_STRUCT(
    MockExpressionNode, 
    (std::string, name) 
    (std::vector<MockExpressionNode>, operands) 
) 

int const tabsize = 4; 

void tab(int indent) 
{ 
    for (int i = 0; i < indent; ++i) 
     std::cout << ' '; 
} 

template< typename ExpressionNode > 
struct ExpressionNodePrinter 
{ 
    ExpressionNodePrinter(int indent = 0) 
     : indent(indent) 
    { 
    } 

    void operator()(ExpressionNode const& node) const { 
     cout << " tag: " << node.name << endl; 
     for (int i=0 ; i < node.operands.size() ; i++) { 
      tab(indent); cout << " arg "<<i<<": "; ExpressionNodePrinter(indent + 2)(node.operands[i]); cout << endl; 
     } 
    } 

    int indent; 
}; 

int test() { 
MockExpressionNode root; 
    InputGrammar< string::const_iterator , MockExpressionNode > g(); 
    std::string litA = "litA"; 
    std::string litB = "litB"; 
    std::string litC = "litC"; 
    std::string litD = "litD"; 
    std::string litE = "litE"; 
    std::string litF = "litF"; 
    std::string source = litA+"("+litB+" ,"+litC+" , "+ litD+" ("+litE+", "+litF+") "+ ")"; 
    string::const_iterator iter = source.begin(); 
    string::const_iterator end = source.end(); 
    bool r = qi::phrase_parse(iter , end , g , root , space); 
    ExpressionNodePrinter<MockExpressionNode> np; 
    np(root); 
}; 

int main() { 
    test(); 
} 

最後,生成錯誤是:

/usr/bin/make -f nbproject/Makefile-linux_amd64_devel.mk SUBPROJECTS= .build-conf 
make[1]: se ingresa al directorio `/home/mineq/NetBeansProjects/InputParserTests' 
/usr/bin/make -f nbproject/Makefile-linux_amd64_devel.mk dist/linux_amd64_devel/GNU-Linux-x86/vpuinputparsertests 
make[2]: se ingresa al directorio `/home/mineq/NetBeansProjects/InputParserTests' 
mkdir -p build/linux_amd64_devel/GNU-Linux-x86 
rm -f build/linux_amd64_devel/GNU-Linux-x86/tests_main.o.d 
g++ `llvm-config --cxxflags` `pkg-config --cflags unittest-cpp` `pkg-config --cflags boost-1.43` `pkg-config --cflags boost-coroutines` -c -g -I../InputParser -MMD -MP -MF build/linux_amd64_devel/GNU-Linux-x86/tests_main.o.d -o build/linux_amd64_devel/GNU-Linux-x86/tests_main.o tests_main.cpp 
       from /home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/auto.hpp:16, 
       from /home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi.hpp:15, 
       from /home/mineq/third_party/boost_1_43_0/boost/spirit/include/qi.hpp:16, 
       from ../InputParser/InputGrammar.h:12, 
       from tests_main.cpp:14: 
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/parse.hpp: In function ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, boost::spirit::qi::skip_flag::enum_type, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Expr = InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode>(), Skipper = MockExpressionNode, Attr = const boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>]’: 
In file included from /home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/detail/parse_auto.hpp:14, 
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/parse.hpp:125: instantiated from ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Expr = InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode>(), Skipper = MockExpressionNode, Attr = const boost::spirit::ascii::space_type]’ 
tests_main.cpp:206: instantiated from here 
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/parse.hpp:99: error: no matching function for call to ‘assertion_failed(mpl_::failed************ (boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, boost::spirit::qi::skip_flag::enum_type, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Expr = InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode>(), Skipper = MockExpressionNode, Attr = const boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>]::error_invalid_expression::************)(InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode> (*)()))’ 
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/parse.hpp:125: instantiated from ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Expr = InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode>(), Skipper = MockExpressionNode, Attr = const boost::spirit::ascii::space_type]’ 
tests_main.cpp:206: instantiated from here 
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/parse.hpp:100: error: no matching function for call to ‘assertion_failed(mpl_::failed************ (boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, boost::spirit::qi::skip_flag::enum_type, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Expr = InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode>(), Skipper = MockExpressionNode, Attr = const boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>]::error_invalid_expression::************)(MockExpressionNode))’ 
       from /home/mineq/third_party/boost_1_43_0/boost/proto/proto.hpp:12, 
       from /home/mineq/third_party/boost_1_43_0/boost/spirit/home/support/meta_compiler.hpp:17, 
       from /home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/meta_compiler.hpp:14, 
       from /home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/action/action.hpp:14, 
       from /home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/action.hpp:14, 
       from /home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi.hpp:14, 
       from /home/mineq/third_party/boost_1_43_0/boost/spirit/include/qi.hpp:16, 
       from ../InputParser/InputGrammar.h:12, 
       from tests_main.cpp:14: 
/home/mineq/third_party/boost_1_43_0/boost/proto/detail/expr0.hpp: At global scope: 
/home/mineq/third_party/boost_1_43_0/boost/proto/proto_fwd.hpp: In instantiation of ‘boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode>()>, 0l>’: 
In file included from /home/mineq/third_party/boost_1_43_0/boost/proto/core.hpp:13, 
/home/mineq/third_party/boost_1_43_0/boost/utility/enable_if.hpp:59: instantiated from ‘boost::disable_if<boost::proto::result_of::is_expr<boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode>()>, 0l>, void>, void>’ 
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/support/meta_compiler.hpp:200: instantiated from ‘boost::spirit::result_of::compile<boost::spirit::qi::domain, InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode>(), boost::fusion::unused_type, void>’ 
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/parse.hpp:107: instantiated from ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, boost::spirit::qi::skip_flag::enum_type, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Expr = InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode>(), Skipper = MockExpressionNode, Attr = const boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>]’ 
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/parse.hpp:125: instantiated from ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Expr = InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode>(), Skipper = MockExpressionNode, Attr = const boost::spirit::ascii::space_type]’ 
tests_main.cpp:206: instantiated from here 
/home/mineq/third_party/boost_1_43_0/boost/proto/detail/expr0.hpp:64: error: field ‘boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode>()>, 0l>::child0’ invalidly declared function type 
       from /home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/auto.hpp:16, 
       from /home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi.hpp:15, 
       from /home/mineq/third_party/boost_1_43_0/boost/spirit/include/qi.hpp:16, 
       from ../InputParser/InputGrammar.h:12, 
       from tests_main.cpp:14: 
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/parse.hpp: In function ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, boost::spirit::qi::skip_flag::enum_type, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Expr = InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode>(), Skipper = MockExpressionNode, Attr = const boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>]’: 
In file included from /home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/detail/parse_auto.hpp:14, 
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/parse.hpp:125: instantiated from ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Expr = InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode>(), Skipper = MockExpressionNode, Attr = const boost::spirit::ascii::space_type]’ 
tests_main.cpp:206: instantiated from here 
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/parse.hpp:107: error: request for member ‘parse’ in ‘boost::spirit::compile [with Domain = boost::spirit::qi::domain, Expr = InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode>()](((InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode> (&)())((InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode> (*)())expr)))’, which is of non-class type ‘InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode>()’ 
       from /home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/auto.hpp:15, 
       from /home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi.hpp:15, 
       from /home/mineq/third_party/boost_1_43_0/boost/spirit/include/qi.hpp:16, 
       from ../InputParser/InputGrammar.h:12, 
       from tests_main.cpp:14: 
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/skip_over.hpp: In function ‘void boost::spirit::qi::skip_over(Iterator&, const Iterator&, const T&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, T = boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, boost::spirit::qi::skip_flag::enum_type, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Expr = InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode>(), Skipper = MockExpressionNode, Attr = const boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>]::skipper_type]’: 
In file included from /home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/auto/auto.hpp:19, 
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/parse.hpp:112: instantiated from ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, boost::spirit::qi::skip_flag::enum_type, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Expr = InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode>(), Skipper = MockExpressionNode, Attr = const boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>]’ 
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/parse.hpp:125: instantiated from ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Expr = InputGrammar<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, MockExpressionNode>(), Skipper = MockExpressionNode, Attr = const boost::spirit::ascii::space_type]’ 
tests_main.cpp:206: instantiated from here 
/home/mineq/third_party/boost_1_43_0/boost/spirit/home/qi/skip_over.hpp:27: error: ‘const struct MockExpressionNode’ has no member named ‘parse’ 
make[2]: *** [build/linux_amd64_devel/GNU-Linux-x86/tests_main.o] Error 1 
make[2]: se sale del directorio `/home/mineq/NetBeansProjects/InputParserTests' 
make[1]: *** [.build-conf] Error 2 
make[1]: se sale del directorio `/home/mineq/NetBeansProjects/InputParserTests' 
make: *** [.build-impl] Error 2 
BUILD FAILED (exit value 2, total time: 1m 48s) 
+1

沒有關於精神的線索,但請注意''test'中'g'的聲明實際上是一個函數聲明。 'g'後面需要省略parens。 – 2010-06-14 00:09:07

+0

是不是應該等同於默認的構造函數? – lurscher 2010-06-14 00:21:31

+0

@lurscher:不,C++解析器更喜歡函數聲明。它不總是*等價。 – greyfade 2010-06-14 02:54:43

回答

2

屬性(一個或多個)總是必須作爲最後一個參數(一個或多個),以解析/ phrase_parse功能傳遞。所以,你需要寫:

bool r = qi::phrase_parse(iter , end , g , space, root); 

此外,你可以從你的語法中刪除所有的語義動作,如果你添加額外的構造函數的ExpressionAST類型:

template< typename Iterator , typename ExpressionAST > 
struct InputGrammar : qi::grammar<Iterator, ExpressionAST(), space_type> { 

    InputGrammar() : InputGrammar::base_type(block) { 
     tag = sp::lexeme[+(alpha)]; 
     block = sp::lit("block") >> "(" >> *instruction >> ")"; 
     command = tag >> "(" >> *instruction >> ")"; 
     instruction = (command | tag); 
    } 
    qi::rule< Iterator , std::string() , space_type > tag; 
    qi::rule< Iterator , ExpressionAST() , space_type > block; 
    qi::rule< Iterator , ExpressionAST() , space_type > function_def; 
    qi::rule< Iterator , ExpressionAST() , space_type > command; 
    qi::rule< Iterator , ExpressionAST() , space_type > instruction; 
}; 

struct MockExpressionNode { 
    // ... 
    MockExpressionNode() {} 
    MockExpressionNode(std::string name) : name(name) {} 
    // ... 
}; 

但即使那樣它也不會編譯,因爲MockExpressionNode數據結構是自遞歸的。這可以通過存儲指針向量(這需要更改語法)或使用boost::recursive_wrapper來解決。