Parser emitting CALL, GOTO, IF, and RETURN. They need added to the renderer.
This commit is contained in:
parent
5c5fdf3375
commit
9cd1aef2f5
3 changed files with 159 additions and 95 deletions
|
@ -27,17 +27,21 @@
|
||||||
enum ParserKeywordE {
|
enum ParserKeywordE {
|
||||||
PARSE_NONE = 0,
|
PARSE_NONE = 0,
|
||||||
PARSE_BOX,
|
PARSE_BOX,
|
||||||
|
PARSE_CALL,
|
||||||
PARSE_CIRCLE,
|
PARSE_CIRCLE,
|
||||||
PARSE_CLEAR,
|
PARSE_CLEAR,
|
||||||
PARSE_COLOR,
|
PARSE_COLOR,
|
||||||
PARSE_COMMENT,
|
PARSE_COMMENT,
|
||||||
PARSE_ELLIPSE,
|
PARSE_ELLIPSE,
|
||||||
PARSE_FILL,
|
PARSE_FILL,
|
||||||
|
PARSE_GOTO,
|
||||||
|
PARSE_IF,
|
||||||
PARSE_LINE,
|
PARSE_LINE,
|
||||||
PARSE_PALETTE,
|
PARSE_PALETTE,
|
||||||
PARSE_PLOT,
|
PARSE_PLOT,
|
||||||
PARSE_RECTANGLE,
|
PARSE_RECTANGLE,
|
||||||
PARSE_RESET,
|
PARSE_RESET,
|
||||||
|
PARSE_RETURN,
|
||||||
// After this are keywords for things that aren't commands but still need to emit bytecode.
|
// After this are keywords for things that aren't commands but still need to emit bytecode.
|
||||||
PARSE_MATH,
|
PARSE_MATH,
|
||||||
PARSE_LABEL
|
PARSE_LABEL
|
||||||
|
|
234
src/vecparse.c
234
src/vecparse.c
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <ctype.h>
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "vecparse.h"
|
#include "vecparse.h"
|
||||||
|
|
||||||
|
@ -46,14 +45,15 @@ typedef struct LabelS {
|
||||||
|
|
||||||
|
|
||||||
static void ensureBufferSize(VecByteCodeT *bytecode, int needed);
|
static void ensureBufferSize(VecByteCodeT *bytecode, int needed);
|
||||||
|
static int labelGetValue(LabelT *labels, char *label);
|
||||||
static void outputByte(VecByteCodeT *bytecode, unsigned short word);
|
static void outputByte(VecByteCodeT *bytecode, unsigned short word);
|
||||||
static void outputWord(VecByteCodeT *bytecode, unsigned short word);
|
static void outputWord(VecByteCodeT *bytecode, unsigned short word);
|
||||||
|
static char *parserGetNextLine(char *str, char **savePtr);
|
||||||
static gboolean parserGetNextValue(char *token, char **valueEnd, char **variables, int *x);
|
static gboolean parserGetNextValue(char *token, char **valueEnd, char **variables, int *x);
|
||||||
static gboolean parserGetWord(char *word, char **tokenEnd);
|
static int parserGetWord(char *wordList, char **tokenEnd);
|
||||||
static gboolean parserGetX(char **tokenEnd, char **variables, int *x);
|
static gboolean parserGetX(char **tokenEnd, char **variables, int *x);
|
||||||
static gboolean parserGetXY(char **tokenEnd, char **variables, int *x, int *y);
|
static gboolean parserGetXY(char **tokenEnd, char **variables, int *x, int *y);
|
||||||
static gboolean parserGetXYZ(char **tokenEnd, char **variables, int *x, int *y, int *z);
|
static gboolean parserGetXYZ(char **tokenEnd, char **variables, int *x, int *y, int *z);
|
||||||
static char *strtoke(char *str, const char *delim, char **savePtr);
|
|
||||||
|
|
||||||
|
|
||||||
static void ensureBufferSize(VecByteCodeT *bytecode, int needed) {
|
static void ensureBufferSize(VecByteCodeT *bytecode, int needed) {
|
||||||
|
@ -71,6 +71,31 @@ static void ensureBufferSize(VecByteCodeT *bytecode, int needed) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int labelGetValue(LabelT *labels, char *label) {
|
||||||
|
int index;
|
||||||
|
int found = -1;
|
||||||
|
|
||||||
|
// Do we know this label? We search ourselves so it's case-insensitive.
|
||||||
|
for (index = 0; index < hmlen(labels); index++) {
|
||||||
|
printf("Label %d of %d; %s == %s\n", index, (int)hmlen(labels), labels[index].key, label);
|
||||||
|
if (strcasecmp(label, labels[index].key) == 0) {
|
||||||
|
found = index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found < 0) {
|
||||||
|
// We don't yet know this label, so it's a forward reference.
|
||||||
|
// Record it with a negative location, so we can resolve it later.
|
||||||
|
index = 0 - (hmlen(labels) + 1);
|
||||||
|
hmput(labels, label, index);
|
||||||
|
} else {
|
||||||
|
index = labels[index].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void outputByte(VecByteCodeT *bytecode, unsigned short word) {
|
static void outputByte(VecByteCodeT *bytecode, unsigned short word) {
|
||||||
unsigned char byte = (unsigned char)word;
|
unsigned char byte = (unsigned char)word;
|
||||||
|
|
||||||
|
@ -92,6 +117,35 @@ static void outputWord(VecByteCodeT *bytecode, unsigned short word) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Custom strtok_r because:
|
||||||
|
// A sequence of two or more contiguous delimiter bytes in the
|
||||||
|
// parsed string is considered to be a single delimiter.
|
||||||
|
// Which is exactly what we don't want for the line parser.
|
||||||
|
static char *parserGetNextLine(char *str, char **savePtr) {
|
||||||
|
char *token = NULL;
|
||||||
|
|
||||||
|
if (str) {
|
||||||
|
*savePtr = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*savePtr) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
token = *savePtr;
|
||||||
|
*savePtr = strpbrk(*savePtr, "\n");
|
||||||
|
|
||||||
|
if (*savePtr) {
|
||||||
|
**savePtr = 0;
|
||||||
|
*savePtr = *savePtr + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (token != NULL && (token[0] == ' ' || token[0] == '\t')) token++;
|
||||||
|
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static gboolean parserGetNextValue(char *token, char **valueEnd, char **variables, int *x) {
|
static gboolean parserGetNextValue(char *token, char **valueEnd, char **variables, int *x) {
|
||||||
char *value;
|
char *value;
|
||||||
char *endPtr = NULL;
|
char *endPtr = NULL;
|
||||||
|
@ -128,7 +182,7 @@ static gboolean parserGetNextValue(char *token, char **valueEnd, char **variable
|
||||||
*x = -*x;
|
*x = -*x;
|
||||||
*x |= 0x4000;
|
*x |= 0x4000;
|
||||||
}
|
}
|
||||||
// Ensure MSb is cleared so we know it's a number.
|
// Ensure MSb is cleared, so we know it's a number.
|
||||||
*x &= 0x7fff;
|
*x &= 0x7fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,16 +190,27 @@ static gboolean parserGetNextValue(char *token, char **valueEnd, char **variable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static gboolean parserGetWord(char *word, char **tokenEnd) {
|
static int parserGetWord(char *wordList, char **tokenEnd) {
|
||||||
char *token;
|
char *token;
|
||||||
|
char *word;
|
||||||
|
char *wordEnd = NULL;
|
||||||
|
int index = -1;
|
||||||
|
|
||||||
// Is this token the "WORD"?
|
// Returns -1 if the word is not found in the wordlist.
|
||||||
|
// Returns a zero-based index of the position in the list
|
||||||
|
// if one of the words is found.
|
||||||
|
|
||||||
token = strtok_r(NULL, " ", tokenEnd);
|
token = strtok_r(NULL, " ", tokenEnd);
|
||||||
if (token == NULL) return FALSE;
|
if (token == NULL) return index;
|
||||||
if (strcasecmp(token, word) != 0) return FALSE;
|
|
||||||
|
|
||||||
return TRUE;
|
word = strtok_r(wordList, " ", &wordEnd);
|
||||||
|
while (word != NULL) {
|
||||||
|
index++;
|
||||||
|
if (strcasecmp(token, word) == 0) break;
|
||||||
|
word = strtok_r(NULL, " ", &wordEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -186,7 +251,7 @@ static gboolean parserGetX(char **tokenEnd, char **variables, int *x) {
|
||||||
*x = -*x;
|
*x = -*x;
|
||||||
*x |= 0x4000;
|
*x |= 0x4000;
|
||||||
}
|
}
|
||||||
// Ensure MSb is cleared so we know it's a number.
|
// Ensure MSb is cleared, so we know it's a number.
|
||||||
*x &= 0x7fff;
|
*x &= 0x7fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,59 +292,6 @@ static gboolean parserGetXYZ(char **tokenEnd, char **variables, int *x, int *y,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Custom strtok_r because:
|
|
||||||
// A sequence of two or more contiguous delimiter bytes in the
|
|
||||||
// parsed string is considered to be a single delimiter.
|
|
||||||
// Which is exactly what we don't want for the line parser.
|
|
||||||
static char *strtoke(char *str, const char *delim, char **savePtr) {
|
|
||||||
/*
|
|
||||||
char *end = NULL;
|
|
||||||
|
|
||||||
if (str == NULL) {
|
|
||||||
str = *savePtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*str == 0) {
|
|
||||||
*savePtr = str;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
str = strpbrk(str, delim);
|
|
||||||
end = str + 1;
|
|
||||||
|
|
||||||
if (*end == 0) {
|
|
||||||
*savePtr++ = end;
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
*end = 0;
|
|
||||||
*savePtr = end + 1;
|
|
||||||
|
|
||||||
return str;
|
|
||||||
*/
|
|
||||||
char *token = NULL; // found token
|
|
||||||
// assign new start in case
|
|
||||||
if (str) {
|
|
||||||
*savePtr = str;
|
|
||||||
}
|
|
||||||
// check whether text to parse left
|
|
||||||
if (!*savePtr) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
// remember current start as found token
|
|
||||||
token = *savePtr;
|
|
||||||
// find next occurrence of delim
|
|
||||||
*savePtr = strpbrk(*savePtr, delim);
|
|
||||||
// replace delim with terminator and move start to follower
|
|
||||||
if (*savePtr) {
|
|
||||||
**savePtr = 0;
|
|
||||||
*savePtr = *savePtr + 1;
|
|
||||||
}
|
|
||||||
// done
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int vecparser(char *programIn, VecByteCodeT *bytecode) {
|
int vecparser(char *programIn, VecByteCodeT *bytecode) {
|
||||||
int keyword;
|
int keyword;
|
||||||
char *line;
|
char *line;
|
||||||
|
@ -301,17 +313,21 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
|
||||||
int result = -1; // Returns -1 on success or line number of first error.
|
int result = -1; // Returns -1 on success or line number of first error.
|
||||||
KeywordsT commands[] = {
|
KeywordsT commands[] = {
|
||||||
{ "BOX", PARSE_BOX },
|
{ "BOX", PARSE_BOX },
|
||||||
|
{ "CALL", PARSE_CALL },
|
||||||
{ "CIRCLE", PARSE_CIRCLE },
|
{ "CIRCLE", PARSE_CIRCLE },
|
||||||
{ "CLEAR", PARSE_CLEAR },
|
{ "CLEAR", PARSE_CLEAR },
|
||||||
{ "COLOR", PARSE_COLOR },
|
{ "COLOR", PARSE_COLOR },
|
||||||
{ "//", PARSE_COMMENT },
|
{ "//", PARSE_COMMENT },
|
||||||
{ "ELLIPSE", PARSE_ELLIPSE },
|
{ "ELLIPSE", PARSE_ELLIPSE },
|
||||||
|
{ "GOTO", PARSE_GOTO },
|
||||||
|
{ "IF", PARSE_IF },
|
||||||
{ "FILL", PARSE_FILL },
|
{ "FILL", PARSE_FILL },
|
||||||
{ "LINE", PARSE_LINE },
|
{ "LINE", PARSE_LINE },
|
||||||
{ "PALETTE", PARSE_PALETTE },
|
{ "PALETTE", PARSE_PALETTE },
|
||||||
{ "PLOT", PARSE_PLOT },
|
{ "PLOT", PARSE_PLOT },
|
||||||
{ "RECTANGLE", PARSE_RECTANGLE },
|
{ "RECTANGLE", PARSE_RECTANGLE },
|
||||||
{ "RESET", PARSE_RESET },
|
{ "RESET", PARSE_RESET },
|
||||||
|
{ "RETURN", PARSE_RETURN },
|
||||||
{ NULL, PARSE_NONE }
|
{ NULL, PARSE_NONE }
|
||||||
};
|
};
|
||||||
OperatorsT math[] = {
|
OperatorsT math[] = {
|
||||||
|
@ -332,19 +348,16 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
|
||||||
|
|
||||||
// Parse code.
|
// Parse code.
|
||||||
lineNumber = 0;
|
lineNumber = 0;
|
||||||
line = strtoke(programIn, "\n", &lineEnd);
|
line = parserGetNextLine(programIn, &lineEnd);
|
||||||
while (line != NULL && (line[0] == ' ' || line[0] == '\t')) line++;
|
|
||||||
while (line != NULL) {
|
while (line != NULL) {
|
||||||
|
|
||||||
printf("%d [%s]\n", lineNumber, line);
|
|
||||||
|
|
||||||
// Get the first token on the line.
|
// Get the first token on the line.
|
||||||
token = strtok_r(line, " ", &tokenEnd);
|
token = strtok_r(line, " ", &tokenEnd);
|
||||||
|
|
||||||
// Is this something we care about? It'll be math, a label, or a keyword.
|
// Is this something we care about? It'll be math, a label, or a keyword.
|
||||||
lineOkay = FALSE;
|
lineOkay = FALSE;
|
||||||
|
|
||||||
// Is this a blank line?
|
// Is this a blank line with no tokens?
|
||||||
if (token == NULL) {
|
if (token == NULL) {
|
||||||
|
|
||||||
// Yep - just move on.
|
// Yep - just move on.
|
||||||
|
@ -400,8 +413,12 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
|
||||||
|
|
||||||
// It's a label.
|
// It's a label.
|
||||||
|
|
||||||
|
// Remove trailing colon.
|
||||||
|
token[strlen(token) - 1] = 0;
|
||||||
|
|
||||||
// Have we already used this label?
|
// Have we already used this label?
|
||||||
x2 = -1;
|
x2 = -1;
|
||||||
|
// We search ourselves so it's case-insensitive.
|
||||||
for (x1 = 0; x1 < hmlen(labels); x1++) {
|
for (x1 = 0; x1 < hmlen(labels); x1++) {
|
||||||
if (strcasecmp(token, labels[x1].key) == 0) {
|
if (strcasecmp(token, labels[x1].key) == 0) {
|
||||||
x2 = x1;
|
x2 = x1;
|
||||||
|
@ -431,7 +448,7 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
|
||||||
case PARSE_BOX:
|
case PARSE_BOX:
|
||||||
// Box (value),(value) to (value),(value)
|
// Box (value),(value) to (value),(value)
|
||||||
if (!parserGetXY(&tokenEnd, variables, &x1, &y1)) break;
|
if (!parserGetXY(&tokenEnd, variables, &x1, &y1)) break;
|
||||||
if (!parserGetWord("TO", &tokenEnd)) break;
|
if (parserGetWord("TO", &tokenEnd) < 0) break;
|
||||||
if (!parserGetXY(&tokenEnd, variables, &x2, &y2)) break;
|
if (!parserGetXY(&tokenEnd, variables, &x2, &y2)) break;
|
||||||
if (IS_NUMBER(x1) && IS_NUMBER(x2)) if (x2 < x1) break;
|
if (IS_NUMBER(x1) && IS_NUMBER(x2)) if (x2 < x1) break;
|
||||||
if (IS_NUMBER(x1)) if (x1 < 0 || x1 > 319) break;
|
if (IS_NUMBER(x1)) if (x1 < 0 || x1 > 319) break;
|
||||||
|
@ -447,10 +464,19 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
|
||||||
lineOkay = TRUE;
|
lineOkay = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PARSE_CALL:
|
||||||
|
// Call (label)
|
||||||
|
if (tokenEnd == NULL) break;
|
||||||
|
x1 = labelGetValue(labels, tokenEnd);
|
||||||
|
outputByte(bytecode, PARSE_CALL);
|
||||||
|
outputWord(bytecode, x1);
|
||||||
|
lineOkay = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
case PARSE_CIRCLE:
|
case PARSE_CIRCLE:
|
||||||
// Circle (value) at (value),(value)
|
// Circle (value) at (value),(value)
|
||||||
if (!parserGetX(&tokenEnd, variables, &y2)) break;
|
if (!parserGetX(&tokenEnd, variables, &y2)) break;
|
||||||
if (!parserGetWord("AT", &tokenEnd)) break;
|
if (parserGetWord("AT", &tokenEnd) < 0) break;
|
||||||
if (!parserGetXY(&tokenEnd, variables, &x1, &y1)) break;
|
if (!parserGetXY(&tokenEnd, variables, &x1, &y1)) break;
|
||||||
if (IS_NUMBER(x1)) if (x1 < 0 || x1 > 319) break;
|
if (IS_NUMBER(x1)) if (x1 < 0 || x1 > 319) break;
|
||||||
if (IS_NUMBER(y1)) if (y1 < 0 || y1 > 199) break;
|
if (IS_NUMBER(y1)) if (y1 < 0 || y1 > 199) break;
|
||||||
|
@ -486,7 +512,7 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
|
||||||
case PARSE_ELLIPSE:
|
case PARSE_ELLIPSE:
|
||||||
// Ellipse (value),(value) to (value),(value)
|
// Ellipse (value),(value) to (value),(value)
|
||||||
if (!parserGetXY(&tokenEnd, variables, &x1, &y1)) break;
|
if (!parserGetXY(&tokenEnd, variables, &x1, &y1)) break;
|
||||||
if (!parserGetWord("TO", &tokenEnd)) break;
|
if (parserGetWord("TO", &tokenEnd) < 0) break;
|
||||||
if (!parserGetXY(&tokenEnd, variables, &x2, &y2)) break;
|
if (!parserGetXY(&tokenEnd, variables, &x2, &y2)) break;
|
||||||
if (IS_NUMBER(x1) && IS_NUMBER(x2)) if (x2 < x1) break;
|
if (IS_NUMBER(x1) && IS_NUMBER(x2)) if (x2 < x1) break;
|
||||||
if (IS_NUMBER(x1)) if (x1 < 0 || x1 > 319) break;
|
if (IS_NUMBER(x1)) if (x1 < 0 || x1 > 319) break;
|
||||||
|
@ -509,7 +535,7 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
|
||||||
if (IS_NUMBER(y1)) if (y1 < 0 || y1 > 199) break;
|
if (IS_NUMBER(y1)) if (y1 < 0 || y1 > 199) break;
|
||||||
// Do they want to fill to a certain color? Or over the current color?
|
// Do they want to fill to a certain color? Or over the current color?
|
||||||
x2 = 16; // 16 == Fill, otherwise FillTo
|
x2 = 16; // 16 == Fill, otherwise FillTo
|
||||||
if (parserGetWord("TO", &tokenEnd)) {
|
if (parserGetWord("TO", &tokenEnd) >= 0) {
|
||||||
if (!parserGetX(&tokenEnd, variables, &x2)) break;
|
if (!parserGetX(&tokenEnd, variables, &x2)) break;
|
||||||
if (IS_NUMBER(x2)) if (x2 < 0 || x2 > 15) break;
|
if (IS_NUMBER(x2)) if (x2 < 0 || x2 > 15) break;
|
||||||
}
|
}
|
||||||
|
@ -520,6 +546,32 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
|
||||||
lineOkay = TRUE;
|
lineOkay = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PARSE_GOTO:
|
||||||
|
// Goto (label)
|
||||||
|
if (tokenEnd == NULL) break;
|
||||||
|
x1 = labelGetValue(labels, tokenEnd);
|
||||||
|
outputByte(bytecode, PARSE_GOTO);
|
||||||
|
outputWord(bytecode, x1);
|
||||||
|
lineOkay = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PARSE_IF:
|
||||||
|
// If (value) (compare) (value) (goto|call) (label)
|
||||||
|
if (!parserGetX(&tokenEnd, variables, &x1)) break;
|
||||||
|
y1 = parserGetWord("== != < > <= >=", &tokenEnd);
|
||||||
|
if (y1 < 0) break;
|
||||||
|
if (!parserGetX(&tokenEnd, variables, &x2)) break;
|
||||||
|
y2 = parserGetWord("goto call", &tokenEnd);
|
||||||
|
if (y2 < 0) break;
|
||||||
|
if (tokenEnd == NULL) break;
|
||||||
|
outputByte(bytecode, PARSE_IF);
|
||||||
|
outputWord(bytecode, x1);
|
||||||
|
outputByte(bytecode, y1);
|
||||||
|
outputWord(bytecode, x2);
|
||||||
|
outputByte(bytecode, y2);
|
||||||
|
outputWord(bytecode, labelGetValue(labels, tokenEnd));
|
||||||
|
break;
|
||||||
|
|
||||||
case PARSE_LABEL:
|
case PARSE_LABEL:
|
||||||
// Won't happen.
|
// Won't happen.
|
||||||
break;
|
break;
|
||||||
|
@ -528,7 +580,7 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
|
||||||
// Line (value),(value) to (value),(value) [to ...]
|
// Line (value),(value) to (value),(value) [to ...]
|
||||||
points = NULL;
|
points = NULL;
|
||||||
if (!parserGetXY(&tokenEnd, variables, &p1.x, &p1.y)) break;
|
if (!parserGetXY(&tokenEnd, variables, &p1.x, &p1.y)) break;
|
||||||
if (!parserGetWord("TO", &tokenEnd)) break;
|
if (parserGetWord("TO", &tokenEnd) < 0) break;
|
||||||
if (!parserGetXY(&tokenEnd, variables, &p2.x, &p2.y)) break;
|
if (!parserGetXY(&tokenEnd, variables, &p2.x, &p2.y)) break;
|
||||||
if (IS_NUMBER(p1.x)) if (p1.x < 0 || p1.x > 319) break;
|
if (IS_NUMBER(p1.x)) if (p1.x < 0 || p1.x > 319) break;
|
||||||
if (IS_NUMBER(p1.y)) if (p1.y < 0 || p1.y > 199) break;
|
if (IS_NUMBER(p1.y)) if (p1.y < 0 || p1.y > 199) break;
|
||||||
|
@ -537,16 +589,14 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
|
||||||
arrput(points, p1);
|
arrput(points, p1);
|
||||||
arrput(points, p2);
|
arrput(points, p2);
|
||||||
isOkay = TRUE;
|
isOkay = TRUE;
|
||||||
while (parserGetWord("TO", &tokenEnd)) {
|
while (parserGetWord("TO", &tokenEnd) >= 0) {
|
||||||
if (!parserGetXY(&tokenEnd, variables, &p1.x, &p1.y)) {
|
if (!parserGetXY(&tokenEnd, variables, &p1.x, &p1.y)) {
|
||||||
// Error. Unwind array.
|
// Error.
|
||||||
while (arrlen(points) > 0) {
|
|
||||||
arrdel(points, 0);
|
|
||||||
}
|
|
||||||
arrfree(points);
|
|
||||||
isOkay = FALSE;
|
isOkay = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (IS_NUMBER(p1.x)) if (p1.x < 0 || p1.x > 319) { isOkay = FALSE; break; }
|
||||||
|
if (IS_NUMBER(p1.y)) if (p1.y < 0 || p1.y > 199) { isOkay = FALSE; break; }
|
||||||
arrput(points, p1);
|
arrput(points, p1);
|
||||||
}
|
}
|
||||||
if (isOkay) {
|
if (isOkay) {
|
||||||
|
@ -556,11 +606,6 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
|
||||||
outputWord(bytecode, points[x1].x);
|
outputWord(bytecode, points[x1].x);
|
||||||
outputWord(bytecode, points[x1].y);
|
outputWord(bytecode, points[x1].y);
|
||||||
}
|
}
|
||||||
// Unwind array.
|
|
||||||
while (arrlen(points) > 0) {
|
|
||||||
arrdel(points, 0);
|
|
||||||
}
|
|
||||||
arrfree(points);
|
|
||||||
lineOkay = TRUE;
|
lineOkay = TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -572,7 +617,7 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
|
||||||
case PARSE_PALETTE:
|
case PARSE_PALETTE:
|
||||||
// Palette (short) AS (short),(short),(short)
|
// Palette (short) AS (short),(short),(short)
|
||||||
if (!parserGetX(&tokenEnd, variables, &x1)) break;
|
if (!parserGetX(&tokenEnd, variables, &x1)) break;
|
||||||
if (!parserGetWord("AS", &tokenEnd)) break;
|
if (parserGetWord("AS", &tokenEnd) < 0) break;
|
||||||
if (!parserGetXYZ(&tokenEnd, variables, &x2, &y1, &y2)) break;
|
if (!parserGetXYZ(&tokenEnd, variables, &x2, &y1, &y2)) break;
|
||||||
if (IS_NUMBER(x1)) if (x1 < 0 || x1 > 15) break;
|
if (IS_NUMBER(x1)) if (x1 < 0 || x1 > 15) break;
|
||||||
if (IS_NUMBER(x2)) if (x2 < 0 || x2 > 15) break;
|
if (IS_NUMBER(x2)) if (x2 < 0 || x2 > 15) break;
|
||||||
|
@ -600,7 +645,7 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
|
||||||
case PARSE_RECTANGLE:
|
case PARSE_RECTANGLE:
|
||||||
// Rectangle (value),(value) to (value),(value)
|
// Rectangle (value),(value) to (value),(value)
|
||||||
if (!parserGetXY(&tokenEnd, variables, &x1, &y1)) break;
|
if (!parserGetXY(&tokenEnd, variables, &x1, &y1)) break;
|
||||||
if (!parserGetWord("TO", &tokenEnd)) break;
|
if (parserGetWord("TO", &tokenEnd) < 0) break;
|
||||||
if (!parserGetXY(&tokenEnd, variables, &x2, &y2)) break;
|
if (!parserGetXY(&tokenEnd, variables, &x2, &y2)) break;
|
||||||
if (IS_NUMBER(x1) && IS_NUMBER(x2)) if (x2 < x1) break;
|
if (IS_NUMBER(x1) && IS_NUMBER(x2)) if (x2 < x1) break;
|
||||||
if (IS_NUMBER(x1)) if (x1 < 0 || x1 > 319) break;
|
if (IS_NUMBER(x1)) if (x1 < 0 || x1 > 319) break;
|
||||||
|
@ -621,8 +666,22 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
|
||||||
lineOkay = TRUE;
|
lineOkay = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PARSE_RETURN:
|
||||||
|
// Return
|
||||||
|
outputByte(bytecode, PARSE_RETURN);
|
||||||
|
lineOkay = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
} // switch
|
} // switch
|
||||||
|
|
||||||
|
// Unwind point array if needed.
|
||||||
|
if (points != NULL) {
|
||||||
|
while (arrlen(points) > 0) {
|
||||||
|
arrdel(points, 0);
|
||||||
|
}
|
||||||
|
arrfree(points);
|
||||||
|
}
|
||||||
|
|
||||||
// Stop looking for this keyword - we handled it.
|
// Stop looking for this keyword - we handled it.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -647,8 +706,7 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move to next line.
|
// Move to next line.
|
||||||
line = strtoke(NULL, "\n", &lineEnd);
|
line = parserGetNextLine(NULL, &lineEnd);
|
||||||
while (line != NULL && (line[0] == ' ' || line[0] == '\t')) line++;
|
|
||||||
lineNumber++;
|
lineNumber++;
|
||||||
} // read program line
|
} // read program line
|
||||||
|
|
||||||
|
|
|
@ -319,6 +319,8 @@ static void renderBytecode(VecByteCodeT *bytecode, VectorDataT *self) {
|
||||||
#define GET_BYTE (bytecode->bytes[index++])
|
#define GET_BYTE (bytecode->bytes[index++])
|
||||||
#define GET_WORD getWord(bytecode, &index)
|
#define GET_WORD getWord(bytecode, &index)
|
||||||
|
|
||||||
|
printf("-----------------------------------\n");
|
||||||
|
|
||||||
self->variables = NULL;
|
self->variables = NULL;
|
||||||
|
|
||||||
while (index < bytecode->length) {
|
while (index < bytecode->length) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue