Added string support to SLOTH (comparisons, string concatenation, etc)
Refactored print_value code
This commit is contained in:
parent
1186419184
commit
28e2352eac
10 changed files with 135 additions and 36 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -9,7 +9,8 @@ src/variables/value.o
|
||||||
src/operations/node.o
|
src/operations/node.o
|
||||||
src/operations/operators.o
|
src/operations/operators.o
|
||||||
src/shell.o
|
src/shell.o
|
||||||
|
src/string.o
|
||||||
sloth
|
sloth
|
||||||
vgcore*
|
vgcore*
|
||||||
.vscode
|
.vscode
|
||||||
.vscode/*
|
.vscode/*
|
||||||
|
|
6
Makefile
6
Makefile
|
@ -1,5 +1,5 @@
|
||||||
sloth: src/main.c src/parser/lex.yy.o src/parser/parser.tab.o src/variables/environment.o src/variables/variable.o src/variables/value.o src/operations/node.o src/operations/operators.o src/shell.o
|
sloth: src/main.c src/parser/lex.yy.o src/parser/parser.tab.o src/variables/environment.o src/variables/variable.o src/variables/value.o src/operations/node.o src/operations/operators.o src/string.o src/shell.o
|
||||||
gcc src/main.c src/parser/lex.yy.o src/parser/parser.tab.o src/variables/environment.o src/variables/variable.o src/variables/value.o src/operations/node.o src/operations/operators.o src/shell.o -ledit -o sloth
|
gcc src/main.c src/parser/lex.yy.o src/parser/parser.tab.o src/variables/environment.o src/variables/variable.o src/variables/value.o src/operations/node.o src/operations/operators.o src/string.o src/shell.o -ledit -o sloth
|
||||||
src/parser/lex.yy.o: src/parser/lex.yy.c src/parser/parser.tab.h
|
src/parser/lex.yy.o: src/parser/lex.yy.c src/parser/parser.tab.h
|
||||||
gcc -c src/parser/lex.yy.c -o src/parser/lex.yy.o
|
gcc -c src/parser/lex.yy.c -o src/parser/lex.yy.o
|
||||||
src/parser/parser.tab.o: src/parser/parser.tab.c
|
src/parser/parser.tab.o: src/parser/parser.tab.c
|
||||||
|
@ -22,5 +22,7 @@ src/operations/node.o: src/operations/node.h src/operations/node.c
|
||||||
gcc -c src/operations/node.c -o src/operations/node.o
|
gcc -c src/operations/node.c -o src/operations/node.o
|
||||||
src/shell.o: src/shell.h src/shell.c
|
src/shell.o: src/shell.h src/shell.c
|
||||||
gcc -c src/shell.c -o src/shell.o
|
gcc -c src/shell.c -o src/shell.o
|
||||||
|
src/string.o: src/string.h src/string.c
|
||||||
|
gcc -c src/string.c -o src/string.o
|
||||||
clean:
|
clean:
|
||||||
rm src/parser/lex.yy.c src/parser/parser.tab.c src/parser/parser.tab.h src/parser/lex.yy.o src/parser/parser.tab.o src/variables/environment.o src/variables/variable.o src/variables/value.o src/operations/node.o src/operations/operators.o src/shell.o sloth
|
rm src/parser/lex.yy.c src/parser/parser.tab.c src/parser/parser.tab.h src/parser/lex.yy.o src/parser/parser.tab.o src/variables/environment.o src/variables/variable.o src/variables/value.o src/operations/node.o src/operations/operators.o src/shell.o sloth
|
||||||
|
|
|
@ -34,7 +34,7 @@ void interpret_file(char* fileName) {
|
||||||
stdin = orig_stdin;
|
stdin = orig_stdin;
|
||||||
|
|
||||||
// Interpret the AST
|
// Interpret the AST
|
||||||
// print_tree(result, 0);
|
// print_tree(result, 0); // For debugging
|
||||||
struct Environment* env = create_environment();
|
struct Environment* env = create_environment();
|
||||||
eval_statement(result, env);
|
eval_statement(result, env);
|
||||||
delete_environment(env);
|
delete_environment(env);
|
||||||
|
|
|
@ -80,17 +80,9 @@ void print_tree(struct Node* node, int tabs) {
|
||||||
case CALLFUNC: printf("FUNCTIONCALL:\n"); break;
|
case CALLFUNC: printf("FUNCTIONCALL:\n"); break;
|
||||||
case STATEMENT: printf("STATEMENT:\n"); break;
|
case STATEMENT: printf("STATEMENT:\n"); break;
|
||||||
case VALUE:
|
case VALUE:
|
||||||
if (node->value->type == BOOLEAN) {
|
printf("VALUE: ");
|
||||||
if (get_long(node->value)) {
|
print_value(node->value);
|
||||||
printf("VALUE: true\n");
|
printf("\n");
|
||||||
} else {
|
|
||||||
printf("VALUE: false\n");
|
|
||||||
}
|
|
||||||
} else if (node->value->type == LONG) {
|
|
||||||
printf("VALUE: %li\n", get_long(node->value));
|
|
||||||
} else { // Assume double
|
|
||||||
printf("VALUE: %lf\n", get_double(node->value));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Error, %d not a valid node type.\n", node->type);
|
printf("Error, %d not a valid node type.\n", node->type);
|
||||||
|
@ -311,19 +303,8 @@ void eval_statement(struct Node* node, struct Environment* env) {
|
||||||
case PRINT:
|
case PRINT:
|
||||||
check_num_nodes(node, 1, "can only print out one expression at a time.");
|
check_num_nodes(node, 1, "can only print out one expression at a time.");
|
||||||
tempVal = eval_expression(node->children[0], env);
|
tempVal = eval_expression(node->children[0], env);
|
||||||
if (tempVal->type == BOOLEAN) {
|
print_value(tempVal);
|
||||||
if (get_long(tempVal)) {
|
printf("\n");
|
||||||
printf("true\n");
|
|
||||||
} else {
|
|
||||||
printf("false\n");
|
|
||||||
}
|
|
||||||
} else if (tempVal->type == LONG) {
|
|
||||||
printf("%li\n", get_long(tempVal));
|
|
||||||
} else if (tempVal ->type == DOUBLE) {
|
|
||||||
printf("%lf\n", get_double(tempVal));
|
|
||||||
} else { // Assume lambda expression
|
|
||||||
printf("<LambdaExpression>\n");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
//------------
|
//------------
|
||||||
case STATEMENT: // Can have a maximum of two children statement nodes
|
case STATEMENT: // Can have a maximum of two children statement nodes
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include "operators.h"
|
#include "operators.h"
|
||||||
#include "../variables/value.h"
|
#include "../variables/value.h"
|
||||||
|
|
||||||
struct Value* add(struct Value* x, struct Value* y) {
|
struct Value* add(struct Value* x, struct Value* y) {
|
||||||
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in add.\n"); }
|
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in add.\n"); }
|
||||||
if (x->type == BOOLEAN || y->type == BOOLEAN) { fprintf(stderr, "Error, cannot add a boolean.\n"); }
|
if (x->type == BOOLEAN || y->type == BOOLEAN) { fprintf(stderr, "Error, cannot add a boolean.\n"); }
|
||||||
|
if ((x->type == STRING || y->type == STRING) && (x->type != STRING || y->type != STRING)) {
|
||||||
|
fprintf(stderr, "Error, cannot add a string with another data type.\n");
|
||||||
|
}
|
||||||
|
|
||||||
struct Value* ans;
|
struct Value* ans;
|
||||||
|
|
||||||
|
@ -16,6 +20,8 @@ struct Value* add(struct Value* x, struct Value* y) {
|
||||||
ans = make_double(get_long(x) + get_double(y));
|
ans = make_double(get_long(x) + get_double(y));
|
||||||
} else if (x->type == DOUBLE && y->type == LONG) {
|
} else if (x->type == DOUBLE && y->type == LONG) {
|
||||||
ans = make_double(get_double(x) + get_long(y));
|
ans = make_double(get_double(x) + get_long(y));
|
||||||
|
} else if (x->type == STRING && y->type == STRING) {
|
||||||
|
ans = make_string(strcat(get_string(x), get_string(y)));
|
||||||
} else { // Both are DOUBLE
|
} else { // Both are DOUBLE
|
||||||
ans = make_double(get_double(x) + get_double(y));
|
ans = make_double(get_double(x) + get_double(y));
|
||||||
}
|
}
|
||||||
|
@ -26,6 +32,7 @@ struct Value* add(struct Value* x, struct Value* y) {
|
||||||
struct Value* subtract(struct Value* x, struct Value* y) {
|
struct Value* subtract(struct Value* x, struct Value* y) {
|
||||||
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in subtract.\n"); }
|
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in subtract.\n"); }
|
||||||
if (x->type == BOOLEAN || y->type == BOOLEAN) { fprintf(stderr, "Error, cannot subtract a boolean.\n"); }
|
if (x->type == BOOLEAN || y->type == BOOLEAN) { fprintf(stderr, "Error, cannot subtract a boolean.\n"); }
|
||||||
|
if (x->type == STRING || y->type == STRING) { fprintf(stderr, "Error, cannot subtract a string.\n"); }
|
||||||
|
|
||||||
struct Value* ans;
|
struct Value* ans;
|
||||||
|
|
||||||
|
@ -46,6 +53,7 @@ struct Value* subtract(struct Value* x, struct Value* y) {
|
||||||
struct Value* division(struct Value* x, struct Value* y) {
|
struct Value* division(struct Value* x, struct Value* y) {
|
||||||
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in divide.\n"); }
|
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in divide.\n"); }
|
||||||
if (x->type == BOOLEAN || y->type == BOOLEAN) { fprintf(stderr, "Error, cannot divide a boolean.\n"); }
|
if (x->type == BOOLEAN || y->type == BOOLEAN) { fprintf(stderr, "Error, cannot divide a boolean.\n"); }
|
||||||
|
if (x->type == STRING || y->type == STRING) { fprintf(stderr, "Error, cannot division a string.\n"); }
|
||||||
|
|
||||||
struct Value* ans;
|
struct Value* ans;
|
||||||
|
|
||||||
|
@ -66,6 +74,7 @@ struct Value* division(struct Value* x, struct Value* y) {
|
||||||
struct Value* multiplication(struct Value* x, struct Value* y) {
|
struct Value* multiplication(struct Value* x, struct Value* y) {
|
||||||
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in multiply.\n"); }
|
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in multiply.\n"); }
|
||||||
if (x->type == BOOLEAN || y->type == BOOLEAN) { fprintf(stderr, "Error, cannot multiply a boolean.\n"); }
|
if (x->type == BOOLEAN || y->type == BOOLEAN) { fprintf(stderr, "Error, cannot multiply a boolean.\n"); }
|
||||||
|
if (x->type == STRING || y->type == STRING) { fprintf(stderr, "Error, cannot multiply a string.\n"); }
|
||||||
|
|
||||||
struct Value* ans;
|
struct Value* ans;
|
||||||
|
|
||||||
|
@ -86,6 +95,9 @@ struct Value* multiplication(struct Value* x, struct Value* y) {
|
||||||
struct Value* less(struct Value* x, struct Value* y) {
|
struct Value* less(struct Value* x, struct Value* y) {
|
||||||
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in <.\n"); }
|
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in <.\n"); }
|
||||||
if (x->type == BOOLEAN || y->type == BOOLEAN) { fprintf(stderr, "Error, cannot numerically compare a boolean.\n"); }
|
if (x->type == BOOLEAN || y->type == BOOLEAN) { fprintf(stderr, "Error, cannot numerically compare a boolean.\n"); }
|
||||||
|
if ((x->type == STRING || y->type == STRING) && (x->type != STRING || y->type != STRING)) {
|
||||||
|
fprintf(stderr, "Error, cannot compare a string with another data type.\n");
|
||||||
|
}
|
||||||
|
|
||||||
struct Value* ans;
|
struct Value* ans;
|
||||||
|
|
||||||
|
@ -96,6 +108,8 @@ struct Value* less(struct Value* x, struct Value* y) {
|
||||||
ans = make_boolean(get_long(x) < get_double(y));
|
ans = make_boolean(get_long(x) < get_double(y));
|
||||||
} else if (x->type == DOUBLE && y->type == LONG) {
|
} else if (x->type == DOUBLE && y->type == LONG) {
|
||||||
ans = make_boolean(get_double(x) < get_long(y));
|
ans = make_boolean(get_double(x) < get_long(y));
|
||||||
|
} else if (x->type == STRING && y->type == STRING) {
|
||||||
|
ans = make_boolean(strcmp(get_string(x), get_string(y)) < 0);
|
||||||
} else { // Both are DOUBLE
|
} else { // Both are DOUBLE
|
||||||
ans = make_boolean(get_double(x) < get_double(y));
|
ans = make_boolean(get_double(x) < get_double(y));
|
||||||
}
|
}
|
||||||
|
@ -106,6 +120,9 @@ struct Value* less(struct Value* x, struct Value* y) {
|
||||||
struct Value* greater(struct Value* x, struct Value* y) {
|
struct Value* greater(struct Value* x, struct Value* y) {
|
||||||
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in greater.\n"); }
|
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in greater.\n"); }
|
||||||
if (x->type == BOOLEAN || y->type == BOOLEAN) { fprintf(stderr, "Error, cannot numerically compare a boolean.\n"); }
|
if (x->type == BOOLEAN || y->type == BOOLEAN) { fprintf(stderr, "Error, cannot numerically compare a boolean.\n"); }
|
||||||
|
if ((x->type == STRING || y->type == STRING) && (x->type != STRING || y->type != STRING)) {
|
||||||
|
fprintf(stderr, "Error, cannot compare a string with another data type.\n");
|
||||||
|
}
|
||||||
|
|
||||||
struct Value* ans;
|
struct Value* ans;
|
||||||
|
|
||||||
|
@ -116,6 +133,8 @@ struct Value* greater(struct Value* x, struct Value* y) {
|
||||||
ans = make_boolean(get_long(x) > get_double(y));
|
ans = make_boolean(get_long(x) > get_double(y));
|
||||||
} else if (x->type == DOUBLE && y->type == LONG) {
|
} else if (x->type == DOUBLE && y->type == LONG) {
|
||||||
ans = make_boolean(get_double(x) > get_long(y));
|
ans = make_boolean(get_double(x) > get_long(y));
|
||||||
|
} else if (x->type == STRING && y->type == STRING) {
|
||||||
|
ans = make_boolean(strcmp(get_string(x), get_string(y)) > 0);
|
||||||
} else { // Both are DOUBLE
|
} else { // Both are DOUBLE
|
||||||
ans = make_boolean(get_double(x) > get_double(y));
|
ans = make_boolean(get_double(x) > get_double(y));
|
||||||
}
|
}
|
||||||
|
@ -126,6 +145,9 @@ struct Value* greater(struct Value* x, struct Value* y) {
|
||||||
struct Value* less_equal(struct Value* x, struct Value* y) {
|
struct Value* less_equal(struct Value* x, struct Value* y) {
|
||||||
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in <=.\n"); }
|
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in <=.\n"); }
|
||||||
if (x->type == BOOLEAN || y->type == BOOLEAN) { fprintf(stderr, "Error, cannot numerically compare a boolean.\n"); }
|
if (x->type == BOOLEAN || y->type == BOOLEAN) { fprintf(stderr, "Error, cannot numerically compare a boolean.\n"); }
|
||||||
|
if ((x->type == STRING || y->type == STRING) && (x->type != STRING || y->type != STRING)) {
|
||||||
|
fprintf(stderr, "Error, cannot compare a string with another data type.\n");
|
||||||
|
}
|
||||||
|
|
||||||
struct Value* ans;
|
struct Value* ans;
|
||||||
|
|
||||||
|
@ -136,6 +158,8 @@ struct Value* less_equal(struct Value* x, struct Value* y) {
|
||||||
ans = make_boolean(get_long(x) <= get_double(y));
|
ans = make_boolean(get_long(x) <= get_double(y));
|
||||||
} else if (x->type == DOUBLE && y->type == LONG) {
|
} else if (x->type == DOUBLE && y->type == LONG) {
|
||||||
ans = make_boolean(get_double(x) <= get_long(y));
|
ans = make_boolean(get_double(x) <= get_long(y));
|
||||||
|
} else if (x->type == STRING && y->type == STRING) {
|
||||||
|
ans = make_boolean(strcmp(get_string(x), get_string(y)) <= 0);
|
||||||
} else { // Both are DOUBLE
|
} else { // Both are DOUBLE
|
||||||
ans = make_boolean(get_double(x) <= get_double(y));
|
ans = make_boolean(get_double(x) <= get_double(y));
|
||||||
}
|
}
|
||||||
|
@ -146,6 +170,9 @@ struct Value* less_equal(struct Value* x, struct Value* y) {
|
||||||
struct Value* greater_equal(struct Value* x, struct Value* y) {
|
struct Value* greater_equal(struct Value* x, struct Value* y) {
|
||||||
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in >=.\n"); }
|
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in >=.\n"); }
|
||||||
if (x->type == BOOLEAN || y->type == BOOLEAN) { fprintf(stderr, "Error, cannot numerically compare a boolean.\n"); }
|
if (x->type == BOOLEAN || y->type == BOOLEAN) { fprintf(stderr, "Error, cannot numerically compare a boolean.\n"); }
|
||||||
|
if ((x->type == STRING || y->type == STRING) && (x->type != STRING || y->type != STRING)) {
|
||||||
|
fprintf(stderr, "Error, cannot compare a string with another data type.\n");
|
||||||
|
}
|
||||||
|
|
||||||
struct Value* ans;
|
struct Value* ans;
|
||||||
|
|
||||||
|
@ -156,6 +183,8 @@ struct Value* greater_equal(struct Value* x, struct Value* y) {
|
||||||
ans = make_boolean(get_long(x) >= get_double(y));
|
ans = make_boolean(get_long(x) >= get_double(y));
|
||||||
} else if (x->type == DOUBLE && y->type == LONG) {
|
} else if (x->type == DOUBLE && y->type == LONG) {
|
||||||
ans = make_boolean(get_double(x) >= get_long(y));
|
ans = make_boolean(get_double(x) >= get_long(y));
|
||||||
|
} else if (x->type == STRING && y->type == STRING) {
|
||||||
|
ans = make_boolean(strcmp(get_string(x), get_string(y)) >= 0);
|
||||||
} else { // Both are DOUBLE
|
} else { // Both are DOUBLE
|
||||||
ans = make_boolean(get_double(x) >= get_double(y));
|
ans = make_boolean(get_double(x) >= get_double(y));
|
||||||
}
|
}
|
||||||
|
@ -165,6 +194,9 @@ struct Value* greater_equal(struct Value* x, struct Value* y) {
|
||||||
|
|
||||||
struct Value* equals(struct Value* x, struct Value* y) {
|
struct Value* equals(struct Value* x, struct Value* y) {
|
||||||
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in ==.\n"); }
|
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in ==.\n"); }
|
||||||
|
if ((x->type == STRING || y->type == STRING) && (x->type != STRING || y->type != STRING)) {
|
||||||
|
fprintf(stderr, "Error, cannot compare a string with another data type.\n");
|
||||||
|
}
|
||||||
|
|
||||||
struct Value* ans;
|
struct Value* ans;
|
||||||
|
|
||||||
|
@ -179,6 +211,8 @@ struct Value* equals(struct Value* x, struct Value* y) {
|
||||||
ans = make_boolean(get_double(x) == get_double(y));
|
ans = make_boolean(get_double(x) == get_double(y));
|
||||||
} else if (x->type == BOOLEAN && y->type == BOOLEAN) {
|
} else if (x->type == BOOLEAN && y->type == BOOLEAN) {
|
||||||
ans = make_boolean(get_long(x) == get_long(y));
|
ans = make_boolean(get_long(x) == get_long(y));
|
||||||
|
} else if (x->type == STRING && y->type == STRING) {
|
||||||
|
ans = make_boolean(strcmp(get_string(x), get_string(y)) == 0);
|
||||||
} else { // Type is a mix between boolean and another type
|
} else { // Type is a mix between boolean and another type
|
||||||
fprintf(stderr, "Error, cannot compare a boolean with another type.\n");
|
fprintf(stderr, "Error, cannot compare a boolean with another type.\n");
|
||||||
}
|
}
|
||||||
|
@ -188,6 +222,9 @@ struct Value* equals(struct Value* x, struct Value* y) {
|
||||||
|
|
||||||
struct Value* not_equals(struct Value* x, struct Value* y) {
|
struct Value* not_equals(struct Value* x, struct Value* y) {
|
||||||
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in !=.\n"); }
|
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in !=.\n"); }
|
||||||
|
if ((x->type == STRING || y->type == STRING) && (x->type != STRING || y->type != STRING)) {
|
||||||
|
fprintf(stderr, "Error, cannot compare a string with another data type.\n");
|
||||||
|
}
|
||||||
|
|
||||||
struct Value* ans;
|
struct Value* ans;
|
||||||
|
|
||||||
|
@ -202,6 +239,8 @@ struct Value* not_equals(struct Value* x, struct Value* y) {
|
||||||
ans = make_boolean(get_double(x) != get_double(y));
|
ans = make_boolean(get_double(x) != get_double(y));
|
||||||
} else if (x->type == BOOLEAN && y->type == BOOLEAN) {
|
} else if (x->type == BOOLEAN && y->type == BOOLEAN) {
|
||||||
ans = make_boolean(get_long(x) != get_long(y));
|
ans = make_boolean(get_long(x) != get_long(y));
|
||||||
|
} else if (x->type == STRING && y->type == STRING) {
|
||||||
|
ans = make_boolean(strcmp(get_string(x), get_string(y)) != 0);
|
||||||
} else { // Type is a mix between boolean and another type
|
} else { // Type is a mix between boolean and another type
|
||||||
fprintf(stderr, "Error, cannot compare a boolean with another type.\n");
|
fprintf(stderr, "Error, cannot compare a boolean with another type.\n");
|
||||||
}
|
}
|
||||||
|
@ -212,6 +251,7 @@ struct Value* not_equals(struct Value* x, struct Value* y) {
|
||||||
struct Value* and(struct Value* x, struct Value* y) {
|
struct Value* and(struct Value* x, struct Value* y) {
|
||||||
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in &&.\n"); }
|
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in &&.\n"); }
|
||||||
if (x->type != BOOLEAN || y->type != BOOLEAN) { fprintf(stderr, "Error, cannot use and AND operation with a non-boolean.\n"); }
|
if (x->type != BOOLEAN || y->type != BOOLEAN) { fprintf(stderr, "Error, cannot use and AND operation with a non-boolean.\n"); }
|
||||||
|
if (x->type == STRING || y->type == STRING) { fprintf(stderr, "Error, cannot AND a string.\n"); }
|
||||||
|
|
||||||
return make_boolean(get_long(x) && get_long(y));
|
return make_boolean(get_long(x) && get_long(y));
|
||||||
}
|
}
|
||||||
|
@ -219,6 +259,7 @@ struct Value* and(struct Value* x, struct Value* y) {
|
||||||
struct Value* or(struct Value* x, struct Value* y) {
|
struct Value* or(struct Value* x, struct Value* y) {
|
||||||
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in ||.\n"); }
|
if (!x || !y) { fprintf(stderr, "Error, uninitialized values being used in ||.\n"); }
|
||||||
if (x->type != BOOLEAN || y->type != BOOLEAN) { fprintf(stderr, "Error, cannot use and OR operation with a non-boolean.\n"); }
|
if (x->type != BOOLEAN || y->type != BOOLEAN) { fprintf(stderr, "Error, cannot use and OR operation with a non-boolean.\n"); }
|
||||||
|
if (x->type == STRING || y->type == STRING) { fprintf(stderr, "Error, cannot OR a string.\n"); }
|
||||||
|
|
||||||
return make_boolean(get_long(x) || get_long(y));
|
return make_boolean(get_long(x) || get_long(y));
|
||||||
}
|
}
|
||||||
|
@ -226,6 +267,7 @@ struct Value* or(struct Value* x, struct Value* y) {
|
||||||
struct Value* not(struct Value* x) {
|
struct Value* not(struct Value* x) {
|
||||||
if (!x) { fprintf(stderr, "Error, uninitialized values being used in !.\n"); }
|
if (!x) { fprintf(stderr, "Error, uninitialized values being used in !.\n"); }
|
||||||
if (x->type != BOOLEAN) { fprintf(stderr, "Error, cannot NOT a non-boolean.\n"); }
|
if (x->type != BOOLEAN) { fprintf(stderr, "Error, cannot NOT a non-boolean.\n"); }
|
||||||
|
if (x->type == STRING) { fprintf(stderr, "Error, cannot negate a string.\n"); }
|
||||||
|
|
||||||
return make_boolean(!get_long(x));
|
return make_boolean(!get_long(x));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "../operations/node.h"
|
#include "../operations/node.h"
|
||||||
#include "../variables/value.h"
|
#include "../variables/value.h"
|
||||||
#include "parser.tab.h"
|
#include "parser.tab.h"
|
||||||
|
#include "../string.h"
|
||||||
|
|
||||||
/* Keep track of line numbers for error reporting */
|
/* Keep track of line numbers for error reporting */
|
||||||
int linenum = 0;
|
int linenum = 0;
|
||||||
|
@ -44,6 +45,7 @@ DIGIT [0-9]
|
||||||
":" {return COLON;}
|
":" {return COLON;}
|
||||||
"true" {yylval.value = make_node(VALUE, make_true(), ""); return VALUE;}
|
"true" {yylval.value = make_node(VALUE, make_true(), ""); return VALUE;}
|
||||||
"false" {yylval.value = make_node(VALUE, make_false(), ""); return VALUE;}
|
"false" {yylval.value = make_node(VALUE, make_false(), ""); return VALUE;}
|
||||||
|
\".*\" {yylval.value = make_node(VALUE, make_string(substring(yytext, 1, strlen(yytext) - 1)), ""); return VALUE; }
|
||||||
{DIGIT} {yylval.value = make_node(VALUE, make_long(atoi(yytext)), ""); return VALUE;}
|
{DIGIT} {yylval.value = make_node(VALUE, make_long(atoi(yytext)), ""); return VALUE;}
|
||||||
{DIGIT}*"."?{DIGIT}+ {yylval.value = make_node(VALUE, make_double(atof(yytext)), ""); return VALUE;}
|
{DIGIT}*"."?{DIGIT}+ {yylval.value = make_node(VALUE, make_double(atof(yytext)), ""); return VALUE;}
|
||||||
[_a-zA-Z][_a-zA-Z0-9]* {yylval.value = make_node(IDENTIFIER, NULL, strdup(yytext)); return IDENTIFIER;}
|
[_a-zA-Z][_a-zA-Z0-9]* {yylval.value = make_node(IDENTIFIER, NULL, strdup(yytext)); return IDENTIFIER;}
|
||||||
|
|
28
src/string.c
Normal file
28
src/string.c
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
char* substring(char* str, int start, int end) {
|
||||||
|
// Add conditions that substring is valid, probably using strlen
|
||||||
|
int stringLength = strlen(str);
|
||||||
|
if (start >= stringLength || end > stringLength) { fprintf(stderr, "Requesting substring outside of valid range.\n"); return NULL; }
|
||||||
|
|
||||||
|
char* substr;
|
||||||
|
int c;
|
||||||
|
int length = end - start;
|
||||||
|
substr = malloc(length + 1);
|
||||||
|
|
||||||
|
if (substr == NULL) {
|
||||||
|
fprintf(stderr, "Unable to allocate memory for substring.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (c = 0; c < length; c++) {
|
||||||
|
substr[c] = str[start + c];
|
||||||
|
}
|
||||||
|
|
||||||
|
substr[c] = '\0';
|
||||||
|
|
||||||
|
return substr;
|
||||||
|
}
|
6
src/string.h
Normal file
6
src/string.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef STRING_H
|
||||||
|
#define STRING_H
|
||||||
|
|
||||||
|
char* substring(char* str, int start, int end);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,9 +1,10 @@
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
#include "../parser/parser.tab.h"
|
#include "../parser/parser.tab.h"
|
||||||
|
|
||||||
|
|
||||||
struct Value* make_value(int type, long num, double dec, struct Node* expr) {
|
struct Value* make_value(int type, long num, double dec, struct Node* expr, char* str) {
|
||||||
/* allocate space */
|
/* allocate space */
|
||||||
struct Value* val = malloc(sizeof(struct Value));
|
struct Value* val = malloc(sizeof(struct Value));
|
||||||
|
|
||||||
|
@ -13,6 +14,8 @@ struct Value* make_value(int type, long num, double dec, struct Node* expr) {
|
||||||
val->value.num = num;
|
val->value.num = num;
|
||||||
} else if (type == DOUBLE){ // Assume DOUBLE
|
} else if (type == DOUBLE){ // Assume DOUBLE
|
||||||
val->value.dec = dec;
|
val->value.dec = dec;
|
||||||
|
} else if (type == STRING) {
|
||||||
|
val->value.str = str;
|
||||||
} else { // Assume lambda expression
|
} else { // Assume lambda expression
|
||||||
val->value.expr = expr;
|
val->value.expr = expr;
|
||||||
}
|
}
|
||||||
|
@ -22,22 +25,25 @@ struct Value* make_value(int type, long num, double dec, struct Node* expr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Value* make_long(long num) {
|
struct Value* make_long(long num) {
|
||||||
return make_value(LONG, num, 0, NULL);
|
return make_value(LONG, num, 0, NULL, NULL);
|
||||||
}
|
}
|
||||||
struct Value* make_double(double dec) {
|
struct Value* make_double(double dec) {
|
||||||
return make_value(DOUBLE, 0, dec, NULL);
|
return make_value(DOUBLE, 0, dec, NULL, NULL);
|
||||||
}
|
}
|
||||||
struct Value* make_true() {
|
struct Value* make_true() {
|
||||||
return make_value(BOOLEAN, 1, 0, NULL);
|
return make_value(BOOLEAN, 1, 0, NULL, NULL);
|
||||||
}
|
}
|
||||||
struct Value* make_false() {
|
struct Value* make_false() {
|
||||||
return make_value(BOOLEAN, 0, 0, NULL);
|
return make_value(BOOLEAN, 0, 0, NULL, NULL);
|
||||||
}
|
}
|
||||||
struct Value* make_boolean(int x) {
|
struct Value* make_boolean(int x) {
|
||||||
return (x)? make_true() : make_false();
|
return (x)? make_true() : make_false();
|
||||||
}
|
}
|
||||||
struct Value* make_expression(struct Node* expr) {
|
struct Value* make_expression(struct Node* expr) {
|
||||||
return make_value(LAMBDA, 0, 0, expr);
|
return make_value(LAMBDA, 0, 0, expr, NULL);
|
||||||
|
}
|
||||||
|
struct Value* make_string(char* str) {
|
||||||
|
return make_value(STRING, 0, 0, NULL, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete_value(struct Value* val) {
|
void delete_value(struct Value* val) {
|
||||||
|
@ -53,6 +59,9 @@ double get_double(struct Value* val) {
|
||||||
struct Node* get_expression(struct Value* val) {
|
struct Node* get_expression(struct Value* val) {
|
||||||
return val->value.expr;
|
return val->value.expr;
|
||||||
}
|
}
|
||||||
|
char* get_string(struct Value* val) {
|
||||||
|
return val->value.str;
|
||||||
|
}
|
||||||
|
|
||||||
void set_long(struct Value* val, long num) {
|
void set_long(struct Value* val, long num) {
|
||||||
val->type = LONG;
|
val->type = LONG;
|
||||||
|
@ -66,3 +75,25 @@ void set_expression(struct Value* val, struct Node* expr) {
|
||||||
val->type = LAMBDA;
|
val->type = LAMBDA;
|
||||||
val->value.expr = expr;
|
val->value.expr = expr;
|
||||||
}
|
}
|
||||||
|
void set_sring(struct Value* val, char* str) {
|
||||||
|
val->type = STRING;
|
||||||
|
val->value.str = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_value(struct Value* val) {
|
||||||
|
if (val->type == BOOLEAN) {
|
||||||
|
if (get_long(val)) {
|
||||||
|
printf("true");
|
||||||
|
} else {
|
||||||
|
printf("false");
|
||||||
|
}
|
||||||
|
} else if (val->type == LONG) {
|
||||||
|
printf("%li", get_long(val));
|
||||||
|
} else if (val->type == STRING) {
|
||||||
|
printf("%s", get_string(val));
|
||||||
|
} else if (val->type == DOUBLE) {
|
||||||
|
printf("%lf", get_double(val));
|
||||||
|
} else { // Assume lambda expression
|
||||||
|
printf("<LambdaExpression>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
#ifndef VALUE_H
|
#ifndef VALUE_H
|
||||||
#define VALUE_H
|
#define VALUE_H
|
||||||
|
|
||||||
enum TypeTag { DOUBLE, LONG, BOOLEAN };
|
enum TypeTag { DOUBLE, LONG, BOOLEAN, STRING };
|
||||||
|
|
||||||
typedef union typeval {
|
typedef union typeval {
|
||||||
long num;
|
long num;
|
||||||
double dec;
|
double dec;
|
||||||
struct Node* expr;
|
struct Node* expr;
|
||||||
|
char* str;
|
||||||
} TypeVal;
|
} TypeVal;
|
||||||
|
|
||||||
struct Value {
|
struct Value {
|
||||||
|
@ -15,13 +16,14 @@ struct Value {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
struct Value* make_value(int type, long num, double dec, struct Node* expr);
|
struct Value* make_value(int type, long num, double dec, struct Node* expr, char* str);
|
||||||
struct Value* make_long(long num);
|
struct Value* make_long(long num);
|
||||||
struct Value* make_double(double dec);
|
struct Value* make_double(double dec);
|
||||||
struct Value* make_true();
|
struct Value* make_true();
|
||||||
struct Value* make_false();
|
struct Value* make_false();
|
||||||
struct Value* make_boolean(int x);
|
struct Value* make_boolean(int x);
|
||||||
struct Value* make_expression(struct Node* expr);
|
struct Value* make_expression(struct Node* expr);
|
||||||
|
struct Value* make_string(char* str);
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
void delete_value(struct Value* val);
|
void delete_value(struct Value* val);
|
||||||
|
@ -30,10 +32,14 @@ void delete_value(struct Value* val);
|
||||||
long get_long(struct Value* val);
|
long get_long(struct Value* val);
|
||||||
double get_double(struct Value* val);
|
double get_double(struct Value* val);
|
||||||
struct Node* get_expression(struct Value* val);
|
struct Node* get_expression(struct Value* val);
|
||||||
|
char* get_string(struct Value* val);
|
||||||
|
|
||||||
// Setters
|
// Setters
|
||||||
void set_long(struct Value* val, long num);
|
void set_long(struct Value* val, long num);
|
||||||
void set_double(struct Value* val, double dec);
|
void set_double(struct Value* val, double dec);
|
||||||
void set_expression(struct Value* val, struct Node* node);
|
void set_expression(struct Value* val, struct Node* node);
|
||||||
|
void set_string(struct Value* val, char* str);
|
||||||
|
|
||||||
|
void print_value(struct Value* val);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Reference in a new issue