feat: add syntax config constants
fix(VarStore): better hash function
This commit is contained in:
parent
19d6f6fd70
commit
a66bfff424
9 changed files with 125 additions and 56 deletions
8
examples/count_in_french.ltor
Normal file
8
examples/count_in_french.ltor
Normal 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)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
set a to input_number()
|
||||
print_number(a)
|
||||
|
11
sandbox.c
11
sandbox.c
|
@ -10,14 +10,11 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
int main () {
|
||||
float ex = 2.00001430511;
|
||||
printf("as bin %d \n", (int) ex);
|
||||
|
||||
struct VariableStore* store = var_store_init();
|
||||
printf("%d", var_store_hash_name(store, "print_number index"));
|
||||
|
||||
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;
|
||||
// list_set(&l1, 0, TYPE_VAR_NAME, &val);
|
||||
|
|
41
src/config.h
41
src/config.h
|
@ -1,6 +1,47 @@
|
|||
#ifndef 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 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
|
|
@ -471,15 +471,11 @@ int evaluate(struct StateContainer* state, char* inputStr, int* resultPtr, unsig
|
|||
int startTrimOffset = 0;
|
||||
int stopTrimOffset = 0;
|
||||
for (int z = 0; z < len; z++) {
|
||||
if (inputStr[startPos+z] != ' ') {
|
||||
break;
|
||||
}
|
||||
if (inputStr[startPos+z] != ' ') break;
|
||||
startTrimOffset++;
|
||||
}
|
||||
for (int z = 1; z < len; z++) {
|
||||
if (inputStr[stopPos-z] != ' ') {
|
||||
break;
|
||||
}
|
||||
if (inputStr[stopPos-z] != ' ') break;
|
||||
stopTrimOffset++;
|
||||
}
|
||||
startPos += startTrimOffset;
|
||||
|
@ -500,9 +496,7 @@ int evaluate(struct StateContainer* state, char* inputStr, int* resultPtr, unsig
|
|||
|
||||
char dumbValue = (char) 0;
|
||||
|
||||
if (buff[0] == '\0') {
|
||||
continue;
|
||||
}
|
||||
if (buff[0] == '\0') continue;
|
||||
if (len == 1 && buff[0] == '(') {
|
||||
list_set(&evalList, evalList.num_elements, TYPE_OPEN_PARENTHESIS, &dumbValue);
|
||||
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);
|
||||
|
||||
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) {
|
||||
// did not find the var name
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include "./config.h"
|
||||
#include "./types.h"
|
||||
#include "./utils.h"
|
||||
#include "./line_processing.h"
|
||||
#include "./stack.h"
|
||||
|
@ -32,9 +34,7 @@ int recognize_comment_statement(char* lineStr)
|
|||
mode = 2;
|
||||
continue;
|
||||
}
|
||||
if (lineStr[i] != ' ') {
|
||||
break;
|
||||
}
|
||||
if (lineStr[i] != ' ') break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
@ -76,8 +76,8 @@ int recognize_termination_keyword(char* needle, char* subject, int from)
|
|||
// recognize "set VAR_NAME to EVALUATION"
|
||||
int recognize_set_statement(char* lineStr, struct SetStatement* res)
|
||||
{
|
||||
static char setStatementStartKeyword[] = "set";
|
||||
static char setStatementStopKeyword[] = "to";
|
||||
static char setStatementStartKeyword[] = SYNTAX_SET_START;
|
||||
static char setStatementStopKeyword[] = SYNTAX_SET_STOP;
|
||||
|
||||
int i = 0;
|
||||
int mode = 1;
|
||||
|
@ -155,8 +155,8 @@ int recognize_set_statement(char* lineStr, struct SetStatement* res)
|
|||
// FIXME: allow for multiline if statement
|
||||
int recognize_if_statement(char* lineStr, struct IfStatement* res)
|
||||
{
|
||||
static char ifStatementStartKeyword[] = "if";
|
||||
static char ifStatementStopKeyword[] = "then";
|
||||
static char ifStatementStartKeyword[] = SYNTAX_IF_START;
|
||||
static char ifStatementStopKeyword[] = SYNTAX_IF_STOP;
|
||||
|
||||
size_t len = strlen(lineStr);
|
||||
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"
|
||||
int recognize_while_statement(char* lineStr, struct WhileStatement* res)
|
||||
{
|
||||
static char whileStatementStartKeyword[] = "while";
|
||||
static char whileStatementStopKeyword[] = "do";
|
||||
static char whileStatementStartKeyword[] = SYNTAX_WHILE_START;
|
||||
static char whileStatementStopKeyword[] = SYNTAX_WHILE_STOP;
|
||||
|
||||
size_t len = strlen(lineStr);
|
||||
if (len < strlen(whileStatementStartKeyword) + 1 + strlen(whileStatementStopKeyword)) return 0;
|
||||
|
@ -347,7 +347,7 @@ int process_line(struct StateContainer* state, char* str)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (recognize_word(str, "end")) {
|
||||
if (recognize_word(str, SYNTAX_END)) {
|
||||
byte lastBlockType;
|
||||
int_stack_pop(state->blockStack, (int*) &lastBlockType); // FIXME: use a stack with size byte instead of int
|
||||
if (!state->skipping && lastBlockType == BLOCK_WHILE) {
|
||||
|
@ -425,10 +425,8 @@ int process_line(struct StateContainer* state, char* str)
|
|||
int res;
|
||||
byte resType;
|
||||
int evalStat = evaluate(state, (char*) &dest, &res, &resType);
|
||||
if (evalStat != 0) {
|
||||
printf("Syntax error for line \"%s\"\n", str);
|
||||
return 0;
|
||||
}
|
||||
if (evalStat != 0) return 0;
|
||||
|
||||
byte doFollow = convert_to_bool(resType, res);
|
||||
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;
|
||||
}
|
||||
|
||||
if (recognize_word(str, "continue")) {
|
||||
if (recognize_word(str, SYNTAX_CONTINUE)) {
|
||||
int 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;
|
||||
}
|
||||
state->linePtr = lastLoopLine;
|
||||
|
@ -462,17 +460,18 @@ int process_line(struct StateContainer* state, char* str)
|
|||
byte lastBlockType;
|
||||
while (lastBlockType != BLOCK_WHILE) {
|
||||
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);
|
||||
|
||||
return 1;
|
||||
}
|
||||
if (recognize_word(str, "break")) {
|
||||
if (recognize_word(str, SYNTAX_BREAK)) {
|
||||
int 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;
|
||||
}
|
||||
|
||||
|
@ -517,7 +516,7 @@ int process_line(struct StateContainer* state, char* str)
|
|||
|
||||
int evalStat = evaluate(state, (char*) &express, &res, &resType);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -533,7 +532,7 @@ int process_line(struct StateContainer* state, char* str)
|
|||
byte resType;
|
||||
int evalStat = evaluate(state, str, &res, &resType);
|
||||
if (evalStat != 0) {
|
||||
printf("Syntax error for line \"%s\"\n", str);
|
||||
printf("Error: could not evaluate expression \"%s\".\n", str);
|
||||
return 0;
|
||||
}
|
||||
state->linePtr++;
|
||||
|
@ -587,7 +586,7 @@ int process_script(struct StateContainer* state, char* script)
|
|||
|
||||
while (state->running && state->linePtr != lineCount) {
|
||||
if (state->linePtr >= lineCount) {
|
||||
printf("Invalid line %d \n", state->linePtr);
|
||||
printf("Error: Invalid line %d \n.", state->linePtr);
|
||||
break;
|
||||
}
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAX_INTEGER 47797852
|
||||
#define MAX_INTEGER 2147483647-1
|
||||
|
||||
struct VariableStore* var_store_init()
|
||||
{
|
||||
|
@ -39,7 +39,8 @@ 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;
|
||||
int num = get_int_rep_from_char(varName[i])*integer_pow(9, i);
|
||||
hash = abs(hash + abs(num));
|
||||
i++;
|
||||
}
|
||||
// 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 key = originalKey;
|
||||
// handle collision, walk along the array
|
||||
while (1)
|
||||
{
|
||||
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;
|
||||
}
|
||||
if (store->container[key].type == 0) return -1;
|
||||
|
||||
|
||||
// check if we found the position
|
||||
if (strcmp(store->container[key].namePtr, varName) == 0) return key;
|
||||
|
||||
key = (key+1) % store->allocatedLength;
|
||||
if (key == originalKey) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (key == originalKey) return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#ifndef VAR_STORE_H_
|
||||
#define VAR_STORE_H_
|
||||
|
||||
#define VAR_STORE_DEBUG_LEVEL (G_DEBUG_LEVEL)
|
||||
#define VAR_STORE_INITIAL_ALLOC_LENGTH 32
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,6 +21,14 @@ void test_evaluation()
|
|||
assert(resType == TYPE_INT);
|
||||
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);
|
||||
assert(resType == TYPE_INT);
|
||||
assert(-12 == resVal);
|
||||
|
@ -53,6 +61,8 @@ void test_evaluation()
|
|||
assert(resType == TYPE_FLOAT);
|
||||
assert(float_almost_equal(-0.4, get_float_from_int_rep(resVal)));
|
||||
|
||||
/* FUNCTIONS */
|
||||
|
||||
evaluate(state, "sqrt(2)-1", &resVal, &resType);
|
||||
assert(resType == TYPE_FLOAT);
|
||||
assert(float_almost_equal(0.41421, get_float_from_int_rep(resVal)));
|
||||
|
@ -89,11 +99,28 @@ void test_evaluation()
|
|||
assert(resType == TYPE_INT);
|
||||
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
|
||||
evaluate(state, "abs(abs(-2))", &resVal, &resType);
|
||||
assert(resType == TYPE_INT);
|
||||
assert(2 == resVal);
|
||||
|
||||
/* COMPARAISON OPERATORS */
|
||||
evaluate(state, "2 = 2", &resVal, &resType);
|
||||
assert(resType == TYPE_INT);
|
||||
assert(1 == resVal);
|
||||
|
@ -154,6 +181,7 @@ void test_evaluation()
|
|||
assert(resType == TYPE_FLOAT);
|
||||
assert(float_almost_equal(5.3, get_float_from_int_rep(resVal)));
|
||||
|
||||
/* VARIABLES */
|
||||
int ex = 43;
|
||||
var_store_set(state->varStore, "var", TYPE_INT, (void*) &ex);
|
||||
evaluate(state, "var", &resVal, &resType);
|
||||
|
@ -176,6 +204,7 @@ void test_evaluation()
|
|||
printf("actually got: %d \n", resVal);
|
||||
assert(7 == resVal);
|
||||
|
||||
/* TYPE FUNCS */
|
||||
evaluate(state, "is_number(123)", &resVal, &resType);
|
||||
assert(resType == TYPE_INT);
|
||||
assert(resVal);
|
||||
|
@ -191,4 +220,8 @@ void test_evaluation()
|
|||
evaluate(state, "is_null(NULL)", &resVal, &resType);
|
||||
assert(resType == TYPE_INT);
|
||||
assert(resVal);
|
||||
|
||||
evaluate(state, "(is_null(NULL) & is_number(42)) | 0", &resVal, &resType);
|
||||
assert(resType == TYPE_INT);
|
||||
assert(resVal);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue