|
@@ -1,3 +1,4 @@
|
|
|
+#include <stdarg.h>
|
|
|
#include <stdio.h>
|
|
|
#include <string.h>
|
|
|
|
|
@@ -5,15 +6,21 @@
|
|
|
#include "Utils.h"
|
|
|
|
|
|
#define TOKEN_BUFFER_LENGTH (1024 * 1024)
|
|
|
+#define ERROR_LENGTH 256
|
|
|
|
|
|
static char tokenBuffer[TOKEN_BUFFER_LENGTH];
|
|
|
static int writeIndex = 0;
|
|
|
static int readIndex = 0;
|
|
|
-
|
|
|
-static const char* TOO_LONG_LITERAL = "literal is too long";
|
|
|
-static const char* UNKNOWN_CHARACTER = "unknown character";
|
|
|
+static int line = 1;
|
|
|
static FILE* file = NULL;
|
|
|
-static const char* error = NULL;
|
|
|
+static char error[ERROR_LENGTH] = {'\0'};
|
|
|
+
|
|
|
+static void tError(const char* format, ...) {
|
|
|
+ va_list args;
|
|
|
+ va_start(args, format);
|
|
|
+ vsnprintf(error, ERROR_LENGTH, format, args);
|
|
|
+ va_end(args);
|
|
|
+}
|
|
|
|
|
|
static bool tAdd(const void* data, int length) {
|
|
|
if(writeIndex + length > TOKEN_BUFFER_LENGTH) {
|
|
@@ -54,7 +61,7 @@ static bool tParseLiteral(int c) {
|
|
|
buffer[0] = c;
|
|
|
while(isLetter(tPeek())) {
|
|
|
if(index >= 63) {
|
|
|
- error = TOO_LONG_LITERAL;
|
|
|
+ tError("literal is too long");
|
|
|
return false;
|
|
|
}
|
|
|
buffer[index++] = tRead();
|
|
@@ -84,19 +91,21 @@ static bool tParseToken() {
|
|
|
return tParseNumber(c);
|
|
|
}
|
|
|
switch(c) {
|
|
|
- case ' ':
|
|
|
- case '\n': return true;
|
|
|
+ case ' ': return true;
|
|
|
+ case '\n': line++; return true;
|
|
|
case '+': return tAddToken(T_ADD);
|
|
|
+ case '*': return tAddToken(T_MUL);
|
|
|
case ';': return tAddToken(T_SEMICOLON);
|
|
|
}
|
|
|
- error = UNKNOWN_CHARACTER;
|
|
|
+ tError("unknown character on line %d: %c", line, c);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
static void tParseFile() {
|
|
|
readIndex = 0;
|
|
|
writeIndex = 0;
|
|
|
- error = NULL;
|
|
|
+ line = 1;
|
|
|
+ error[0] = '\0';
|
|
|
while(tParseToken()) {
|
|
|
}
|
|
|
}
|
|
@@ -104,12 +113,12 @@ static void tParseFile() {
|
|
|
bool tTokenize(const char* path) {
|
|
|
file = fopen(path, "r");
|
|
|
if(file == NULL) {
|
|
|
- error = "cannot read file";
|
|
|
+ tError("cannot read file '%s'", path);
|
|
|
return true;
|
|
|
}
|
|
|
tParseFile();
|
|
|
fclose(file);
|
|
|
- return error != NULL;
|
|
|
+ return error[0] != '\0';
|
|
|
}
|
|
|
|
|
|
const char* tGetError() {
|
|
@@ -145,6 +154,7 @@ const char* tGetTokenName(Token token) {
|
|
|
switch(token) {
|
|
|
case T_INT: return "int";
|
|
|
case T_ADD: return "+";
|
|
|
+ case T_MUL: return "*";
|
|
|
case T_PRINT: return "print";
|
|
|
case T_SEMICOLON: return ";";
|
|
|
case T_END: return "end";
|