File indexing completed on 2024-04-14 05:44:24
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 "emacsregexpconverter.h" 0008 0009 #include <KLocalizedString> 0010 #include <KMessageBox> 0011 0012 #include "altnregexp.h" 0013 #include "compoundregexp.h" 0014 #include "concregexp.h" 0015 #include "positionregexp.h" 0016 #include "regexp.h" 0017 #include "repeatregexp.h" 0018 #include "textrangeregexp.h" 0019 #include "textregexp.h" 0020 0021 bool EmacsRegExpConverter::canParse() 0022 { 0023 return false; 0024 } 0025 0026 QString EmacsRegExpConverter::toString(AltnRegExp *regexp, bool markSelection) 0027 { 0028 QString res; 0029 0030 bool first = true; 0031 const RegExpList children = regexp->children(); 0032 for (RegExp *child : children) { 0033 if (!first) { 0034 res += QLatin1String("\\|"); 0035 } 0036 first = false; 0037 res += toStr(child, markSelection); 0038 } 0039 0040 return res; 0041 } 0042 0043 QString EmacsRegExpConverter::toString(ConcRegExp *regexp, bool markSelection) 0044 { 0045 QString res; 0046 0047 const RegExpList children = regexp->children(); 0048 for (RegExp *child : children) { 0049 QString startPar; 0050 QString endPar; 0051 if (child->precedence() < regexp->precedence()) { 0052 startPar = QStringLiteral("\\("); 0053 endPar = QStringLiteral("\\)"); 0054 } 0055 0056 res += startPar + toStr(child, markSelection) + endPar; 0057 } 0058 0059 return res; 0060 } 0061 0062 QString EmacsRegExpConverter::toString(LookAheadRegExp * /*regexp*/, bool /*markSelection*/) 0063 { 0064 static bool haveWarned = false; 0065 if (!haveWarned) { 0066 KMessageBox::error(nullptr, i18n("Look ahead regular expressions not supported in Emacs style")); 0067 haveWarned = true; 0068 } 0069 0070 return QString(); 0071 } 0072 0073 QString EmacsRegExpConverter::toString(TextRangeRegExp *regexp, bool /*markSelection*/) 0074 { 0075 QString txt; 0076 0077 bool foundCarrot = false; 0078 bool foundDash = false; 0079 bool foundParenthesis = false; 0080 0081 // print the single characters, but keep "^" as the very 0082 // last element of the characters. 0083 QStringList chars = regexp->chars(); 0084 for (int i = 0; i < chars.count(); i++) { 0085 if (chars.at(i).at(0) == QLatin1Char(']')) { 0086 foundParenthesis = true; 0087 } else if (chars.at(i).at(0) == QLatin1Char('-')) { 0088 foundDash = true; 0089 } else if (chars.at(i).at(0) == QLatin1Char('^')) { 0090 foundCarrot = true; 0091 } else { 0092 txt.append(chars.at(i).at(0)); 0093 } 0094 } 0095 0096 // Now insert the ranges. 0097 const auto range = regexp->range(); 0098 for (const StringPair &elm : range) { 0099 txt.append(elm.first + QLatin1Char('-') + elm.second); 0100 } 0101 0102 // Ok, its time to build each part of the regexp, here comes the rule: 0103 // if a ']' is one of the characters, then it must be the first one in the 0104 // list (after then opening '[' and eventually negation '^') 0105 // Next if a '-' is one of the characters, then it must come 0106 // finally if '^' is one of the characters, then it must not be the first 0107 // one! 0108 0109 QString res = QStringLiteral("["); 0110 0111 if (regexp->negate()) { 0112 res.append(QLatin1String("^")); 0113 } 0114 0115 // a ']' must be the first character in teh range. 0116 if (foundParenthesis) { 0117 res.append(QLatin1String("]")); 0118 } 0119 0120 // a '-' must be the first character ( only coming after a ']') 0121 if (foundDash) { 0122 res.append(QLatin1String("-")); 0123 } 0124 0125 res += txt; 0126 0127 // Insert equivalents to \s,\S,\d,\D,\w, and \W 0128 // non-digit, non-space, and non-word is not supported in Emacs style 0129 if (regexp->digit()) { 0130 res += QStringLiteral("0-9"); 0131 } 0132 0133 if (regexp->space()) { 0134 res += QLatin1Char(' ') + QLatin1Char((char)9); // Tab char 0135 } 0136 0137 if (regexp->wordChar()) { 0138 res += QStringLiteral("a-zA-Z"); 0139 } 0140 0141 if (foundCarrot) { 0142 res.append(QLatin1Char('^')); 0143 } 0144 0145 res.append(QLatin1Char(']')); 0146 0147 return res; 0148 } 0149 0150 QString EmacsRegExpConverter::toString(CompoundRegExp *regexp, bool markSelection) 0151 { 0152 return toStr(regexp->child(), markSelection); 0153 } 0154 0155 QString EmacsRegExpConverter::toString(DotRegExp * /*regexp*/, bool /*markSelection*/) 0156 { 0157 return QStringLiteral("."); 0158 } 0159 0160 QString EmacsRegExpConverter::toString(PositionRegExp *regexp, bool /*markSelection*/) 0161 { 0162 static bool haveWarned = false; 0163 switch (regexp->position()) { 0164 case PositionRegExp::BEGLINE: 0165 return QStringLiteral("^"); 0166 case PositionRegExp::ENDLINE: 0167 return QStringLiteral("$"); 0168 case PositionRegExp::WORDBOUNDARY: 0169 case PositionRegExp::NONWORDBOUNDARY: 0170 if (!haveWarned) { 0171 KMessageBox::error(nullptr, i18n("Word boundary and non word boundary is not supported in Emacs syntax")); 0172 haveWarned = true; 0173 return QString(); 0174 } 0175 } 0176 return QString(); 0177 } 0178 0179 QString EmacsRegExpConverter::toString(RepeatRegExp *regexp, bool markSelection) 0180 { 0181 RegExp *child = regexp->child(); 0182 QString cText = toStr(child, markSelection); 0183 QString startPar; 0184 QString endPar; 0185 0186 if (child->precedence() < regexp->precedence()) { 0187 startPar = QStringLiteral("\\("); 0188 endPar = QStringLiteral("\\)"); 0189 } 0190 0191 if (regexp->min() == 0 && regexp->max() == -1) { 0192 return startPar + cText + endPar + QStringLiteral("*"); 0193 } else if (regexp->min() == 0 && regexp->max() == 1) { 0194 return startPar + cText + endPar + QStringLiteral("?"); 0195 } else if (regexp->min() == 1 && regexp->max() == -1) { 0196 return startPar + cText + endPar + QStringLiteral("+"); 0197 } else { 0198 QString res = QString(); 0199 for (int i = 0; i < regexp->min(); ++i) { 0200 res += QStringLiteral("\\(") + cText + QStringLiteral("\\)"); 0201 } 0202 if (regexp->max() != -1) { 0203 for (int i = regexp->min(); i < regexp->max(); ++i) { 0204 res += QStringLiteral("\\(") + cText + QStringLiteral("\\)?"); 0205 } 0206 } else { 0207 res += QLatin1String("+"); 0208 } 0209 0210 return res; 0211 } 0212 } 0213 0214 QString EmacsRegExpConverter::toString(TextRegExp *regexp, bool /*markSelection*/) 0215 { 0216 QList<QChar> list; 0217 list << QLatin1Char('$') << QLatin1Char('^') << QLatin1Char('.') << QLatin1Char('*') << QLatin1Char('+') << QLatin1Char('?') << QLatin1Char('[') 0218 << QLatin1Char(']') << QLatin1Char('\\'); 0219 0220 QString res = escape(regexp->text(), list, QLatin1Char('\\')); 0221 return res; 0222 } 0223 0224 QString EmacsRegExpConverter::name() 0225 { 0226 return QStringLiteral("Emacs"); 0227 } 0228 0229 int EmacsRegExpConverter::features() 0230 { 0231 return WordStart | WordEnd; 0232 }