No Description

parseutil.cpp 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. #include "parseutil.h"
  2. #include <QDebug>
  3. #include <QRegularExpression>
  4. #include <QStack>
  5. ParseUtil::ParseUtil()
  6. {
  7. }
  8. void ParseUtil::strip_comment(QString *line) {
  9. bool in_string = false;
  10. for (int i = 0; i < line->length(); i++) {
  11. if (line->at(i) == '"') {
  12. in_string = !in_string;
  13. } else if (line->at(i) == '@') {
  14. if (!in_string) {
  15. line->truncate(i);
  16. break;
  17. }
  18. }
  19. }
  20. }
  21. QList<QStringList>* ParseUtil::parseAsm(QString text) {
  22. QList<QStringList> *parsed = new QList<QStringList>;
  23. QStringList lines = text.split('\n');
  24. for (QString line : lines) {
  25. QString label;
  26. //QString macro;
  27. //QStringList *params;
  28. strip_comment(&line);
  29. if (line.trimmed().isEmpty()) {
  30. } else if (line.contains(':')) {
  31. label = line.left(line.indexOf(':'));
  32. QStringList *list = new QStringList;
  33. list->append(".label"); // This is not a real keyword. It's used only to make the output more regular.
  34. list->append(label);
  35. parsed->append(*list);
  36. // There should not be anything else on the line.
  37. // gas will raise a syntax error if there is.
  38. } else {
  39. line = line.trimmed();
  40. //parsed->append(line.split(QRegExp("\\s*,\\s*")));
  41. QString macro;
  42. QStringList params;
  43. int index = line.indexOf(QRegExp("\\s+"));
  44. macro = line.left(index);
  45. params = line.right(line.length() - index).trimmed().split(QRegExp("\\s*,\\s*"));
  46. params.prepend(macro);
  47. parsed->append(params);
  48. }
  49. //if (macro != NULL) {
  50. // if (macros->contains(macro)) {
  51. // void* function = macros->value(macro);
  52. // if (function != NULL) {
  53. // std::function function(params);
  54. // }
  55. // }
  56. //}
  57. }
  58. return parsed;
  59. }
  60. int ParseUtil::evaluateDefine(QString define, QMap<QString, int>* knownDefines) {
  61. QList<Token> tokens = tokenizeExpression(define, knownDefines);
  62. QList<Token> postfixExpression = generatePostfix(tokens);
  63. return evaluatePostfix(postfixExpression);
  64. }
  65. QList<Token> ParseUtil::tokenizeExpression(QString expression, QMap<QString, int>* knownIdentifiers) {
  66. QList<Token> tokens;
  67. QStringList tokenTypes = (QStringList() << "hex" << "decimal" << "identifier" << "operator" << "leftparen" << "rightparen");
  68. QRegularExpression re("^(?<hex>0x[0-9a-fA-F]+)|(?<decimal>[0-9]+)|(?<identifier>[a-zA-Z_0-9]+)|(?<operator>[+\\-*\\/<>|^%]+)|(?<leftparen>\\()|(?<rightparen>\\))");
  69. expression = expression.trimmed();
  70. while (!expression.isEmpty()) {
  71. QRegularExpressionMatch match = re.match(expression);
  72. if (!match.hasMatch()) {
  73. qDebug() << "Failed to tokenize expression: " << expression;
  74. break;
  75. }
  76. for (QString tokenType : tokenTypes) {
  77. QString token = match.captured(tokenType);
  78. if (!token.isEmpty()) {
  79. if (tokenType == "identifier") {
  80. if (knownIdentifiers->contains(token)) {
  81. QString actualToken = QString("%1").arg(knownIdentifiers->value(token));
  82. expression = expression.replace(0, token.length(), actualToken);
  83. token = actualToken;
  84. tokenType = "decimal";
  85. } else {
  86. qDebug() << "Unknown identifier found in expression: " << token;
  87. }
  88. }
  89. tokens.append(Token(token, tokenType));
  90. expression = expression.remove(0, token.length()).trimmed();
  91. break;
  92. }
  93. }
  94. }
  95. return tokens;
  96. }
  97. QMap<QString, int> Token::precedenceMap = QMap<QString, int>(
  98. {
  99. {"*", 3},
  100. {"/", 3},
  101. {"+", 4},
  102. {"-", 4},
  103. {"<<", 5},
  104. {">>", 5},
  105. {"&", 8},
  106. {"^", 9},
  107. {"|", 10}
  108. });
  109. // Shunting-yard algorithm for generating postfix notation.
  110. // https://en.wikipedia.org/wiki/Shunting-yard_algorithm
  111. QList<Token> ParseUtil::generatePostfix(QList<Token> tokens) {
  112. QList<Token> output;
  113. QStack<Token> operatorStack;
  114. for (Token token : tokens) {
  115. if (token.type == TokenType::Number) {
  116. output.append(token);
  117. } else if (token.value == "(") {
  118. operatorStack.push(token);
  119. } else if (token.value == ")") {
  120. while (!operatorStack.empty() && operatorStack.top().value != "(") {
  121. output.append(operatorStack.pop());
  122. }
  123. if (!operatorStack.empty()) {
  124. // pop the left parenthesis token
  125. operatorStack.pop();
  126. } else {
  127. qDebug() << "Mismatched parentheses detected in expression!";
  128. }
  129. } else {
  130. // token is an operator
  131. while (!operatorStack.isEmpty()
  132. && operatorStack.top().operatorPrecedence <= token.operatorPrecedence
  133. && operatorStack.top().value != "(") {
  134. output.append(operatorStack.pop());
  135. }
  136. operatorStack.push(token);
  137. }
  138. }
  139. while (!operatorStack.isEmpty()) {
  140. if (operatorStack.top().value == "(" || operatorStack.top().value == ")") {
  141. qDebug() << "Mismatched parentheses detected in expression!";
  142. } else {
  143. output.append(operatorStack.pop());
  144. }
  145. }
  146. return output;
  147. }
  148. // Evaluate postfix expression.
  149. // https://en.wikipedia.org/wiki/Reverse_Polish_notation#Postfix_evaluation_algorithm
  150. int ParseUtil::evaluatePostfix(QList<Token> postfix) {
  151. QStack<Token> stack;
  152. for (Token token : postfix) {
  153. if (token.type == TokenType::Operator) {
  154. int op2 = stack.pop().value.toInt(nullptr, 0);
  155. int op1 = stack.pop().value.toInt(nullptr, 0);
  156. int result = 0;
  157. if (token.value == "*") {
  158. result = op1 * op2;
  159. } else if (token.value == "/") {
  160. result = op1 / op2;
  161. } else if (token.value == "+") {
  162. result = op1 + op2;
  163. } else if (token.value == "-") {
  164. result = op1 - op2;
  165. } else if (token.value == "<<") {
  166. result = op1 << op2;
  167. } else if (token.value == ">>") {
  168. result = op1 >> op2;
  169. } else if (token.value == "&") {
  170. result = op1 & op2;
  171. } else if (token.value == "^") {
  172. result = op1 ^ op2;
  173. } else if (token.value == "|") {
  174. result = op1 | op2;
  175. } else {
  176. qDebug() << "Unsupported postfix operator: " << token.value;
  177. }
  178. stack.push(Token(QString("%1").arg(result), "decimal"));
  179. } else {
  180. stack.push(token);
  181. }
  182. }
  183. return stack.pop().value.toInt(nullptr, 0);
  184. }