I think the key here is recursion.
Addressing the nested part of your grammar (handling repetition, and minor details like uppercase, is left has an exercise ;-) ),
we can write:
expr := num '(' left expr right ')'
| empty;
where
num is a sequence of (one or more) digits while
left and
right are sequences of (zero or more) letters.
We may write something like the following code:
#include <iostream>
using namespace std;
struct Exc
{
string msg;
size_t pos;
};
bool get_num( const string & input, size_t & pos, size_t & num )
{
num = 0;
bool result = false;
while ( pos < input.length() && input[pos] >= '0' && input[pos] <= '9')
{
result = true;
num = num * 10 + (input[pos] - '0');
++pos;
}
return result;
}
bool get_lbrace( const string & input, size_t & pos )
{
if ( pos >= input.length() || input[pos] != '(') return false;
++pos;
return true;
}
bool get_rbrace( const string & input, size_t & pos )
{
if ( pos >= input.length() || input[pos] != ')') return false;
++pos;
return true;
}
bool get_alpha( const string & input, size_t & pos, string & alpha)
{
bool result = false;
alpha = "";
while ( pos < input.length() && input[pos] >='a' && input[pos] <='z')
{
result = true;
alpha += input[pos];
++pos;
}
return result;
}
void expr( string & input, size_t & pos)
{
size_t num;
string left = "";
string right = "";
if ( ! get_num( input, pos, num )) return;
size_t bkpos = pos;
for (size_t n=0; n<num; ++n)
{
pos = bkpos;
if ( ! get_lbrace( input, pos ))
{
Exc exc = {"missing left brace", pos};
throw exc;
}
get_alpha( input, pos, left );
cout << left;
expr(input, pos);
get_alpha(input, pos, right);
cout << right;
if ( ! get_rbrace( input, pos))
{
Exc exc = {"missing right brace", pos};
throw exc;
}
}
}
int main()
{
string myexpr = "12(a3(b2(ywz))c)";
size_t pos = 0;
try
{
expr( myexpr, pos);
}
catch( Exc exc )
{
cerr << endl << exc.msg << " at " << exc.pos << endl;
}
cout << endl;
}