File indexing completed on 2024-03-24 05:54:38
0001 /* 0002 * SPDX-FileCopyrightText: 2002-2004 Jesper K. Pedersen <blackie@kde.org> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-only 0005 **/ 0006 0007 #include "qtregexpconverter.h" 0008 0009 #include "altnregexp.h" 0010 #include "compoundregexp.h" 0011 #include "concregexp.h" 0012 #include "dotregexp.h" 0013 #include "lookaheadregexp.h" 0014 #include "positionregexp.h" 0015 #include "qtregexphighlighter.h" 0016 #include "regexp.h" 0017 #include "repeatregexp.h" 0018 #include "textrangeregexp.h" 0019 #include "textregexp.h" 0020 0021 extern RegExp *parseQtRegExp(const QString &qstr, bool *ok); 0022 0023 bool QtRegExpConverter::canParse() 0024 { 0025 return true; 0026 } 0027 0028 RegExp *QtRegExpConverter::parse(const QString &txt, bool *ok) 0029 { 0030 return parseQtRegExp(txt, ok); 0031 } 0032 0033 QString QtRegExpConverter::toString(AltnRegExp *regexp, bool markSelection) 0034 { 0035 QString res; 0036 0037 bool first = true; 0038 const RegExpList list = regexp->children(); 0039 for (RegExp *r : list) { 0040 if (!first) { 0041 res += QLatin1String("|"); 0042 } 0043 0044 first = false; 0045 if (markSelection && !regexp->isSelected() && r->isSelected()) { 0046 res += QStringLiteral("(") + toStr(r, markSelection) + QStringLiteral(")"); 0047 } else { 0048 res += toStr(r, markSelection); 0049 } 0050 } 0051 return res; 0052 } 0053 0054 QString QtRegExpConverter::toString(ConcRegExp *regexp, bool markSelection) 0055 { 0056 QString res; 0057 bool childSelected = false; 0058 0059 const auto children = regexp->children(); 0060 for (const auto child : children) { 0061 QString startPar; 0062 QString endPar; 0063 if (child->precedence() < regexp->precedence()) { 0064 if (markSelection) { 0065 startPar = QStringLiteral("(?:"); 0066 } else { 0067 startPar = QStringLiteral("("); 0068 } 0069 endPar = QStringLiteral(")"); 0070 } 0071 0072 // Note these two have different tests! They are activated in each their iteration of the loop. 0073 if (markSelection && !childSelected && !regexp->isSelected() && child->isSelected()) { 0074 res += QLatin1String("("); 0075 childSelected = true; 0076 } 0077 0078 if (markSelection && childSelected && !regexp->isSelected() && !child->isSelected()) { 0079 res += QLatin1String(")"); 0080 childSelected = false; 0081 } 0082 0083 res += startPar + toStr(child, markSelection) + endPar; 0084 } 0085 if (markSelection && childSelected && !regexp->isSelected()) { 0086 res += QLatin1String(")"); 0087 } 0088 return res; 0089 } 0090 0091 QString QtRegExpConverter::toString(LookAheadRegExp *regexp, bool markSelection) 0092 { 0093 if (regexp->lookAheadType() == LookAheadRegExp::POSITIVE) { 0094 return QStringLiteral("(?=") + toStr(regexp->child(), markSelection) + QStringLiteral(")"); 0095 } else { 0096 return QStringLiteral("(?!") + toStr(regexp->child(), markSelection) + QStringLiteral(")"); 0097 } 0098 } 0099 0100 QString QtRegExpConverter::toString(TextRangeRegExp *regexp, bool /*markSelection*/) 0101 { 0102 QString txt; 0103 0104 bool foundCarrot = false; 0105 bool foundDash = false; 0106 bool foundParenthesis = false; 0107 0108 // Now print the rest of the single characters, but keep "^" as the very 0109 // last element of the characters. 0110 QStringList chars = regexp->chars(); 0111 for (int i = 0; i < chars.count(); i++) { 0112 if (chars.at(i).at(0) == QLatin1Char(']')) { 0113 foundParenthesis = true; 0114 } else if (chars.at(i).at(0) == QLatin1Char('-')) { 0115 foundDash = true; 0116 } else if (chars.at(i).at(0) == QLatin1Char('^')) { 0117 foundCarrot = true; 0118 } else { 0119 txt.append(chars.at(i).at(0)); 0120 } 0121 } 0122 0123 // Now insert the ranges. 0124 const auto range = regexp->range(); 0125 for (const StringPair &elm : range) { 0126 txt.append(elm.first + QLatin1Char('-') + elm.second); 0127 } 0128 0129 // Ok, its time to build each part of the regexp, here comes the rule: 0130 // if a ']' is one of the characters, then it must be the first one in the 0131 // list (after then opening '[' and eventually negation '^') 0132 // Next if a '-' is one of the characters, then it must come 0133 // finally if '^' is one of the characters, then it must not be the first 0134 // one! 0135 0136 QString res = QStringLiteral("["); 0137 0138 if (regexp->negate()) { 0139 res.append(QLatin1String("^")); 0140 } 0141 0142 // a ']' must be the first character in teh range. 0143 if (foundParenthesis) { 0144 res.append(QLatin1String("]")); 0145 } 0146 0147 // a '-' must be the first character ( only coming after a ']') 0148 if (foundDash) { 0149 res.append(QLatin1String("-")); 0150 } 0151 0152 res += txt; 0153 0154 // Insert \s,\S,\d,\D,\w, and \W 0155 if (regexp->digit()) { 0156 res += QStringLiteral("\\d"); 0157 } 0158 0159 if (regexp->nonDigit()) { 0160 res += QStringLiteral("\\D"); 0161 } 0162 0163 if (regexp->space()) { 0164 res += QStringLiteral("\\s"); 0165 } 0166 0167 if (regexp->nonSpace()) { 0168 res += QStringLiteral("\\S"); 0169 } 0170 0171 if (regexp->wordChar()) { 0172 res += QStringLiteral("\\w"); 0173 } 0174 0175 if (regexp->nonWordChar()) { 0176 res += QStringLiteral("\\W"); 0177 } 0178 0179 if (foundCarrot) { 0180 res.append(QLatin1Char('^')); 0181 } 0182 0183 res.append(QLatin1String("]")); 0184 0185 return res; 0186 } 0187 0188 QString QtRegExpConverter::toString(CompoundRegExp *regexp, bool markSelection) 0189 { 0190 if (markSelection && !regexp->isSelected() && regexp->child()->isSelected()) { 0191 return QStringLiteral("(") + toStr(regexp->child(), markSelection) + QStringLiteral(")"); 0192 } else { 0193 return toStr(regexp->child(), markSelection); 0194 } 0195 } 0196 0197 QString QtRegExpConverter::toString(DotRegExp * /*regexp*/, bool /*markSelection*/) 0198 { 0199 return QStringLiteral("."); 0200 } 0201 0202 QString QtRegExpConverter::toString(PositionRegExp *regexp, bool /*markSelection*/) 0203 { 0204 switch (regexp->position()) { 0205 case PositionRegExp::BEGLINE: 0206 return QStringLiteral("^"); 0207 case PositionRegExp::ENDLINE: 0208 return QStringLiteral("$"); 0209 case PositionRegExp::WORDBOUNDARY: 0210 return QStringLiteral("\\b"); 0211 case PositionRegExp::NONWORDBOUNDARY: 0212 return QStringLiteral("\\B"); 0213 } 0214 Q_ASSERT(false); 0215 return QString(); 0216 } 0217 0218 QString QtRegExpConverter::toString(RepeatRegExp *regexp, bool markSelection) 0219 { 0220 RegExp *child = regexp->child(); 0221 QString cText = toStr(child, markSelection); 0222 QString startPar; 0223 QString endPar; 0224 QString quantity; 0225 0226 if (markSelection) { 0227 if (!regexp->isSelected() && child->isSelected()) { 0228 startPar = QStringLiteral("("); 0229 endPar = QStringLiteral(")"); 0230 } else if (child->precedence() < regexp->precedence()) { 0231 startPar = QStringLiteral("(?:"); 0232 endPar = QStringLiteral(")"); 0233 } 0234 } else if (child->precedence() < regexp->precedence()) { 0235 startPar = QStringLiteral("("); 0236 endPar = QStringLiteral(")"); 0237 } 0238 0239 if (regexp->min() == 0 && regexp->max() == -1) { 0240 quantity = QStringLiteral("*"); 0241 } else if (regexp->min() == 0 && regexp->max() == 1) { 0242 quantity = QStringLiteral("?"); 0243 } else if (regexp->min() == 1 && regexp->max() == -1) { 0244 quantity = QStringLiteral("+"); 0245 } else if (regexp->max() == -1) { 0246 quantity = QStringLiteral("{") + QString::number(regexp->min()) + QStringLiteral(",") + QStringLiteral("}"); 0247 } else { 0248 quantity = QStringLiteral("{") + QString::number(regexp->min()) + QStringLiteral(",") + QString::number(regexp->max()) + QStringLiteral("}"); 0249 } 0250 0251 return startPar + cText + endPar + quantity; 0252 } 0253 0254 QString QtRegExpConverter::toString(TextRegExp *regexp, bool /*markSelection*/) 0255 { 0256 QList<QChar> list; 0257 list << QLatin1Char('$') << QLatin1Char('^') << QLatin1Char('.') << QLatin1Char('*') << QLatin1Char('+') << QLatin1Char('?') << QLatin1Char('[') 0258 << QLatin1Char(']') << QLatin1Char('\\') << QLatin1Char('{') << QLatin1Char('}') << QLatin1Char('(') << QLatin1Char(')') << QLatin1Char('|'); 0259 0260 QString res = escape(regexp->text(), list, QLatin1Char('\\')); 0261 return res; 0262 } 0263 0264 QString QtRegExpConverter::name() 0265 { 0266 return QStringLiteral("Qt"); 0267 } 0268 0269 int QtRegExpConverter::features() 0270 { 0271 return WordBoundary | NonWordBoundary | PosLookAhead | NegLookAhead | CharacterRangeNonItems | ExtRange; 0272 } 0273 0274 RegexpHighlighter *QtRegExpConverter::highlighter(QTextEdit *edit) // krazy:exclude=qclasses 0275 { 0276 return new QtRegexpHighlighter(edit); 0277 }