Break printColored() into own function.
Replace (pch) with (ch). Fix error memory bug. Add sugar for (? fil) => (? "fil"). Inline some of (fil). Simplify (print) and allow for varargs. Total up valgrind errors when testing.
This commit is contained in:
parent
581dfed359
commit
59c6ff50b5
62
src/env.c
62
src/env.c
|
@ -127,7 +127,7 @@ void addToEnv(struct Environment* env, const char* name, const Object obj)
|
||||||
if (is_local) {
|
if (is_local) {
|
||||||
temp_env->strings[i] =
|
temp_env->strings[i] =
|
||||||
calloc(sizeof(char), strlen(name) + 1);
|
calloc(sizeof(char), strlen(name) + 1);
|
||||||
strncpy(temp_env->strings[i], name, strlen(name));
|
strcpy(temp_env->strings[i], name);
|
||||||
temp_env->objects[i] = cloneObject(obj);
|
temp_env->objects[i] = cloneObject(obj);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -155,7 +155,7 @@ void addToEnv(struct Environment* env, const char* name, const Object obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
env->strings[old_size] = malloc(strlen(name) + 1);
|
env->strings[old_size] = malloc(strlen(name) + 1);
|
||||||
strncpy(env->strings[old_size], name, strlen(name) + 1);
|
strcpy(env->strings[old_size], name);
|
||||||
env->objects[old_size] = cloneObject(obj);
|
env->objects[old_size] = cloneObject(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,10 +278,40 @@ const int purple = 35;
|
||||||
const int teal = 36;
|
const int teal = 36;
|
||||||
const int white = 37;
|
const int white = 37;
|
||||||
const int colors[] = {
|
const int colors[] = {
|
||||||
green, cyan, yellow, purple, red, white
|
white, green, cyan, yellow, purple, red
|
||||||
};
|
};
|
||||||
const int colorCount = array_length(colors);
|
const int colorCount = array_length(colors);
|
||||||
|
|
||||||
|
int getColor(int depth)
|
||||||
|
{
|
||||||
|
depth = depth >= 0 ? depth : depth * -1;
|
||||||
|
return colors[depth % colorCount];
|
||||||
|
}
|
||||||
|
|
||||||
|
void printColored(const char* code)
|
||||||
|
{
|
||||||
|
int c = 0;
|
||||||
|
int depth = 0;
|
||||||
|
printf("[%dm", getColor(depth));
|
||||||
|
while (code[c]) {
|
||||||
|
if (code[c] == '(') {
|
||||||
|
depth += 1;
|
||||||
|
printf("[%dm", getColor(depth));
|
||||||
|
} else if (code[c] == ')') {
|
||||||
|
depth -= 1;
|
||||||
|
printf(")[%dm", getColor(depth));
|
||||||
|
c++;
|
||||||
|
continue;
|
||||||
|
} else if (code[c] == '=' && code[c + 1] == '>') {
|
||||||
|
printf("[1m=>[0;%dm", getColor(depth));
|
||||||
|
c += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printf("%c", code[c]);
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char* getHelp(const char* symbol)
|
char* getHelp(const char* symbol)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < currentHelp; i++) {
|
for (int i = 0; i < currentHelp; i++) {
|
||||||
|
@ -293,24 +323,7 @@ char* getHelp(const char* symbol)
|
||||||
for (int ti = 0; ti < h.testCount; ti += 2) {
|
for (int ti = 0; ti < h.testCount; ti += 2) {
|
||||||
const char* test = h.tests[ti];
|
const char* test = h.tests[ti];
|
||||||
const char* expected = h.tests[ti + 1];
|
const char* expected = h.tests[ti + 1];
|
||||||
textCursor += sprintf(textCursor, "\n ");
|
textCursor += sprintf(textCursor, "\n %s => ", test);
|
||||||
int c = 0;
|
|
||||||
int depth = -1;
|
|
||||||
while (test[c]) {
|
|
||||||
if (test[c] == '(') {
|
|
||||||
depth += 1;
|
|
||||||
textCursor += sprintf(textCursor, "[%dm", colors[depth % colorCount]);
|
|
||||||
} else if (test[c] == ')') {
|
|
||||||
depth -= 1;
|
|
||||||
textCursor += sprintf(textCursor, ")[%dm", colors[depth % colorCount]);
|
|
||||||
c++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
textCursor += sprintf(textCursor, "%c", test[c]);
|
|
||||||
c++;
|
|
||||||
}
|
|
||||||
//textCursor += sprintf(textCursor, "\n %s [1m=>[0m %s", test, expected);
|
|
||||||
textCursor += sprintf(textCursor, " [0m[1m=>[0m ");
|
|
||||||
if (expected[0] == '\0') {
|
if (expected[0] == '\0') {
|
||||||
textCursor += sprintf(textCursor, "<empty string>");
|
textCursor += sprintf(textCursor, "<empty string>");
|
||||||
} else {
|
} else {
|
||||||
|
@ -320,7 +333,10 @@ char* getHelp(const char* symbol)
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "Help not found!";
|
const char* notFound = "Help not found!";
|
||||||
|
char* help = malloc(sizeof(char) * (strlen(notFound) + 1));
|
||||||
|
sprintf(help, "%s", notFound);
|
||||||
|
return help;
|
||||||
}
|
}
|
||||||
|
|
||||||
fnn(segfault, "seg", "Induces a segfault.")
|
fnn(segfault, "seg", "Induces a segfault.")
|
||||||
|
@ -428,7 +444,7 @@ struct Environment defaultEnv()
|
||||||
pf("seg", segfault),
|
pf("seg", segfault),
|
||||||
//pfn(segfault),
|
//pfn(segfault),
|
||||||
pf("prn", print),
|
pf("prn", print),
|
||||||
pf("pch", pChar),
|
pf("ch", numToChar),
|
||||||
pf("penv", printEnvO),
|
pf("penv", printEnvO),
|
||||||
pf("sys", systemCall),
|
pf("sys", systemCall),
|
||||||
pf("loadfile", loadFile),
|
pf("loadfile", loadFile),
|
||||||
|
|
|
@ -46,6 +46,8 @@ int getStructIndex(struct Environment* env, const char* name);
|
||||||
/// Needs to be freed!
|
/// Needs to be freed!
|
||||||
char* getHelp(const char* symbol);
|
char* getHelp(const char* symbol);
|
||||||
|
|
||||||
|
void printColored(const char* code);
|
||||||
|
|
||||||
int runTests();
|
int runTests();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -590,6 +590,7 @@ void cleanObject(Object* target)
|
||||||
break;
|
break;
|
||||||
case TYPE_ERROR:
|
case TYPE_ERROR:
|
||||||
#ifndef SIMPLE_ERRORS
|
#ifndef SIMPLE_ERRORS
|
||||||
|
free(target->error->plContext);
|
||||||
free(target->error->context);
|
free(target->error->context);
|
||||||
free(target->error);
|
free(target->error);
|
||||||
target->error = NULL;
|
target->error = NULL;
|
||||||
|
|
|
@ -479,9 +479,16 @@ Result parse(struct Slice* slices)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SUGAR
|
||||||
|
#define sugar(_desc, _code) ;
|
||||||
|
#else
|
||||||
|
#define sugar(_desc, _code) _code
|
||||||
|
#endif
|
||||||
|
|
||||||
Result readSeq(struct Slice* tokens)
|
Result readSeq(struct Slice* tokens)
|
||||||
{
|
{
|
||||||
Object res = listObject();
|
Object res = listObject();
|
||||||
|
int isHelp = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
struct Slice* next = tokens;
|
struct Slice* next = tokens;
|
||||||
struct Slice* rest = next->text ? &next[1] : NULL;
|
struct Slice* rest = next->text ? &next[1] : NULL;
|
||||||
|
@ -489,12 +496,18 @@ Result readSeq(struct Slice* tokens)
|
||||||
return (Result) {res, rest};
|
return (Result) {res, rest};
|
||||||
}
|
}
|
||||||
Result r = parse(tokens);
|
Result r = parse(tokens);
|
||||||
|
sugar("(? fil) => (? 'fil')",
|
||||||
|
if (isHelp && r.obj.type == TYPE_SYMBOL) {
|
||||||
|
r.obj.type = TYPE_STRING;
|
||||||
|
}
|
||||||
|
)
|
||||||
if (r.obj.type == TYPE_ERROR) {
|
if (r.obj.type == TYPE_ERROR) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
nf_addToList(&res, cloneObject(r.obj));
|
nf_addToList(&res, cloneObject(r.obj));
|
||||||
tokens = r.slices;
|
tokens = r.slices;
|
||||||
cleanObject(&r.obj);
|
cleanObject(&r.obj);
|
||||||
|
isHelp = next->text[0] == '?';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -626,7 +639,8 @@ Object parseEval(const char* input, struct Environment* env)
|
||||||
Object parsed = parse(tok).obj;
|
Object parsed = parse(tok).obj;
|
||||||
if (parsed.type == TYPE_ERROR) {
|
if (parsed.type == TYPE_ERROR) {
|
||||||
obj = parsed; // TODO Check necessity
|
obj = parsed; // TODO Check necessity
|
||||||
obj.error->plContext = lastOpen;
|
obj.error->plContext = malloc(sizeof(struct Slice));
|
||||||
|
*obj.error->plContext = *lastOpen;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (tok[i].text[0] == ')') {
|
if (tok[i].text[0] == ')') {
|
||||||
|
@ -668,7 +682,7 @@ int _readFile(FILE* input, struct Environment* env)
|
||||||
char line[LINE_MAX];
|
char line[LINE_MAX];
|
||||||
if (fgets(line, LINE_MAX, input)) {
|
if (fgets(line, LINE_MAX, input)) {
|
||||||
if (line[0] != '#' || line[1] != '!') {
|
if (line[0] != '#' || line[1] != '!') {
|
||||||
strncat(page, line, strlen(line) - 1);
|
strcat(page, line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int isQuote = 0;
|
int isQuote = 0;
|
||||||
|
@ -713,7 +727,10 @@ void repl(struct Environment* env)
|
||||||
}
|
}
|
||||||
add_history(buf);
|
add_history(buf);
|
||||||
Object o = parseEval(buf, env);
|
Object o = parseEval(buf, env);
|
||||||
printObj(&o);
|
char output[1024];
|
||||||
|
stringNObj(output, &o, 1024);
|
||||||
|
printColored(output);
|
||||||
|
printf("[0m\n");
|
||||||
cleanObject(&o);
|
cleanObject(&o);
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
73
src/plfunc.c
73
src/plfunc.c
|
@ -39,14 +39,15 @@ Object filter(Object* params, int length, struct Environment* env)
|
||||||
|
|
||||||
Object filtered = listObject();
|
Object filtered = listObject();
|
||||||
FOR_POINTER_IN_LIST(&list) {
|
FOR_POINTER_IN_LIST(&list) {
|
||||||
Object l = startList(cloneObject(condition));
|
Object cloned = cloneObject(condition);
|
||||||
|
Object first_eval = eval(&cloned, env);
|
||||||
Object testee = cloneObject(*POINTER);
|
Object testee = cloneObject(*POINTER);
|
||||||
nf_addToList(&l, testee);
|
Object e = listEvalLambda(&first_eval, &testee, env);
|
||||||
Object e = eval(&l, env);
|
|
||||||
if (e.number) {
|
if (e.number) {
|
||||||
nf_addToList(&filtered, testee); // May need to re-clone testee?
|
nf_addToList(&filtered, testee); // May need to re-clone testee?
|
||||||
}
|
}
|
||||||
cleanObject(&l);
|
cleanObject(&e);
|
||||||
|
cleanObject(&cloned);
|
||||||
}
|
}
|
||||||
return filtered;
|
return filtered;
|
||||||
}
|
}
|
||||||
|
@ -144,14 +145,11 @@ Object isString(Object* params, int length, struct Environment* env)
|
||||||
return test.type == TYPE_STRING ? boolObject(1) : boolObject(0);
|
return test.type == TYPE_STRING ? boolObject(1) : boolObject(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the int value of a string's first character
|
|
||||||
Object charVal(Object* params, int length, struct Environment* env)
|
Object charVal(Object* params, int length, struct Environment* env)
|
||||||
{
|
{
|
||||||
Object test = params[0];
|
Object test = params[0];
|
||||||
|
|
||||||
return numberObject(test.string[0]);
|
return numberObject(test.string[0]);
|
||||||
// return test.type == TYPE_STRING && test.string[0] == '\0' ?
|
|
||||||
// boolObject(1) : boolObject(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Object isErr(Object* params, int length, struct Environment* env)
|
Object isErr(Object* params, int length, struct Environment* env)
|
||||||
|
@ -165,17 +163,20 @@ Object parseEvalO(Object* params, int length, struct Environment* env)
|
||||||
{
|
{
|
||||||
Object text = params[0];
|
Object text = params[0];
|
||||||
|
|
||||||
if (text.type == TYPE_SYMBOL) {
|
switch (text.type) {
|
||||||
Object string = eval(&text, env);
|
case TYPE_SYMBOL: {
|
||||||
Object parsed = parseEval(string.string, env);
|
Object string = eval(&text, env);
|
||||||
cleanObject(&string);
|
Object parsed = parseEval(string.string, env);
|
||||||
return parsed;
|
cleanObject(&string);
|
||||||
} else if (text.type == TYPE_SLIST) {
|
return parsed;
|
||||||
return evalList(&text, env);
|
}
|
||||||
} else if (text.type != TYPE_STRING) {
|
case TYPE_SLIST:
|
||||||
return errorObject(CAN_ONLY_EVAL_STRINGS);
|
return evalList(&text, env);
|
||||||
|
case TYPE_STRING:
|
||||||
|
return parseEval(text.string, env);
|
||||||
|
default:
|
||||||
|
return errorObject(CAN_ONLY_EVAL_STRINGS);
|
||||||
}
|
}
|
||||||
return parseEval(text.string, env);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Object listEquality(const Object* list1, const Object* list2)
|
Object listEquality(const Object* list1, const Object* list2)
|
||||||
|
@ -231,21 +232,6 @@ Object _basicOp(const Object* obj1, const Object* obj2, const char op,
|
||||||
const int n2 = obj2->number;
|
const int n2 = obj2->number;
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case '+':
|
|
||||||
if (eitherIsNot(TYPE_NUMBER, obj1, obj2)) {
|
|
||||||
Object objects[2] = {*obj1, *obj2};
|
|
||||||
return catObjects(objects, 2, env);
|
|
||||||
}
|
|
||||||
return numberObject(n1 + n2);
|
|
||||||
case '-':
|
|
||||||
return numberObject(n1 - n2);
|
|
||||||
case '*':
|
|
||||||
return numberObject(n1 * n2);
|
|
||||||
case '/':
|
|
||||||
return numberObject(n1 / n2);
|
|
||||||
case '%':
|
|
||||||
return numberObject(n1 % n2);
|
|
||||||
|
|
||||||
case '&':
|
case '&':
|
||||||
return boolObject(n1 != 0 && n2 != 0);
|
return boolObject(n1 != 0 && n2 != 0);
|
||||||
case '|':
|
case '|':
|
||||||
|
@ -363,24 +349,21 @@ BASIC_OP(or, '|')
|
||||||
|
|
||||||
Object print(Object* params, int length, struct Environment* env)
|
Object print(Object* params, int length, struct Environment* env)
|
||||||
{
|
{
|
||||||
Object p = params[0];
|
for (int i = 0; i < length; i++) {
|
||||||
Object c = cloneObject(p);
|
_printObj(¶ms[i], 0);
|
||||||
Object e = eval(&c, env);
|
}
|
||||||
_printObj(&e, 0);
|
|
||||||
cleanObject(&c);
|
|
||||||
cleanObject(&e);
|
|
||||||
return numberObject(0);
|
return numberObject(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object pChar(Object* params, int length, struct Environment* env)
|
Object numToChar(Object* params, int length, struct Environment* env)
|
||||||
{
|
{
|
||||||
Object c = params[0];
|
Object c = params[0];
|
||||||
|
|
||||||
if (c.type != TYPE_NUMBER) {
|
if (c.type != TYPE_NUMBER) {
|
||||||
return errorObject(BAD_NUMBER);
|
return errorObject(BAD_NUMBER);
|
||||||
}
|
}
|
||||||
printf("%c", c.number % 256);
|
char ch[1] = {c.number % 256};
|
||||||
return numberObject(0);
|
return stringFromSlice(ch, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object printEnvO(Object* params, int length, struct Environment* env)
|
Object printEnvO(Object* params, int length, struct Environment* env)
|
||||||
|
@ -392,12 +375,14 @@ Object printEnvO(Object* params, int length, struct Environment* env)
|
||||||
Object takeInput(Object* params, int length, struct Environment* env)
|
Object takeInput(Object* params, int length, struct Environment* env)
|
||||||
{
|
{
|
||||||
Object prompt = params[0];
|
Object prompt = params[0];
|
||||||
if (prompt.type == TYPE_STRING) {
|
if (length > 0 && prompt.type == TYPE_STRING) {
|
||||||
printf("%s", prompt.string);
|
printf("%s", prompt.string);
|
||||||
}
|
}
|
||||||
char input[256] = "";
|
char input[256] = "";
|
||||||
fgets(input, 256, stdin);
|
if (fgets(input, 256, stdin)) {
|
||||||
return stringFromSlice(input, strlen(input) - 1);
|
return stringFromSlice(input, strlen(input) - 1);
|
||||||
|
}
|
||||||
|
return errorWithContext(NULL_PARSE, "fgets() error");
|
||||||
}
|
}
|
||||||
|
|
||||||
Object loadFile(Object* params, int length, struct Environment* env)
|
Object loadFile(Object* params, int length, struct Environment* env)
|
||||||
|
|
17
src/plfunc.h
17
src/plfunc.h
|
@ -38,6 +38,7 @@ fn(catObjects,
|
||||||
fn(filter,
|
fn(filter,
|
||||||
"Filter a list based on the given condition.",
|
"Filter a list based on the given condition.",
|
||||||
"(fil (fn (a) (< 50 a)) (25 60 100))", "( 60 100 )",
|
"(fil (fn (a) (< 50 a)) (25 60 100))", "( 60 100 )",
|
||||||
|
"(fil (fn (a) (< 0 (len a))) ( () (1) (1 2) () ))", "( ( 1 ) ( 1 2 ) )",
|
||||||
);
|
);
|
||||||
|
|
||||||
/// LIST, ANY => LIST
|
/// LIST, ANY => LIST
|
||||||
|
@ -160,15 +161,19 @@ fn(possessive,
|
||||||
|
|
||||||
fn(print, "Prints the string representation of the given object to stdout.");
|
fn(print, "Prints the string representation of the given object to stdout.");
|
||||||
|
|
||||||
fn(pChar, "Prints the ascii character for the given number value.");
|
fn(numToChar,
|
||||||
|
"Gets a string containing the ascii character for the given number value.",
|
||||||
|
"(ch 107)", "k",
|
||||||
|
"(ch 0x21)", "!",
|
||||||
|
);
|
||||||
|
|
||||||
fn(printEnvO, "Prints out the current scoped environment.");
|
fn(printEnvO, "Prints out the current scoped environment.");
|
||||||
|
|
||||||
fn(systemCall,
|
fn(systemCall,
|
||||||
"Opens a shell and runs the given command, returning the command's exit code.\n"
|
"Opens a shell and runs the given command, returning 0 if successful.\n"
|
||||||
"(sys \"echo yee\")\n"
|
"If the argument is not a string, returns 255.\n",
|
||||||
"yee\n"
|
"(sys \"echo yee > /dev/null\")", "0",
|
||||||
"=> 0"
|
"(sys 5)", "255",
|
||||||
);
|
);
|
||||||
|
|
||||||
fn(loadFile,
|
fn(loadFile,
|
||||||
|
@ -179,8 +184,6 @@ fn(loadFile,
|
||||||
"=> 0"
|
"=> 0"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @code
|
/// @code
|
||||||
/// () => STRING
|
/// () => STRING
|
||||||
/// STRING => STRING
|
/// STRING => STRING
|
||||||
|
|
33
src/tests.sh
33
src/tests.sh
|
@ -1,9 +1,10 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
VALCOM="valgrind -q --leak-check=full --track-origins=yes"
|
VALCOM="valgrind -q --leak-check=full --error-exitcode=1 --track-origins=yes"
|
||||||
|
|
||||||
TOTAL_PASSES=0
|
TOTAL_PASSES=0
|
||||||
TOTAL_FAILS=0
|
TOTAL_FAILS=0
|
||||||
|
TOTAL_VALGRIND_ERRORS=0
|
||||||
FAILS=0
|
FAILS=0
|
||||||
FAIL_OUTPUT=""
|
FAIL_OUTPUT=""
|
||||||
VALGRIND=false
|
VALGRIND=false
|
||||||
|
@ -37,7 +38,12 @@ title() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pass() {
|
pass() {
|
||||||
echo -n "[1;32m✓[0m"
|
local color=32
|
||||||
|
if [[ "$2" != "0" ]]; then
|
||||||
|
((TOTAL_VALGRIND_ERRORS++))
|
||||||
|
color=33
|
||||||
|
fi
|
||||||
|
echo -n "[1;${color}m✓[0m"
|
||||||
((TOTAL_PASSES++))
|
((TOTAL_PASSES++))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,20 +62,26 @@ check() {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local output
|
local output
|
||||||
|
local exit_code=0
|
||||||
if $VALGRIND; then
|
if $VALGRIND; then
|
||||||
echo -ne "\n $1\r "
|
echo -ne "\n $1"
|
||||||
output="$($VALCOM ./pl "(loadfile \"examples/lib.pbl\") $2" | grep -v PLT)"
|
output="$($VALCOM ./pl "(loadfile \"examples/lib.pbl\") $2")"
|
||||||
|
exit_code=$?
|
||||||
|
if [[ "$exit_code" == "0" ]]; then
|
||||||
|
echo -ne "\r "
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
output="$(./pl "(loadfile \"examples/lib.pbl\") $2" | grep -v PLT)"
|
output="$(./pl "(loadfile \"examples/lib.pbl\") $2")"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
if [ "$3" == "$regex" ]; then
|
if [ "$3" == "$regex" ]; then
|
||||||
if [[ "$output" =~ ^$4$ ]]; then
|
if [[ "$output" =~ ^$4$ ]]; then
|
||||||
pass "$1"
|
pass "$1" $exit_code
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
elif [ "$output" == "$3" ]; then
|
elif [ "$output" == "$3" ]; then
|
||||||
pass "$1"
|
pass "$1" $exit_code
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -208,6 +220,7 @@ check "NoMapList" "(map sq)" "( )"
|
||||||
check "BadNumber" "(5df)" regex "BAD_NUMBER.*"
|
check "BadNumber" "(5df)" regex "BAD_NUMBER.*"
|
||||||
check "BadHex" "(0x0zf)" regex "BAD_NUMBER.*"
|
check "BadHex" "(0x0zf)" regex "BAD_NUMBER.*"
|
||||||
check "BadBinary" "(0b01120)" regex "BAD_NUMBER.*"
|
check "BadBinary" "(0b01120)" regex "BAD_NUMBER.*"
|
||||||
|
check "UnsupportedNumber" "(00000)" regex "UNSUPPORTED_NUMBER.*"
|
||||||
check "BadParens1" "(hey()" regex "'MISMATCHED_PARENS.*"
|
check "BadParens1" "(hey()" regex "'MISMATCHED_PARENS.*"
|
||||||
check "BadParens2" "(hey)(" regex "'MISMATCHED_PARENS.*"
|
check "BadParens2" "(hey)(" regex "'MISMATCHED_PARENS.*"
|
||||||
check "BadParens3" "((hey(" regex "'MISMATCHED_PARENS.*"
|
check "BadParens3" "((hey(" regex "'MISMATCHED_PARENS.*"
|
||||||
|
@ -244,7 +257,11 @@ echo ""
|
||||||
if [ "$TOTAL_PASSES" -ne "0" ]; then
|
if [ "$TOTAL_PASSES" -ne "0" ]; then
|
||||||
echo -n "[1;32m"
|
echo -n "[1;32m"
|
||||||
fi
|
fi
|
||||||
echo "$TOTAL_PASSES Tests Passed[0m"
|
echo -n "$TOTAL_PASSES Tests Passed[0m"
|
||||||
|
if [ "$TOTAL_VALGRIND_ERRORS" -ne "0" ]; then
|
||||||
|
echo -n " [33m($TOTAL_VALGRIND_ERRORS with valgrind errors)[0m"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
|
||||||
if [ "$TOTAL_FAILS" -ne "0" ]; then
|
if [ "$TOTAL_FAILS" -ne "0" ]; then
|
||||||
echo -n "[1;31m"
|
echo -n "[1;31m"
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Is the char a standalone token?
|
// Is the char a standalone token?
|
||||||
static const char singleTokens[] = "()+-*/='";
|
static const char singleTokens[] = "()+-*/='?";
|
||||||
|
|
||||||
int isSingle(const char c)
|
int isSingle(const char c)
|
||||||
{
|
{
|
||||||
|
@ -48,7 +48,6 @@ int notWhitespace(const char c)
|
||||||
return !isWhitespace(c);
|
return !isWhitespace(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return needs to be freed, if not null
|
|
||||||
struct Slice* nf_tokenize(const char* input, struct Error* err)
|
struct Slice* nf_tokenize(const char* input, struct Error* err)
|
||||||
{
|
{
|
||||||
if (!input) {
|
if (!input) {
|
||||||
|
|
Loading…
Reference in New Issue