int RegularExpression::match(const std::string& subject, std::string::size_type offset, Match& mtch, int options) const { poco_assert (offset <= subject.length()); int ovec[OVEC_SIZE]; int rc = pcre_exec(_pcre, _extra, subject.c_str(), int(subject.size()), int(offset), options & 0xFFFF, ovec, OVEC_SIZE); if (rc == PCRE_ERROR_NOMATCH) { mtch.offset = std::string::npos; mtch.length = 0; return 0; } else if (rc == PCRE_ERROR_BADOPTION) { throw RegularExpressionException("bad option"); } else if (rc == 0) { throw RegularExpressionException("too many captured substrings"); } else if (rc < 0) { std::ostringstream msg; msg << "PCRE error " << rc; throw RegularExpressionException(msg.str()); } mtch.offset = ovec[0] < 0 ? std::string::npos : ovec[0]; mtch.length = ovec[1] - mtch.offset; return rc; }
RegularExpression::RegularExpression(const std::string& pattern, int options, bool study): _pcre(0), _extra(0) { const char* error; int offs; _pcre = pcre_compile(pattern.c_str(), options, &error, &offs, 0); if (!_pcre) { std::ostringstream msg; msg << error << " (at offset " << offs << ")"; throw RegularExpressionException(msg.str()); } if (study) _extra = pcre_study(_pcre, 0, &error); }
int RegularExpression::match(const std::string& subject, std::string::size_type offset, MatchVec& matches, int options) const { poco_assert (offset <= subject.length()); matches.clear(); int ovec[OVEC_SIZE]; int rc = pcre_exec(_pcre, _extra, subject.c_str(), int(subject.size()), int(offset), options & 0xFFFF, ovec, OVEC_SIZE); if (rc == PCRE_ERROR_NOMATCH) { return 0; } else if (rc == PCRE_ERROR_BADOPTION) { throw RegularExpressionException("bad option"); } else if (rc == 0) { throw RegularExpressionException("too many captured substrings"); } else if (rc < 0) { std::ostringstream msg; msg << "PCRE error " << rc; throw RegularExpressionException(msg.str()); } matches.reserve(rc); for (int i = 0; i < rc; ++i) { Match m; m.offset = ovec[i*2] < 0 ? std::string::npos : ovec[i*2] ; m.length = ovec[i*2 + 1] - m.offset; matches.push_back(m); } return rc; }
/// <summary>Parses all the keywords/macros in a string and replaces them recursively</summary> /// <param name="text">Source text to parse</param> /// <param name="depth">Debugging output depth</param> /// <returns>Fully parsed text</returns> /// <exception cref="Logic::FileFormatException">Macro contains wrong number of parameters</exception> /// <exception cref="Logic::Language::RegularExpressionException">RegEx error</exception> wstring DescriptionParser::Parse(wstring text, int depth) const { UINT Position; wsmatch match; wstring r; try { #ifdef PRINT_CONSOLE Console << Cons::Cyan << Indent(depth) << "Parsing: " << Cons::White << text << ENDL; #endif // Find/Replace all macros: {AAAA:bbb}, {AAAA:bbb,ccc}, {AAAA:bbb,ccc,ddd} ... for (Position = 0; regex_search(text.cbegin()+Position, text.cend(), match, MatchMacro); ) // Manually track position for in-place replacement + avoid infinite loop { // Recursively generate replacement text r = onMatchMacro(match, depth); #ifdef PRINT_CONSOLE Console << Indent(depth) << "Replacing text: " << Cons::Yellow << match[0].str() << Cons::White << " with " << Cons::Green << r << ENDL; #endif // Advance position to beyond inserted text, and insert text Position = (match[0].first - text.cbegin()) + r.length(); text.replace(match[0].first, match[0].second, r); } // Find/Replace all keywords: {AAAAA}, AAAAA for (Position = 0; regex_search(text.cbegin()+Position, text.cend(), match, MatchKeyword); ) { // Recursively generate replacement text r = onMatchKeyword(match, depth); #ifdef PRINT_CONSOLE Console << Indent(depth) << "Replacing text: " << Cons::Yellow << match[0].str() << Cons::White << " with " << Cons::Green << r << ENDL; #endif // Advance position to beyond inserted text, and insert text Position = (match[0].first - text.cbegin()) + r.length(); text.replace(match[0].first, match[0].second, r); } return text; } catch (regex_error& e) { throw RegularExpressionException(HERE, e); } }
std::string::size_type RegularExpression::substOne(std::string& subject, std::string::size_type offset, const std::string& replacement, int options) const { if (offset >= subject.length()) return std::string::npos; int ovec[OVEC_SIZE]; int rc = pcre_exec(_pcre, _extra, subject.c_str(), int(subject.size()), int(offset), options & 0xFFFF, ovec, OVEC_SIZE); if (rc == PCRE_ERROR_NOMATCH) { return std::string::npos; } else if (rc == PCRE_ERROR_BADOPTION) { throw RegularExpressionException("bad option"); } else if (rc == 0) { throw RegularExpressionException("too many captured substrings"); } else if (rc < 0) { std::ostringstream msg; msg << "PCRE error " << rc; throw RegularExpressionException(msg.str()); } std::string result; std::string::size_type len = subject.length(); std::string::size_type pos = 0; std::string::size_type rp = std::string::npos; while (pos < len) { if (ovec[0] == pos) { std::string::const_iterator it = replacement.begin(); std::string::const_iterator end = replacement.end(); while (it != end) { if (*it == '$' && !(options & RE_NO_VARS)) { ++it; if (it != end) { char d = *it; if (d >= '0' && d <= '9') { int c = d - '0'; if (c < rc) { int o = ovec[c*2]; int l = ovec[c*2 + 1] - o; result.append(subject, o, l); } } else { result += '$'; result += d; } ++it; } else result += '$'; } else result += *it++; } pos = ovec[1]; rp = result.length(); } else result += subject[pos++]; } subject = result; return rp; }