Leading whitespace is now ignored and blank lines will not throw off where the error mark is displayed. Start of labels.

This commit is contained in:
Scott Duensing 2022-12-04 19:56:56 -06:00
parent 4c644e0eaa
commit 5c5fdf3375

View file

@ -21,6 +21,7 @@
#include <errno.h>
#include <ctype.h>
#include "common.h"
#include "vecparse.h"
@ -38,6 +39,11 @@ typedef struct OperatorsS {
ParserMathT id;
} OperatorsT;
typedef struct LabelS {
char *key;
int value;
} LabelT;
static void ensureBufferSize(VecByteCodeT *bytecode, int needed);
static void outputByte(VecByteCodeT *bytecode, unsigned short word);
@ -47,6 +53,7 @@ static gboolean parserGetWord(char *word, char **tokenEnd);
static gboolean parserGetX(char **tokenEnd, char **variables, int *x);
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 char *strtoke(char *str, const char *delim, char **savePtr);
static void ensureBufferSize(VecByteCodeT *bytecode, int needed) {
@ -101,7 +108,6 @@ static gboolean parserGetNextValue(char *token, char **valueEnd, char **variable
// It's a variable. Do we know it?
*x = -1;
for (index=0; index<arrlen(variables); index++) {
printf("Checking GN %d of %ld, %s = %s\n", index, arrlen(variables), variables[index], value);
if (strcasecmp(variables[index], value) == 0) {
// Set MSb to indicate it's a variable.
index |= 0x8000;
@ -159,7 +165,6 @@ static gboolean parserGetX(char **tokenEnd, char **variables, int *x) {
// It's a variable. Do we know it?
*x = -1;
for (index=0; index<arrlen(variables); index++) {
printf("Checking GX %d of %ld, %s = %s\n", index, arrlen(variables), variables[index], value);
if (strcasecmp(variables[index], value) == 0) {
// Set MSb to indicate it's a variable.
index |= 0x8000;
@ -222,6 +227,59 @@ 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 keyword;
char *line;
@ -239,6 +297,7 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
PointT p2;
PointT *points = NULL;
char **variables = NULL;
LabelT *labels = NULL;
int result = -1; // Returns -1 on success or line number of first error.
KeywordsT commands[] = {
{ "BOX", PARSE_BOX },
@ -273,15 +332,26 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
// Parse code.
lineNumber = 0;
line = strtok_r(programIn, "\n", &lineEnd);
line = strtoke(programIn, "\n", &lineEnd);
while (line != NULL && (line[0] == ' ' || line[0] == '\t')) line++;
while (line != NULL) {
printf("%d [%s]\n", lineNumber, line);
// Get the first token on the line.
token = strtok_r(line, " ", &tokenEnd);
// Is this something we care about? It'll be math, a label, or a keyword.
lineOkay = FALSE;
// Is this a blank line?
if (token == NULL) {
// Yep - just move on.
lineOkay = TRUE;
} else { // blank line
// Is it math?
if (strlen(token) > 1 && token[0] == '%') {
@ -290,7 +360,7 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
// Look up variable index in table, or add it if needed.
// Variable index is stored in y1 for later.
y1 = -1;
for (y2=0; y2<arrlen(variables); y2++) {
for (y2 = 0; y2 < arrlen(variables); y2++) {
if (strcasecmp(variables[y2], token) == 0) {
y1 = y2; // Found.
break;
@ -317,12 +387,6 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
outputByte(bytecode, math[keyword].id);
outputWord(bytecode, x1);
lineOkay = TRUE;
//***DEBUG***
if (math[keyword].id == MATH_ASSIGN) {
for (y1=0; y1<arrlen(variables); y1++) {
printf("Variable %d = %s\n", y1, variables[y1]);
}
}
break;
}
keyword++;
@ -336,6 +400,20 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
// It's a label.
// Have we already used this label?
x2 = -1;
for (x1 = 0; x1 < hmlen(labels); x1++) {
if (strcasecmp(token, labels[x1].key) == 0) {
x2 = x1;
break;
}
}
if (x2 < 0) {
// New label. Add to hashmap.
hmput(labels, token, bytecode->length);
lineOkay = TRUE;
}
} else { // doing a label
// It's a keyword.
@ -559,6 +637,8 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
} // math
} // blank line
// Is everything still okay?
if (!lineOkay) {
// Nope - error.
@ -567,7 +647,8 @@ int vecparser(char *programIn, VecByteCodeT *bytecode) {
}
// Move to next line.
line = strtok_r(NULL, "\n", &lineEnd);
line = strtoke(NULL, "\n", &lineEnd);
while (line != NULL && (line[0] == ' ' || line[0] == '\t')) line++;
lineNumber++;
} // read program line