大量の意味不明なエラーメッセージと格闘した結果

今回のターゲット文法は

epxr ::= int_lit
       | '(' op expr expr ')'

int_lit ::= token(int_lit_s)
op ::= token(op_s)

int_lit_s ::= digit digit*
op ::= alpha alpha*

token(T) ::= T ' '*

token(T)はジェネリックなルールであり、Tに対してTの後ろの空白文字を食ってしまうルール。

パーザのソース

#include <iostream>
#include <string>
#include <boost/lexical_cast.hpp>
#include <boost/function.hpp>
#include "peg.hpp"

using namespace peg;
using namespace std;

template<class T>
struct token : public T
{
  void action(const T& t, const rep<peg::ws>&) {
    *static_cast<T*>(this) = t;
  }
};

struct int_lit_s
{
  int v;
  void action(digit x, const rep<digit>& y) {
    string s;
    s += x;
    s.append(y.begin(), y.end());
    v = boost::lexical_cast<int>(s);
  }
};

typedef token<int_lit_s> int_lit;

struct op_s
{
  boost::function<int(int,int)> v;
  
  void action(alpha x, const rep<alpha>& name) {
    string s;
    s += x;
    s.append(name.begin(), name.end());
    if (s == "add") {
      v = std::plus<int>();
    } else {
      v = std::minus<int>();
    }
  }
};

typedef token<op_s> op;
typedef token<ch<'('>::type> open_paren;
typedef token<ch<')'>::type> close_paren;

struct expr
{
  int v;
  void action(int_lit e, sor orr,
              open_paren, op o, const expr& e1, const expr& e2, close_paren) {
    if (orr.left) {
      v = e.v;
    } else {
      v = o.v(e1.v, e2.v);
    }
  }
};

void test(const string& s)
{
  cout << s << " ---> ";
  parser<expr> parser;
  expr e;

  if (!parser.parse(e, s.begin(), s.end())) {
    cout << "parse error" << endl;
  } else {
    cout << e.v << endl;
  }
  
}

int main()
{
  test("1");
  test("42");
  test("(add 10 23)");
  test("(add 100 (sub 20 5))");
  test("(add (add 10 20) (add 5 13))");
  test("(add)");
  return 0;
}

実行結果

1 ---> 1
42 ---> 42
(add 10 23) ---> 33
(add 100 (sub 20 5)) ---> 115
(add (add 10 20) (add 5 13)) ---> 48
(add) ---> parse error

例によって、少しでも間違えると意味不明なエラーメッセージが大量に出る。
例えば、const参照で受け取るべき引数を参照にしてしまっていたら…

/home/kik/include/boost/fusion/functional/invocation/invoke.hpp: In static member function ‘static typename boost::function_types::result_type<Function>::type boost::fusion::detail::invoke_mem_fn<Function, Sequence, 8, false>::call(F&, Sequence&) [with F = void (expr::*)(int_lit, peg::sor, open_paren, op, expr&, const expr&, close_paren), Function = void (expr::*)(int_lit, peg::sor, open_paren, op, expr&, const expr&, close_paren), Sequence = const boost::fusion::joint_view<const boost::fusion::single_view<expr*>, const boost::fusion::vector<token<int_lit_s>, peg::sor, token<peg::chr<peg::chr_range_constraint<'(', '('> > >, token<op_s>, expr, expr, token<peg::chr<peg::chr_range_constraint<')', ')'> > >, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >]’:
/home/kik/include/boost/fusion/functional/invocation/invoke.hpp:178:   instantiated from ‘typename boost::fusion::result_of::invoke<Function, const Sequence>::type boost::fusion::invoke(Function, const Sequence&) [with Function = void (expr::*)(int_lit, peg::sor, open_paren, op, expr&, const expr&, close_paren), Sequence = boost::fusion::joint_view<const boost::fusion::single_view<expr*>, const boost::fusion::vector<token<int_lit_s>, peg::sor, token<peg::chr<peg::chr_range_constraint<'(', '('> > >, token<op_s>, expr, expr, token<peg::chr<peg::chr_range_constraint<')', ')'> > >, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >]’
peg.hpp:228:   instantiated from ‘bool peg::pi::parse_fun(Fun, T&, Input&, Input) [with Fun = void (expr::*)(int_lit, peg::sor, open_paren, op, expr&, const expr&, close_paren), T = expr, Input = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >]’
peg.hpp:240:   instantiated from ‘bool peg::parser<T>::parse(T&, Input, Input) [with Input = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, T = expr]’
sample-1.cpp:70:   instantiated from here
/home/kik/include/boost/fusion/functional/invocation/invoke.hpp:279: error: invalid initialization of reference of type ‘expr&’ from expression of type ‘const expr’
/home/kik/include/boost/fusion/functional/invocation/invoke.hpp:279: error: return-statement with a value, in function returning 'void'

かろうじて、最後から2行目を読めば何が悪いのか分かる