parse.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. #include "parse.h"
  2. #include <QObject>
  3. QVector<Token> lex(const QString& code) {
  4. QVector<Token> tokens;
  5. size_t i = 0;
  6. size_t lineCounter = 0;
  7. size_t columnCounter = 0;
  8. while(i < code.size()) {
  9. if(code[i] == '\n') {
  10. tokens.push_back({lineCounter, columnCounter, TokenTypeEOL, i, i + 1});
  11. ++lineCounter;
  12. columnCounter = 0;
  13. ++i;
  14. }
  15. else if(code[i] == ',') {
  16. tokens.push_back({lineCounter, columnCounter, TokenTypeComma, i, i + 1});
  17. ++i;
  18. }
  19. else if(code[i] == '#') {
  20. tokens.push_back({lineCounter, columnCounter, TokenTypeHash, i, i + 1});
  21. ++i;
  22. }
  23. else if(code[i] == '%') {
  24. tokens.push_back({lineCounter, columnCounter, TokenTypePercent, i, i + 1});
  25. ++i;
  26. }
  27. else if(code[i] == '$') {
  28. tokens.push_back({lineCounter, columnCounter, TokenTypeDollar, i, i + 1});
  29. ++i;
  30. }
  31. else if(code[i] == '/' && (i+1) < code.size() && code[i+1] == '/') {
  32. size_t s = i + 2;
  33. while(s < code.size() && code[s] != '\n') {
  34. ++s;
  35. }
  36. i = s;
  37. }
  38. else if(code[i].isSpace()) {
  39. ++i;
  40. }
  41. else if(code[i].isDigit()) {
  42. size_t s = i + 1;
  43. while(s < code.size() && code[s].isDigit()){
  44. ++s;
  45. }
  46. tokens.push_back({lineCounter, columnCounter, TokenTypeNumber, i, s});
  47. i = s;
  48. }
  49. else if(code[i].isLetter()) {
  50. size_t s = i + 1;
  51. while(s < code.size() && code[s].isLetter()){
  52. ++s;
  53. }
  54. tokens.push_back({lineCounter, columnCounter, TokenTypeWord, i, s});
  55. i = s;
  56. }
  57. else {
  58. tokens.push_back({lineCounter, columnCounter, TokenTypeError, i, i + 1});
  59. ++i;
  60. }
  61. ++columnCounter;
  62. }
  63. return tokens;
  64. }
  65. QVector<QVector<Instruction>> parse(const QString& code, const QVector<Token>& tokens, QVector<ParseError>& errors) {
  66. size_t i = 0;
  67. auto skipToEol = [&tokens, &i](){
  68. while(i < tokens.size() && tokens[i].tokenType != TokenTypeEOL) {
  69. ++i;
  70. }
  71. ++i;
  72. };
  73. while(i < tokens.size()) {
  74. if(tokens[i].tokenType != TokenTypeWord) {
  75. errors += ParseError(tokens[i].line, tokens[i].column, QObject::tr("is not a valid Instruction"));
  76. //lets fast forward to next line
  77. skipToEol();
  78. continue;
  79. }
  80. else {
  81. auto getTokenText = [&](size_t k){
  82. return code.mid(tokens[k].begin, tokens[k].end - tokens[k].begin).toUpper();
  83. };
  84. QString word = getTokenText(i);
  85. if(word.compare("CREATE", Qt::CaseInsensitive)) {
  86. }
  87. else if(word.compare("MOVE", Qt::CaseInsensitive)) {
  88. }
  89. else if(word.compare("DIE", Qt::CaseInsensitive)) {
  90. if(i + 1 >= tokens.size() || tokens[i + 1].tokenType != TokenTypeEOL) {
  91. errors += ParseError(tokens[i - 1].line, tokens[i - 1].column, QObject::tr("error"));
  92. }
  93. skipToEol();
  94. }
  95. else if(word.compare("TRANS", Qt::CaseInsensitive)) {
  96. skipToEol();
  97. }
  98. else if(word.compare("RTRANS", Qt::CaseInsensitive)) {
  99. skipToEol();
  100. }
  101. else if(word.compare("TURN", Qt::CaseInsensitive)) {
  102. skipToEol();
  103. }
  104. else if(word.compare("JUMP", Qt::CaseInsensitive)) {
  105. skipToEol();
  106. }
  107. else if(word.compare("AJUMP", Qt::CaseInsensitive)) {
  108. skipToEol();
  109. }
  110. else if(word.compare("BJUMP", Qt::CaseInsensitive)) {
  111. skipToEol();
  112. }
  113. else if(word.compare("TURN", Qt::CaseInsensitive)) {
  114. skipToEol();
  115. }
  116. else if(word.compare("SCAN", Qt::CaseInsensitive)) {
  117. skipToEol();
  118. }
  119. else if(word.compare("FARSCAN", Qt::CaseInsensitive)) {
  120. skipToEol();
  121. }
  122. else if(word.compare("SET", Qt::CaseInsensitive)) {
  123. skipToEol();
  124. }
  125. else if(word.compare("ADD", Qt::CaseInsensitive)) {
  126. skipToEol();
  127. }
  128. else if(word.compare("SUB", Qt::CaseInsensitive)) {
  129. skipToEol();
  130. }
  131. else if(word.compare("MUL", Qt::CaseInsensitive)) {
  132. skipToEol();
  133. }
  134. else if(word.compare("DIV", Qt::CaseInsensitive)) {
  135. skipToEol();
  136. }
  137. else if(word.compare("MOD", Qt::CaseInsensitive)) {
  138. skipToEol();
  139. }
  140. else if(word.compare("MIN", Qt::CaseInsensitive)) {
  141. skipToEol();
  142. }
  143. else if(word.compare("MAX", Qt::CaseInsensitive)) {
  144. skipToEol();
  145. }
  146. else if(word.compare("RANDOM", Qt::CaseInsensitive)) {
  147. skipToEol();
  148. }
  149. else if(word.compare("IF", Qt::CaseInsensitive)) {
  150. skipToEol();
  151. }
  152. else if(word.compare("IFN", Qt::CaseInsensitive)) {
  153. skipToEol();
  154. }
  155. else if(word.compare("IFG", Qt::CaseInsensitive)) {
  156. skipToEol();
  157. }
  158. else if(word.compare("IFL", Qt::CaseInsensitive)) {
  159. skipToEol();
  160. }
  161. else if(word.compare("IFGE", Qt::CaseInsensitive)) {
  162. skipToEol();
  163. }
  164. else if(word.compare("IFLE", Qt::CaseInsensitive)) {
  165. skipToEol();
  166. }
  167. else if(word.compare("INIT", Qt::CaseInsensitive)) {
  168. skipToEol();
  169. }
  170. else if(word.compare("BREAK", Qt::CaseInsensitive)) {
  171. skipToEol();
  172. }
  173. else if(word.compare("RESUME", Qt::CaseInsensitive)) {
  174. skipToEol();
  175. }
  176. else if(word.compare("SLEEP", Qt::CaseInsensitive)) {
  177. skipToEol();
  178. }
  179. else if(word.compare("QUIT", Qt::CaseInsensitive)) {
  180. skipToEol();
  181. }
  182. else {
  183. errors += ParseError(tokens[i].line, tokens[i].column, QObject::tr("is not a valid Instruction"));
  184. skipToEol();
  185. }
  186. }
  187. }
  188. }