--- a/src/server/util/object.c Wed Nov 09 11:51:19 2022 +0100 +++ b/src/server/util/object.c Sat Nov 12 11:01:11 2022 +0100 @@ -27,11 +27,13 @@ */ #include <cx/string.h> +#include <cx/linked_list.h> +#include <cx/compare.h> #include "../public/nsapi.h" #include "object.h" - +#include "util.h" #include "pool.h" #include "../daemon/func.h" @@ -106,6 +108,281 @@ context->last_req_code = REQ_NOACTION; } + +/* ------------------------------ Expression ------------------------------ */ + +Expression* condition_create(pool_handle_t *pool, CxList *tokens) { + + + + return NULL; +} + + +typedef struct { + pool_handle_t *pool; + CxList *op_stack; + CxList *ex_stack; + CxList *tokens; + size_t *pos; + int expect_value; +} ExprParser; + +typedef struct { + NSAPIExpressionOperator operator; + int expect_value; + int open_parenthesis; +} ExprOpStackItem; + +static void expr_free(pool_handle_t *pool, NSAPIExpression *expr) { + if(expr->left) { + expr_free(pool, expr->left); + } + if(expr->right) { + expr_free(pool, expr->right); + } + if(expr->type == NSAPI_EXPRESSION_STRING && expr->value.str.ptr) { + pool_free(pool, (char*)expr->value.str.ptr); + } else if(expr->type == NSAPI_EXPRESSION_VARIABLE && expr->value.var.ptr) { + pool_free(pool, (char*)expr->value.var.ptr); + } + pool_free(pool, expr); +} + +static NSAPIExpressionOperator expr_operator(cxstring token) { + if(!cx_strcmp(token, cx_str("+"))) { + return NSAPI_EXPRESSION_ADD; + } else if(!cx_strcmp(token, cx_str("-"))) { + return NSAPI_EXPRESSION_SUB; + } else if(!cx_strcmp(token, cx_str("*"))) { + return NSAPI_EXPRESSION_MUL; + } else if(!cx_strcmp(token, cx_str("/"))) { + return NSAPI_EXPRESSION_DIV; + } else if(!cx_strcmp(token, cx_str("%"))) { + return NSAPI_EXPRESSION_MOD; + } else if(!cx_strcmp(token, cx_str("not"))) { + return NSAPI_EXPRESSION_NOT; + } else if(!cx_strcmp(token, cx_str("and"))) { + return NSAPI_EXPRESSION_AND; + } else if(!cx_strcmp(token, cx_str("or"))) { + return NSAPI_EXPRESSION_OR; + } else if(!cx_strcmp(token, cx_str("xor"))) { + return NSAPI_EXPRESSION_XOR; + } else if(!cx_strcmp(token, cx_str("=="))) { + return NSAPI_EXPRESSION_EQ; + } else if(!cx_strcmp(token, cx_str("!="))) { + return NSAPI_EXPRESSION_NEQ; + } else if(!cx_strcmp(token, cx_str(">"))) { + return NSAPI_EXPRESSION_GT; + } else if(!cx_strcmp(token, cx_str("<"))) { + return NSAPI_EXPRESSION_LT; + } else if(!cx_strcmp(token, cx_str(">="))) { + return NSAPI_EXPRESSION_GE; + } else if(!cx_strcmp(token, cx_str("<="))) { + return NSAPI_EXPRESSION_LE; + } + return NSAPI_EXPRESSION_NOOP; +} + +static int token_is_int(cxstring token) { + for(size_t i=0;i<token.length;i++) { + if(!isdigit(token.ptr[i])) { + return 0; + } + } + return 1; +} + +static int expr_set_value(pool_handle_t *pool, NSAPIExpression *expr, cxstring token) { + if(token.length >= 2 && token.ptr[0] == '\"' && token.ptr[token.length-1] == '\"') { + expr->value.str = cx_strcast(cx_strdup_a(pool_allocator(pool), cx_strsubsl(token, 1, token.length-2))); + expr->type = NSAPI_EXPRESSION_STRING; + } else if(token.length >= 2 && token.ptr[0] == '$' && isalpha(token.ptr[1])) { + expr->value.var = cx_strcast(cx_strdup_a(pool_allocator(pool), cx_strsubs(token, 1))); + expr->type = NSAPI_EXPRESSION_VARIABLE; + } else if(token_is_int(token)) { + if(!util_strtoint(token.ptr, &expr->value.i)) { + return 1; + } + expr->type = NSAPI_EXPRESSION_INT; + } else if(!strcmp(token.ptr, "true")) { + expr->type = NSAPI_EXPRESSION_BOOL; + expr->value.b = 1; + } else if(!strcmp(token.ptr, "false")) { + expr->type = NSAPI_EXPRESSION_BOOL; + expr->value.b = 0; + } else { + return 1; + } + // TODO: double + return 0; +} + +cxstring expr_next_token(CxList *tokens, size_t *pos) { + cxstring *token = cxListAt(tokens, *pos); + if(token) { + (*pos)++; + return *token; + } + return (cxstring){NULL, 0}; +} + +NSAPIExpression* expr_parser_pop(ExprParser *parser) { + CxList *stack = parser->ex_stack; + if(stack->size == 0) { + return NULL; + } + NSAPIExpression *ret = cxListAt(stack, stack->size-1); + cxListRemove(stack, stack->size-1); + return ret; +} + +// takes items from ex_stack and adds a new operator expression to ex_stack +static int expr_add_operator(ExprParser *parser, ExprOpStackItem *op) { + NSAPIExpression *exp = pool_malloc(parser->pool, sizeof(NSAPIExpression)); + exp->operator = op->operator; + // op->expect_value == TRUE means, that the operator was found in a case + // a value was expected. + // For example: 1 + - 2 + // After + a value is expected, but there is the - operator + // in that case, the - operator is a unary expression + if(op->expect_value) { + // We expected a value but got an operator? This must be an unary operator + exp->type = NSAPI_EXPRESSION_UNARY; + exp->left = expr_parser_pop(parser); + exp->right = NULL; + } else { + // binary operator + exp->type = NSAPI_EXPRESSION_BINARY; + exp->right = expr_parser_pop(parser); + exp->left = expr_parser_pop(parser); + } + + if(!exp->left && !exp->right) { + return 1; // error + } + + cxListAdd(parser->ex_stack, exp); + + parser->expect_value = TRUE; + return 0; +} + +// converts the token to a value expression (int, bool, str, ...) +// and adds it to parser->ex_stack +// sets parser->expect_value to false +static int expr_add_value(ExprParser *parser, cxstring token) { + NSAPIExpression *exp = pool_malloc(parser->pool, sizeof(NSAPIExpression)); + ZERO(exp, sizeof(NSAPIExpression)); + if(expr_set_value(parser->pool, exp, token)) { + return 1; + } + cxListAdd(parser->ex_stack, exp); + parser->expect_value = FALSE; + return 0; +} + + +static NSAPIExpression* expr_parse_expr(ExprParser *parser) { + CxList *op_stack = parser->op_stack; + CxList *ex_stack = parser->ex_stack; + + // Shunting yard algorithm + cxstring token = expr_next_token(parser->tokens, parser->pos); + for(;token.ptr;token=expr_next_token(parser->tokens, parser->pos)) { + NSAPIExpressionOperator op = expr_operator(token); + if(op != NSAPI_EXPRESSION_NOOP) { + ExprOpStackItem new_op; + new_op.operator = op; + new_op.expect_value = parser->expect_value; + new_op.open_parenthesis = FALSE; + while(op_stack->size > 0) { + ExprOpStackItem *stack_item = cxListAt(op_stack, op_stack->size-1); + if(stack_item->operator == NSAPI_EXPRESSION_NOOP) { + break; + } + // check presedence + if(op >= stack_item->operator) { + break; + } + if(expr_add_operator(parser, stack_item)) { + return NULL; + } + cxListRemove(op_stack, op_stack->size-1); + } + cxListAdd(op_stack, &new_op); + parser->expect_value = TRUE; + } else if(token.length == 1 && token.ptr[0] == '(') { + ExprOpStackItem new_op; + new_op.operator = NSAPI_EXPRESSION_NOOP; + new_op.expect_value = 0; + new_op.open_parenthesis = 1; + cxListAdd(op_stack, &new_op); + parser->expect_value = TRUE; + } else if(token.length == 1 && token.ptr[0] == ')') { + int found_open_bracket = FALSE; + while(op_stack->size > 0) { + ExprOpStackItem *stack_item = cxListAt(op_stack, op_stack->size-1); + cxListRemove(op_stack, op_stack->size-1); + if(stack_item->open_parenthesis) { + found_open_bracket = TRUE; + break; + } else { + if(expr_add_operator(parser, stack_item)) { + return NULL; + } + } + } + if(!found_open_bracket) { + return NULL; + } + parser->expect_value = FALSE; + } else { + if(expr_add_value(parser, token)) { + return NULL; + } + } + } + + while(op_stack->size > 0) { + ExprOpStackItem *stack_item = cxListAt(op_stack, op_stack->size-1); + if(stack_item->open_parenthesis) { + return NULL; + } + if(expr_add_operator(parser, stack_item)) { + return NULL; + } + cxListRemove(op_stack, op_stack->size-1); + } + + if(ex_stack->size != 1) { + return NULL; + } + + return cxListAt(ex_stack, 0); +} + +NSAPIExpression* expr_parse_logical_expr(pool_handle_t *pool, CxList *tokens, size_t *pos) { + CxList *op_stack = cxLinkedListCreate(pool_allocator(pool), cx_cmp_ptr, sizeof(ExprOpStackItem)); + CxList *ex_stack = cxPointerLinkedListCreate(pool_allocator(pool), cx_cmp_ptr); + + ExprParser parser; + parser.pool = pool; + parser.op_stack = op_stack; + parser.ex_stack = ex_stack; + parser.tokens = tokens; + parser.pos = pos; + parser.expect_value = TRUE; + + NSAPIExpression *ret = expr_parse_expr(&parser); + cxListDestroy(op_stack); + cxListDestroy(ex_stack); + + return ret; +} + + + int condition_evaluate(Condition *condition, Session *sn, Request *rq) { return 1; }