関数呼び出し構文を AST で表現するときに root node はどーすりゃ良いのかにゃー問題

Boost.Spirit 使うたびにいっつもう〜う〜うなること.関数呼び出し式(より一般には postfix expression)を AST で表現するとき,何を関数呼び出し式に対する root node とするか.どうも以下のように関数呼び出し式の '(' (開きカッコ)にディレクティブを引っ掛けて root node 作るしか方策がないようだけれど,これがとてつもなく気に入らにゃい.う〜う〜う〜.他にきれいに root node 生成する方策にゃいのかにゃー.関数名を root node にすると expression_list が空のとき(引数のリストが空のとき)に identifier がそのまま上に上がっちゃうんだよにゃー(関数呼び出し構文に semantics があるのに対応する AST のノードが生成されない). epsilon に root_node_d を引っ掛けても identifier を root node としたときと同じことになるし.

#define BOOST_SPIRIT_DUMP_PARSETREE_AS_XML

#include <string>
#include <map>
#include <iostream>
#include <boost/spirit/core.hpp>
#include <boost/spirit/utility/confix.hpp>
#include <boost/spirit/tree/ast.hpp>
#include <boost/spirit/tree/tree_to_xml.hpp>
#include <boost/thread/once.hpp>

namespace spirit = boost::spirit;


class Grammar
  : public spirit::grammar< Grammar >
{
public:
  enum parser_ids
  {
    translation_unit_parser_id = 100
  , statement_parser_id
  , primary_expression_parser_id
  , literal_parser_id
  , postfix_expression_parser_id
  , function_call_expression_parser_id
  , expression_parser_id
  , expression_list_parser_id
  , identifier_parser_id
  };

private:
  static void initializeRuleNameMap() //throw()
  {
    try{
      rule_name_map_[translation_unit_parser_id] = "translation unit";
      rule_name_map_[statement_parser_id] = "statement";
      rule_name_map_[primary_expression_parser_id] = "primary expression";
      rule_name_map_[literal_parser_id] = "literal";
      rule_name_map_[postfix_expression_parser_id] = "postfix expression";
      rule_name_map_[function_call_expression_parser_id]
        = "function call expression";
      rule_name_map_[expression_parser_id] = "expression";
      rule_name_map_[expression_list_parser_id] = "expression list";
      rule_name_map_[identifier_parser_id] = "identifier";
    }
    catch(...){
      ; // Do nothing.
    }
  }

public:
  Grammar()
  {
    boost::call_once( &initializeRuleNameMap
                    , rule_name_map_initialized_once_ );
  }

public:
  template< class Scanner >
  class definition
  {
  public:
    definition( Grammar const &/*self*/ )
    {
      using namespace boost::spirit;

      translation_unit
        = *statement
        ;
      statement
        = !expression >> no_node_d[ ch_p( ';' ) ]
        ;
      primary_expression
        = no_node_d[ ch_p( '(' ) ] >> expression >> no_node_d[ ch_p( ')' ) ]
        | literal
        ;
      literal
        = leaf_node_d[ lexeme_d[ !ch_p( '-' ) >> +digit_p ] ]
        ;
      postfix_expression
        = primary_expression
        | function_call_expression
        ;
      function_call_expression
        = identifier
            >> root_node_d[ ch_p( '(' ) ] // これがちょー気に入らにゃいっ!!
            >> !expression_list
            >> no_node_d[ ch_p( ')' ) ]
        ;
      expression
        = postfix_expression
        ;
      expression_list
        = expression >> *( root_node_d[ ch_p( ',' ) ] >> expression )
        ;
      identifier
        = leaf_node_d[ lexeme_d[
              ( ch_p( '_' ) | alpha_p ) >> *( ch_p( '_' ) | alnum_p ) ]
            ]
        ;
    }

    spirit::rule<
        Scanner
      , spirit::parser_tag< translation_unit_parser_id >
      > const &start() const
    {
      return translation_unit;
    }

  private:
#define DECLARE_RULE( RULE_NAME )                          \
spirit::rule<                                              \
    Scanner, spirit::parser_tag< RULE_NAME ## _parser_id > \
  > RULE_NAME
/**/

    DECLARE_RULE( translation_unit );
    DECLARE_RULE( statement );
    DECLARE_RULE( primary_expression );
    DECLARE_RULE( literal );
    DECLARE_RULE( postfix_expression );
    DECLARE_RULE( function_call_expression );
    DECLARE_RULE( expression );
    DECLARE_RULE( expression_list );
    DECLARE_RULE( identifier );

#undef DECLARE_RULE
  }; // class definition

  static
  std::map< boost::spirit::parser_id, std::string > const &
  getRuleNameMap()
  {
    return rule_name_map_;
  }

private:
  static boost::once_flag rule_name_map_initialized_once_;
  static std::map< spirit::parser_id, std::string > rule_name_map_;
}; // Grammar



boost::once_flag Grammar::rule_name_map_initialized_once_ = BOOST_ONCE_INIT;
std::map< spirit::parser_id, std::string > Grammar::rule_name_map_
  = std::map< spirit::parser_id, std::string >();



class SkipGrammar
  : public spirit::grammar< SkipGrammar >
{
public:
  template< class Scanner >
  class definition
  {
  public:
    definition( SkipGrammar const &/*self*/ )
    {
      using namespace boost::spirit;

      skip_rule
        = space_p
        | eol_p
        | confix_p( ch_p( '#' ), *anychar_p, eol_p | end_p )
        ;
    }

    spirit::rule< Scanner > const &start() const
    {
      return skip_rule;
    }

  private:
    spirit::rule< Scanner > skip_rule;
  }; // class definition
}; // class SkipGrammar



template< class T >
T const &as_const( T const &x )
{
  return x;
}



int main()
{
  std::string str( "cos( 0 );           # 1.0\n"
                   "log( 2, sin( 0 ) ); # 0.0\n"
                   "func();             # no arguments" );
  Grammar g;
  SkipGrammar skip_g;
  spirit::tree_parse_info< std::string::const_iterator >
    info = spirit::ast_parse( as_const( str ).begin()
                            , as_const( str ).end()
                            , g
                            , skip_g );

  if( info.full ){
    spirit::tree_to_xml( std::cout
                       , info.trees
                       , str
                       , g.getRuleNameMap() );
  }
  else{
    std::cout << "failed to parse" << std::endl;
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}