Warning, file /education/cantor/src/backends/julia/juliahighlighter.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-License-Identifier: GPL-2.0-or-later 0003 SPDX-FileCopyrightText: 2016 Ivan Lakhtanov <ivan.lakhtanov@gmail.com> 0004 */ 0005 0006 #include "juliahighlighter.h" 0007 #include "juliakeywords.h" 0008 #include "juliasession.h" 0009 0010 #include <climits> 0011 #include <QTextEdit> 0012 #include <QDebug> 0013 0014 JuliaHighlighter::JuliaHighlighter(QObject *parent, JuliaSession* session) 0015 : Cantor::DefaultHighlighter(parent, session) 0016 { 0017 addKeywords(JuliaKeywords::instance()->keywords()); 0018 addVariables(JuliaKeywords::instance()->variables()); 0019 addFunctions(JuliaKeywords::instance()->functions()); 0020 } 0021 0022 void JuliaHighlighter::highlightBlock(const QString &text) 0023 { 0024 if (skipHighlighting(text)) { 0025 return; 0026 } 0027 0028 // Do some backend independent highlighting (brackets etc.) 0029 DefaultHighlighter::highlightBlock(text); 0030 0031 // Now we are about to make correct strings and comments highlighting 0032 // 0033 // Main idea: as soon as string starts comment or anything else cant start 0034 // until current string ends. The same with comment, except '#' comment 0035 // that ends by newline 0036 // 0037 // To pass information to next block, we are using next states 0038 const int IN_MULTILINE_COMMENT = 1; 0039 const int IN_CHARACTER = 2; 0040 const int IN_SINGLE_QUOTE_STRING = 4; 0041 const int IN_TRIPLE_QUOTE_STRING = 8; 0042 0043 // Markers of scopes start, ends 0044 static const QRegularExpression multiLineCommentStart(QStringLiteral("#=")); 0045 static const QRegularExpression multiLineCommentEnd(QStringLiteral("=#")); 0046 static const QRegularExpression characterStartEnd(QStringLiteral("'")); 0047 static const QRegularExpression singleQuoteStringStartEnd(QStringLiteral("\"")); 0048 static const QRegularExpression tripleQuoteStringStartEnd(QStringLiteral("\"\"\"")); 0049 static const QRegularExpression singleLineCommentStart(QStringLiteral("#(?!=)")); 0050 0051 // Get current state 0052 int state = previousBlockState(); 0053 if (state == -1) { 0054 state = 0; 0055 } 0056 0057 // This 4 arrays establish matching between state, start marker, end marker 0058 // and format to apply 0059 QList<int> flags = { 0060 IN_TRIPLE_QUOTE_STRING, 0061 IN_SINGLE_QUOTE_STRING, 0062 IN_CHARACTER, 0063 IN_MULTILINE_COMMENT 0064 }; 0065 const QVector<QRegularExpression> regexps_starts = { 0066 tripleQuoteStringStartEnd, 0067 singleQuoteStringStartEnd, 0068 characterStartEnd, 0069 multiLineCommentStart 0070 }; 0071 const QVector<QRegularExpression> regexps_ends = { 0072 tripleQuoteStringStartEnd, 0073 singleQuoteStringStartEnd, 0074 characterStartEnd, 0075 multiLineCommentEnd 0076 }; 0077 QList<QTextCharFormat> formats = { 0078 stringFormat(), 0079 stringFormat(), 0080 stringFormat(), 0081 commentFormat() 0082 }; 0083 0084 int pos = 0; // current position in block 0085 while (pos < text.length()) { 0086 // Trying to close current environments 0087 bool triggered = false; 0088 for (int i = 0; i < flags.size() && !triggered; i++) { 0089 int flag = flags[i]; 0090 QTextCharFormat &format = formats[i]; 0091 if (state & flag) { // Found current state 0092 // find where end marker is 0093 const QRegularExpressionMatch match = regexps_ends.at(i).match(text, pos); 0094 const int new_pos = match.capturedStart(0); 0095 int length; 0096 if (new_pos == -1) { 0097 // not in this block, highlight till the end 0098 length = text.length() - pos; 0099 } else { 0100 // highlight untill the marker and modify state 0101 length = new_pos - pos + match.capturedLength(0); 0102 state -= flag; 0103 } 0104 // Apply format to the found area 0105 setFormat(pos, length, format); 0106 pos = pos + length; 0107 triggered = true; 0108 } 0109 } 0110 if (triggered) { // We have done something move to next iteration 0111 continue; 0112 } 0113 0114 // Now we should found the scope that start the closest to current 0115 // position 0116 QRegularExpressionMatch match; // closest marker 0117 int minPos = INT_MAX; // closest pos 0118 int minIdx = -1; // closest scope index 0119 for (int i = 0; i < regexps_starts.size(); i++) { 0120 match = regexps_starts.at(i).match(text, pos); 0121 const int newPos = match.capturedStart(0); 0122 if (newPos != -1) { 0123 minPos = qMin(minPos, newPos); 0124 minIdx = i; 0125 } 0126 } 0127 0128 // Check where single line comment starts 0129 const int singleLineCommentStartPos = text.indexOf(singleLineCommentStart, pos); 0130 0131 if (singleLineCommentStartPos != -1 0132 && singleLineCommentStartPos < minPos) { 0133 // single line comment starts earlier 0134 setFormat(singleLineCommentStartPos, text.length() - singleLineCommentStartPos, commentFormat()); 0135 break; 0136 } else if (match.hasMatch()) { 0137 // We are going to another scope 0138 state += flags[minIdx]; 0139 pos = minPos + match.capturedLength(0); 0140 setFormat(minPos, match.capturedLength(0), formats[minIdx]); 0141 } else { // There is nothing to highlight 0142 break; 0143 } 0144 } 0145 0146 setCurrentBlockState(state); 0147 } 0148 0149 QString JuliaHighlighter::nonSeparatingCharacters() const 0150 { 0151 return QLatin1String("[\\w¡-ﻼ!]"); 0152 }