+
+ static void parse_groups(const std::string & str,
+ std::map<int, std::string> & groups_bynum,
+ std::map<std::string, int> & groups_byname)
+ {
+ int gnum = 0;
+ bool esc = false;
+ for (int i = 0; i < str.size(); ++i)
+ {
+ if (!esc && str[i] == '\\')
+ {
+ esc = true;
+ continue;
+ }
+ if (!esc && str[i] == '(') //group starts
+ {
+ gnum++;
+ if (i+1 < str.size() && str[i+1] == '?') //group with attrs
+ {
+ i++;
+ if (i+1 < str.size() && str[i+1] == 'P') //optional, python
+ i++;
+ if (i+1 < str.size() && str[i+1] == '<') //named
+ {
+ i++;
+ std::string gname;
+ bool term = false;
+ while (++i < str.size())
+ {
+ if (str[i] == '>') { term = true; break; }
+ if (!isalnum(str[i]))
+ throw mp::filter::FilterException
+ ("Only alphanumeric chars allowed, found "
+ " in '"
+ + str
+ + "' at "
+ + boost::lexical_cast<std::string>(i));
+ gname += str[i];
+ }
+ if (!term)
+ throw mp::filter::FilterException
+ ("Unterminated group name '" + gname
+ + " in '" + str +"'");
+ groups_bynum[gnum] = gname;
+ groups_byname[gname] = gnum;
+ std::cout << "Found named group '" << gname
+ << "' at $" << gnum << std::endl;
+ }
+ }
+ }
+ esc = false;
+ }
+ }
+
+ static std::string sub_vars (const std::string & in,
+ const std::map<std::string, std::string> & vars)
+ {
+ std::string out;
+ bool esc = false;
+ for (int i = 0; i < in.size(); ++i)
+ {
+ if (!esc && in[i] == '\\')
+ {
+ esc = true;
+ continue;
+ }
+ if (!esc && in[i] == '$') //var
+ {
+ if (i+1 < in.size() && in[i+1] == '{') //ref prefix
+ {
+ ++i;
+ std::string name;
+ bool term = false;
+ while (++i < in.size())
+ {
+ if (in[i] == '}') { term = true; break; }
+ name += in[i];
+ }
+ if (!term) throw mp::filter::FilterException
+ ("Unterminated var ref in '"+in+"' at "
+ + boost::lexical_cast<std::string>(i));
+ std::map<std::string, std::string>::const_iterator it
+ = vars.find(name);
+ if (it != vars.end())
+ out += it->second;
+ }
+ else
+ {
+ throw mp::filter::FilterException
+ ("Malformed or trimmed var ref in '"
+ +in+"' at "+boost::lexical_cast<std::string>(i));
+ }
+ continue;
+ }
+ //passthru
+ out += in[i];
+ esc = false;
+ }
+ return out;
+ }