Compiler.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. #include <stdarg.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include "Compiler.h"
  6. #include "Operation.h"
  7. #include "Tokenizer.h"
  8. #define MAX_BYTES (1024 * 1024)
  9. #define ERROR_LENGTH 256
  10. #define VARS 256
  11. static char error[ERROR_LENGTH] = {'\0'};
  12. static unsigned char byteCode[MAX_BYTES];
  13. static int writeIndex = 0;
  14. static int16 line = 1;
  15. static const char* vars[VARS];
  16. static int varIndex = 0;
  17. static void cError(const char* format, ...) {
  18. va_list args;
  19. va_start(args, format);
  20. vsnprintf(error, ERROR_LENGTH, format, args);
  21. va_end(args);
  22. }
  23. static int cAddVar(const char* var) {
  24. for(int i = 0; i < varIndex; i++) {
  25. if(strcmp(var, vars[i]) == 0) {
  26. return i;
  27. }
  28. }
  29. if(varIndex >= VARS) {
  30. cError("variable buffer is too small");
  31. return -1;
  32. }
  33. int index = varIndex;
  34. vars[varIndex++] = var;
  35. return index;
  36. }
  37. static void cUnexpectedToken(Token t) {
  38. cError("unexpected token on line %d: %s", line, tGetTokenName(t));
  39. }
  40. static void* cReserveBytes(int length) {
  41. if(writeIndex + length > MAX_BYTES) {
  42. cError("the compiler buffer is too small");
  43. return NULL;
  44. }
  45. unsigned char* p = byteCode + writeIndex;
  46. writeIndex += length;
  47. return p;
  48. }
  49. static void cSetBytes(const void* data, void* dest, int length) {
  50. memcpy(dest, data, length);
  51. }
  52. static bool cAddBytes(const void* data, int length) {
  53. void* p = cReserveBytes(length);
  54. if(p == NULL) {
  55. return false;
  56. }
  57. cSetBytes(data, p, length);
  58. return true;
  59. }
  60. static bool cAddOperation(Operation token) {
  61. unsigned char c = token;
  62. return cAddBytes(&c, 1);
  63. }
  64. static Token tReadTokenAndLine() {
  65. Token t = tReadToken();
  66. if(tReadInt16(&line)) {
  67. return t;
  68. }
  69. return T_END;
  70. }
  71. static bool cConsumeToken(Token wanted) {
  72. Token t = tReadTokenAndLine();
  73. if(wanted == t) {
  74. return true;
  75. }
  76. cError("unexpected token on line %d: expected '%s' got '%s'", line, tGetTokenName(wanted), tGetTokenName(t));
  77. return false;
  78. }
  79. static bool cConsumeTokenIf(Token t) {
  80. if(tPeekToken() == t) {
  81. tReadTokenAndLine();
  82. return true;
  83. }
  84. return false;
  85. }
  86. static bool cExpression();
  87. static bool cPrimary() {
  88. if(cConsumeTokenIf(T_INT)) {
  89. int value;
  90. return tReadInt(&value) && cAddOperation(OP_PUSH_INT) && cAddBytes(&value, sizeof(int));
  91. } else if(cConsumeTokenIf(T_FLOAT)) {
  92. float value;
  93. return tReadFloat(&value) && cAddOperation(OP_PUSH_FLOAT) && cAddBytes(&value, sizeof(float));
  94. } else if(cConsumeTokenIf(T_NULL)) {
  95. return cAddOperation(OP_PUSH_NULL);
  96. } else if(cConsumeTokenIf(T_TRUE)) {
  97. return cAddOperation(OP_PUSH_TRUE);
  98. } else if(cConsumeTokenIf(T_FALSE)) {
  99. return cAddOperation(OP_PUSH_FALSE);
  100. } else if(cConsumeTokenIf(T_OPEN_BRACKET)) {
  101. return cExpression() && cConsumeToken(T_CLOSE_BRACKET);
  102. } else if(cConsumeTokenIf(T_LITERAL)) {
  103. const char* literal = tReadString();
  104. if(literal == NULL) {
  105. cError("literal without string on line %d", line);
  106. return false;
  107. }
  108. int varPointer = cAddVar(literal);
  109. if(varPointer == -1) {
  110. return false;
  111. }
  112. return cAddOperation(OP_GET) && cAddBytes(&varPointer, sizeof(int));
  113. }
  114. cUnexpectedToken(tPeekToken());
  115. return false;
  116. }
  117. static bool cMul() {
  118. if(!cPrimary()) {
  119. return false;
  120. }
  121. while(cConsumeTokenIf(T_MUL)) {
  122. if(!cPrimary() || !cAddOperation(OP_MUL)) {
  123. return false;
  124. }
  125. }
  126. return true;
  127. }
  128. static bool cAdd() {
  129. if(!cMul()) {
  130. return false;
  131. }
  132. while(cConsumeTokenIf(T_ADD)) {
  133. if(!cMul() || !cAddOperation(OP_ADD)) {
  134. return false;
  135. }
  136. }
  137. return true;
  138. }
  139. static bool cExpression() {
  140. return cAdd();
  141. }
  142. static bool cLiteral() {
  143. const char* literal = tReadString();
  144. if(literal == NULL) {
  145. cError("literal without string on line %d", line);
  146. return false;
  147. }
  148. Token t = tReadTokenAndLine();
  149. if(t != T_SET) {
  150. cUnexpectedToken(t);
  151. return false;
  152. }
  153. int varPointer = cAddVar(literal);
  154. if(varPointer == -1) {
  155. return false;
  156. }
  157. return cExpression() && cAddOperation(OP_SET) && cAddBytes(&varPointer, sizeof(int)) && cConsumeToken(T_SEMICOLON);
  158. }
  159. static bool cPrint() {
  160. return cExpression() && cConsumeToken(T_SEMICOLON) && cAddOperation(OP_PRINT);
  161. }
  162. static bool cLine() {
  163. Token t = tReadTokenAndLine();
  164. if(t == T_END) {
  165. return false;
  166. } else if(!cAddOperation(OP_LINE) || !cAddBytes(&line, sizeof(line))) {
  167. return false;
  168. }
  169. if(t == T_PRINT) {
  170. return cPrint();
  171. } else if(t == T_LITERAL) {
  172. return cLiteral();
  173. }
  174. cUnexpectedToken(t);
  175. return false;
  176. }
  177. static void cForEachLine() {
  178. writeIndex = 0;
  179. varIndex = 0;
  180. if(!cAddOperation(OP_PUSH)) {
  181. return;
  182. }
  183. void* globalVars = cReserveBytes(sizeof(int));
  184. if(globalVars == NULL) {
  185. return;
  186. }
  187. while(cLine()) {
  188. }
  189. if(!cAddOperation(OP_POP)) {
  190. return;
  191. }
  192. cSetBytes(&varIndex, globalVars, sizeof(int));
  193. cAddBytes(&varIndex, sizeof(int));
  194. }
  195. unsigned char* cCompile(int* codeLength) {
  196. error[0] = '\0';
  197. cForEachLine();
  198. if(error[0] != '\0') {
  199. return NULL;
  200. }
  201. unsigned char* bytes = malloc(writeIndex);
  202. memcpy(bytes, byteCode, writeIndex);
  203. *codeLength = writeIndex;
  204. return bytes;
  205. }
  206. const char* cGetError() {
  207. return error;
  208. }