#include #include #include #include "Compiler.h" #include "Operation.h" #include "Tokenizer.h" #define MAX_BYTES (1024 * 1024) static const char* UNEXPECTED_TOKEN = "unexpected token"; static const char* FULL_BUFFER = "the compiler buffer is too small"; static const char* error = NULL; static unsigned char byteCode[MAX_BYTES]; static int writeIndex = 0; static bool cAddBytes(const void* data, int length) { if(writeIndex + length > MAX_BYTES) { error = FULL_BUFFER; return false; } memcpy(byteCode + writeIndex, data, length); writeIndex += length; return true; } static bool cAddOperation(Operation token) { unsigned char c = token; return cAddBytes(&c, 1); } static bool cConsumeToken(Token t) { if(tReadToken() == t) { return true; } error = UNEXPECTED_TOKEN; return false; } static bool cConsumeTokenIf(Token t) { if(tPeekToken() == t) { tReadToken(); return true; } return false; } static bool cConstant() { if(cConsumeToken(T_INT)) { int value; return tReadInt(&value) && cAddOperation(OP_PUSH_INT) && cAddBytes(&value, sizeof(int)); } return false; } static bool cAdd() { if(!cConstant()) { return false; } while(cConsumeTokenIf(T_ADD)) { if(!cConstant() || !cAddOperation(OP_ADD)) { return false; } } return true; } static bool cPrint() { return cAdd() && cConsumeToken(T_SEMICOLON) && cAddOperation(OP_PRINT); } static bool cLine() { Token t = tReadToken(); if(t == T_END) { return false; } else if(t == T_PRINT) { return cPrint(); } error = UNEXPECTED_TOKEN; return false; } unsigned char* cCompile(int* codeLength) { while(cLine()) { } if(error != NULL) { return NULL; } unsigned char* bytes = malloc(writeIndex); memcpy(bytes, byteCode, writeIndex); *codeLength = writeIndex; return bytes; } const char* cGetError() { return error; }