Ваше описание немного сбивает с толку (например, вы упоминаете «разделены двоеточием», но я не вижу двоеточий во входных данных). Я предполагаю, что вы предполагаете, что элементы в квадратных скобках являются необязательными параметрами, в скобках - обязательными параметрами, а в фигурных скобках - «данными».
В этом случае кажется, что ваша грамматика выглядит примерно так:
func: name optionalParams '(' paramList ')' '{' data '}'
paramList: param |
paramlist ',' param
optionalParams: // empty
| '[' paramList ']'
name: WORD
param: WORD
data: WORD
Это достаточно простая грамматика, и Дух, вероятно, будет с ней работать очень хорошо. Spirit имеет тенденцию приводить к очень длинному времени компиляции для больших грамматик, но эта грамматика достаточно мала, чтобы время компиляции было вполне разумным.
Очевидной альтернативой было бы написать вместо этого анализатор спуска (как рекурсивный анализатор спуска, но в этом случае рекурсия не понадобится). В этом случае вы в основном пишете функцию для каждого уровня грамматики, читаете соответствующий ввод и возвращаете структуру (например, вектор), содержащую прочитанные данные. Например, optionalParams
, вероятно, наиболее сложный для анализа (просто потому, что он необязательный):
typedef std::string param;
std::vector<param> read_optional_params(std::istream &in) {
std::vector<param> ret;
char ch = in.peek();
if (ch == '[' ) {
in >> ch;
param temp;
while (in >> temp && temp != "]")
ret.push_back(temp);
if ((ch=in.peek) == ',')
in >> ch;
}
return ret;
}
На верхнем уровне у вас будет что-то вроде:
function read_func(std::istream &in) {
std::string name = read_name(in);
std::vector<param> optional_params = read_optional_params(in);
std::vector<param> mandatory_params = read_mandatory_params(in);
std::string data = read_data(in);
if (in.fail()) {
// malformed input
}
function func = function(name);
for (int i=0; i<optional_params.size(); i++)
func.addOptionalParam(optional_params[i]);
for (int i=0; i<mandatory_params.size(); i++)
func.addMandatoryParam(mandatoryParams[i]);
func.setData(data);
return func;
}