Boost.Spirit
is always the right way to go: you'll be benefitted by type-safety, clear parser structure and syntax.
#include <boost/spirit/home/qi.hpp>
#include <vector>
#include <string>
namespace qi = boost::spirit::qi;
using std::vector;
using namespace qi;
template <typename Iterator = std::string::const_iterator>
struct my_parser : grammar<Iterator, vector<std::string>(), blank_type>
{
my_parser(const std::string &openingDelim, const std::string &closingDelim) : my_parser::base_type(query)
{
open = openingDelim;
close = closingDelim;
beforeOpen = *(char_ - open);
afterOpen = *(char_ - close);
//when synthesizing the resulting attribute, ignore everything before openingDelim and after closingDelim
query = (omit[beforeOpen >> open] >> afterOpen >> omit[close]) % beforeOpen;
}
rule<Iterator, vector<std::string>(), blank_type> query;
rule<Iterator, std::string(), blank_type> open, close, beforeOpen, afterOpen;
};
int main()
{
my_parser<> p("$deli:", ":deli$");
std::string s("start $deli:foo:deli$ something else $deli:baa:deli$ doesnt matter");
vector<std::string> result;
bool b = phrase_parse(s.begin(), s.end(), p, blank, result);
}