gemstone/src/lex/util.c

125 lines
2.0 KiB
C

#include <lex/util.h>
#include <string.h>
#include <stdlib.h>
#include <glib.h>
#include <mem/cache.h>
// implementation based on:
// https://github.com/sunxfancy/flex-bison-examples/blob/master/error-handling/ccalc.c
char* buffer = NULL;
static int eof = 0;
static int nRow = 0;
static int nBuffer = 0;
static int lBuffer = 0;
static int nTokenStart = 0;
static int nTokenLength = 0;
static int nTokenNextStart = 0;
void lex_init(void) {
buffer = mem_alloc(MemoryNamespaceStatic, MAX_READ_BUFFER_SIZE);
}
void lex_reset(void) {
eof = 0;
nRow = 0;
nBuffer = 0;
lBuffer = 0;
nTokenStart = 0;
nTokenLength = 0;
nTokenNextStart = 0;
}
void beginToken(char *t) {
nTokenStart = nTokenNextStart;
nTokenLength = (int) strlen(t);
nTokenNextStart = nBuffer + 1;
yylloc.first_line = nRow;
yylloc.first_column = nTokenStart;
yylloc.last_line = nRow;
yylloc.last_column = nTokenStart + nTokenLength - 1;
}
int nextChar(char *dst) {
int frc;
if (eof)
return 0;
while (nBuffer >= lBuffer) {
frc = getNextLine();
if (frc != 0) {
return 0;
}
}
dst[0] = buffer[nBuffer];
nBuffer += 1;
return dst[0] != 0;
}
int getNextLine(void) {
char *p;
nBuffer = 0;
nTokenStart = -1;
nTokenNextStart = 1;
eof = 0;
p = fgets(buffer, MAX_READ_BUFFER_SIZE, yyin);
if (p == NULL) {
if (ferror(yyin)) {
return -1;
}
eof = 1;
return 1;
}
nRow += 1;
lBuffer = (int) strlen(buffer);
return 0;
}
struct ConstEscSeq {
char* esc;
char* rep;
};
static struct ConstEscSeq sequences[] = {
{
"\\n",
"\n"
},
{
"\\\\",
"\\"
},
{
"\\t",
"\t"
},
{
"\\r",
"\r"
}
};
char* collapse_escape_sequences(char* string) {
GString* unesc = g_string_new(string);
for (int i = 0; i < 4; i++) {
g_string_replace(unesc, sequences[i].esc, sequences[i].rep, 0);
}
char* str = mem_strdup(MemoryNamespaceLex, unesc->str);
g_string_free(unesc, TRUE);
return str;
}