parser.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. Parser functions and class implementations for malio interpreter
  3. For details on specifications of the Malio language, please see:
  4. https://notabug.org/Malio
  5. Copyright 2015 - Malio dev team
  6. This file is part of malio-cpp
  7. malio-cpp is free software: you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation, either version 3 of the License, or
  10. (at your option) any later version.
  11. malio-cpp is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <iostream>
  19. #include <string>
  20. #include <sstream>
  21. #include <fstream>
  22. #include <vector>
  23. #include <algorithm>
  24. #include <map>
  25. #include "parser.h"
  26. #include "builtins.h"
  27. // reserved keywords:
  28. std::vector<std::string> keywords {
  29. "print",
  30. "program",
  31. "int",
  32. "char",
  33. "dec",
  34. "string",
  35. "boolean",
  36. "end",
  37. "writef",
  38. "copyf",
  39. "#",
  40. "null"
  41. };
  42. // -- Exceptions class definitions:
  43. malio::Exception::Exception(std::string err):
  44. errortype(err)
  45. {
  46. std::cout << errortype << ": ";
  47. }
  48. malio::SyntaxError::SyntaxError(std::string what):
  49. Exception("SyntaxError"), explanation(what)
  50. {
  51. std::cout << explanation << std::endl;
  52. }
  53. malio::NameError::NameError(std::string what):
  54. Exception("NameError"), explanation(what)
  55. {
  56. std::cout << explanation << " is not defined." << std::endl;
  57. }
  58. // -- Parser functions:
  59. int malio::read(std::string filename)
  60. {
  61. std::string program_name;
  62. std::tuple<std::string, std::string> action;
  63. std::ifstream file(filename);
  64. if (file.is_open()) {
  65. std::string buffer;
  66. while(std::getline(file, buffer)) {
  67. // Process the line as needed:
  68. action = malio::parse(buffer);
  69. if (std::get<0>(action) == "comment")
  70. continue;
  71. else if (std::get<0>(action) == "program") {
  72. program_name = std::get<1>(action);
  73. continue;
  74. }
  75. else if (std::get<0>(action) == "end") {
  76. // std::cout << "Program exit OK.\n";
  77. break;
  78. }
  79. else if (std::get<0>(action) == "print")
  80. malio::print(std::get<1>(action));
  81. else if (std::get<0>(action) == "writef")
  82. malio::writef(std::get<1>(action), "testwf.txt");
  83. }
  84. file.close();
  85. return 0;
  86. }
  87. else {
  88. std::cerr << "Failed to open file " << filename << std::endl;
  89. return 1;
  90. }
  91. }
  92. // take a full line of code and parse it, return the action to perform by
  93. // the interpreter:
  94. std::tuple<std::string, std::string>
  95. malio::parse(std::string line)
  96. {
  97. std::stringstream ss(line);
  98. std::string buffer;
  99. std::tuple<std::string, std::string> action;
  100. bool ignore_names(false);
  101. // When we enter this loop, we need to consider the order of evaluation
  102. // of things:
  103. // 1. Is it a comment? Then ignore the rest of the line.
  104. // 2. Is it a program directive? Then fetch the program information
  105. // 3. Is it a print statement? Then print the rest of the line. Ignore
  106. // names never seen before.
  107. // 4. Everything else; first come, first served.
  108. while(ss >> buffer) {
  109. if (buffer.at(0) == '#') {
  110. std::get<0>(action) = "comment"; // tuple syntax is horrible!
  111. std::get<1>(action) = "";
  112. break;
  113. }
  114. else if (buffer == "program") {
  115. std::get<0>(action) = "program";
  116. ignore_names = true;
  117. continue;
  118. }
  119. else if (buffer == "end") {
  120. std::get<0>(action) = "end";
  121. std::get<1>(action) = "";
  122. break;
  123. }
  124. else if (buffer == "print") {
  125. std::get<0>(action) = "print";
  126. ignore_names = true;
  127. continue; // fill in the buffer with the remainder of the line.
  128. }
  129. else if (buffer == "writef") {
  130. std::get<0>(action) = "writef";
  131. ignore_names = true;
  132. continue;
  133. }
  134. else if (
  135. std::find(
  136. keywords.begin(), keywords.end(), buffer
  137. ) == keywords.end() && !ignore_names
  138. ) {
  139. // Not in the name database? GTFO!
  140. throw malio::NameError(buffer);
  141. }
  142. else {
  143. std::get<1>(action).append(buffer);
  144. std::get<1>(action).append(" ");
  145. }
  146. }
  147. return action;
  148. }