feat: add syntax config constants

fix(VarStore): better hash function
This commit is contained in:
Matthieu Bessat 2022-05-17 10:27:32 +02:00
parent 19d6f6fd70
commit a66bfff424
9 changed files with 125 additions and 56 deletions

View file

@ -0,0 +1,8 @@
definir index comme 0
tant que index < 10 faire
print_number(index)
definir index comme index + 1
fin
print_number(index)

View file

@ -1,3 +0,0 @@
set a to input_number()
print_number(a)

View file

@ -10,13 +10,10 @@
#include <stdlib.h> #include <stdlib.h>
int main () { int main () {
float ex = 2.00001430511; struct VariableStore* store = var_store_init();
printf("as bin %d \n", (int) ex); printf("%d", var_store_hash_name(store, "print_number index"));
return 0; return 0;
// struct VariableStore* store = var_store_init();
// printf("%d", var_store_hash_name(store, "var"));
// return 0;
//struct List l1; //struct List l1;
// short val = 17; // short val = 17;

View file

@ -1,6 +1,47 @@
#ifndef G_CONFIG_H_ #ifndef G_CONFIG_H_
#define G_CONFIG_H_ #define G_CONFIG_H_
#define PRESET_ENGLISH 0
#define PRESET_FRENCH 1
// 0: no logs; 1: medium debug; 2: full debug
#define G_DEBUG_LEVEL 0 #define G_DEBUG_LEVEL 0
#define SYNTAX_PRESET PRESET_ENGLISH
// Define your own custom syntax here
#if SYNTAX_PRESET == PRESET_ENGLISH
#define SYNTAX_END "end"
#define SYNTAX_SET_START "set"
#define SYNTAX_SET_STOP "to"
#define SYNTAX_IF_START "if"
#define SYNTAX_IF_STOP "then"
#define SYNTAX_WHILE_START "while"
#define SYNTAX_WHILE_STOP "do"
#define SYNTAX_CONTINUE "continue"
#define SYNTAX_BREAK "break"
#endif
#if SYNTAX_PRESET == PRESET_FRENCH
#define SYNTAX_END "fin"
#define SYNTAX_SET_START "definir"
#define SYNTAX_SET_STOP "comme"
#define SYNTAX_IF_START "si"
#define SYNTAX_IF_STOP "alors"
#define SYNTAX_WHILE_START "tant que"
#define SYNTAX_WHILE_STOP "faire"
#define SYNTAX_CONTINUE "continuer"
// JPP
#define SYNTAX_BREAK "casser"
#endif
#endif #endif

View file

@ -471,15 +471,11 @@ int evaluate(struct StateContainer* state, char* inputStr, int* resultPtr, unsig
int startTrimOffset = 0; int startTrimOffset = 0;
int stopTrimOffset = 0; int stopTrimOffset = 0;
for (int z = 0; z < len; z++) { for (int z = 0; z < len; z++) {
if (inputStr[startPos+z] != ' ') { if (inputStr[startPos+z] != ' ') break;
break;
}
startTrimOffset++; startTrimOffset++;
} }
for (int z = 1; z < len; z++) { for (int z = 1; z < len; z++) {
if (inputStr[stopPos-z] != ' ') { if (inputStr[stopPos-z] != ' ') break;
break;
}
stopTrimOffset++; stopTrimOffset++;
} }
startPos += startTrimOffset; startPos += startTrimOffset;
@ -500,9 +496,7 @@ int evaluate(struct StateContainer* state, char* inputStr, int* resultPtr, unsig
char dumbValue = (char) 0; char dumbValue = (char) 0;
if (buff[0] == '\0') { if (buff[0] == '\0') continue;
continue;
}
if (len == 1 && buff[0] == '(') { if (len == 1 && buff[0] == '(') {
list_set(&evalList, evalList.num_elements, TYPE_OPEN_PARENTHESIS, &dumbValue); list_set(&evalList, evalList.num_elements, TYPE_OPEN_PARENTHESIS, &dumbValue);
continue; continue;
@ -546,6 +540,7 @@ int evaluate(struct StateContainer* state, char* inputStr, int* resultPtr, unsig
if (EVALUATOR_DEBUG_LEVEL >= 2) var_store_print(state->varStore); if (EVALUATOR_DEBUG_LEVEL >= 2) var_store_print(state->varStore);
int varKey = (int) var_store_get_key(state->varStore, buff); int varKey = (int) var_store_get_key(state->varStore, buff);
if (EVALUATOR_DEBUG_LEVEL >= 2) printf("got var key '%d' \n", varKey);
if (varKey == -1) { if (varKey == -1) {
// did not find the var name // did not find the var name

View file

@ -1,3 +1,5 @@
#include "./config.h"
#include "./types.h"
#include "./utils.h" #include "./utils.h"
#include "./line_processing.h" #include "./line_processing.h"
#include "./stack.h" #include "./stack.h"
@ -32,9 +34,7 @@ int recognize_comment_statement(char* lineStr)
mode = 2; mode = 2;
continue; continue;
} }
if (lineStr[i] != ' ') { if (lineStr[i] != ' ') break;
break;
}
} }
i++; i++;
} }
@ -76,8 +76,8 @@ int recognize_termination_keyword(char* needle, char* subject, int from)
// recognize "set VAR_NAME to EVALUATION" // recognize "set VAR_NAME to EVALUATION"
int recognize_set_statement(char* lineStr, struct SetStatement* res) int recognize_set_statement(char* lineStr, struct SetStatement* res)
{ {
static char setStatementStartKeyword[] = "set"; static char setStatementStartKeyword[] = SYNTAX_SET_START;
static char setStatementStopKeyword[] = "to"; static char setStatementStopKeyword[] = SYNTAX_SET_STOP;
int i = 0; int i = 0;
int mode = 1; int mode = 1;
@ -155,8 +155,8 @@ int recognize_set_statement(char* lineStr, struct SetStatement* res)
// FIXME: allow for multiline if statement // FIXME: allow for multiline if statement
int recognize_if_statement(char* lineStr, struct IfStatement* res) int recognize_if_statement(char* lineStr, struct IfStatement* res)
{ {
static char ifStatementStartKeyword[] = "if"; static char ifStatementStartKeyword[] = SYNTAX_IF_START;
static char ifStatementStopKeyword[] = "then"; static char ifStatementStopKeyword[] = SYNTAX_IF_STOP;
size_t len = strlen(lineStr); size_t len = strlen(lineStr);
if (len < strlen(ifStatementStartKeyword) + 1 + strlen(ifStatementStopKeyword)) return 0; if (len < strlen(ifStatementStartKeyword) + 1 + strlen(ifStatementStopKeyword)) return 0;
@ -222,8 +222,8 @@ int recognize_if_statement(char* lineStr, struct IfStatement* res)
// recognize "while EXPRESSION then \n begin (...) \n end" // recognize "while EXPRESSION then \n begin (...) \n end"
int recognize_while_statement(char* lineStr, struct WhileStatement* res) int recognize_while_statement(char* lineStr, struct WhileStatement* res)
{ {
static char whileStatementStartKeyword[] = "while"; static char whileStatementStartKeyword[] = SYNTAX_WHILE_START;
static char whileStatementStopKeyword[] = "do"; static char whileStatementStopKeyword[] = SYNTAX_WHILE_STOP;
size_t len = strlen(lineStr); size_t len = strlen(lineStr);
if (len < strlen(whileStatementStartKeyword) + 1 + strlen(whileStatementStopKeyword)) return 0; if (len < strlen(whileStatementStartKeyword) + 1 + strlen(whileStatementStopKeyword)) return 0;
@ -347,7 +347,7 @@ int process_line(struct StateContainer* state, char* str)
return 1; return 1;
} }
if (recognize_word(str, "end")) { if (recognize_word(str, SYNTAX_END)) {
byte lastBlockType; byte lastBlockType;
int_stack_pop(state->blockStack, (int*) &lastBlockType); // FIXME: use a stack with size byte instead of int int_stack_pop(state->blockStack, (int*) &lastBlockType); // FIXME: use a stack with size byte instead of int
if (!state->skipping && lastBlockType == BLOCK_WHILE) { if (!state->skipping && lastBlockType == BLOCK_WHILE) {
@ -425,10 +425,8 @@ int process_line(struct StateContainer* state, char* str)
int res; int res;
byte resType; byte resType;
int evalStat = evaluate(state, (char*) &dest, &res, &resType); int evalStat = evaluate(state, (char*) &dest, &res, &resType);
if (evalStat != 0) { if (evalStat != 0) return 0;
printf("Syntax error for line \"%s\"\n", str);
return 0;
}
byte doFollow = convert_to_bool(resType, res); byte doFollow = convert_to_bool(resType, res);
if (LINE_PROCESSING_DEBUG_LEVEL >= 2) printf("Got %s, doFollow: %d \n", get_repr(resType, &res), doFollow); if (LINE_PROCESSING_DEBUG_LEVEL >= 2) printf("Got %s, doFollow: %d \n", get_repr(resType, &res), doFollow);
@ -450,10 +448,10 @@ int process_line(struct StateContainer* state, char* str)
return 1; return 1;
} }
if (recognize_word(str, "continue")) { if (recognize_word(str, SYNTAX_CONTINUE)) {
int lastLoopLine; int lastLoopLine;
if (!int_stack_pop(state->loopStack, &lastLoopLine)) { if (!int_stack_pop(state->loopStack, &lastLoopLine)) {
printf("Syntax error: unexpected continue, not in a loop \n"); printf("Syntax error: unexpected continue, not in a loop.\n");
return 0; return 0;
} }
state->linePtr = lastLoopLine; state->linePtr = lastLoopLine;
@ -462,17 +460,18 @@ int process_line(struct StateContainer* state, char* str)
byte lastBlockType; byte lastBlockType;
while (lastBlockType != BLOCK_WHILE) { while (lastBlockType != BLOCK_WHILE) {
if (!int_stack_pop(state->blockStack, &lastBlockType)) { if (!int_stack_pop(state->blockStack, &lastBlockType)) {
printf("Syntax error: unexpected continue \n"); printf("Syntax error: unexpected continue.\n");
return 0;
} }
} }
int_stack_pop(state->blockStack, &lastBlockType); int_stack_pop(state->blockStack, &lastBlockType);
return 1; return 1;
} }
if (recognize_word(str, "break")) { if (recognize_word(str, SYNTAX_BREAK)) {
int lastLoopLine; int lastLoopLine;
if (!int_stack_pop(state->loopStack, &lastLoopLine)) { if (!int_stack_pop(state->loopStack, &lastLoopLine)) {
printf("Syntax error: unexpected break, not in a loop \n"); printf("Syntax error: unexpected break, not in a loop.\n");
return 0; return 0;
} }
@ -517,7 +516,7 @@ int process_line(struct StateContainer* state, char* str)
int evalStat = evaluate(state, (char*) &express, &res, &resType); int evalStat = evaluate(state, (char*) &express, &res, &resType);
if (evalStat != 0) { if (evalStat != 0) {
printf("Syntax error for line \"%s\"\n", str); printf("Error: could not evaluate the expression associated with the content of the variable to set \"%s\".\n", str);
return 0; return 0;
} }
@ -533,7 +532,7 @@ int process_line(struct StateContainer* state, char* str)
byte resType; byte resType;
int evalStat = evaluate(state, str, &res, &resType); int evalStat = evaluate(state, str, &res, &resType);
if (evalStat != 0) { if (evalStat != 0) {
printf("Syntax error for line \"%s\"\n", str); printf("Error: could not evaluate expression \"%s\".\n", str);
return 0; return 0;
} }
state->linePtr++; state->linePtr++;
@ -587,7 +586,7 @@ int process_script(struct StateContainer* state, char* script)
while (state->running && state->linePtr != lineCount) { while (state->running && state->linePtr != lineCount) {
if (state->linePtr >= lineCount) { if (state->linePtr >= lineCount) {
printf("Invalid line %d \n", state->linePtr); printf("Error: Invalid line %d \n.", state->linePtr);
break; break;
} }
int lineLen = (lineEnds[state->linePtr] - lineStarts[state->linePtr]); int lineLen = (lineEnds[state->linePtr] - lineStarts[state->linePtr]);
@ -596,7 +595,7 @@ int process_script(struct StateContainer* state, char* script)
int stat = process_line(state, line); int stat = process_line(state, line);
if (!stat) { if (!stat) {
printf("Abnormal end of run at line %d: '%s' \n", state->linePtr, line); printf("Error: Abnormal end of run at line %d: '%s'.\n", state->linePtr, line);
return 0; return 0;
} }
} }

View file

@ -4,7 +4,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#define MAX_INTEGER 47797852 #define MAX_INTEGER 2147483647-1
struct VariableStore* var_store_init() struct VariableStore* var_store_init()
{ {
@ -39,7 +39,8 @@ int var_store_hash_name(struct VariableStore* store, char* varName)
int hash = 0; int hash = 0;
int i = 0; int i = 0;
while (varName[i] != '\0') { while (varName[i] != '\0') {
hash += (get_int_rep_from_char(varName[i])*integer_pow(9, i)) % MAX_INTEGER; int num = get_int_rep_from_char(varName[i])*integer_pow(9, i);
hash = abs(hash + abs(num));
i++; i++;
} }
// FIXME: when reallocating, we should copy all variables to their new key // FIXME: when reallocating, we should copy all variables to their new key
@ -125,20 +126,17 @@ int var_store_get_key(struct VariableStore* store, char* varName)
int originalKey = var_store_hash_name(store, varName); int originalKey = var_store_hash_name(store, varName);
int key = originalKey; int key = originalKey;
// handle collision, walk along the array // handle collision, walk along the array
while (1) while (1) {
{
//printf("inter key: %d %d \n", key, store->container[key].type); //printf("inter key: %d %d \n", key, store->container[key].type);
if (store->container[key].type == 0) { if (store->container[key].type == 0) return -1;
return -1;
}
if (strcmp(store->container[key].namePtr, varName) == 0) { // check if we found the position
// we found the position if (strcmp(store->container[key].namePtr, varName) == 0) return key;
return key;
}
key = (key+1) % store->allocatedLength; key = (key+1) % store->allocatedLength;
if (key == originalKey) {
return -1; if (key == originalKey) return -1;
}
} }
} }

View file

@ -3,6 +3,7 @@
#ifndef VAR_STORE_H_ #ifndef VAR_STORE_H_
#define VAR_STORE_H_ #define VAR_STORE_H_
#define VAR_STORE_DEBUG_LEVEL (G_DEBUG_LEVEL)
#define VAR_STORE_INITIAL_ALLOC_LENGTH 32 #define VAR_STORE_INITIAL_ALLOC_LENGTH 32
/** /**

View file

@ -21,6 +21,14 @@ void test_evaluation()
assert(resType == TYPE_INT); assert(resType == TYPE_INT);
assert(-4 == resVal); assert(-4 == resVal);
evaluate(state, " - 6 ", &resVal, &resType);
assert(resType == TYPE_INT);
assert(-6 == resVal);
evaluate(state, " 1+ (- 45 ) ", &resVal, &resType);
assert(resType == TYPE_INT);
assert(-44 == resVal);
evaluate(state, "-(4+9)+1", &resVal, &resType); evaluate(state, "-(4+9)+1", &resVal, &resType);
assert(resType == TYPE_INT); assert(resType == TYPE_INT);
assert(-12 == resVal); assert(-12 == resVal);
@ -53,6 +61,8 @@ void test_evaluation()
assert(resType == TYPE_FLOAT); assert(resType == TYPE_FLOAT);
assert(float_almost_equal(-0.4, get_float_from_int_rep(resVal))); assert(float_almost_equal(-0.4, get_float_from_int_rep(resVal)));
/* FUNCTIONS */
evaluate(state, "sqrt(2)-1", &resVal, &resType); evaluate(state, "sqrt(2)-1", &resVal, &resType);
assert(resType == TYPE_FLOAT); assert(resType == TYPE_FLOAT);
assert(float_almost_equal(0.41421, get_float_from_int_rep(resVal))); assert(float_almost_equal(0.41421, get_float_from_int_rep(resVal)));
@ -89,11 +99,28 @@ void test_evaluation()
assert(resType == TYPE_INT); assert(resType == TYPE_INT);
assert(4 == resVal); assert(4 == resVal);
evaluate(state, "max(25, 4)", &resVal, &resType);
assert(resType == TYPE_INT);
assert(25 == resVal);
evaluate(state, "max(-25, 42)", &resVal, &resType);
assert(resType == TYPE_INT);
assert(42 == resVal);
evaluate(state, "max( (1+1)^(6+1-1) , 4+2)", &resVal, &resType);
assert(resType == TYPE_INT);
assert(64 == resVal);
evaluate(state, "max(floor(exp(1))^(4+1) , -2)", &resVal, &resType);
assert(resType == TYPE_INT);
assert(32 == resVal);
// testing function composition is important // testing function composition is important
evaluate(state, "abs(abs(-2))", &resVal, &resType); evaluate(state, "abs(abs(-2))", &resVal, &resType);
assert(resType == TYPE_INT); assert(resType == TYPE_INT);
assert(2 == resVal); assert(2 == resVal);
/* COMPARAISON OPERATORS */
evaluate(state, "2 = 2", &resVal, &resType); evaluate(state, "2 = 2", &resVal, &resType);
assert(resType == TYPE_INT); assert(resType == TYPE_INT);
assert(1 == resVal); assert(1 == resVal);
@ -154,6 +181,7 @@ void test_evaluation()
assert(resType == TYPE_FLOAT); assert(resType == TYPE_FLOAT);
assert(float_almost_equal(5.3, get_float_from_int_rep(resVal))); assert(float_almost_equal(5.3, get_float_from_int_rep(resVal)));
/* VARIABLES */
int ex = 43; int ex = 43;
var_store_set(state->varStore, "var", TYPE_INT, (void*) &ex); var_store_set(state->varStore, "var", TYPE_INT, (void*) &ex);
evaluate(state, "var", &resVal, &resType); evaluate(state, "var", &resVal, &resType);
@ -176,6 +204,7 @@ void test_evaluation()
printf("actually got: %d \n", resVal); printf("actually got: %d \n", resVal);
assert(7 == resVal); assert(7 == resVal);
/* TYPE FUNCS */
evaluate(state, "is_number(123)", &resVal, &resType); evaluate(state, "is_number(123)", &resVal, &resType);
assert(resType == TYPE_INT); assert(resType == TYPE_INT);
assert(resVal); assert(resVal);
@ -191,4 +220,8 @@ void test_evaluation()
evaluate(state, "is_null(NULL)", &resVal, &resType); evaluate(state, "is_null(NULL)", &resVal, &resType);
assert(resType == TYPE_INT); assert(resType == TYPE_INT);
assert(resVal); assert(resVal);
evaluate(state, "(is_null(NULL) & is_number(42)) | 0", &resVal, &resType);
assert(resType == TYPE_INT);
assert(resVal);
} }