まず、サポートする構文を書き留めてから、それをサポートするコードを書きます。
そのためには、BNF 表記を使用すると便利です。また、コード部分に Spirit ライブラリを使用するのは非常に簡単です。
Command := ACommand | BCommand
ACommand := 'A' AOperation
AOperation := 'some_operation' | 'some_other_operation'
BCommand := 'B' BOperation
BOperation := 'some_operation_for_B' | 'some_other_operation_for_B'
これは簡単に Spirit パーサーに変換されます。すべてのプロダクション ルールはワンライナーになり、すべての終了記号は関数に変換されます。
#include "stdafx.h"
#include <boost/spirit/core.hpp>
#include <iostream>
#include <string>
using namespace std;
using namespace boost::spirit;
namespace {
void AOperation(char const*, char const*) { cout << "AOperation\n"; }
void AOtherOperation(char const*, char const*) { cout << "AOtherOperation\n"; }
void BOperation(char const*, char const*) { cout << "BOperation\n"; }
void BOtherOperation(char const*, char const*) { cout << "BOtherOperation\n"; }
}
struct arguments : public grammar<arguments>
{
template <typename ScannerT>
struct definition
{
definition(arguments const& /*self*/)
{
command
= acommand | bcommand;
acommand = chlit<char>('A')
>> ( a_someoperation | a_someotheroperation );
a_someoperation = str_p( "some_operation" ) [ &AOperation ];
a_someotheroperation = str_p( "some_other_operation" )[ &AOtherOperation ];
bcommand = chlit<char>('B')
>> ( b_someoperation | b_someotheroperation );
b_someoperation = str_p( "some_operation_for_B" ) [ &BOperation ];
b_someotheroperation = str_p( "some_other_operation_for_B" )[ &BOtherOperation ];
}
rule<ScannerT> command;
rule<ScannerT> acommand, bcommand;
rule<ScannerT> a_someoperation, a_someotheroperation;
rule<ScannerT> b_someoperation, b_someotheroperation;
rule<ScannerT> const&
start() const { return command; }
};
};
template<typename parse_info >
bool test( parse_info pi ) {
if( pi.full ) {
cout << "success" << endl;
return true;
} else {
cout << "fail" << endl;
return false;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
arguments args;
test( parse( "A some_operation", args, space_p ) );
test( parse( "A some_other_operation", args, space_p ) );
test( parse( "B some_operation_for_B", args, space_p ) );
test( parse( "B some_other_operation_for_B", args, space_p ) );
test( parse( "A some_other_operation_for_B", args, space_p ) );
return 0;
}