feat: line processing and basic variable support
This commit is contained in:
parent
cb2a1df61f
commit
11fa2b1e6f
21 changed files with 893 additions and 136 deletions
3
Makefile
3
Makefile
|
@ -10,3 +10,6 @@ build:
|
|||
test:
|
||||
gcc ${TEST_SRCS_ENC} ./tests/* -o ./bin/test ${CXXFLAGS_WITHOUT_PKGS}
|
||||
./bin/test
|
||||
sandbox:
|
||||
gcc ${TEST_SRCS_ENC} ./sandbox.c -o ./bin/sandbox ${CXXFLAGS_WITHOUT_PKGS}
|
||||
./bin/sandbox
|
||||
|
|
92
sandbox.c
Normal file
92
sandbox.c
Normal file
|
@ -0,0 +1,92 @@
|
|||
#include <stdio.h>
|
||||
#include "./src/types.h"
|
||||
#include "./src/list.h"
|
||||
#include "./src/number_parsing.h"
|
||||
#include "./src/funcs.h"
|
||||
#include "./src/utils.h"
|
||||
#include "./src/var_store.h"
|
||||
#include "./src/line_processing.h"
|
||||
#include "./src/state.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
int main () {
|
||||
// struct List l1;
|
||||
|
||||
// short val = 17;
|
||||
// list_set(&l1, 0, TYPE_VAR_NAME, &val);
|
||||
// list_print(&l1);
|
||||
|
||||
// return 0;
|
||||
|
||||
// int yes = 1234;
|
||||
// int dst = 0;
|
||||
// memcpy(&dst, &yes, 4);
|
||||
// printf("yes: %d \n", dst);
|
||||
|
||||
struct VariableStore* store = var_store_init();
|
||||
|
||||
// int hashRes = var_store_hash_name(store, "HelloWorld++");
|
||||
// printf("hashRes: %d \n", hashRes);
|
||||
int val = 1234;
|
||||
var_store_set(store, "foo", TYPE_INT, &val);
|
||||
|
||||
//printf("Pos of var: %d \n", var_store_get_pos(store, "foo"));
|
||||
|
||||
//byte type = var_store_get_type(store, "foo");
|
||||
//printf("Type of var: %d \n", type);
|
||||
|
||||
//int key = var_store_get_pos(store, "foo");
|
||||
//printf("size of type %d \n", get_size_of_type(store->container[key].type));
|
||||
//printf("%d \n", *((int*) store->container[key].dataPtr));
|
||||
|
||||
int val2 = 0;
|
||||
var_store_copy(store, "foo", &val2);
|
||||
|
||||
printf("Value of var: %d \n", val2);
|
||||
|
||||
printf("==== \n");
|
||||
printf("==== \n");
|
||||
struct StateContainer* state = state_init();
|
||||
process_line(state, "# some random comment");
|
||||
process_line(state, "set VAR_A to 8.5");
|
||||
process_line(state, "set VAR_B to 1.5");
|
||||
process_line(state, "set VAR_C to VAR_A+VAR_B");
|
||||
process_line(state, "print_number(sqrt(VAR_C))");
|
||||
|
||||
// struct List l1;
|
||||
|
||||
// list_append_int(&l1, 4);
|
||||
// list_append_char(&l1, '*');
|
||||
// list_append_int(&l1, 5);
|
||||
|
||||
// list_print(&l1);
|
||||
|
||||
// list_delete(&l1, 0);
|
||||
|
||||
// list_print(&l1);
|
||||
|
||||
// list_delete(&l1, 0);
|
||||
|
||||
// list_print(&l1);
|
||||
|
||||
// float res = 0;
|
||||
|
||||
// void* ptr = &res;
|
||||
|
||||
// printf("%d\n", sizeof(ptr));
|
||||
// int found = identify_func_name("ABS");
|
||||
// printf("found: %d \n", found);
|
||||
|
||||
// unsigned char argsType[1] = { TYPE_FLOAT };
|
||||
// int argsVals[1] = { get_int_rep_from_float(-3.145) };
|
||||
// int resVal = 0;
|
||||
// unsigned char resType = 0;
|
||||
// execute_func(found, 1, argsType, argsVals, &resVal, &resType);
|
||||
// printf("func res type: %d \n", resType);
|
||||
// printf("func res: %f \n", get_float_from_int_rep(resVal));
|
||||
|
||||
// int stat = parse_float("1052.254", &res);
|
||||
// printf("float parsing stat: %d \n", stat);
|
||||
// printf("final float: %f \n", res);
|
||||
}
|
||||
|
|
@ -6,6 +6,8 @@
|
|||
#include "./operate.h"
|
||||
#include "./number_parsing.h"
|
||||
#include "./funcs.h"
|
||||
#include "./var_store.h"
|
||||
#include "./state.h"
|
||||
|
||||
/**
|
||||
This sub script will look for pattern like Number Operator Number
|
||||
|
@ -154,6 +156,31 @@ int evaluator_reduce_parenthesis_pattern(struct List* evalList) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int evaluator_reduce_var(struct StateContainer* state, struct List* evalList) {
|
||||
int patternPos = -1;
|
||||
for (int i = 0; i < evalList->num_elements; i++) {
|
||||
if (
|
||||
list_get_type(evalList, i) == TYPE_VAR_NAME
|
||||
) {
|
||||
patternPos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (patternPos == -1) return -1;
|
||||
|
||||
int varKey;
|
||||
list_get(evalList, patternPos, &varKey);
|
||||
|
||||
byte type = var_store_get_type_from_key(state->varStore, varKey);
|
||||
|
||||
byte varVal[get_size_of_type(type)];
|
||||
var_store_copy_from_key(state->varStore, varKey, &varVal);
|
||||
|
||||
list_set(evalList, patternPos, type, &varVal);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
This func will look for a function call pattern that is ready to be evaluated
|
||||
First we will look for this kind of pattern
|
||||
|
@ -169,10 +196,14 @@ if we don't find a comma next, we try to find a closing parenthesis
|
|||
if we don't find that, we throw an error
|
||||
|
||||
*/
|
||||
int evaluator_reduce_function_call(struct List* evalList) {
|
||||
int evaluator_reduce_function_call(struct List* evalList, int initialPosition) {
|
||||
int patternPos = -1;
|
||||
|
||||
for (int i = 0; i < evalList->num_elements; i++) {
|
||||
if (initialPosition >= evalList->num_elements) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = initialPosition; i < evalList->num_elements; i++) {
|
||||
if (
|
||||
list_get_type(evalList, i) == TYPE_FUNC_NAME &&
|
||||
list_get_type(evalList, i+1) == TYPE_OPEN_PARENTHESIS
|
||||
|
@ -239,7 +270,10 @@ int evaluator_reduce_function_call(struct List* evalList) {
|
|||
}
|
||||
|
||||
// we cannot reduce more, it's probably because the func call is not ready to be reduced, meaning that the arguments need to be evaluated
|
||||
return -1;
|
||||
|
||||
// we need to return to the state of primitive function detection, just skip this primitive
|
||||
// we need to revaluate at patternPos+2
|
||||
return evaluator_reduce_function_call(evalList, patternPos+2);
|
||||
}
|
||||
// now pos is the index of the last component for this func call
|
||||
|
||||
|
@ -287,7 +321,7 @@ Arguments:
|
|||
- Input String: char pointer (the source of the evaluation)
|
||||
- Result: int pointer (where the result of the evaluation will be written)
|
||||
*/
|
||||
int evaluate(char* inputStr, int* resultPtr, unsigned char* typePtr) {
|
||||
int evaluate(struct StateContainer* state, char* inputStr, int* resultPtr, unsigned char* typePtr) {
|
||||
int i = 0;
|
||||
int _len = strlen(inputStr);
|
||||
// we want first to parse the expression and create a stack
|
||||
|
@ -461,18 +495,27 @@ int evaluate(char* inputStr, int* resultPtr, unsigned char* typePtr) {
|
|||
}
|
||||
|
||||
if (st != 0) {
|
||||
// identify token
|
||||
// first try a variable then a func name
|
||||
// not a float, check if this is a common function name
|
||||
short funcID = identify_func_name(buff);
|
||||
if (funcID == -1) {
|
||||
// did not find the func name
|
||||
printf("ERR Evaluator: could not identify token \"%s\" \n", buff);
|
||||
return 200;
|
||||
short varKey = (short) var_store_get_key(state->varStore, buff);
|
||||
if (varKey == -1) {
|
||||
// did not find the var name
|
||||
short funcID = identify_func_name(buff);
|
||||
if (funcID == -1) {
|
||||
// did not find the func name
|
||||
printf("ERR Evaluator: could not identify token \"%s\" \n", buff);
|
||||
return 200;
|
||||
}
|
||||
if (funcID >= 0) {
|
||||
list_set(&evalList, evalList.num_elements, TYPE_FUNC_NAME, &funcID);
|
||||
}
|
||||
}
|
||||
if (funcID >= 0) {
|
||||
list_set(&evalList, evalList.num_elements, TYPE_FUNC_NAME, &funcID);
|
||||
if (varKey >= 0) {
|
||||
list_set(&evalList, evalList.num_elements, TYPE_VAR_NAME, &varKey);
|
||||
}
|
||||
}
|
||||
printf("end of l\n");
|
||||
printf("end of a token id\n");
|
||||
}
|
||||
|
||||
// check the content of this thing
|
||||
|
@ -484,15 +527,21 @@ int evaluate(char* inputStr, int* resultPtr, unsigned char* typePtr) {
|
|||
|
||||
// we are going to look for pattern to reduce
|
||||
// the order is really important here
|
||||
int reduceFuncOpStat = evaluator_reduce_function_call(&evalList);
|
||||
int reduceVarOpStat = evaluator_reduce_var(state, &evalList);
|
||||
int reduceFuncOpStat = evaluator_reduce_function_call(&evalList, 0);
|
||||
int reduceMinusOpStat = evaluator_reduce_minus_pattern(&evalList);
|
||||
int reduceOperatorOpStat = evaluator_reduce_operator_pattern(&evalList);
|
||||
int reduceParenthesisOpStat = evaluator_reduce_parenthesis_pattern(&evalList);
|
||||
|
||||
if (reduceVarOpStat > 0) {
|
||||
printf("ERR Evaluator: var name reducing failed, dumping evalList: \n");
|
||||
list_print(&evalList);
|
||||
return reduceVarOpStat;
|
||||
}
|
||||
if (reduceFuncOpStat > 0) {
|
||||
printf("ERR Evaluator: function reducing failed, dumping evalList: \n");
|
||||
list_print(&evalList);
|
||||
return reduceOperatorOpStat;
|
||||
return reduceFuncOpStat;
|
||||
}
|
||||
if (reduceOperatorOpStat > 0) {
|
||||
printf("ERR Evaluator: operator reducing failed, dumping evalList: \n");
|
||||
|
@ -501,6 +550,7 @@ int evaluate(char* inputStr, int* resultPtr, unsigned char* typePtr) {
|
|||
}
|
||||
|
||||
if (
|
||||
reduceVarOpStat == -1 &&
|
||||
reduceFuncOpStat == -1 &&
|
||||
reduceOperatorOpStat == -1 &&
|
||||
reduceParenthesisOpStat == -1 &&
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "./state.h"
|
||||
#ifndef EVALUATOR_H_
|
||||
#define EVALUATOR_H_
|
||||
|
||||
int evaluate(char* inputStr, int* resultPtr, unsigned char* typePtr);
|
||||
int evaluate(struct StateContainer* state, char* inputStr, int* resultPtr, unsigned char* typePtr);
|
||||
|
||||
#endif
|
||||
|
|
40
src/funcs.c
40
src/funcs.c
|
@ -27,6 +27,25 @@ int abs_impl(int* res, unsigned char* resType, unsigned char* types, int* args)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int print_number_impl(int* res, unsigned char* resType, unsigned char* types, int* args)
|
||||
{
|
||||
if (types[0] == TYPE_INT) {
|
||||
int val = args[0];
|
||||
printf("REAL_PRINT: %d\n", val);
|
||||
}
|
||||
if (types[0] == TYPE_FLOAT) {
|
||||
float val = get_float_from_int_rep(args[0]);
|
||||
printf("REAL_PRINT: %f\n", val);
|
||||
}
|
||||
if (is_type_number(types[0])) {
|
||||
*res = 1;
|
||||
*resType = TYPE_INT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int simple_float_func(float (*func)(float), int* res, unsigned char* resType, unsigned char* types, int* args)
|
||||
{
|
||||
float x = 0;
|
||||
|
@ -42,14 +61,15 @@ int simple_float_func(float (*func)(float), int* res, unsigned char* resType, un
|
|||
return 0;
|
||||
}
|
||||
|
||||
// #define SIMPLE_FUNC_BINDING(name) ({\
|
||||
// int #name_impl(int* res, unsigned char* resType, unsigned char* types, int* args)\
|
||||
// {\
|
||||
// return simple_float_func(&m_#name, res, resType, types, args);\
|
||||
// }\
|
||||
// })
|
||||
//
|
||||
//
|
||||
/*
|
||||
#define SIMPLE_FUNC_BINDING(name) ({\
|
||||
int #name_impl(int* res, unsigned char* resType, unsigned char* types, int* args)\
|
||||
{\
|
||||
return simple_float_func(&m_#name, res, resType, types, args);\
|
||||
}\
|
||||
})
|
||||
*/
|
||||
|
||||
// SIMPLE_FUNC_BINDING(sqrt)
|
||||
//
|
||||
// SIMPLE_FUNC_BINDING(exp)
|
||||
|
@ -162,8 +182,6 @@ int random_int_impl(int* res, unsigned char* resType, unsigned char* types, int*
|
|||
upper = args[1];
|
||||
}
|
||||
|
||||
int i;
|
||||
|
||||
// rand returns a value between 0 and RAND_MAX (which is close to infinite)
|
||||
int num = (rand() % (upper - lower + 1)) + lower;
|
||||
*resType = TYPE_INT;
|
||||
|
@ -196,6 +214,8 @@ struct FuncIntro intros[] = {
|
|||
|
||||
{"max", &max_impl, 2},
|
||||
{"get_pi", &get_pi_impl, 0},
|
||||
|
||||
{"print_number", &print_number_impl, 1},
|
||||
{"", 0, 0}
|
||||
};
|
||||
|
||||
|
|
255
src/line_processing.c
Normal file
255
src/line_processing.c
Normal file
|
@ -0,0 +1,255 @@
|
|||
#include "./utils.h"
|
||||
#include "./line_processing.h"
|
||||
#include "./evaluator.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int cmp_str_in_place(char* against, char* str, int from)
|
||||
{
|
||||
|
||||
int i = 0;
|
||||
while (against[i] != '\0') {
|
||||
if (against[i] != str[from+i]) {
|
||||
return 0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int is_char_accepted_in_var_name(char symbol)
|
||||
{
|
||||
int c = (int) symbol;
|
||||
return (
|
||||
(c >= 65 && c <= 90) ||
|
||||
(c >= 97 && c <= 122) ||
|
||||
(c >= 48 && c <= 57) ||
|
||||
c == 45 || c == 95
|
||||
);
|
||||
}
|
||||
|
||||
int recognize_comment_statement(char* lineStr)
|
||||
{
|
||||
int i = 0;
|
||||
int mode = 1;
|
||||
/*
|
||||
recognize pattern : ^\s*#.*$
|
||||
mode 1 any space
|
||||
mode 2 the start of the comment
|
||||
*/
|
||||
while (lineStr[i] != '\0') {
|
||||
if (mode == 1) {
|
||||
if (lineStr[i] == '#') {
|
||||
mode = 2;
|
||||
continue;
|
||||
}
|
||||
if (lineStr[i] != ' ') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (mode != 2) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
struct SetStatement {
|
||||
short name_start;
|
||||
short name_stop;
|
||||
short expression_start;
|
||||
};
|
||||
|
||||
int recognize_set_statement(char* lineStr, struct SetStatement* res)
|
||||
{
|
||||
int i = 0;
|
||||
int mode = 1;
|
||||
int arg = 0;
|
||||
/*
|
||||
recognize pattern : ^\s*set ([a-zA-Z0-9_-]+) to (\S)+
|
||||
mode 1 any space
|
||||
mode 2 set
|
||||
mode 3 any space
|
||||
mode 4 var name
|
||||
mode 5 any space
|
||||
mode 6 to
|
||||
mode 7 any space
|
||||
mode 8 the expression
|
||||
*/
|
||||
while (lineStr[i] != '\0') {
|
||||
if (mode == 1) {
|
||||
if (lineStr[i] == 's') {
|
||||
mode = 2;
|
||||
arg = 0;
|
||||
continue;
|
||||
}
|
||||
if (lineStr[i] != ' ') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mode == 2) {
|
||||
if (arg == 0 && lineStr[i] == 's') {
|
||||
arg++;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (arg == 1 && lineStr[i] == 'e') {
|
||||
arg++;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (arg == 2 && lineStr[i] == 't') {
|
||||
mode = 3;
|
||||
arg = 0;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (mode == 3) {
|
||||
if (arg > 0 && is_char_accepted_in_var_name(lineStr[i])) {
|
||||
mode = 4;
|
||||
arg = 0;
|
||||
res->name_start = i;
|
||||
continue;
|
||||
}
|
||||
if (lineStr[i] != ' ') {
|
||||
break;
|
||||
}
|
||||
arg++;
|
||||
}
|
||||
if (mode == 4) {
|
||||
if (lineStr[i] == ' ') {
|
||||
mode = 5;
|
||||
arg = 0;
|
||||
res->name_stop = i;
|
||||
continue;
|
||||
}
|
||||
if (!is_char_accepted_in_var_name(lineStr[i])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mode == 5) {
|
||||
if (arg > 0 && lineStr[i] == 't') {
|
||||
mode = 6;
|
||||
arg = 0;
|
||||
continue;
|
||||
}
|
||||
if (lineStr[i] != ' ') {
|
||||
break;
|
||||
}
|
||||
arg++;
|
||||
}
|
||||
if (mode == 6) {
|
||||
if (arg == 0 && lineStr[i] == 't') {
|
||||
arg++;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (arg == 1 && lineStr[i] == 'o') {
|
||||
mode = 7;
|
||||
arg = 0;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (mode == 7) {
|
||||
if (arg == 0 && lineStr[i] != ' ') {
|
||||
break;
|
||||
}
|
||||
if (arg > 0 && lineStr[i] != ' ') {
|
||||
// success
|
||||
mode = 8;
|
||||
res->expression_start = i;
|
||||
break;
|
||||
}
|
||||
arg++;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
// printf("End of set statement parsing \n");
|
||||
// printf("index %d \n", i);
|
||||
// printf("mode %d \n", mode);
|
||||
// printf("arg %d \n", arg);
|
||||
|
||||
if (mode != 8) {
|
||||
// we've failed to recognize the pattern
|
||||
return 0;
|
||||
}
|
||||
|
||||
// return a struct with anchors to the groups
|
||||
return 1;
|
||||
}
|
||||
|
||||
int process_line(struct StateContainer* state, char* str)
|
||||
{
|
||||
printf("\n ======= PROCESSING LINE '%s' =======\n", str);
|
||||
// process
|
||||
int len = strlen(str);
|
||||
// int startPos = 0;
|
||||
// int stopPos = len-1;
|
||||
// // modifiy the start and stop pos to trim spaces
|
||||
// int startTrimOffset = 0;
|
||||
// int stopTrimOffset = 0;
|
||||
// for (int z = 0; z < len; z++) {
|
||||
// if (inputStr[startPos+z] != ' ') {
|
||||
// break;
|
||||
// }
|
||||
// startTrimOffset++;
|
||||
// }
|
||||
// for (int z = 1; z < len; z++) {
|
||||
// if (inputStr[stopPos-z] != ' ') {
|
||||
// break;
|
||||
// }
|
||||
// stopTrimOffset++;
|
||||
// }
|
||||
// startPos += startTrimOffset;
|
||||
// stopPos -= stopTrimOffset;
|
||||
|
||||
// check for comment
|
||||
// if (str[startPos] == '#') {
|
||||
// return;
|
||||
// }
|
||||
|
||||
//int stat = 0;
|
||||
if (recognize_comment_statement(str)) {
|
||||
printf("Comment recognized \n");
|
||||
return 1;
|
||||
}
|
||||
struct SetStatement setStatementParsing;
|
||||
if (recognize_set_statement(str, &setStatementParsing)) {
|
||||
printf("Set statement recognized \n");
|
||||
// handle the set statement (set a variable)
|
||||
int nameLen = setStatementParsing.name_stop-setStatementParsing.name_start;
|
||||
char* name = (char*) malloc(sizeof(char) * nameLen);
|
||||
for (int z = 0; z < nameLen; z++) {
|
||||
name[z] = str[setStatementParsing.name_start + z];
|
||||
}
|
||||
name[len] = '\0';
|
||||
|
||||
int res;
|
||||
byte resType;
|
||||
int evalStat = evaluate(state, str + setStatementParsing.expression_start, &res, &resType);
|
||||
if (evalStat != 0) {
|
||||
printf("Syntax error for line \"%s\"\n", str);
|
||||
}
|
||||
|
||||
printf("==> Set '%s' to %s \n", name, get_repr(resType, &res));
|
||||
var_store_set(state->varStore, name, resType, &res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// we evaluate but we dont care about the result
|
||||
int res;
|
||||
byte resType;
|
||||
int evalStat = evaluate(state, str, &res, &resType);
|
||||
if (evalStat != 0) {
|
||||
printf("Syntax error for line \"%s\"\n", str);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
7
src/line_processing.h
Normal file
7
src/line_processing.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#include "./state.h"
|
||||
#ifndef LINE_PROCESSING_H_
|
||||
#define LINE_PROCESSING_H_
|
||||
|
||||
int process_line(struct StateContainer* state, char* str);
|
||||
|
||||
#endif
|
39
src/list.c
39
src/list.c
|
@ -13,37 +13,6 @@ struct List {
|
|||
};
|
||||
*/
|
||||
|
||||
// get size in byte of a particular type
|
||||
int get_size_of_type(unsigned char type)
|
||||
{
|
||||
int t = (int) type;
|
||||
// underlying type is int (4 bytes)
|
||||
if (t == TYPE_INT || t == TYPE_FLOAT) {
|
||||
return 4;
|
||||
}
|
||||
// underlying type is short (1 byte)
|
||||
if (t == TYPE_FUNC_NAME) {
|
||||
return 2;
|
||||
}
|
||||
// underlying type is char (1 byte)
|
||||
if (t == TYPE_OPERATOR) {
|
||||
return 1;
|
||||
}
|
||||
if (
|
||||
t == TYPE_OPEN_PARENTHESIS ||
|
||||
t == TYPE_CLOSE_PARENTHESIS ||
|
||||
t == TYPE_COMMA
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int is_type_number(unsigned char type)
|
||||
{
|
||||
return type == TYPE_INT || type == TYPE_FLOAT;
|
||||
}
|
||||
|
||||
unsigned char list_get_type(struct List* list, int index) {
|
||||
if (index >= list->num_elements) {
|
||||
return 0;
|
||||
|
@ -84,7 +53,7 @@ int list_get(struct List* list, int index, void* resultPtr)
|
|||
if (type == TYPE_OPERATOR) {
|
||||
*((char*) resultPtr) = *((char*) valuePtr);
|
||||
}
|
||||
if (type == TYPE_FUNC_NAME) {
|
||||
if (type == TYPE_FUNC_NAME || type == TYPE_VAR_NAME) {
|
||||
*((short*) resultPtr) = *((short*) valuePtr);
|
||||
}
|
||||
|
||||
|
@ -245,6 +214,12 @@ void list_print(struct List* list)
|
|||
|
||||
printf("type: FUNC_NAME, val: %d", d);
|
||||
}
|
||||
if (type == TYPE_VAR_NAME) {
|
||||
short d = 0;
|
||||
list_get(list, i, &d);
|
||||
|
||||
printf("type: VAR_NAME, val: %d", d);
|
||||
}
|
||||
if (type == TYPE_OPEN_PARENTHESIS) {
|
||||
printf("type: OPEN_PARENTHESIS");
|
||||
}
|
||||
|
|
|
@ -44,13 +44,9 @@ struct List {
|
|||
int data_ptr;
|
||||
int ptrArray[LIST_SIZE];
|
||||
unsigned char typeArray[LIST_SIZE];
|
||||
unsigned char data[LIST_SIZE];
|
||||
unsigned char data[LIST_SIZE]; // FIXME: remove this bc we want to use malloc
|
||||
};
|
||||
|
||||
int is_type_number(unsigned char type);
|
||||
|
||||
int get_size_of_type(unsigned char type);
|
||||
|
||||
unsigned char list_get_type(struct List* list, int index);
|
||||
|
||||
int list_get(struct List* list, int index, void* valuePtr);
|
||||
|
|
25
src/state.c
Normal file
25
src/state.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
#include "./utils.h"
|
||||
#include "./var_store.h"
|
||||
#include "./state.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
// #define STATE_LEN 255
|
||||
// #define VARIABLES_LEN 255
|
||||
|
||||
// struct ProcessingState {
|
||||
// int linePtr;
|
||||
|
||||
// int variableStore[VARIABLES_LEN];
|
||||
// int functionStore[255];
|
||||
// //int stringStore[255]
|
||||
// int data[STACK_LEN];
|
||||
// };
|
||||
|
||||
struct StateContainer* state_init()
|
||||
{
|
||||
struct StateContainer* ptr = (struct StateContainer*) malloc(sizeof(struct StateContainer));
|
||||
ptr->varStore = var_store_init();
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
26
src/state.h
Normal file
26
src/state.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
This is where we store the state of our program
|
||||
we store:
|
||||
- the variables names and their values (for now only int)
|
||||
- the functions names and their references
|
||||
*/
|
||||
#include "./utils.h"
|
||||
#include "./var_store.h"
|
||||
#ifndef STATE_H_
|
||||
#define STATE_H_
|
||||
|
||||
struct StateContainer {
|
||||
// the line we are currently processing
|
||||
int linePtr;
|
||||
// usefull when we are in SKIP_BLOCK mode, we'will count the nb of block (begin/end)
|
||||
int blocStack;
|
||||
// FULL, SKIP_BLOC, etc
|
||||
byte mode;
|
||||
struct VariableStore* varStore;
|
||||
// struct FunctionStore* funcStore;
|
||||
// struct StringStore* strStore ??
|
||||
};
|
||||
|
||||
struct StateContainer* state_init();
|
||||
|
||||
#endif
|
55
src/types.c
Normal file
55
src/types.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
#include "./utils.h"
|
||||
#include "./types.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int is_type_number(byte type)
|
||||
{
|
||||
return type == TYPE_INT || type == TYPE_FLOAT;
|
||||
}
|
||||
|
||||
// get size in byte of a particular type
|
||||
int get_size_of_type(byte type)
|
||||
{
|
||||
int t = (int) type;
|
||||
// underlying type is int (4 bytes)
|
||||
if (t == TYPE_INT || t == TYPE_FLOAT) {
|
||||
return 4;
|
||||
}
|
||||
// underlying type is short (2 bytes)
|
||||
if (t == TYPE_FUNC_NAME || t == TYPE_VAR_NAME) {
|
||||
return 2;
|
||||
}
|
||||
// underlying type is char (1 byte)
|
||||
if (t == TYPE_OPERATOR) {
|
||||
return 1;
|
||||
}
|
||||
if (
|
||||
t == TYPE_OPEN_PARENTHESIS ||
|
||||
t == TYPE_CLOSE_PARENTHESIS ||
|
||||
t == TYPE_COMMA
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
char* get_repr(byte type, void* valPtr)
|
||||
{
|
||||
char* res= (char*) malloc(sizeof(char)*32);
|
||||
if (type == 0) {
|
||||
sprintf(res, "NULL");
|
||||
return res;
|
||||
}
|
||||
if (type == TYPE_INT) {
|
||||
sprintf(res, "INT(%d)", *((int*) valPtr));
|
||||
return res;
|
||||
}
|
||||
if (type == TYPE_FLOAT) {
|
||||
sprintf(res, "FLOAT(%f)", *((float*) valPtr));
|
||||
return res;
|
||||
}
|
||||
|
||||
sprintf(res, "UNKNOWN(%d)", type);
|
||||
return res;
|
||||
}
|
12
src/types.h
12
src/types.h
|
@ -1,8 +1,20 @@
|
|||
#include "./utils.h"
|
||||
#ifndef TYPES_H_
|
||||
#define TYPES_H_
|
||||
|
||||
#define TYPE_INT 2
|
||||
#define TYPE_FLOAT 3
|
||||
#define TYPE_OPERATOR 32
|
||||
#define TYPE_COMMA 33
|
||||
#define TYPE_FUNC_NAME 34
|
||||
#define TYPE_VAR_NAME 35
|
||||
#define TYPE_OPEN_PARENTHESIS 64
|
||||
#define TYPE_CLOSE_PARENTHESIS 65
|
||||
|
||||
int is_type_number(byte type);
|
||||
|
||||
int get_size_of_type(byte type);
|
||||
|
||||
char* get_repr(byte type, void* data);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
#define CST_PI 3.1415926535
|
||||
|
||||
// define custom type (unsigned char)
|
||||
typedef unsigned char byte;
|
||||
|
||||
int get_int_rep_from_float(float ft);
|
||||
|
||||
float get_float_from_int_rep(int representation);
|
||||
|
@ -25,6 +28,8 @@ float m_exp(float x);
|
|||
|
||||
float m_ln(float x);
|
||||
|
||||
float m_log(float base, float x);
|
||||
|
||||
float m_sin(float x);
|
||||
|
||||
float m_cos(float x);
|
||||
|
|
184
src/var_store.c
Normal file
184
src/var_store.c
Normal file
|
@ -0,0 +1,184 @@
|
|||
#include "./types.h"
|
||||
#include "./var_store.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct VariableStore* var_store_init()
|
||||
{
|
||||
struct VariableStore* store = (struct VariableStore*) malloc(sizeof(struct VariableStore));
|
||||
if (store == NULL) {
|
||||
printf("[ERR] VARSTORE: malloc failed for variable store \n");
|
||||
return NULL;
|
||||
}
|
||||
store->allocatedLength = VAR_STORE_INITIAL_ALLOC_LENGTH;
|
||||
store->length = 0;
|
||||
store->container = (struct VariableContainer*) malloc(sizeof(struct VariableContainer) * store->allocatedLength);
|
||||
if (store->container == NULL) {
|
||||
printf("[ERR] VARSTORE: malloc failed for first variable container \n");
|
||||
return NULL;
|
||||
}
|
||||
for (int i = 0; i < store->allocatedLength; i++) {
|
||||
store->container[i].type = 0;
|
||||
}
|
||||
return store;
|
||||
}
|
||||
|
||||
#define MAX_INTEGER 47797852
|
||||
|
||||
int var_store_hash_name(struct VariableStore* store, char* varName)
|
||||
{
|
||||
int hash = 0;
|
||||
int i = 0;
|
||||
while (varName[i] != '\0') {
|
||||
hash += (get_int_rep_from_char(varName[i])*integer_pow(9, i)) % MAX_INTEGER;
|
||||
i++;
|
||||
}
|
||||
return hash % store->allocatedLength;
|
||||
}
|
||||
|
||||
byte var_store_set(struct VariableStore* store, char* varName, byte type, void* valuePtr)
|
||||
{
|
||||
//printf("set variable at var name: '%s' \n", varName);
|
||||
if (!(type == TYPE_FLOAT || type == TYPE_INT)) {
|
||||
printf("[ERR] VARSTORE: unsupported type, cannot store type %d\n", type);
|
||||
return 0;
|
||||
}
|
||||
void* dataPtr;
|
||||
if (type == TYPE_FLOAT || type == TYPE_INT) {
|
||||
dataPtr = malloc(sizeof(int));
|
||||
if (dataPtr == NULL) {
|
||||
printf("[ERR] VARSTORE: malloc failed for data\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// copy the value to the place to store
|
||||
// copy from stack to heap
|
||||
memcpy(dataPtr, valuePtr, sizeof(int));
|
||||
}
|
||||
|
||||
char* namePtr = (char*) malloc(strlen(varName));
|
||||
if (namePtr == NULL) {
|
||||
printf("[ERR] VARSTORE: malloc failed for var name\n");
|
||||
return 1;
|
||||
}
|
||||
strcpy(namePtr, varName);
|
||||
|
||||
int originalKey = var_store_hash_name(store, varName);
|
||||
int key = originalKey;
|
||||
// handle collision, walk along the array
|
||||
while (1)
|
||||
{
|
||||
if (store->container[key].type == 0) {
|
||||
break;
|
||||
}
|
||||
if (strcmp(store->container[key].namePtr, varName) == 0) {
|
||||
// we found a variable with the same exact key, so we overwrite it
|
||||
break;
|
||||
}
|
||||
key = (key+1) % store->allocatedLength;
|
||||
if (key == originalKey) {
|
||||
// end the search to avoid endless loop
|
||||
printf("[ERR] VARSTORE: cannot set variable, not enough containers \n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
//printf("set variable at key: %d \n", key);
|
||||
store->container[key].type = type;
|
||||
store->container[key].namePtr = namePtr;
|
||||
store->container[key].dataPtr = dataPtr;
|
||||
|
||||
store->length++;
|
||||
if (2*store->length >= store->allocatedLength) {
|
||||
// do smth to double the store->allocatedLength
|
||||
// e.g reallocate the store->container
|
||||
store->allocatedLength = 2*store->allocatedLength;
|
||||
store->container = (struct VariableContainer*) realloc(store->container, sizeof(struct VariableContainer) * store->allocatedLength);
|
||||
if (store->container == NULL) {
|
||||
printf("[ERR] VARSTORE: relloc failed for container \n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get the real position of a variable (in order to handle collisions)
|
||||
// return -1 if no pos are found
|
||||
int var_store_get_key(struct VariableStore* store, char* varName)
|
||||
{
|
||||
//printf("get key for %s \n", varName);
|
||||
int originalKey = var_store_hash_name(store, varName);
|
||||
int key = originalKey;
|
||||
// handle collision, walk along the array
|
||||
while (1)
|
||||
{
|
||||
//printf("inter key: %d %d \n", key, store->container[key].type);
|
||||
if (store->container[key].type == 0) {
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(store->container[key].namePtr, varName) == 0) {
|
||||
// we found the position
|
||||
return key;
|
||||
}
|
||||
key = (key+1) % store->allocatedLength;
|
||||
if (key == originalKey) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte var_store_exists(struct VariableStore* store, char* varName)
|
||||
{
|
||||
return var_store_get_key(store, varName) != -1;
|
||||
}
|
||||
|
||||
byte var_store_get_type_from_key(struct VariableStore* store, int key)
|
||||
{
|
||||
return store->container[key].type;
|
||||
}
|
||||
|
||||
byte var_store_get_type(struct VariableStore* store, char* varName)
|
||||
{
|
||||
int key = var_store_get_key(store, varName);
|
||||
if (key < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return var_store_get_type_from_key(store, key);
|
||||
}
|
||||
|
||||
byte var_store_copy_from_key(struct VariableStore* store, int key, void* dst)
|
||||
{
|
||||
if (key < 0) {
|
||||
return 1;
|
||||
}
|
||||
memcpy(dst, store->container[key].dataPtr, (size_t) get_size_of_type(store->container[key].type));
|
||||
return 0;
|
||||
}
|
||||
|
||||
byte var_store_copy(struct VariableStore* store, char* varName, void* dst)
|
||||
{
|
||||
return var_store_copy_from_key(store, var_store_get_key(store, varName), dst);
|
||||
}
|
||||
|
||||
int var_store_get_int(struct VariableStore* store, char* varName)
|
||||
{
|
||||
if (var_store_get_type(store, varName) != TYPE_INT) {
|
||||
return 0;
|
||||
}
|
||||
int val;
|
||||
var_store_copy(store, varName, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
float var_store_get_float(struct VariableStore* store, char* varName)
|
||||
{
|
||||
if (var_store_get_type(store, varName) != TYPE_FLOAT) {
|
||||
return 0;
|
||||
}
|
||||
float val;
|
||||
var_store_copy(store, varName, &val);
|
||||
return val;
|
||||
}
|
64
src/var_store.h
Normal file
64
src/var_store.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
#include "./types.h"
|
||||
#include "./utils.h"
|
||||
#ifndef VAR_STORE_H_
|
||||
#define VAR_STORE_H_
|
||||
|
||||
#define VAR_STORE_INITIAL_ALLOC_LENGTH 32
|
||||
|
||||
/**
|
||||
|
||||
Variable store
|
||||
|
||||
With an Hash Table
|
||||
|
||||
This is a store in the heap
|
||||
|
||||
Features:
|
||||
- resizable, when we have too much variable we can reallocate more memory to store
|
||||
|
||||
*/
|
||||
|
||||
struct VariableContainer {
|
||||
byte type;
|
||||
char* namePtr;
|
||||
void* dataPtr;
|
||||
};
|
||||
|
||||
struct VariableStore {
|
||||
int allocatedLength;
|
||||
int length;
|
||||
struct VariableContainer* container; // with (storeAllocatedLength) items
|
||||
};
|
||||
|
||||
struct VariableStore* var_store_init();
|
||||
|
||||
int var_store_hash_name(struct VariableStore* store, char* varName);
|
||||
|
||||
// get a pointer to the area of memory where is store the variable
|
||||
//void* var_store_get_ptr(struct VariableStore* store, char* varName);
|
||||
int var_store_get_key(struct VariableStore* store, char* varName);
|
||||
|
||||
// return 1 if var exists 0 else
|
||||
byte var_store_exists(struct VariableStore* store, char* varName);
|
||||
|
||||
// get type of the variable
|
||||
// return NULL if the var doesn't exists
|
||||
byte var_store_get_type_from_key(struct VariableStore* store, int key);
|
||||
byte var_store_get_type(struct VariableStore* store, char* varName);
|
||||
|
||||
byte var_store_copy_from_key(struct VariableStore* store, int key, void* dest);
|
||||
byte var_store_copy(struct VariableStore* store, char* varName, void* dest);
|
||||
|
||||
// for debug purpose
|
||||
int var_store_get_int(struct VariableStore* store, char* varName);
|
||||
float var_store_get_float(struct VariableStore* store, char* varName);
|
||||
|
||||
// OR
|
||||
//byte var_store_get_ptr(char* varName, void** ptrPtr);
|
||||
|
||||
// store a variable
|
||||
byte var_store_set(struct VariableStore* store, char* varName, byte type, void* valuePtr);
|
||||
|
||||
byte var_store_delete(struct VariableStore* store, char* varName);
|
||||
|
||||
#endif
|
60
test.c
60
test.c
|
@ -1,60 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include "./src/types.h"
|
||||
#include "./src/list.h"
|
||||
#include "./src/number_parsing.h"
|
||||
#include "./src/funcs.h"
|
||||
#include "./src/utils.h"
|
||||
|
||||
int some_computation(int a, int b, int* resPtr)
|
||||
{
|
||||
*resPtr = a+b;
|
||||
return 0;
|
||||
}
|
||||
|
||||
float test_func(float x)
|
||||
{
|
||||
return m_float_pow(x,2)-2;
|
||||
}
|
||||
|
||||
int main () {
|
||||
// test of euler
|
||||
printf("lel : %f \n", m_sqrt(64));
|
||||
|
||||
|
||||
// struct List l1;
|
||||
|
||||
// list_append_int(&l1, 4);
|
||||
// list_append_char(&l1, '*');
|
||||
// list_append_int(&l1, 5);
|
||||
|
||||
// list_print(&l1);
|
||||
|
||||
// list_delete(&l1, 0);
|
||||
|
||||
// list_print(&l1);
|
||||
|
||||
// list_delete(&l1, 0);
|
||||
|
||||
// list_print(&l1);
|
||||
|
||||
// float res = 0;
|
||||
|
||||
// void* ptr = &res;
|
||||
|
||||
// printf("%d\n", sizeof(ptr));
|
||||
// int found = identify_func_name("ABS");
|
||||
// printf("found: %d \n", found);
|
||||
|
||||
// unsigned char argsType[1] = { TYPE_FLOAT };
|
||||
// int argsVals[1] = { get_int_rep_from_float(-3.145) };
|
||||
// int resVal = 0;
|
||||
// unsigned char resType = 0;
|
||||
// execute_func(found, 1, argsType, argsVals, &resVal, &resType);
|
||||
// printf("func res type: %d \n", resType);
|
||||
// printf("func res: %f \n", get_float_from_int_rep(resVal));
|
||||
|
||||
// int stat = parse_float("1052.254", &res);
|
||||
// printf("float parsing stat: %d \n", stat);
|
||||
// printf("final float: %f \n", res);
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#include "./test_utils.h"
|
||||
#include "./test_evaluation.h"
|
||||
#include "./test_line_processing.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
|
@ -7,4 +8,5 @@ int main()
|
|||
printf("== UNIT TESTS == \n");
|
||||
test_utils();
|
||||
test_evaluation();
|
||||
test_line_processing();
|
||||
}
|
||||
|
|
|
@ -5,68 +5,80 @@
|
|||
#include "../src/number_parsing.h"
|
||||
#include "../src/utils.h"
|
||||
#include "../src/evaluator.h"
|
||||
#include "../src/state.h"
|
||||
|
||||
void test_evaluation()
|
||||
{
|
||||
printf("== test evaluation == \n");
|
||||
|
||||
struct StateContainer* state = state_init();
|
||||
|
||||
// test int parsing
|
||||
int resVal = 0;
|
||||
unsigned char resType = 0;
|
||||
|
||||
evaluate("-4", &resVal, &resType);
|
||||
evaluate(state, "-4", &resVal, &resType);
|
||||
assert(resType == TYPE_INT);
|
||||
assert(-4 == resVal);
|
||||
|
||||
evaluate("-(4+9)+1", &resVal, &resType);
|
||||
evaluate(state, "-(4+9)+1", &resVal, &resType);
|
||||
assert(resType == TYPE_INT);
|
||||
assert(-12 == resVal);
|
||||
|
||||
evaluate("(-(8-9+5))+8", &resVal, &resType);
|
||||
evaluate(state, "(-(8-9+5))+8", &resVal, &resType);
|
||||
assert(resType == TYPE_INT);
|
||||
assert(4 == resVal);
|
||||
|
||||
evaluate("2^6", &resVal, &resType);
|
||||
evaluate(state, "2^6", &resVal, &resType);
|
||||
assert(resType == TYPE_INT);
|
||||
assert(64 == resVal);
|
||||
|
||||
evaluate("3 + 4", &resVal, &resType);
|
||||
evaluate(state, "3 + 4", &resVal, &resType);
|
||||
assert(resType == TYPE_INT);
|
||||
assert(7 == resVal);
|
||||
|
||||
evaluate("(2*4)+0+0", &resVal, &resType);
|
||||
evaluate(state, "(2*4)+0+0", &resVal, &resType);
|
||||
assert(resType == TYPE_INT);
|
||||
assert(8 == resVal);
|
||||
|
||||
evaluate("2.5-(2+0.1)", &resVal, &resType);
|
||||
evaluate(state, "2.5-(2+0.1)", &resVal, &resType);
|
||||
assert(resType == TYPE_FLOAT);
|
||||
assert(float_almost_equal(0.4, get_float_from_int_rep(resVal)));
|
||||
|
||||
evaluate("1^0 + (7*(5 +2))", &resVal, &resType);
|
||||
evaluate(state, "1^0 + (7*(5 +2))", &resVal, &resType);
|
||||
assert(resType == TYPE_INT);
|
||||
assert(50 == resVal);
|
||||
|
||||
evaluate("- ( 0.1+ 0.3 )", &resVal, &resType);
|
||||
evaluate(state, "- ( 0.1+ 0.3 )", &resVal, &resType);
|
||||
assert(resType == TYPE_FLOAT);
|
||||
assert(float_almost_equal(-0.4, get_float_from_int_rep(resVal)));
|
||||
|
||||
evaluate("sqrt(2)-1", &resVal, &resType);
|
||||
evaluate(state, "sqrt(2)-1", &resVal, &resType);
|
||||
assert(resType == TYPE_FLOAT);
|
||||
assert(float_almost_equal(0.41421, get_float_from_int_rep(resVal)));
|
||||
|
||||
evaluate("(abs((0-1)*2)) + abs(2)", &resVal, &resType);
|
||||
evaluate(state, "(abs((0-1)*2)) + abs(2)", &resVal, &resType);
|
||||
assert(resType == TYPE_INT);
|
||||
assert(4 == resVal);
|
||||
|
||||
evaluate("exp(2)-1", &resVal, &resType);
|
||||
evaluate(state, "exp(2)-1", &resVal, &resType);
|
||||
assert(resType == TYPE_FLOAT);
|
||||
assert(float_almost_equal(6.389, get_float_from_int_rep(resVal)));
|
||||
|
||||
evaluate("(cos(2)^2)+(sin(2)^2)", &resVal, &resType);
|
||||
evaluate(state, "(cos(2)^2)+(sin(2)^2)", &resVal, &resType);
|
||||
assert(resType == TYPE_FLOAT);
|
||||
assert(float_almost_equal(1, get_float_from_int_rep(resVal)));
|
||||
|
||||
evaluate("random_int(1, 100)", &resVal, &resType);
|
||||
evaluate(state, "random_int(1, 100)", &resVal, &resType);
|
||||
assert(resType == TYPE_INT);
|
||||
printf(" - random int: %d \n", resVal);
|
||||
|
||||
evaluate(state, "abs(2)+abs(-2)", &resVal, &resType);
|
||||
assert(resType == TYPE_INT);
|
||||
assert(4 == resVal);
|
||||
|
||||
// testing function composition is important
|
||||
evaluate(state, "abs(abs(-2))", &resVal, &resType);
|
||||
assert(resType == TYPE_INT);
|
||||
assert(2 == resVal);
|
||||
}
|
||||
|
|
32
tests/test_line_processing.c
Normal file
32
tests/test_line_processing.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "../src/types.h"
|
||||
#include "../src/number_parsing.h"
|
||||
#include "../src/utils.h"
|
||||
#include "../src/evaluator.h"
|
||||
#include "../src/state.h"
|
||||
#include "../src/var_store.h"
|
||||
|
||||
void test_line_processing()
|
||||
{
|
||||
printf("== test line processing == \n");
|
||||
|
||||
struct StateContainer* state = state_init();
|
||||
|
||||
assert(process_line(state, "#"));
|
||||
assert(process_line(state, "# some random comment"));
|
||||
assert(process_line(state, "set VAR_A to 8.5"));
|
||||
printf("%d \n", var_store_get_int(state->varStore, "VAR_A"));
|
||||
assert(float_almost_equal(8.5, var_store_get_float(state->varStore, "VAR_A")));
|
||||
|
||||
assert(process_line(state, "set VAR_B to 1.5"));
|
||||
assert(float_almost_equal(1.5, var_store_get_float(state->varStore, "VAR_B")));
|
||||
|
||||
assert(process_line(state, "set VAR_C to 142"));
|
||||
assert(142 == var_store_get_int(state->varStore, "VAR_C"));
|
||||
|
||||
assert(process_line(state, "set VAR_D to VAR_A+VAR_B"));
|
||||
assert(float_almost_equal(10, var_store_get_float(state->varStore, "VAR_D")));
|
||||
|
||||
}
|
1
tests/test_line_processing.h
Normal file
1
tests/test_line_processing.h
Normal file
|
@ -0,0 +1 @@
|
|||
void test_line_processing();
|
Loading…
Reference in a new issue