Fix no-context error-handling.
Centralize parts of number-parsing.
This commit is contained in:
parent
3f4d8fd7af
commit
83b1b9212e
|
@ -824,6 +824,9 @@ errorWithAllocatedContextLineNo(enum errorCode code, char* context, int lineNo,
|
|||
|
||||
inline Object errorWithContextLineNo(enum errorCode code, const char* context, int lineNo, const char* fileName)
|
||||
{
|
||||
if (!context) {
|
||||
context = "";
|
||||
}
|
||||
char* copiedContext = malloc(sizeof(char) * ERR_LEN);
|
||||
strcpy(copiedContext, context);
|
||||
return errorWithAllocatedContextLineNo(code, copiedContext, lineNo, fileName);
|
||||
|
|
126
src/pebblisp.c
126
src/pebblisp.c
|
@ -328,24 +328,24 @@ Object structAccess(Object* params, unused int length, unused struct Environment
|
|||
Result parse(struct Slice* slices)
|
||||
{
|
||||
struct Slice* token = slices;
|
||||
if (token && token->text) {
|
||||
struct Slice* rest = &slices[1];
|
||||
if (token->text[0] == '\'' && token->text[1] == '(') {
|
||||
Result r = readSeq(&slices[2]);
|
||||
if (r.obj.type == TYPE_LIST) {
|
||||
r.obj.type = TYPE_SLIST;
|
||||
}
|
||||
return r;
|
||||
} else if (token->text[0] == '(') {
|
||||
return readSeq(rest);
|
||||
} else {
|
||||
Result r = parseAtom(token);
|
||||
r.slices = &r.slices[1];
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
if (!token || !token->text) {
|
||||
return (Result) { errorObject(NULL_PARSE), NULL };
|
||||
}
|
||||
|
||||
struct Slice* rest = &slices[1];
|
||||
if (token->text[0] == '\'' && token->text[1] == '(') {
|
||||
Result r = readSeq(&slices[2]);
|
||||
if (r.obj.type == TYPE_LIST) {
|
||||
r.obj.type = TYPE_SLIST;
|
||||
}
|
||||
return r;
|
||||
} else if (token->text[0] == '(') {
|
||||
return readSeq(rest);
|
||||
} else {
|
||||
Result r = parseAtom(token);
|
||||
r.slices = &r.slices[1];
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NO_SUGAR
|
||||
|
@ -382,33 +382,47 @@ Result readSeq(struct Slice* tokens)
|
|||
}
|
||||
}
|
||||
|
||||
Object parseDecimal(struct Slice* s)
|
||||
int hexChar(char c)
|
||||
{
|
||||
int num = 0;
|
||||
for (int i = 0; i < s->length; i++) {
|
||||
if (!isDigit(s->text[i])) {
|
||||
return errorObject(BAD_NUMBER);
|
||||
}
|
||||
num *= 10;
|
||||
num += s->text[i] - '0';
|
||||
if (isDigit(c)) {
|
||||
return c - '0';
|
||||
}
|
||||
return numberObject(num);
|
||||
if (c >= 'a' && c <= 'f') {
|
||||
return c - 'a' + 10;
|
||||
}
|
||||
if (c >= 'A' && c <= 'F'){
|
||||
return c - 'A' + 10;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
Object parseHex(struct Slice* s)
|
||||
int binChar(char c)
|
||||
{
|
||||
if (c == '0' || c == '1') {
|
||||
return c - '0';
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int decChar(char c)
|
||||
{
|
||||
if (isDigit(c)) {
|
||||
return c - '0';
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
Object parseNum(int base, const char* text, int length, int (*func)(char))
|
||||
{
|
||||
int num = 0;
|
||||
for (int i = 2; i < s->length; i++) {
|
||||
const char c = s->text[i];
|
||||
if (!isHex(c)) {
|
||||
return errorObject(BAD_NUMBER);
|
||||
}
|
||||
num *= 16;
|
||||
if (isDigit(c)) {
|
||||
num += c - '0';
|
||||
} else /* is hex */ {
|
||||
num += c - 'a' + 10;
|
||||
for (int i = 0; i < length; i++) {
|
||||
const char c = text[i];
|
||||
int value = func(c);
|
||||
if (value < 0) {
|
||||
throw(BAD_NUMBER, "at %s", text);
|
||||
}
|
||||
num *= base;
|
||||
num += value;
|
||||
}
|
||||
return numberObject(num);
|
||||
}
|
||||
|
@ -440,30 +454,28 @@ Result parseAtom(struct Slice* s)
|
|||
const char c = s->text[0];
|
||||
if (isDigit(c)) {
|
||||
if (c != '0' || s->length == 1) {
|
||||
return (Result) { parseDecimal(s), s };
|
||||
#ifndef LOW_MEM
|
||||
} else if (s->text[1] == 'x') {
|
||||
return (Result) { parseHex(s), s };
|
||||
} else if (s->text[1] == 'b') {
|
||||
return (Result) { parseBin(s), s };
|
||||
#endif
|
||||
} else {
|
||||
return (Result) { errorWithContext(UNSUPPORTED_NUMBER_TYPE, s->text), s };
|
||||
return (Result) { parseNum(10, s->text, s->length, decChar), s };
|
||||
}
|
||||
} else if (s->length == 1 && c == 'T') {
|
||||
#ifndef LOW_MEM
|
||||
if (s->text[1] == 'x') {
|
||||
return (Result) { parseNum(16, s->text + 2, s->length - 2, hexChar), s };
|
||||
}
|
||||
if (s->text[1] == 'b') {
|
||||
return (Result) { parseNum(2, s->text + 2, s->length - 2, binChar), s };
|
||||
}
|
||||
#endif
|
||||
return (Result) { errorWithContext(UNSUPPORTED_NUMBER_TYPE, s->text), s };
|
||||
}
|
||||
if (s->length == 1 && c == 'T') {
|
||||
return (Result) { trueObject(), s };
|
||||
} else if (s->length == 1 && c == 'F') {
|
||||
}
|
||||
if (s->length == 1 && c == 'F') {
|
||||
return (Result) { falseObject(), s };
|
||||
} else if (c == '"'/* || c == '\''*/) {
|
||||
}
|
||||
if (c == '"') {
|
||||
return (Result) { objFromSlice(s->text, s->length), s };
|
||||
} else if (s->text[s->length] == '.') {
|
||||
/*
|
||||
struct InlinedFunction f ={
|
||||
.func = structAccess,
|
||||
.arguments = malloc(sizeof(Object) * 2),
|
||||
.argCount = 2,
|
||||
};
|
||||
f.arguments[0] = symFromSlice(s->text, s->length);
|
||||
}
|
||||
if (s->text[s->length] == '.') {
|
||||
struct Slice* next = s + 2;
|
||||
f.arguments[1] = stringFromSlice(next->text, next->length);
|
||||
|
||||
|
@ -523,7 +535,7 @@ Object parseEval(const char* input, struct Environment* env)
|
|||
cleanObject(&obj);
|
||||
Object parsed = parse(tok).obj;
|
||||
if (parsed.type == TYPE_ERROR) {
|
||||
obj = parsed; // TODO Check necessity
|
||||
obj = parsed;
|
||||
#ifdef STANDALONE
|
||||
obj.error->plContext = malloc(sizeof(struct Slice));
|
||||
*obj.error->plContext = *lastOpen;
|
||||
|
|
|
@ -107,7 +107,7 @@ Object at(Object* params, unused int length, unused struct Environment* env)
|
|||
return cloneObject(*found);
|
||||
}
|
||||
|
||||
return errorObject(INDEX_PAST_END);
|
||||
throw(INDEX_PAST_END, "Tried to access index %ld from list of len %d", index.number, listLength(&list));
|
||||
}
|
||||
|
||||
Object rest(Object* params, unused int length, unused struct Environment* env)
|
||||
|
|
|
@ -18,7 +18,7 @@ int isSingle(const char c)
|
|||
int i = 0;
|
||||
while (singleTokens[i] != '\0') {
|
||||
if (singleTokens[i] == c) {
|
||||
return singleTokens[i];
|
||||
return 1;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
@ -30,11 +30,6 @@ int isDigit(const char c)
|
|||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
int isHex(const char c)
|
||||
{
|
||||
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
|
||||
}
|
||||
|
||||
int isWhitespace(const char c)
|
||||
{
|
||||
return c == ' ' || c == '\t' || c == '\n';
|
||||
|
|
Loading…
Reference in New Issue