|
@@ -207,6 +207,14 @@ static Token nextToken() {
|
|
|
return tokenReadIndex < tokenWriteIndex ? tokens[tokenReadIndex++] : END;
|
|
return tokenReadIndex < tokenWriteIndex ? tokens[tokenReadIndex++] : END;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static const char* peekLiteral() {
|
|
|
|
|
+ Token t = peekToken();
|
|
|
|
|
+ if(t != LITERAL) {
|
|
|
|
|
+ return nullptr;
|
|
|
|
|
+ }
|
|
|
|
|
+ return (char*)(tokens + tokenReadIndex + sizeof(Token));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static const char* readString() {
|
|
static const char* readString() {
|
|
|
if(tokenReadIndex >= tokenWriteIndex) {
|
|
if(tokenReadIndex >= tokenWriteIndex) {
|
|
|
THROW_ERROR("readString on empty buffer, line %zu", lineCounter);
|
|
THROW_ERROR("readString on empty buffer, line %zu", lineCounter);
|
|
@@ -270,6 +278,21 @@ static double readDouble() {
|
|
|
THROW_ERROR("Unexpected unknown token on line %zu", lineCounter);
|
|
THROW_ERROR("Unexpected unknown token on line %zu", lineCounter);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static void consumeToken(Token t) {
|
|
|
|
|
+ Token actual = nextToken();
|
|
|
|
|
+ if(t != actual) {
|
|
|
|
|
+ unexpectedToken(actual);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void consumeLiteral(const char* name) {
|
|
|
|
|
+ consumeToken(LITERAL);
|
|
|
|
|
+ const char* actual = readString();
|
|
|
|
|
+ if(strcmp(actual, name) != 0) {
|
|
|
|
|
+ THROW_ERROR("Unexpected literal(%s) on line %zu", actual, lineCounter);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static void compileConstant() {
|
|
static void compileConstant() {
|
|
|
Token t = nextToken();
|
|
Token t = nextToken();
|
|
|
if(t == STRING) {
|
|
if(t == STRING) {
|
|
@@ -296,7 +319,36 @@ static void compileExpression() {
|
|
|
compileAdd();
|
|
compileAdd();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static void compileLine(Token t);
|
|
|
|
|
+
|
|
|
|
|
+static void compileIf() {
|
|
|
|
|
+ compileExpression();
|
|
|
|
|
+ CODE(codePushInstruction(JUMP_ON_0));
|
|
|
|
|
+ size_t posIndex = codeGetWritePosition();
|
|
|
|
|
+ CODE(codePushSize(0));
|
|
|
|
|
+ consumeLiteral("then");
|
|
|
|
|
+ consumeToken(NEWLINE);
|
|
|
|
|
+ while(true) {
|
|
|
|
|
+ const char* s = peekLiteral();
|
|
|
|
|
+ if(s == nullptr || strcmp(s, "endif") != 0) {
|
|
|
|
|
+ compileLine(nextToken());
|
|
|
|
|
+ continue;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ consumeLiteral("endif");
|
|
|
|
|
+ consumeToken(NEWLINE);
|
|
|
|
|
+ size_t endIndex = codeGetWritePosition();
|
|
|
|
|
+ codeSetWritePosition(posIndex);
|
|
|
|
|
+ CODE(codePushSize(endIndex));
|
|
|
|
|
+ codeSetWritePosition(endIndex);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static void compileLine(Token t) {
|
|
static void compileLine(Token t) {
|
|
|
|
|
+ if(t == NEWLINE) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
if(t != LITERAL) {
|
|
if(t != LITERAL) {
|
|
|
unexpectedToken(t);
|
|
unexpectedToken(t);
|
|
|
}
|
|
}
|
|
@@ -308,6 +360,8 @@ static void compileLine(Token t) {
|
|
|
}
|
|
}
|
|
|
nextToken();
|
|
nextToken();
|
|
|
CODE(codePushInstruction(PRINT_NEWLINE));
|
|
CODE(codePushInstruction(PRINT_NEWLINE));
|
|
|
|
|
+ } else if(strcmp(s, "if") == 0) {
|
|
|
|
|
+ compileIf();
|
|
|
} else {
|
|
} else {
|
|
|
THROW_ERROR("Unexpected literal(%s) on line %zu", s, lineCounter);
|
|
THROW_ERROR("Unexpected literal(%s) on line %zu", s, lineCounter);
|
|
|
}
|
|
}
|