QRegular expression - c++

I can't find a way to match the text before opening curly bracket (i.e. p) using regex and Qt. My input file reads :
solvers
{
p
{
solver PCG;
preconditioner DIC;
tolerance 1e-06;
relTol 0.05;
}
q
{
solver PCG;
relTol 0.03;
}
}
and corresponding code from .cpp is :
rule.pattern = QRegularExpression("\\b(\\w+)(?=[\\s+\n]?\\{)",
QRegularExpression::MultilineOption);
Is anyone with better knowledge of Qt and regex can explain to me a way to achieve that?
EDIT #1
Thanks for the reply and comment. Two things :
I mistype my input file had no ">" symbol so I edited it in the above completed input.
I was trying to match the "p" of p-block and the "q" of q-block. A more extended version of my input is now edited above.
I found \}\s*(\w+)(?=\s*\{) to matched the "q" q-block but does not work in the code.
It seems to struggle with the return to line between "p" and the bracket "{".
EDIT #2 : show the code
in highlighter.cpp
#include "highlighter.h"
Highlighter::Highlighter(QTextDocument *parent)
: QSyntaxHighlighter(parent)
{
HighlightingRule rule;
(...)
varFormat.setFontWeight(QFont::Bold);
varFormat.setForeground(Qt::darkMagenta);
rule.pattern = QRegularExpression("^\\s+(\\w+)\\s*$",QRegularExpression::MultilineOption);
rule.format = varFormat;
highlightingRules.append(rule);
(...) }
void Highlighter::highlightBlock(const QString &text)
{
foreach (const HighlightingRule &rule, highlightingRules) {
QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
while (matchIterator.hasNext()) {
QRegularExpressionMatch match = matchIterator.next();
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
}
}
setCurrentBlockState(0);
int startIndex = 0;
if (previousBlockState() != 1)
startIndex = text.indexOf(commentStartExpression);
while (startIndex >= 0) {
QRegularExpressionMatch match = commentEndExpression.match(text, startIndex);
int endIndex = match.capturedStart();
int commentLength = 0;
if (endIndex == -1) {
setCurrentBlockState(1);
commentLength = text.length() - startIndex;
} else {
commentLength = endIndex - startIndex
+ match.capturedLength();
}
setFormat(startIndex, commentLength, multiLineCommentFormat);
startIndex = text.indexOf(commentStartExpression, startIndex + commentLength);
}
}

Have a look at [\\s+\n]?, it matches 1 or 0 occurrences of any whitespace or + characters. But there are more than 1 whitespace betwee solvers and {.
Replacing (?=[\\s+\n]?\\{) with (?=\\s*{) will already fix the issue. But you may also use
QRegularExpression("^\\s*(\\w+)\\s*\\{", QRegularExpression::MultilineOption)
to match the
^ - start of a line
\\s* - 0+ whitespaces
(\\w+) - Group 1 (you can get it via match.captured(1)): one or more word chars
\\s* - 0+ whitespaces followed with
\{ - a literal {.
See the regex demo.

Because p is not after {, but is after }
You can go this way:
[\{\}]\s*(\w+)(?=\s*\{) see https://regex101.com/r/wA1vu2/3
Or this this one:
(?P<tagname>[^{}\s]*)(?P<postspace>\s*)(?P<json_item>\{[^{}]*\})
?P<tagname> name of the match
?P<json_item>\{[^{}]*\} - leaf level item
(?P<postspace>\s*) - space between leaf item and leaf name
(?P<tagname>[^{}\s]*) - leaf name
https://regex101.com/r/wA1vu2/1/

Related

Capitalize First Letter Of Each Name after Hyphen "-" and Space " "

I'm currently using this String extension to Capitalize the letter of each word in a textField :
"happy sunshine" .toTitleCase() gives "Happy Sunshine"
extension StringExtension on String {
String toTitleCase() => replaceAll(RegExp(' +'), ' ')
.split(' ')
.map((str) => str.toCapitalized())
.join(' ');
String toCapitalized() =>
length > 0 ? '${this[0].toUpperCase()}${substring(1).toLowerCase()}' : '';
}
but I'd also like to Capitalize letters that come after a hyphen - with the same toTitleCase method
ex : "very-happy sunshine" .toTitleCase() would give "Very-Happy Sunshine"
Currently .toTitleCase() gives "Very-happy Sunshine" : (
I am sure a wizard with expert knowledge in regular expression can do this better but I think this solution solves your problem:
void main() {
print('happy sunshine'.toTitleCase()); // Happy Sunshine
print('very-happy sunshine'.toTitleCase()); // Very-Happy Sunshine
}
extension StringExtension on String {
String toTitleCase() => replaceAllMapped(
RegExp(r'(?<= |-|^).'), (match) => match[0]!.toUpperCase());
}
If you call the method a lot of times, you might consider having the RegExp as a cached value like:
extension StringExtension on String {
static final RegExp _toTitleCaseRegExp = RegExp(r'(?<= |-|^).');
String toTitleCase() =>
replaceAllMapped(_toTitleCaseRegExp, (match) => match[0]!.toUpperCase());
}
You can tweak your code as well. But I've used the same thing somewhere in my project so you can do something like this as well.
Working: First I'm creating an empty array looping through each character in a particular string and checking if space (" ") and hyphen ("-") are current_position - 1 then I'm making current_position to uppercase.
String capitalize(String s) {
String result = "";
for (int i = 0; i < s.length; i++) {
if (i == 0) {
result += s[i].toUpperCase();
} else if (s[i - 1] == " ") {
result += s[i].toUpperCase();
} else if (s[i - 1] == "-") {
result += s[i].toUpperCase();
} else {
result += s[i];
}
}
return result;
}

If statement fails with regex comparison

public list[str] deleteBlockComments(list[str] fileLines)
{
bool blockComment = false;
list[str] sourceFile = [];
for(fileLine <- fileLines)
{
fileLine = trim(fileLine);
println(fileLine);
if (/^[\t]*[\/*].*$/ := fileLine)
{
blockComment = true;
}
if (/^[\t]*[*\/].*$/ := fileLine)
{
blockComment = false;
}
println(blockComment);
if(!blockComment)
{
sourceFile = sourceFile + fileLine;
}
}
return sourceFile;
}
For some reason, I am not able to detect /* at the beginning of a string. If I execute this on the command line, it seems to work fine.
Can someone tell me what I am doing wrong? In the picture below you can see the string to be compared above the comparison result (false).
[\/*] is a character set that matches forward slash or star, not both one after the other. Simply remove the square brackets and your pattern should start behaving as you expect.
While we're at it, let's also get rid of the superfluous square brackets around \t
^\t*\/*.*$

Extract strings inside double quotes with QRegularExpression

I have a string like below:
on prepareFrame
go to frame 10
goToNetPage "http://www.apple.com"
goToNetPage "http://www.cnn.com"
etc..
end
I want to extract all the urls from this string by using QRegularExpression. I've already tried:
QRegularExpression regExp("goToNetPage \"\\w+\"");
QRegularExpressionMatchIterator i = regExp.globalMatch(handler);
while (i.hasNext()) {
QRegularExpressionMatch match = i.next();
QString handler = match.captured(0);
}
But this not working.
You may use
QRegExp regExp("goToNetPage\\s*\"([^\"]+)");
QStringList MyList;
int pos = 0;
while ((pos = regExp.indexIn(handler, pos)) != -1) {
MyList << regExp.cap(1);
pos += regExp.matchedLength();
}
The pattern is
goToNetPage\s*"([^"]+)
It matches goToNetPage, 0 or more whitespace chars, " and then captures into Group 1 any 1+ chars other than " - the required value is accessed using regExp.cap(1).

condition in regular expression qt

I wrote a regular expression for find the scopes('{'|'}'). I want to find the scopes that wasn't commented, but I don't understand where I have mistake. Here are a fragment of code:
while (start >= 0 && end >=0) {
start = text.indexOf("\n", start);
end = text.indexOf(QRegExp("^.*[{](?!=[//]|[/*]|[*]))"),start);
end2 = text.indexOf(QRegExp("^.*[}](?!=[//]|[/*]|[*]))"), start);
if (end < end2) {
text.replace(end,"\n{\n");
}
else text.replace(end2,"\n}\n");
++start;
}
For example, we have some text:
//dfsdkfj ksjdfksjdf { <- this symbol should be skipped
public SystemBlock()
{ //<- this symbol should be found.
this.producer = "none";
this.motherBoard = "none";
this.processor = "none";
this.ram = "none";
this.gpu = "none";
this.price = 0;
this.eventSupport = null;
}
First of all, it is generally impossible to correctly parse C++ code with regular expressions. Think about nested comments, line continuations, strings containing "//", "/*" etc.!
Secondly, it is generally hard to have a regex not match something. See this question for more details.
But your specific example can be parsed with a regex like this: ^(?!(//|/\*))*{
:
end = text.indexOf(QRegExp("^(?!(//|/\\*))*\\{"),start);
end2 = text.indexOf(QRegExp("^(?!(//|/\\*))*\\}"), start);

Regex to replaces slashes inside of JSON

I have some JSON I am parsing that looks like this:
{
"dhkplhfnhceodhffomolpfigojocbpcb": {
"external_crx": "C:\Program Files\Babylon\Babylon-Pro\Utils\BabylonChrome.crx",
"external_version": "1.1"
}
}
Unfortunately, JSON.NET does gives me an error because of the single slashes. Is there a way to either allow single slashes? If not, what is a Regex I can use to double slash the filepath in a safe way with out messing up other entries that might have the correct double slash?
Update The error (using JsonTextReader) is "Bad JSON escape sequence: \P. Line 4, position 25." It turns out there is more that meets the eye on this issue, because the backslash is there to support hex and octal values (http://json.codeplex.com/discussions/244265). How will I know when I'm looking at a hex/octal and not just a filepath backslash that someone forgot to double backslash?
case 'u':
// ...
case 'x':
hexValues = new char[2];
for (int i = 0; i < hexValues.Length; i++)
{
if ((currentChar = MoveNext()) != '\0' || !_end)
hexValues[i] = currentChar;
else
throw CreateJsonReaderException("Unexpected end while parsing unicode character. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
}
hexChar = Convert.ToChar(int.Parse(new string(hexValues), NumberStyles.HexNumber, NumberFormatInfo.InvariantInfo));
_buffer.Append(hexChar);
break;
default:
var octValues = new char[3];
var octLength = 0;
for (int i = 0; i < octValues.Length; i++)
{
var octalChar = i==0 ? currentChar : PeekNext();
if ((octalChar > 1 || !_end) && octalChar>='0' && octalChar<'8')
{
octValues[i] = (char)octalChar;
if(i!=0) MoveNext();
octLength++;
}
else
{
break;
}
}
if (octLength>0)
{
hexChar = Convert.ToChar(Convert.ToInt32(new string(octValues, 0, octLength), 8));
_buffer.Append(hexChar);
break;
}
throw CreateJsonReaderException("Bad JSON escape sequence: {0}. Line {1}, position {2}.", #"\" + currentChar, _currentLineNumber, _currentLinePosition);
}
}
else
{
throw CreateJsonReaderException("Unterminated string. Expected delimiter: {0}. Line {1}, position {2}.", quote, _currentLineNumber, _currentLinePosition);
}
break;
To replace single backslashes with double backslashes, but leave existing doubles alone, search for
(?<!\\)\\(?!\\)
and replace that with
\\\\
For C#, RegexBuddy creates this code snippet:
resultString = Regex.Replace(subjectString,
#"(?<!\\) # lookbehind: Check that previous character isn't a \
\\ # match a \
(?!\\) # lookahead: Check that the following character isn't a \",
#"\\", RegexOptions.IgnorePatternWhitespace);
What is the Error?
what is your deserializeObject?
If you use something like :
data = JsonConvert.DeserializeObject<Dictionary<Object, Object>>(jsonText);
You shouldn't have any problems.