From 0eb904eb16dde87caf2d21193b05f6f9c497cc22 Mon Sep 17 00:00:00 2001 From: Ivan Olenichev Date: Tue, 17 Mar 2020 18:04:24 +0600 Subject: [PATCH] keyboard_update --- Software/qmk_kbd_list.h | 45 ++ Software/qmk_kbd_list.ui | 91 ++++ Software/qmk_parser.cpp | 895 +++++++++++++++++++++++++++++++++++++++ Software/qmk_parser.h | 53 +++ 4 files changed, 1084 insertions(+) create mode 100644 Software/qmk_kbd_list.h create mode 100644 Software/qmk_kbd_list.ui create mode 100644 Software/qmk_parser.cpp create mode 100644 Software/qmk_parser.h diff --git a/Software/qmk_kbd_list.h b/Software/qmk_kbd_list.h new file mode 100644 index 0000000..0852372 --- /dev/null +++ b/Software/qmk_kbd_list.h @@ -0,0 +1,45 @@ +#ifndef QMK_KBD_LIST_H +#define QMK_KBD_LIST_H + +#include + +#include + +namespace Ui { +class qmk_kbd_list; +} + +class qmk_kbd_list : public QWidget +{ + Q_OBJECT + +public: + explicit qmk_kbd_list(QWidget *parent = 0); + ~qmk_kbd_list(); + + void setInfo(QFileInfoList revisions, QFileInfoList keymaps); + QFileInfo getRev(); + QFileInfo getKeymap(); + +signals: + void kbdSelected(int rev, int keymap); + +private slots: + void on_ok_clicked(); + + void on_cancel_clicked(); + +private: + Ui::qmk_kbd_list *ui; + + QFileInfoList m_revisions; + QFileInfoList m_keymaps; + //bool m_isShowing; + + int m_currentRev; + int m_currentKeymap; + + void closeEvent ( QCloseEvent * e ); +}; + +#endif // QMK_KBD_LIST_H diff --git a/Software/qmk_kbd_list.ui b/Software/qmk_kbd_list.ui new file mode 100644 index 0000000..500e620 --- /dev/null +++ b/Software/qmk_kbd_list.ui @@ -0,0 +1,91 @@ + + + qmk_kbd_list + + + + 0 + 0 + 391 + 339 + + + + Form + + + + + 10 + 40 + 181 + 251 + + + + + + + 10 + 300 + 181 + 26 + + + + Ok + + + + + + 200 + 300 + 181 + 26 + + + + Cancel + + + + + + 10 + 10 + 91 + 21 + + + + Revisions + + + + + + 200 + 10 + 111 + 21 + + + + Keymaps + + + + + + 200 + 40 + 181 + 251 + + + + + + + diff --git a/Software/qmk_parser.cpp b/Software/qmk_parser.cpp new file mode 100644 index 0000000..0aeae39 --- /dev/null +++ b/Software/qmk_parser.cpp @@ -0,0 +1,895 @@ +#include "qmk_parser.h" + +qmk_parser::qmk_parser() +{ + +} + +qmk_parser::~qmk_parser() +{ + +} + +QString qmk_parser::parseFiles(QString mainLayout, QString revLayout, QString mainConfig, QString revConfig, QString keymapConfig, QString keymap, QString keycodes, bool ignoreUndefinedKeys) +{ + m_isError = false; + + QVector allMacroList; + QVector tempMacroList; + QStringList macroInFile; + int allMacroListSize; + + macroInFile = findMacro(deleteCommentsAndStrings(mainLayout)); + foreach (QString macro, macroInFile) + allMacroList.push_back(parseMacro(macro)); + + macroInFile = findMacro(deleteCommentsAndStrings(mainConfig)); + foreach (QString macro, macroInFile) + tempMacroList.push_back(parseMacro(macro)); + allMacroListSize = allMacroList.size(); + for (int i = (allMacroListSize - 1); i >= 0; i--) + { + foreach (QStringList tempMacro, tempMacroList) + { + if (tempMacro[0] == allMacroList[i][0]) + { + allMacroList.remove(i); + break; + } + } + } + allMacroList.append(tempMacroList); + tempMacroList.clear(); + + macroInFile = findMacro(deleteCommentsAndStrings(revLayout)); + foreach (QString macro, macroInFile) + tempMacroList.push_back(parseMacro(macro)); + allMacroListSize = allMacroList.size(); + for (int i = (allMacroListSize - 1); i >= 0; i--) + { + foreach (QStringList tempMacro, tempMacroList) + { + if (tempMacro[0] == allMacroList[i][0]) + { + allMacroList.remove(i); + break; + } + } + } + allMacroList.append(tempMacroList); + tempMacroList.clear(); + + macroInFile = findMacro(deleteCommentsAndStrings(revConfig)); + foreach (QString macro, macroInFile) + tempMacroList.push_back(parseMacro(macro)); + allMacroListSize = allMacroList.size(); + for (int i = (allMacroListSize - 1); i >= 0; i--) + { + foreach (QStringList tempMacro, tempMacroList) + { + if (tempMacro[0] == allMacroList[i][0]) + { + allMacroList.remove(i); + break; + } + } + } + allMacroList.append(tempMacroList); + tempMacroList.clear(); + + macroInFile = findMacro(deleteCommentsAndStrings(keymapConfig)); + foreach (QString macro, macroInFile) + tempMacroList.push_back(parseMacro(macro)); + allMacroListSize = allMacroList.size(); + for (int i = (allMacroListSize - 1); i >= 0; i--) + { + foreach (QStringList tempMacro, tempMacroList) + { + if (tempMacro[0] == allMacroList[i][0]) + { + allMacroList.remove(i); + break; + } + } + } + allMacroList.append(tempMacroList); + tempMacroList.clear(); + + keymap = deleteCommentsAndStrings(keymap); + macroInFile = findMacro(keymap); + foreach (QString macro, macroInFile) + tempMacroList.push_back(parseMacro(macro)); + allMacroListSize = allMacroList.size(); + for (int i = (allMacroListSize - 1); i >= 0; i--) + { + foreach (QStringList tempMacro, tempMacroList) + { + if (tempMacro[0] == allMacroList[i][0]) + { + allMacroList.remove(i); + break; + } + } + } + allMacroList.append(tempMacroList); + tempMacroList.clear(); + + QString matrix = findExpression(keymap, "keymaps"); + QString matrixWithMacro = setMacroToExpression(matrix, allMacroList); + + QString clearedKeycodes = deleteCommentsAndStrings(keycodes); + QStringList macroInKeycodes = findMacro(clearedKeycodes); + QVector macroKeycodesList; + foreach (QString s, macroInKeycodes) + macroKeycodesList.push_back(parseMacro(s)); + + matrixWithMacro = setMacroToExpression(matrixWithMacro, macroKeycodesList); + + int assignIndex = matrixWithMacro.indexOf("="); + QString matrixVal = matrixWithMacro.mid(assignIndex + 1, matrixWithMacro.size() - assignIndex - 1); + + int leftBracketCnt = 0; + for (int i = 0; i < matrixVal.size(); i++) + { + if (matrixVal[i] == "{") + leftBracketCnt++; + else if (matrixVal[i] == "}") + break; + } + + QVector>> matrix3; + QVector> matrix2; + QVector matrix1; + + if (leftBracketCnt == 1) + matrix1 = parseOneDimArr(matrixVal); + else if (leftBracketCnt == 2) + matrix2 = parseTwoDimArr(matrixVal); + else if (leftBracketCnt == 3) + matrix3 = parseThreeDimArr(matrixVal); + else + return QString("Error - not correct dimensions in matrix data"); + + if (m_isError) + return QString("Parsing keyboard matrix error (ullegal matrix in keymap file)"); + + QStringList keycodeEnums = findEnums(clearedKeycodes); + + QVector> enumValues; + QVector> tempEnumValues; + + foreach (QString s, keycodeEnums) { + if (!(getEnumName(s).contains("mouse", Qt::CaseInsensitive))) + { + tempEnumValues = getEnumValues(s); + foreach (QVector enumValue, tempEnumValues) + { + if (!(enumValue[0].contains("mouse", Qt::CaseInsensitive))) + enumValues.push_back(enumValue); + } + } + } + + QVector fnEnumVal(2); + fnEnumVal[0] = "MO(1)"; + fnEnumVal[1] = "1"; + enumValues.push_back(fnEnumVal); + + m_Rows.clear(); + m_Columns.clear(); + m_diodeDirection = 0; + foreach (QStringList macro, allMacroList) { + if (macro[0] == "MATRIX_ROW_PINS") + m_Rows = parseOneDimArr(macro[1].right(macro[1].size() - macro[1].indexOf("{"))); + else if (macro[0] == "MATRIX_COL_PINS") + m_Columns = parseOneDimArr(macro[1].right(macro[1].size() - macro[1].indexOf("{"))); + else if (macro[0] == "DIODE_DIRECTION") + { + if (macro[1] == "COL2ROW") + m_diodeDirection = 1; + else + m_diodeDirection = 2; + } + } + + if (!matrix3.isEmpty()) + { + foreach (QVector> matrix2x, matrix3) + matrix2.append(matrix2x); + } + + if (!matrix2.isEmpty()) + { + foreach (QVector matrix1x, matrix2) + matrix1.append(matrix1x); + } + + if ((matrix1.size() != (m_Columns.size() * m_Rows.size())) && (matrix1.size() != (2 * m_Columns.size() * m_Rows.size()))) + return QString("Error - matrix has not correct count of elements (maybe there is too many dimensions)"); + + m_Matrix.resize(m_Rows.size()); + + for (int i = 0; i < m_Rows.size(); i++) + { + m_Matrix[i].resize(m_Columns.size()); + for (int j = 0; j < m_Columns.size(); j++) + { + m_Matrix[i][j] = -1; + foreach (QVector value, enumValues) + { + if (matrix1[i * m_Columns.size() + j] == value[0]) + { + m_Matrix[i][j] = value[1].toInt(); + break; + } + } + if (m_Matrix[i][j] == -1) + m_Matrix[i][j] = strToNum(matrix1[i * m_Columns.size() + j]); + if (m_Matrix[i][j] == -1) + { + if (!ignoreUndefinedKeys) + return QString("Error - undefined elements in matrix (%1)!").arg(matrix1[i * m_Columns.size() + j]); + else + m_Matrix[i][j] = 0; + } + } + } + + if (matrix1.size() == (m_Columns.size() * m_Rows.size())) + m_FnMatrix = m_Matrix; + else + { + m_FnMatrix.resize(m_Rows.size()); + for (int i = 0; i < m_Rows.size(); i++) + { + m_FnMatrix[i].resize(m_Columns.size()); + for (int j = 0; j < m_Columns.size(); j++) + { + m_FnMatrix[i][j] = -1; + foreach (QVector value, enumValues) + { + if (matrix1[m_Columns.size() * m_Rows.size() + i * m_Columns.size() + j] == value[0]) + { + m_FnMatrix[i][j] = value[1].toInt(); + break; + } + } + if (m_FnMatrix[i][j] == -1) + { + m_FnMatrix[i][j] = strToNum(matrix1[m_Columns.size() * m_Rows.size() + i * m_Columns.size() + j]); + if (m_FnMatrix[i][j] == 1) // QMK FEATURE: CODE 0x01 IS TRANSPARENT + m_FnMatrix[i][j] = 0; + } + if (m_FnMatrix[i][j] == -1) + { + if (!ignoreUndefinedKeys) + return QString("Error - undefined elements in matrix (%1)!").arg(matrix1[m_Columns.size() * m_Rows.size() + i * m_Columns.size() + j]); + else + m_FnMatrix[i][j] = 0; + } + if (m_FnMatrix[i][j] == 0) + m_FnMatrix[i][j] = m_Matrix[i][j]; + } + } + } + + return QString(""); +} + +QStringList qmk_parser::findMacro(QString src) +{ + QStringList lines = src.split("\n"); + QStringList macro; + QString macroStr; + bool macroFound = false; + foreach (QString str, lines) { + if (!macroFound) + { + if (str.contains("#define")) + { + macroFound = true; + str = str.right(str.length() - 7); + } + } + if (macroFound) + { + if (str.at(str.length() - 1) == "\\") + macroStr += str.left(str.length() - 1); + else + { + macroStr += str; + macro.push_back(macroStr); + macroFound = false; + macroStr.clear(); + } + } + } + return macro; +} + +QStringList qmk_parser::parseMacro(QString macro) +{ + QString inputMacro; + QStringList parsedMacro; + + inputMacro = macro.replace(QRegExp("^[ \t\v\r\n\f]+"), ""); + inputMacro = inputMacro.replace(QRegExp("[ \t\v\r\n\f]+"), " "); + int firstSpace = inputMacro.indexOf(QRegExp("[ \t\v\r\n\f]+")); + QString macroName = inputMacro.left(firstSpace); + if (macroName.contains("(")) + { + int leftBracketCnt = 0; + int rightBracketCnt = 0; + int argStart = inputMacro.indexOf("("); + int argEnd = 0; + for (int i = 0; i < inputMacro.size(); i++) + { + if (inputMacro[i] == "(") + leftBracketCnt++; + else if (inputMacro[i] == ")") + { + rightBracketCnt++; + if (rightBracketCnt == leftBracketCnt) + { + argEnd = i; + break; + } + } + } + if (argEnd <= argStart) + { + m_isError = true; + return parsedMacro; + } + QString args = inputMacro.mid(argStart + 1, argEnd - argStart - 1); + + macroName = macroName.left(macroName.indexOf("(")); + parsedMacro.append(macroName); + + args += "\n"; + args.replace(QRegExp("^[ \t\v\r\n\f]+"), ""); + args.replace(QRegExp("[ \t\v\r\n\f]+$"), ""); + QStringList argsList = args.split(QRegExp("[, \t\v\r\n\f]+")); + + parsedMacro.append(argsList); + + QString body = inputMacro.right(inputMacro.size() - argEnd - 1); + body += "\n"; + body = body.replace(QRegExp("^[ \t\v\r\n\f]+"), ""); + body = body.replace(QRegExp("[ \t\v\r\n\f]+$"), ""); + parsedMacro.append(body); + } + else + { + parsedMacro.append(macroName); + + if (!((firstSpace < 1) || ((inputMacro.size() - firstSpace) < 0))) + { + QString body = inputMacro.right(inputMacro.size() - firstSpace); + body += "\n"; + body = body.replace(QRegExp("^[ \t\v\r\n\f]+"), ""); + body = body.replace(QRegExp("[ \t\v\r\n\f]+$"), ""); + parsedMacro.append(body); + } + } + + return parsedMacro; +} + +QString qmk_parser::deleteCommentsAndStrings(QString src, bool deleteStrings) +{ + QString srcNoComments(src); + int i = 0; + bool isOneLineComment = false; + bool isMultiLineComment = false; + bool isString = false; + QVector> deleteAreas; + QVector tempArea(2, 0); + while (i < srcNoComments.size()) { + if (isOneLineComment) + { + if ((srcNoComments[i-1] != "\\") && (srcNoComments[i] == "\n")) + { + tempArea[1] = i; + deleteAreas.push_back(tempArea); + isOneLineComment = false; + } + } + else if (isMultiLineComment) + { + if ((srcNoComments[i-1] == "*") && (srcNoComments[i] == "/")) + { + tempArea[1] = i + 1; + deleteAreas.push_back(tempArea); + isMultiLineComment = false; + } + } + else if (isString) + { + if ((srcNoComments[i-1] != "\\") && (srcNoComments[i] == "\"")) + { + tempArea[1] = i + 1; + if (deleteStrings) + deleteAreas.push_back(tempArea); + isString = false; + } + } + else + { + if (srcNoComments[i] == "\"") + { + tempArea[0] = i; + isString = true; + } + else if (i < (srcNoComments.size() - 1)) + { + if ((srcNoComments[i] == "/") && (srcNoComments[i+1] == "/")) + { + tempArea[0] = i; + isOneLineComment = true; + } + else if ((srcNoComments[i] == "/") && (srcNoComments[i+1] == "*")) + { + tempArea[0] = i; + isMultiLineComment = true; + } + } + } + i++; + } + if (isOneLineComment) + { + tempArea[1] = srcNoComments.size(); + deleteAreas.push_back(tempArea); + } + if (isMultiLineComment) + m_isError = true; + if (isString) + m_isError = true; + + for (int i = (deleteAreas.size() - 1); i >= 0; i--) + srcNoComments.replace(deleteAreas[i][0], deleteAreas[i][1] - deleteAreas[i][0], ""); + + // THIS PART IS SIMPLE #IF 0 DELETER. #IF 0 IS IN KEYCODE.H. WORKS UNCORRECT IN OTHER SITUATIONS!!! + bool isIfZero = false; + QStringList srcLines = srcNoComments.split("\n"); + QString srcOut; + for (int i = 0; i < srcLines.size(); i++) + { + if (srcLines[i].contains(QRegExp("^[\\s]*#if[\\s]*0"))) + isIfZero = true; + if ((!isIfZero) && (!srcLines[i].contains("#endif")) && (!srcLines[i].contains("#else")) && (!srcLines[i].contains("#if"))) + srcOut += (srcLines[i] + "\n"); + if (isIfZero) + { + if ((srcLines[i].contains("#endif")) || (srcLines[i].contains("#else"))) + isIfZero = false; + } + } + + return srcOut; +} + +QString qmk_parser::findExpression(QString src, QString expression) +{ + QStringList srcList = src.split("\n"); + QString fullExpression; + foreach (QString str, srcList) + { + if (fullExpression.size() == 0) + { + if (str.contains(expression)) + { + fullExpression = fullExpression + str + "\n"; + if (str.contains(";")) + break; + } + } + else + { + fullExpression = fullExpression + str + "\n"; + if (str.contains(";")) + break; + } + } + fullExpression.replace(QRegExp("[ \t\v\r\n\f]+"), " "); + fullExpression.replace(QRegExp("^[ \t\v\r\n\f]+"), ""); + fullExpression.replace(QRegExp("[ \t\v\r\n\f]+$"), ""); + return fullExpression; +} + +QString qmk_parser::setMacroToExpression(QString expression, QVector macroList) +{ + expression.replace("\\", ""); + bool expressionHasMacro = true; + + while (expressionHasMacro) + { + expressionHasMacro = false; + foreach (QStringList macro, macroList) + { + int macroIndex = expression.indexOf(macro[0]); + if (macroIndex >= 0) + { + if (macroIndex > 0) + { + if (QString(expression[macroIndex-1]).contains(QRegExp("[A-Za-z0-9_]"))) + macroIndex = -1; + } + if ((macroIndex + macro[0].size()) < expression.size()) + { + if (QString(expression[macroIndex + macro[0].size()]).contains(QRegExp("[A-Za-z0-9_]"))) + macroIndex = -1; + } + } + if (macroIndex >= 0) + { + if (macro.size() > 2) // MACRO WITH ARGUMENTS + { + int leftBracketCnt = 0; + int rightBracketCnt = 0; + int argStart = expression.indexOf("(", macroIndex); + int argEnd = 0; + for (int i = macroIndex; i < expression.size(); i++) + { + if (expression[i] == "(") + leftBracketCnt++; + else if (expression[i] == ")") + { + rightBracketCnt++; + if (rightBracketCnt == leftBracketCnt) + { + argEnd = i; + break; + } + } + } + if (argEnd <= argStart) + { + m_isError = true; + return QString(""); + } + QString args = expression.mid(argStart + 1, argEnd - argStart - 1); + + args += "\n"; + args.replace(QRegExp("^[ \t\v\r\n\f]+"), ""); + args.replace(QRegExp("[ \t\v\r\n\f]+$"), ""); + QStringList argsList = args.split(QRegExp("[, \t\v\r\n\f]+")); + + if (argsList.size() != (macro.size() - 2)) + { + m_isError = true; + return QString(""); + } + + QString replacedText = macro[macro.size() - 1]; + + for (int i = 0; i < argsList.size(); i++) + replacedText.replace (macro[i + 1], argsList[i]); + + expression.replace(macroIndex, argEnd - macroIndex + 1, replacedText); + } + else if (macro.size() == 2) // MACRO WITHOUT ARGUMENTS + expression.replace(macro[0], macro[1]); + + if (macro.size() >= 2) + expressionHasMacro = true; + } + } + } + return expression; +} + +QStringList qmk_parser::findEnums(QString src) +{ + QStringList output; + QStringList srcRows = src.split("\n"); + QString currentEnum; + foreach (QString s, srcRows) + { + if (currentEnum.isEmpty()) + { + if (s.contains("enum")) + { + currentEnum = s + "\n"; + if (s.contains(";")) + { + output.push_back(currentEnum); + currentEnum.clear(); + } + } + } + else + { + currentEnum = currentEnum + s + "\n"; + if (s.contains(";")) + { + output.push_back(currentEnum); + currentEnum.clear(); + } + } + } + return output; +} + +QString qmk_parser::getEnumName(QString enumSrc) +{ + if (!enumSrc.contains("{")) + return QString(""); + enumSrc = enumSrc.left(enumSrc.indexOf("{")); + enumSrc = enumSrc.simplified(); + QStringList enumNameList = enumSrc.split(QRegExp("\\s")); + if (enumNameList.size() != 2) + return QString(""); + if (enumNameList[0] != "enum") + return QString(""); + return enumNameList[1]; +} + +QVector> qmk_parser::getEnumValues(QString src) +{ + QVector> output; + QVector value(2); + QVector leftBrackets; + QVector rightBrackets; + for (int i = 0; i < src.size(); i++) + { + if (src[i] == "{") + leftBrackets.push_back(i); + if (src[i] == "}") + rightBrackets.push_back(i); + } + if ((leftBrackets.size() != 1) || (rightBrackets.size() != 1)) + { + m_isError = true; + return output; + } + QString enumContent = src.mid(leftBrackets[0] + 1, rightBrackets[0] - leftBrackets[0] - 1); + QStringList enumValues = enumContent.split(QRegExp("[\\s]*,[\\s]*")); + + int currentIndex = 0; + foreach (QString s, enumValues) + { + if (s.contains("=")) + { + QStringList enumValueBody = s.split(QRegExp("[\\s]*=[\\s]*")); + currentIndex = strToNum(enumValueBody[1].simplified()); + if (currentIndex == -1) + { + m_isError = true; + return output; + } + value[0] = enumValueBody[0].simplified(); + value[1] = QString::number(currentIndex); + currentIndex++; + } + else + { + value[0] = s.simplified(); + value[1] = QString::number(currentIndex); + currentIndex++; + } + output.push_back(value); + } + + return output; +} + +QVector qmk_parser::parseOneDimArr(QString arr) +{ + arr.replace("{", ""); + arr.replace("}", ""); + arr.replace("\\", ""); + QVector output; + QStringList arrElements = arr.split(QRegExp("[\\s]*,[\\s]*")); + foreach (QString str, arrElements) + output.push_back(str.simplified()); + return output; +} + +QVector> qmk_parser::parseTwoDimArr(QString arr) +{ + QVector> output; + QVector leftBracketIndexes; + QVector rightBracketIndexes; + for (int i = 0; i < arr.size(); i++) + { + if (arr[i] == "{") + leftBracketIndexes.push_back(i); + else if (arr[i] == "}") + rightBracketIndexes.push_back(i); + } + if (leftBracketIndexes.size() != rightBracketIndexes.size()) + { + m_isError = true; + return output; + } + if ((leftBracketIndexes[1] < rightBracketIndexes[0]) && (leftBracketIndexes[leftBracketIndexes.size() - 1] < rightBracketIndexes[rightBracketIndexes.size() - 2])) + { + leftBracketIndexes.remove(0); + rightBracketIndexes.remove(rightBracketIndexes.size() - 1); + } + for (int i = 0; i < (leftBracketIndexes.size() - 1); i++) + { + if (!((leftBracketIndexes[i] < rightBracketIndexes[i]) && (leftBracketIndexes[i + 1] > rightBracketIndexes[i]))) + { + m_isError = true; + return output; + } + } + + output.resize(leftBracketIndexes.size()); + QVector arrIndexes; + for (int i = 0; i < leftBracketIndexes.size(); i++) + { + int startIndex = 0; + if (i > 0) + startIndex = rightBracketIndexes[i - 1] + 1; + QString indexStr = arr.mid(startIndex, leftBracketIndexes[i] - startIndex); + int index = 0; + if ((indexStr.contains("[")) && (indexStr.contains("]"))) + { + indexStr = indexStr.mid(indexStr.indexOf("[") + 1, indexStr.indexOf("]") - indexStr.indexOf("[") - 1); + indexStr = indexStr.simplified(); + index = strToNum(indexStr); + if (index < 0) + { + m_isError = true; + return output; + } + arrIndexes.push_back(index); + } + QString oneDimentionStr = arr.mid(leftBracketIndexes[i], rightBracketIndexes[i] - leftBracketIndexes[i] + 1); + if (!arrIndexes.isEmpty()) + output[index] = parseOneDimArr(oneDimentionStr); + else + output[i] = parseOneDimArr(oneDimentionStr); + } + + if ((arrIndexes.size() != 0) && (arrIndexes.size() != output.size())) + { + output.clear(); + m_isError = true; + return output; + } + + return output; +} + +QVector>> qmk_parser::parseThreeDimArr(QString arr) +{ + QVector>> output; + QVector leftBracketIndexes; + QVector rightBracketIndexes; + for (int i = 0; i < arr.size(); i++) + { + if (arr[i] == "{") + leftBracketIndexes.push_back(i); + else if (arr[i] == "}") + rightBracketIndexes.push_back(i); + } + if (leftBracketIndexes.size() != rightBracketIndexes.size()) + { + m_isError = true; + return output; + } + if ((leftBracketIndexes[2] < rightBracketIndexes[0]) && (leftBracketIndexes[leftBracketIndexes.size() - 1] < rightBracketIndexes[rightBracketIndexes.size() - 3])) + { + arr = arr.mid(leftBracketIndexes[0] + 1, rightBracketIndexes[rightBracketIndexes.size() - 1] - leftBracketIndexes[0] - 1); + +// leftBracketIndexes.remove(0); +// rightBracketIndexes.remove(rightBracketIndexes.size() - 1); + } + +// QVector leftBracket2dimIndexes; +// QVector rightBracket2dimIndexes; + leftBracketIndexes.clear(); + rightBracketIndexes.clear(); + + int leftBracketCounter = 0; + int rightBracketCounter = 0; + for (int i = 0; i < arr.size(); i++) + { + if (arr[i] == "{") + { + if (leftBracketCounter == rightBracketCounter) + leftBracketIndexes.push_back(i); + leftBracketCounter++; + } + else if (arr[i] == "}") + { + rightBracketCounter++; + if (leftBracketCounter == rightBracketCounter) + rightBracketIndexes.push_back(i); + } + } + + if (leftBracketIndexes.size() != rightBracketIndexes.size()) + { + m_isError = true; + return output; + } + + output.resize(leftBracketIndexes.size()); + + QVector arrIndexes; + for (int i = 0; i < leftBracketIndexes.size(); i++) + { + int startIndex = 0; + if (i > 0) + startIndex = rightBracketIndexes[i - 1] + 1; + QString indexStr = arr.mid(startIndex, leftBracketIndexes[i] - startIndex); + int index = 0; + if ((indexStr.contains("[")) && (indexStr.contains("]"))) + { + indexStr = indexStr.mid(indexStr.indexOf("[") + 1, indexStr.indexOf("]") - indexStr.indexOf("[") - 1); + indexStr = indexStr.simplified(); + index = strToNum(indexStr); + if (index < 0) + { + m_isError = true; + return output; + } + arrIndexes.push_back(index); + } + QString oneDimentionStr = arr.mid(leftBracketIndexes[i], rightBracketIndexes[i] - leftBracketIndexes[i] + 1); + if (!arrIndexes.isEmpty()) + output[index] = parseTwoDimArr(oneDimentionStr); + else + output[i] = parseTwoDimArr(oneDimentionStr); + } + + if ((arrIndexes.size() != 0) && (arrIndexes.size() != output.size())) + { + output.clear(); + m_isError = true; + return output; + } + + return output; +} + +int qmk_parser::strToNum(QString s) +{ + bool success = false; + int number; + if ((s[0] != "0") || (s.size() == 1)) + number = s.toInt(&success, 10); + else + { + if ((s[1] == "x") || (s[1] == "X")) + number = s.right(s.size() - 2).toInt(&success, 16); + else if ((s[1] == "b") || (s[1] == "B")) + number = s.right(s.size() - 2).toInt(&success, 2); + else + number = s.right(s.size() - 1).toInt(&success, 8); + } + if (!success) + number = -1; // ERROR SIGN + return number; +} + +QVector qmk_parser::getColumns() +{ + return m_Columns; +} + +QVector qmk_parser::getRows() +{ + return m_Rows; +} + +QVector> qmk_parser::getMatrix() +{ + return m_Matrix; +} + +QVector> qmk_parser::getFnMatrix() +{ + return m_FnMatrix; +} + +int qmk_parser::getDiodeDirection() +{ + return m_diodeDirection; +} diff --git a/Software/qmk_parser.h b/Software/qmk_parser.h new file mode 100644 index 0000000..1f75505 --- /dev/null +++ b/Software/qmk_parser.h @@ -0,0 +1,53 @@ +#ifndef QMK_PARSER_H +#define QMK_PARSER_H + +#include +#include + +class qmk_parser +{ +public: + qmk_parser(); + ~qmk_parser(); + + // Parsing of all needed qmk files. If parsing finishes processing without errors, returns zero-size str, else returns error description + QString parseFiles(QString mainLayout, QString revLayout, QString mainConfig, QString revConfig, QString keymapConfig, QString keymap, QString keycodes, bool ignoreUndefinedKeys = true); + + QStringList findMacro(QString src); + QStringList parseMacro(QString macro); + + QString deleteCommentsAndStrings(QString src, bool deleteStrings = true); + + QString findExpression(QString src, QString expression); + + QStringList findEnums(QString src); + + QString getEnumName(QString enumSrc); + QVector> getEnumValues(QString src); // val 0 - name, val 1 - number in text format + + QString setMacroToExpression(QString expression, QVector macroList); + + QVector parseOneDimArr(QString arr); + QVector> parseTwoDimArr(QString arr); + QVector>> parseThreeDimArr(QString arr); + + int strToNum(QString s); + + QVector getColumns(); + QVector getRows(); + QVector> getMatrix(); + QVector> getFnMatrix(); + int getDiodeDirection(); + +private: + + bool m_isError; + QVector m_Columns; + QVector m_Rows; + int m_diodeDirection; + QVector > m_Matrix; + QVector > m_FnMatrix; + +}; + +#endif // QMK_PARSER_H