#include "config-parser.h" #define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <string.h> #include <ctype.h> #include <limits.h> #include <stack> #include "lexeme-parser.h" // -------------------------------------------------------------------------------------------- // // // Implementation: helper classes // // ConfigParser::parserState scm::ConfigParser::parserState::parserState() { idx = 0; nalloc = c_alloc_init; name_space = new char[c_alloc_init]; *name_space = '\0'; name_buf_nalloc = 0; } scm::ConfigParser::parserState::parserState( const parserState &state) { idx = state.idx; nalloc = state.nalloc; name_space = new char[nalloc]; strcpy(name_space, state.name_space); name_buf_nalloc = state.name_buf_nalloc; if (name_buf_nalloc > 0) name_buf = new char[name_buf_nalloc]; } scm::ConfigParser::parserState::~parserState() { delete[] name_space; if (name_buf_nalloc > 0) delete[] name_buf; } void scm::ConfigParser::parserState::truncate_name_space() { char *ptr = strrchr(name_space, '.'); if (ptr == NULL) *name_space = '\0'; else *ptr = '\0'; } void scm::ConfigParser::parserState::append_name_space( const char *name) { int ptr = (int)strlen(name_space); int nsize = ptr + (int)strlen(name) + 2; if (nsize > nalloc) { nalloc = nsize; char *buf = new char[nalloc]; strcpy(buf, name_space); delete[] name_space; name_space = buf; } if (ptr > 0) { name_space[ptr] = '.'; name_space[ptr + 1] = '\0'; } strcat(name_space, name); } const char *scm::ConfigParser::parserState::get_global_name(const char *varname) { int ptr = (int)strlen(name_space); int nsize = ptr + (int)strlen(varname) + 2; if (nsize > name_buf_nalloc) { if (name_buf_nalloc > 0) delete[] name_buf; name_buf_nalloc = nsize; name_buf = new char[name_buf_nalloc]; } strcpy(name_buf, name_space); if (ptr > 0) { name_buf[ptr] = '.'; name_buf[ptr + 1] = '\0'; } strcat(name_buf, varname); return name_buf; } // -------------------------------------------------------------------------------------------- // // // Implementation: ConfigureParser // scm::ConfigParser::ConfigParser() { nvars = 0; nalloc_vars = c_alloc_vars_init; var = new cfgVector[nalloc_vars]; } scm::ConfigParser::~ConfigParser() { nvars = 0; nalloc_vars = 0; delete[] var; } // -------------------------------------------------------------------------------------------- // bool scm::ConfigParser::run(const char *filename) { parserCallBack pcb; return run(filename, pcb); } bool scm::ConfigParser::run(const char *filename, parserCallBack &pcb) { // removing elements in config -- but keeping memory nvars = 0; LexemeList lexeme_list; if (!LexemeParser::run(filename, lexeme_list)) return false; if (lexeme_list.get_size() == 0) return true; // nothing to parse // --- preliminary check if (!parse_syntax(lexeme_list, false, pcb)) return false; return parse_syntax(lexeme_list, true, pcb); } // * get rpn expression form * // // -------------------------------------------------------------------------------------------- // bool scm::ConfigParser::get_rpn( mem_buffer<int> &rpn, mem_buffer<int> &rpn_key, const LexemeList &lexeme_list, const int lex_beg, const int lex_end) const { std::stack<int> narg_stack; rpn.reset(); rpn_key.reset(); if ((lex_beg < 0) || (lex_end > lexeme_list.get_size() - 1)) { printf(" CONFIG:> incorrect expression range (%i, %i), lexeme list size = %i\n", lex_beg, lex_end, lexeme_list.get_size()); return false; } std::stack<int> hstack; Lexeme::TYPE lex_type; bool status = true; enum YARD_STATE { EXPECT_OPERAND, EXPECT_OPERATOR } state = EXPECT_OPERAND; int idx = lex_beg; while (idx <= lex_end) { lex_type = lexeme_list.get_type(idx); // ----------------------------------------------------- // if ((Lexeme::is_value(lex_type)) || (lex_type == Lexeme::IS_NAME)) { if (state != EXPECT_OPERAND) { printf(" CONFIG:> unexpected lexeme '%s' (line, %i)\n", lexeme_list.get_token(idx), lexeme_list.get_tag(idx)); status = false; break; } // --- adding value | variable reference to output // but postpone variable check to evaluation step rpn.append(idx); // --- adding not a function key to number of arguments rpn_key.append(-1); state = EXPECT_OPERATOR; idx++; // --- processing index operator if ((lex_type == Lexeme::IS_NAME) && (idx <= lex_end)) { if (lexeme_list.get_type(idx) == Lexeme::IS_BRACKET_OPEN) { // --- pushing '[' to stack hstack.push(idx); state = EXPECT_OPERAND; idx++; } } continue; // --> next iteration } // ----------------------------------------------------- // if ((Lexeme::is_function(lex_type)) || (Lexeme::is_ctor(lex_type)) || (lex_type == Lexeme::IS_COMMAND)) { if (state != EXPECT_OPERAND) { printf(" CONFIG:> unexpected lexeme '%s' (line, %i)\n", lexeme_list.get_token(idx), lexeme_list.get_tag(idx)); status = false; break; } // --- pushing function to stack hstack.push(idx); // --- processing function opening parenthesis idx++; if (idx > lex_end) { printf(" CONFIG:> expecting function '%s' call (line, %i)\n", lexeme_list.get_token(idx - 1), lexeme_list.get_tag(idx - 1)); status = false; break; } if (lexeme_list.get_type(idx) != Lexeme::IS_PAREN_OPEN) { printf(" CONFIG:> expecting function '%s' call (line, %i)\n", lexeme_list.get_token(idx - 1), lexeme_list.get_tag(idx - 1)); printf(" CONFIG:> unexpected lexeme '%s' (line, %i)\n", lexeme_list.get_token(idx), lexeme_list.get_tag(idx)); status = false; break; } // --- pushing '(' to stack hstack.push(idx); // --- checking for void function closing parenthesis idx++; if (idx > lex_end) { printf(" CONFIG:> expecting function '%s' call (line, %i)\n", lexeme_list.get_token(idx - 2), lexeme_list.get_tag(idx - 2)); status = false; break; } if (lexeme_list.get_type(idx) == Lexeme::IS_PAREN_CLOSE) { // --- removing function & '(' from stack hstack.pop(); hstack.pop(); // --- adding function to output rpn.append(idx - 2); // --- adding 0 as number of arguments rpn_key.append(0); state = EXPECT_OPERATOR; idx++; } else { // --- adding 1 as number of expected arguments narg_stack.push(1); state = EXPECT_OPERAND; } continue; // --> next iteration } // ----------------------------------------------------- // if (lex_type == Lexeme::IS_PAREN_OPEN) { if (state != EXPECT_OPERAND) { printf(" CONFIG:> unexpected lexeme '%s' (line, %i)\n", lexeme_list.get_token(idx), lexeme_list.get_tag(idx)); status = false; break; } // --- pushing '(' to stack hstack.push(idx); state = EXPECT_OPERAND; idx++; continue; // --> next iteration } // ----------------------------------------------------- // if (lex_type == Lexeme::IS_PAREN_CLOSE) { if (state != EXPECT_OPERATOR) { printf(" CONFIG:> unexpected lexeme '%s' (line, %i)\n", lexeme_list.get_token(idx), lexeme_list.get_tag(idx)); status = false; break; } // --- pop till '(' found & remove '(' from stack int stack_idx; bool flag = false; while (!hstack.empty()) { stack_idx = hstack.top(); if (lexeme_list.get_type(stack_idx) == Lexeme::IS_BRACKET_OPEN) break; hstack.pop(); if (lexeme_list.get_type(stack_idx) == Lexeme::IS_PAREN_OPEN) { flag = true; break; } rpn.append(stack_idx); // --- adding not a function key to number of arguments rpn_key.append(-1); } if (!flag) { printf(" CONFIG:> missing parenthesis '(' (line, %i)\n", lexeme_list.get_tag(idx)); status = false; break; } // --- checking if function is at the top of the stack if (!hstack.empty()) { stack_idx = hstack.top(); if ((lexeme_list.is_function(stack_idx)) || (lexeme_list.is_ctor(stack_idx)) || (lexeme_list.get_type(stack_idx) == Lexeme::IS_COMMAND)) { hstack.pop(); rpn.append(stack_idx); // --- adding number of expected arguments from stack int narg = narg_stack.top(); narg_stack.pop(); rpn_key.append(narg); } } state = EXPECT_OPERATOR; idx++; continue; // --> next iteration } // ----------------------------------------------------- // if (lex_type == Lexeme::IS_COMMA) { if (state != EXPECT_OPERATOR) { printf(" CONFIG:> unexpected lexeme '%s' (line, %i)\n", lexeme_list.get_token(idx), lexeme_list.get_tag(idx)); status = false; break; } // --- pop till '(' found & keep '(' on stack int stack_idx; bool flag = false; while (!hstack.empty()) { stack_idx = hstack.top(); if (lexeme_list.get_type(stack_idx) == Lexeme::IS_BRACKET_OPEN) break; if (lexeme_list.get_type(stack_idx) == Lexeme::IS_PAREN_OPEN) { flag = true; break; } hstack.pop(); rpn.append(stack_idx); // --- adding not a function key to number of arguments rpn_key.append(-1); } if (!flag) { printf(" CONFIG:> missing parenthesis '(' or misplaced ',' delimeter (line, %i)\n", lexeme_list.get_tag(idx)); status = false; break; } // --- checking if function is on top of the stack // --- temporary removing '(' hstack.pop(); if (hstack.empty()) { printf(" CONFIG:> misplaced ',' delimiter (line, %i)\n", lexeme_list.get_tag(idx)); status = false; break; } if ((!lexeme_list.is_function(hstack.top())) && (!lexeme_list.is_ctor(hstack.top())) && (lexeme_list.get_type(hstack.top()) != Lexeme::IS_COMMAND)) { printf(" CONFIG:> misplaced ',' delimiter (line, %i)\n", lexeme_list.get_tag(idx)); status = false; break; } // --- adding '(' back to stack hstack.push(stack_idx); // --- increase number of expected arguments int narg = narg_stack.top(); narg_stack.pop(); narg++; narg_stack.push(narg); state = EXPECT_OPERAND; idx++; continue; // --> next iteration } // ----------------------------------------------------- // if (Lexeme::is_operator(lex_type)) { // --- handling operators if (((is_operator_unary(lex_type)) && (state != EXPECT_OPERAND)) || ((is_operator_binary(lex_type)) && (state != EXPECT_OPERATOR))) { printf(" CONFIG:> unexpected lexeme '%s' (line, %i)\n", lexeme_list.get_token(idx), lexeme_list.get_tag(idx)); status = false; break; } int stack_idx; while (!hstack.empty()) { stack_idx = hstack.top(); if (lexeme_list.is_operator(stack_idx)) { Lexeme::TYPE stack_type = lexeme_list.get_type(stack_idx); if (((is_operator_assoc_left(lex_type)) && (!operator_priority_lt(stack_type, lex_type))) || ((is_operator_assoc_right(lex_type)) && (operator_priority_lt(lex_type, stack_type)))) { hstack.pop(); rpn.append(stack_idx); // --- adding not a function key to number of arguments rpn_key.append(-1); continue; } } break; } hstack.push(idx); state = EXPECT_OPERAND; idx++; continue; // --> next iteration } // ----------------------------------------------------- // if (lex_type == Lexeme::IS_BRACKET_CLOSE) { if (state != EXPECT_OPERATOR) { printf(" CONFIG:> unexpected lexeme '%s' (line, %i)\n", lexeme_list.get_token(idx), lexeme_list.get_tag(idx)); status = false; break; } // --- pop till '[' found & remove '[' from stack & add '[' to output int stack_idx; bool flag = false; while (!hstack.empty()) { stack_idx = hstack.top(); if (lexeme_list.get_type(stack_idx) == Lexeme::IS_PAREN_OPEN) break; hstack.pop(); rpn.append(stack_idx); // --- adding not a function key to number of arguments rpn_key.append(-1); if (lexeme_list.get_type(stack_idx) == Lexeme::IS_BRACKET_OPEN) { flag = true; break; } } if (!flag) { printf(" CONFIG:> missing bracket '[' (line, %i)\n", lexeme_list.get_tag(idx)); status = false; break; } state = EXPECT_OPERATOR; idx++; continue; // --> next iteration } // ----------------------------------------------------- // printf(" CONFIG:> unexpected lexeme in expression: '%s' (line, %i)\n", lexeme_list.get_token(idx), lexeme_list.get_tag(idx)); status = false; break; } // --- removing elements until stack is empty or getting '(' int stack_idx; while (!hstack.empty()) { stack_idx = hstack.top(); if (lexeme_list.get_type(stack_idx) == Lexeme::IS_PAREN_OPEN) { printf(" CONFIG:> missing bracket ')' (line, %i)\n", lexeme_list.get_tag(stack_idx)); status = false; break; } if (lexeme_list.get_type(stack_idx) == Lexeme::IS_BRACKET_OPEN) { printf(" CONFIG:> missing bracket ']' (line, %i)\n", lexeme_list.get_tag(stack_idx)); status = false; break; } hstack.pop(); rpn.append(stack_idx); // --- adding not a function key to number of arguments rpn_key.append(-1); } // ----------------------------------------------------- // return status && (rpn.get_size() != 0) && (state == EXPECT_OPERATOR); } // -------------------------------------------------------------------------------------------- // // * evaluate rpn expression * // // -------------------------------------------------------------------------------------------- // bool scm::ConfigParser::evaluate_rpn( std::stack<cfgVector> &dyn_expr, const mem_buffer<int> &rpn, const mem_buffer<int> &rpn_key, const int rpn_begin, const int rpn_end, const LexemeList &lexeme_list, const char *name_space, const bool exe_cntrl) const { Lexeme::TYPE lex_type; int eidx; mem_buffer<char> arg_name_buf; for (int i = max(rpn_begin, 0); i <= min(rpn_end, rpn.get_size() - 1); i++) { eidx = rpn.get_value(i); lex_type = lexeme_list.get_type(eidx); // ----------------------------------------------------- // if (is_operator_binary(lex_type)) { if (dyn_expr.size() >= 2) { cfgVector a = dyn_expr.top(); dyn_expr.pop(); cfgVector b = dyn_expr.top(); dyn_expr.pop(); bool arg_defined = ((a.is_defined()) && (b.is_defined())); if (lex_type == Lexeme::IS_OP_ADD) b += a; else if (lex_type == Lexeme::IS_OP_SUB) b -= a; else if (lex_type == Lexeme::IS_OP_MUL) b *= a; else if (lex_type == Lexeme::IS_OP_DIV) b /= a; else if (lex_type == Lexeme::IS_OP_MOD) b %= a; else if (lex_type == Lexeme::IS_OP_EXP) b ^= a; else if (lex_type == Lexeme::IS_OP_EQ) b = (b == a); else if (lex_type == Lexeme::IS_OP_NEQ) b = (b != a); else if (lex_type == Lexeme::IS_OP_LT) b = (b < a); else if (lex_type == Lexeme::IS_OP_GT) b = (b > a); else if (lex_type == Lexeme::IS_OP_LEQ) b = (b <= a); else if (lex_type == Lexeme::IS_OP_GEQ) b = (b >= a); else if (lex_type == Lexeme::IS_OP_LOGICAL_AND) b = b.logical_and(a); else if (lex_type == Lexeme::IS_OP_LOGICAL_OR) b = b.logical_or(a); else { printf(" CONFIG:> unknown binary operation: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } if ((exe_cntrl || arg_defined) && (!b.is_defined())) { printf(" CONFIG:> incorrect types of operands: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } dyn_expr.push(b); } else { printf(" CONFIG:> insufficient number of arguments: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } // --> next iteration continue; } // ----------------------------------------------------- // if (lex_type == Lexeme::IS_BRACKET_OPEN) { // --- index operator if (dyn_expr.size() >= 2) { cfgVector op = dyn_expr.top(); dyn_expr.pop(); cfgVector a = dyn_expr.top(); dyn_expr.pop(); bool arg_defined = ((a.is_defined()) && (op.is_defined())); if (exe_cntrl || arg_defined) { int index; if (!op.get_if_single(&index)) { printf(" CONFIG:> incorrect index value: '[]' (line, %i)\n", lexeme_list.get_tag(eidx)); return false; } cfgVector value = cfgVector(a.get(index)); if (!value.is_defined()) { printf(" CONFIG:> incorrect types of operands: '[]' (line, %i)\n", lexeme_list.get_tag(eidx)); return false; } dyn_expr.push(value); } else { dyn_expr.push(cfgVector()); } } else { printf(" CONFIG:> insufficient number of arguments: '[]' (line, %i)\n", lexeme_list.get_tag(eidx)); return false; } // --> next iteration continue; } // ----------------------------------------------------- // if (is_operator_unary(lex_type)) { if (dyn_expr.size() >= 1) { cfgVector op = dyn_expr.top(); dyn_expr.pop(); cfgVector res; bool arg_defined = (op.is_defined()); if (lex_type == Lexeme::IS_OP_PLUS) res = +op; else if (lex_type == Lexeme::IS_OP_MINUS) res = -op; else { printf(" CONFIG:> unknown unary operation: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } if ((exe_cntrl || arg_defined) && (!res.is_defined())) { printf(" CONFIG:> incorrect type of operand: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } dyn_expr.push(res); } else { printf(" CONFIG:> insufficient number of arguments: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } // --> next iteration continue; } // ----------------------------------------------------- // if (Lexeme::is_function(lex_type)) { if (rpn_key.get_value(i) != function_nargs(lex_type)) { printf(" CONFIG:> incorrect number (%i) of arguments in function: '%s' (line, %i)\n", rpn_key.get_value(i), lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } if (function_nargs(lex_type) == 2) { if (dyn_expr.size() >= 2) { cfgVector op2 = dyn_expr.top(); dyn_expr.pop(); cfgVector op1 = dyn_expr.top(); dyn_expr.pop(); cfgVector res; bool arg_defined = ((op1.is_defined()) && (op2.is_defined())); if (lex_type == Lexeme::IS_MIN_FUNCTION) res = cfgVector::cfg_min(op1, op2); else if (lex_type == Lexeme::IS_MAX_FUNCTION) res = cfgVector::cfg_max(op1, op2); else if (lex_type == Lexeme::IS_DOT_PRODUCT_FUNCTION) res = cfgVector::cfg_dot_product(op1, op2); else if (lex_type == Lexeme::IS_UNIRAND_FUNCTION) { if (exe_cntrl || arg_defined) { double a, b; if (!op1.get_if_single(&a)) { printf(" CONFIG:> incorrect type of operand: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } if (!op2.get_if_single(&b)) { printf(" CONFIG:> incorrect type of operand: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } double value = a + (rand() / (RAND_MAX / (b - a))); res = cfgVector(cfgValue(value)); } else { res = cfgVector(); } } else { printf(" CONFIG:> unknown function: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } if ((exe_cntrl || arg_defined) && (!res.is_defined())) { printf(" CONFIG:> incorrect type of operand: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } dyn_expr.push(res); } else { printf(" CONFIG:> insufficient number of arguments: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } // --> next iteration continue; } if (function_nargs(lex_type) == 1) { if (dyn_expr.size() >= 1) { cfgVector op = dyn_expr.top(); dyn_expr.pop(); cfgVector res; bool arg_defined = (op.is_defined()); if (lex_type == Lexeme::IS_VECMIN_FUNCTION) res = cfgVector::cfg_vecmin(op); else if (lex_type == Lexeme::IS_VECMAX_FUNCTION) res = cfgVector::cfg_vecmax(op); else if (lex_type == Lexeme::IS_SIN_FUNCTION) res = cfgVector::cfg_sin(op); else if (lex_type == Lexeme::IS_COS_FUNCTION) res = cfgVector::cfg_cos(op); else if (lex_type == Lexeme::IS_TAN_FUNCTION) res = cfgVector::cfg_tan(op); else if (lex_type == Lexeme::IS_LOG_FUNCTION) res = cfgVector::cfg_log(op); else if (lex_type == Lexeme::IS_SQRT_FUNCTION) res = cfgVector::cfg_sqrt(op); else if (lex_type == Lexeme::IS_ABS_FUNCTION) res = cfgVector::cfg_abs(op); else if (lex_type == Lexeme::IS_L2NORM_FUNCTION) res = cfgVector::cfg_l2norm(op); else if (lex_type == Lexeme::IS_CNORM_FUNCTION) res = cfgVector::cfg_cnorm(op); else if (lex_type == Lexeme::IS_TO_STRING_FUNCTION) res = cfgVector::cfg_to_string(op); else if (lex_type == Lexeme::IS_SIZE_FUNCTION) res = cfgVector(cfgValue(op.get_size())); else if (lex_type == Lexeme::IS_DEFINED_FUNCTION) { if (exe_cntrl || arg_defined) { std::string name; if (!op.get_if_single(name)) { printf(" CONFIG:> incorrect type of operand: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } res = (is_varname(name.c_str())) ? cfgVector(cfgValue(true)) : cfgVector(cfgValue(false)); } else { res = cfgVector(); } } else { printf(" CONFIG:> unknown function: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } if ((exe_cntrl || arg_defined) && (!res.is_defined())) { printf(" CONFIG:> incorrect type of operand: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } dyn_expr.push(res); } else { printf(" CONFIG:> insufficient number of arguments: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } // --> next iteration continue; } printf(" CONFIG:> unknown function: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } // ----------------------------------------------------- // if (Lexeme::is_ctor(lex_type)) { if (lex_type == Lexeme::IS_VECTOR_CTOR) { int narg = rpn_key.get_value(i); if (narg < 0) { printf(" CONFIG:> incorrect number of arguments: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } cfgVector vec; if (dyn_expr.size() >= (unsigned int)narg) { std::stack<cfgValue> vec_arg; for (int k = 0; k < narg; k++) { cfgVector arg = dyn_expr.top(); dyn_expr.pop(); if ((exe_cntrl) && (!arg.is_defined())) { printf(" CONFIG:> undefined argument: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } if ((exe_cntrl || (arg.is_defined())) && (!arg.is_single())) { printf(" CONFIG:> incorrect argument size > 1: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } vec_arg.push(arg.get(0)); } cfgVector vec; // --- using stack to append values in correct order while (!vec_arg.empty()) { vec.append(vec_arg.top()); vec_arg.pop(); } dyn_expr.push(vec); } else { printf(" CONFIG:> insufficient number of arguments: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } // --> next iteration continue; } if (lex_type == Lexeme::IS_VECTOR_CONST_CTOR) { if (rpn_key.get_value(i) != 2) { printf(" CONFIG:> incorrect number (%i) of arguments in constructor: '%s' (line, %i)\n", rpn_key.get_value(i), lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } if (dyn_expr.size() >= 2) { cfgVector vec_value = dyn_expr.top(); dyn_expr.pop(); cfgVector vec_size = dyn_expr.top(); dyn_expr.pop(); bool arg_defined = ((vec_value.is_defined()) && (vec_size.is_defined())); if (exe_cntrl || arg_defined) { int size; if (!vec_size.get_if_single(&size)) { printf(" CONFIG:> incorrect size argument: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } if (size < 0) { printf(" CONFIG:> invalid size (%i) argument: '%s' (line, %i)\n", size, lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } if (!vec_value.is_defined()) { printf(" CONFIG:> undefined argument: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } if (!vec_value.is_single()) { printf(" CONFIG:> incorrect argument size > 1: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } cfgVector vec; vec.set(vec_value.get(0), size); dyn_expr.push(vec); } else { dyn_expr.push(cfgVector()); } } else { printf(" CONFIG:> insufficient number of arguments: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } // --> next iteration continue; } if (lex_type == Lexeme::IS_VECTOR_UNIRAND_CTOR) { if (rpn_key.get_value(i) != 3) { printf(" CONFIG:> incorrect number (%i) of arguments in constructor: '%s' (line, %i)\n", rpn_key.get_value(i), lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } if (dyn_expr.size() >= 3) { cfgVector vec_b = dyn_expr.top(); dyn_expr.pop(); cfgVector vec_a = dyn_expr.top(); dyn_expr.pop(); cfgVector vec_size = dyn_expr.top(); dyn_expr.pop(); bool arg_defined = ((vec_b.is_defined()) && (vec_a.is_defined()) && (vec_size.is_defined())); if (exe_cntrl || arg_defined) { int size; if (!vec_size.get_if_single(&size)) { printf(" CONFIG:> incorrect size argument: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } if (size < 0) { printf(" CONFIG:> invalid size (%i) argument: '%s' (line, %i)\n", size, lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } double a, b; if (!vec_a.get_if_single(&a)) { printf(" CONFIG:> incorrect type of operand: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } if (!vec_b.get_if_single(&b)) { printf(" CONFIG:> incorrect type of operand: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } double value = (a == b) ? a : a + (rand() / (RAND_MAX / (b - a))); cfgVector vec; vec.set(cfgValue(value), size); for (int k = 1; k < size; k++) { value = a + (rand() / (RAND_MAX / (b - a))); vec.change(k, cfgValue(value)); } dyn_expr.push(vec); } else { dyn_expr.push(cfgVector()); } } else { printf(" CONFIG:> insufficient number of arguments: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } // --> next iteration continue; } printf(" CONFIG:> unknown constructor: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } // ----------------------------------------------------- // if (Lexeme::is_value(lex_type)) { cfgVector vec(cfgValue::make_implicit(lexeme_list.get_token(eidx))); if (!vec.is_defined()) { printf(" CONFIG:> incorrect constant value: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } dyn_expr.push(vec); // --> next iteration continue; } // ----------------------------------------------------- // if (lex_type == Lexeme::IS_NAME) { if (exe_cntrl) { cfgVector arg; arg_name_buf.reset(); arg_name_buf.append(name_space, strlen(name_space)); arg_name_buf.append('.'); arg_name_buf.append(lexeme_list.get_token(eidx), strlen(lexeme_list.get_token(eidx))); arg_name_buf.append('\0'); if (is_varname(arg_name_buf.get_ptr())) arg = get_variable(arg_name_buf.get_ptr()); else { if (is_varname(lexeme_list.get_token(eidx))) { arg = get_variable(lexeme_list.get_token(eidx)); } else { printf(" CONFIG:> reference to undefined variable: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } } dyn_expr.push(arg); } else { dyn_expr.push(cfgVector()); } // --> next iteration continue; } // ----------------------------------------------------- // printf(" CONFIG:> unexpected lexeme in expression: '%s' (line, %i)\n", lexeme_list.get_token(eidx), lexeme_list.get_tag(eidx)); return false; } return true; } bool scm::ConfigParser::evaluate_rpn( cfgVector &res, const mem_buffer<int> &rpn, const mem_buffer<int> &rpn_key, const LexemeList &lexeme_list, const char *name_space, const bool exe_cntrl) const { std::stack<cfgVector> dyn_expr; if (!evaluate_rpn(dyn_expr, rpn, rpn_key, 0, rpn.get_size() - 1, lexeme_list, name_space, exe_cntrl)) { res = cfgVector(); return false; } if (dyn_expr.size() != 1) { res = cfgVector(); printf(" CONFIG:> undefined expression (line, %i)\n", lexeme_list.get_tag(rpn.get_value(0))); return false; } res = cfgVector(dyn_expr.top()); // delay res type checking [in add] return true; } // -------------------------------------------------------------------------------------------- // bool scm::ConfigParser::set_command( cfgCommand &command, const mem_buffer<int> &rpn, const mem_buffer<int> &rpn_key, const LexemeList &lexeme_list, const bool exe_cntrl) const { const int rpn_size = rpn.get_size(); std::stack<cfgVector> dyn_expr; command.reset(); command.set_name(lexeme_list.get_token(rpn.get_value(rpn_size - 1))); if (!evaluate_rpn(dyn_expr, rpn, rpn_key, 0, rpn_size - 2, lexeme_list, "", exe_cntrl)) { printf(" CONFIG:> undefined command arguments '%s' (line, %i)\n", lexeme_list.get_token(rpn.get_value(rpn_size - 1)), lexeme_list.get_tag(rpn.get_value(rpn_size - 1))); return false; } if (dyn_expr.size() != rpn_key.get_value(rpn_size - 1)) { printf(" CONFIG:> incorrect number (%li) of command '%s' arguments (line, %i)\n", dyn_expr.size(), lexeme_list.get_token(rpn.get_value(rpn_size - 1)), lexeme_list.get_tag(rpn.get_value(rpn_size - 1))); return false; } // --- copy arguments in correct order std::stack<cfgVector> dyn_expr_back; while (!dyn_expr.empty()) { dyn_expr_back.push(dyn_expr.top()); dyn_expr.pop(); } cfgVector arg; while (!dyn_expr_back.empty()) { arg = dyn_expr_back.top(); if (exe_cntrl || (arg.is_defined())) if (!command.add_arg(arg)) { printf(" CONFIG:> undefined command arguments '%s' (line, %i)\n", lexeme_list.get_token(rpn.get_value(rpn_size - 1)), lexeme_list.get_tag(rpn.get_value(rpn_size - 1))); return false; } dyn_expr_back.pop(); } // ----------------------------------------------------- // return true; // delay arg type checking [in add] } // -------------------------------------------------------------------------------------------- // // * syntax analysis * // // -------------------------------------------------------------------------------------------- // bool scm::ConfigParser::parse_syntax( const LexemeList &lexeme_list, const bool exe_cntrl, parserCallBack &pcb) { const int nlexeme = lexeme_list.get_size(); if (nlexeme == 0) return true; parserState state; if (!parse_block(state, lexeme_list, exe_cntrl, pcb)) return false; if (state.idx < nlexeme) { printf(" CONFIG:> unexpected lexeme: '%s' (line, %i)\n", lexeme_list.get_token(state.idx), lexeme_list.get_tag(state.idx)); return false; } return true; } bool scm::ConfigParser::parse_block( parserState &state, const LexemeList &lexeme_list, const bool exe_cntrl, parserCallBack &pcb) { const int nlexeme = lexeme_list.get_size(); while (state.idx < nlexeme) { if (lexeme_list.get_type(state.idx) == Lexeme::IS_COMMAND) { if (!parse_command(state, lexeme_list, exe_cntrl, pcb)) return false; continue; } if (lexeme_list.get_type(state.idx) == Lexeme::IS_KEY_WHILE) { if (!parse_while_statement(state, lexeme_list, exe_cntrl, pcb)) return false; continue; } if (lexeme_list.get_type(state.idx) == Lexeme::IS_KEY_IF) { if (!parse_if_statement(state, lexeme_list, exe_cntrl, pcb)) return false; continue; } if (lexeme_list.get_type(state.idx) == Lexeme::IS_NAME) { if ((state.idx + 1 < nlexeme) && (lexeme_list.get_type(state.idx + 1) == Lexeme::IS_BRACE_OPEN)) { if (!parse_name_space(state, lexeme_list, exe_cntrl, pcb)) return false; continue; } if ((state.idx + 1 < nlexeme) && (lexeme_list.get_type(state.idx + 1) == Lexeme::IS_ASSIGNMENT)) { if (!parse_assignment(state, lexeme_list, exe_cntrl, pcb)) return false; continue; } if ((state.idx + 1 < nlexeme) && (lexeme_list.get_type(state.idx + 1) == Lexeme::IS_BRACKET_OPEN)) { if (!parse_address_assignment(state, lexeme_list, exe_cntrl, pcb)) return false; continue; } printf(" CONFIG:> expecting '=' or '{' for name: '%s' (line, %i)\n", lexeme_list.get_token(state.idx), lexeme_list.get_tag(state.idx)); return false; } break; // unknown lexeme found } return true; } bool scm::ConfigParser::parse_command( parserState &state, const LexemeList &lexeme_list, const bool exe_cntrl, parserCallBack &pcb) { mem_buffer<int> rpn; mem_buffer<int> rpn_key; const int nlexeme = lexeme_list.get_size(); int beg_idx = state.idx; if (strcmp(state.name_space, "")) { // --- nesting commands in namespaces is not allowed! printf(" CONFIG:> nested command '%s' found (line, %i)\n", lexeme_list.get_token(beg_idx), lexeme_list.get_tag(beg_idx)); return false; } // --- setting pointer to first lexeme in expression const int expr_begin = state.idx; int expr_end; // --- matching end of expression state.idx++; bool is_closed = false; while ((state.idx < nlexeme) && (!is_closed)) { if (lexeme_list.get_type(state.idx) == Lexeme::IS_SEMICOLON) { is_closed = true; expr_end = state.idx - 1; } state.idx++; } if (!is_closed) { printf(" CONFIG:> unclosed command '%s' statement, missing ';' (line, %i)\n", lexeme_list.get_token(beg_idx), lexeme_list.get_tag(beg_idx)); return false; } // --- converting to postfix notation if (!get_rpn(rpn, rpn_key, lexeme_list, expr_begin, expr_end)) { printf(" CONFIG:> failed to process command '%s' statement (line, %i)\n", lexeme_list.get_token(beg_idx), lexeme_list.get_tag(beg_idx)); return false; } if (rpn.get_value(rpn.get_size() - 1) != beg_idx) { printf(" CONFIG:> incorrect command '%s' expression (line, %i)\n", lexeme_list.get_token(beg_idx), lexeme_list.get_tag(beg_idx)); return false; } // --- evaluating command arguments cfgCommand command; if (!set_command(command, rpn, rpn_key, lexeme_list, exe_cntrl)) { printf(" CONFIG:> failed to set command '%s' (line, %i)\n", lexeme_list.get_token(beg_idx), lexeme_list.get_tag(beg_idx)); return false; } if (!exe_cntrl) return true; // --- calling command bool status = pcb.call_back(command); if (!status) { printf(" CONFIG:> command '%s' failed -- stop (line, %i)\n", lexeme_list.get_token(beg_idx), lexeme_list.get_tag(beg_idx)); } return status; } bool scm::ConfigParser::parse_name_space( parserState &state, const LexemeList &lexeme_list, const bool exe_cntrl, parserCallBack &pcb) { const int nlexeme = lexeme_list.get_size(); int beg_idx = state.idx; // --- no dots allowed in namespace name at least for now if (strchr(lexeme_list.get_token(state.idx), '.') != NULL) { printf(" CONFIG:> '.' not allowed in namespaces: '%s' (line, %i)\n", lexeme_list.get_token(beg_idx), lexeme_list.get_tag(beg_idx)); return false; } state.append_name_space(lexeme_list.get_token(state.idx)); state.idx += 2; if (!parse_block(state, lexeme_list, exe_cntrl, pcb)) return false; // --- closing namespace [}] if ((state.idx < nlexeme) && (lexeme_list.get_type(state.idx) == Lexeme::IS_BRACE_CLOSE)) { state.truncate_name_space(); state.idx++; return true; } // --- unclosed namespace [}] printf(" CONFIG:> unclosed namespace '%s', missing '}' (line, %i)\n", lexeme_list.get_token(beg_idx), lexeme_list.get_tag(beg_idx)); return false; } bool scm::ConfigParser::parse_assignment( parserState &state, const LexemeList &lexeme_list, const bool exe_cntrl, parserCallBack &pcb) { mem_buffer<int> rpn; mem_buffer<int> rpn_key; const int nlexeme = lexeme_list.get_size(); int beg_idx = state.idx; const char *global_varname = state.get_global_name(lexeme_list.get_token(beg_idx)); // --- setting state at expression: NAME = EXPRESSION; state.idx += 2; // --- setting pointer to first lexeme in expression const int expr_begin = state.idx; int expr_end; // --- matching end of expression bool is_closed = false; while ((state.idx < nlexeme) && (!is_closed)) { if (lexeme_list.get_type(state.idx) == Lexeme::IS_SEMICOLON) { is_closed = true; expr_end = state.idx - 1; } state.idx++; } if (!is_closed) { printf(" CONFIG:> unclosed assignment statement '%s = ', missing ';' (line, %i)\n", global_varname, lexeme_list.get_tag(beg_idx)); return false; } // --- converting to postfix notation if (!get_rpn(rpn, rpn_key, lexeme_list, expr_begin, expr_end)) { printf(" CONFIG:> failed to process expression for variable: '%s' (line, %i)\n", global_varname, lexeme_list.get_tag(beg_idx)); return false; } // --- evaluating postfix expression (need namespace - not full variable name) cfgVector value; if (!evaluate_rpn(value, rpn, rpn_key, lexeme_list, state.name_space, exe_cntrl)) { printf(" CONFIG:> failed to evaluate expression for variable: '%s' (line, %i)\n", global_varname, lexeme_list.get_tag(beg_idx)); return false; } if ((exe_cntrl) && (!value.is_defined())) { printf(" CONFIG:> failed to evaluate expression for variable: '%s' (line, %i)\n", global_varname, lexeme_list.get_tag(beg_idx)); return false; } // --- setting variable name value.set_name(global_varname); if (value.is_name_empty()) { printf(" CONFIG:> invalid variable name: '%s' (line, %i)\n", global_varname, lexeme_list.get_tag(beg_idx)); return false; } // --- adding variable if (exe_cntrl) add_unsafe(value); return true; } bool scm::ConfigParser::parse_address_assignment( parserState &state, const LexemeList &lexeme_list, const bool exe_cntrl, parserCallBack &pcb) { mem_buffer<int> rpn; mem_buffer<int> rpn_key; const int nlexeme = lexeme_list.get_size(); int beg_idx = state.idx; const char *global_varname = state.get_global_name(lexeme_list.get_token(beg_idx)); // --- setting state at index: NAME[INDEX] = EXPRESSION; state.idx += 2; // --- setting pointer to last lexeme in index const int index_begin = state.idx; int index_end; // --- matching end of index bool is_closed = false; while ((state.idx < nlexeme) && (!is_closed)) { if ((lexeme_list.get_type(state.idx) == Lexeme::IS_ASSIGNMENT) && (lexeme_list.get_type(state.idx - 1) == Lexeme::IS_BRACKET_CLOSE)) { is_closed = true; index_end = state.idx - 2; } state.idx++; } if (!is_closed) { printf(" CONFIG:> unclosed index operator '%s[] = ', missing ']' (line, %i)\n", global_varname, lexeme_list.get_tag(beg_idx)); return false; } if (index_end < index_begin) { printf(" CONFIG:> no arguments in index operator '%s[] = ' (line, %i)\n", global_varname, lexeme_list.get_tag(beg_idx)); return false; } // --- converting to postfix notation if (!get_rpn(rpn, rpn_key, lexeme_list, index_begin, index_end)) { printf(" CONFIG:> failed to process expression for index of variable: '%s' (line, %i)\n", global_varname, lexeme_list.get_tag(beg_idx)); return false; } // --- evaluating postfix expression (need namespace - not full variable name) cfgVector vec_index; if (!evaluate_rpn(vec_index, rpn, rpn_key, lexeme_list, state.name_space, exe_cntrl)) { printf(" CONFIG:> failed to evaluate index of variable: '%s' (line, %i)\n", global_varname, lexeme_list.get_tag(beg_idx)); return false; } int index = 0; if ((exe_cntrl | (vec_index.is_defined())) && (!vec_index.get_if_single(&index))) { printf(" CONFIG:> incorrect argument for index of variable: '%s' (line, %i)\n", global_varname, lexeme_list.get_tag(beg_idx)); return false; } // --- setting pointer to first lexeme in expression const int expr_begin = state.idx; int expr_end; // --- matching end of expression is_closed = false; while ((state.idx < nlexeme) && (!is_closed)) { if (lexeme_list.get_type(state.idx) == Lexeme::IS_SEMICOLON) { is_closed = true; expr_end = state.idx - 1; } state.idx++; } if (!is_closed) { printf(" CONFIG:> unclosed assignment statement '%s = ', missing ';' (line, %i)\n", global_varname, lexeme_list.get_tag(beg_idx)); return false; } // --- converting to postfix notation if (!get_rpn(rpn, rpn_key, lexeme_list, expr_begin, expr_end)) { printf(" CONFIG:> failed to process expression for variable: '%s' (line, %i)\n", global_varname, lexeme_list.get_tag(beg_idx)); return false; } // --- evaluating postfix expression (need namespace - not full variable name) cfgVector value; if (!evaluate_rpn(value, rpn, rpn_key, lexeme_list, state.name_space, exe_cntrl)) { printf(" CONFIG:> failed to evaluate expression for variable: '%s' (line, %i)\n", global_varname, lexeme_list.get_tag(beg_idx)); return false; } if ((exe_cntrl) && (!value.is_defined())) { printf(" CONFIG:> failed to evaluate expression for variable: '%s' (line, %i)\n", global_varname, lexeme_list.get_tag(beg_idx)); return false; } if ((exe_cntrl || (value.is_defined())) && (!value.is_single())) { printf(" CONFIG:> incorrect expression for variable: '%s' (line, %i)\n", global_varname, lexeme_list.get_tag(beg_idx)); return false; } // --- setting variable name value.set_name(global_varname); if (value.is_name_empty()) { printf(" CONFIG:> invalid variable name: '%s' (line, %i)\n", global_varname, lexeme_list.get_tag(beg_idx)); return false; } if (!exe_cntrl) return true; // --- adding value only if vector is already allocated for (int k = 0; k < nvars; k++) { if (var[k].is_name_eq(value)) { if ((index < 0) || (index >= var[k].get_size())) { printf(" CONFIG:> out of range index (%i) for vector(%i): '%s' (line, %i)\n", index, var[k].get_size(), global_varname, lexeme_list.get_tag(beg_idx)); return false; } var[k].change(index, value.get(0)); return true; } } printf(" CONFIG:> variable '%s' doesn't exist (line, %i)\n", global_varname, lexeme_list.get_tag(beg_idx)); return false; } bool scm::ConfigParser::parse_if_statement( parserState &state, const LexemeList &lexeme_list, const bool exe_cntrl, parserCallBack &pcb) { mem_buffer<int> rpn; mem_buffer<int> rpn_key; const int nlexeme = lexeme_list.get_size(); int beg_idx = state.idx; // --- setting state at expression: IF EXPRESSION THEN ... state.idx++; // --- setting pointer to first lexeme in expression const int expr_begin = state.idx; int expr_end; // --- matching end of expression bool is_closed = false; while ((state.idx < nlexeme) && (!is_closed)) { if (lexeme_list.get_type(state.idx) == Lexeme::IS_KEY_THEN) { is_closed = true; expr_end = state.idx - 1; } state.idx++; } if (!is_closed) { printf(" CONFIG:> unclosed 'if' statement, missing 'then' (line, %i)\n", lexeme_list.get_tag(beg_idx)); return false; } // --- converting to postfix notation if (!get_rpn(rpn, rpn_key, lexeme_list, expr_begin, expr_end)) { printf(" CONFIG:> failed to process 'if' statement expression (line, %i)\n", lexeme_list.get_tag(beg_idx)); return false; } // --- evaluating postfix expression cfgVector value; if (!evaluate_rpn(value, rpn, rpn_key, lexeme_list, state.name_space, exe_cntrl)) { printf(" CONFIG:> failed to evaluate 'if' statement expression, expecting bool value (line, %i)\n", lexeme_list.get_tag(beg_idx)); return false; } bool if_cntrl = false; if (exe_cntrl || (value.is_defined())) { if (!value.get_if_single(&if_cntrl)) { printf(" CONFIG:> failed to evaluate 'if' statement expression, expecting bool value (line, %i)\n", lexeme_list.get_tag(beg_idx)); return false; } } if (!parse_block(state, lexeme_list, (exe_cntrl && if_cntrl), pcb)) return false; // --- processing 'else' case if ((state.idx < nlexeme) && (lexeme_list.get_type(state.idx) == Lexeme::IS_KEY_ELSE)) { state.idx++; if (!parse_block(state, lexeme_list, (exe_cntrl && (!if_cntrl)), pcb)) return false; } if ((state.idx < nlexeme) && (lexeme_list.get_type(state.idx) == Lexeme::IS_KEY_ENDIF)) { state.idx++; return true; } printf(" CONFIG:> unclosed 'if' statement, missing 'endif' (line, %i)\n", lexeme_list.get_tag(beg_idx)); return false; } bool scm::ConfigParser::parse_while_statement( parserState &state, const LexemeList &lexeme_list, const bool exe_cntrl, parserCallBack &pcb) { const int c_max_iters = INT_MAX; // max iters to handle infinite cycles mem_buffer<int> rpn; mem_buffer<int> rpn_key; const int nlexeme = lexeme_list.get_size(); int beg_idx = state.idx; // --- setting state at expression: WHILE EXPRESSION DO ... state.idx++; // --- setting pointer to first lexeme in expression const int expr_begin = state.idx; int expr_end; // --- matching end of expression bool is_closed = false; while ((state.idx < nlexeme) && (!is_closed)) { if (lexeme_list.get_type(state.idx) == Lexeme::IS_KEY_DO) { is_closed = true; expr_end = state.idx - 1; } state.idx++; } if (!is_closed) { printf(" CONFIG:> unclosed 'while' statement, missing 'do' (line, %i)\n", lexeme_list.get_tag(beg_idx)); return false; } // --- evaluating while condition bool while_cntrl; // converting to postfix notation if (!get_rpn(rpn, rpn_key, lexeme_list, expr_begin, expr_end)) { printf(" CONFIG:> failed to process 'while' statement expression (line, %i)\n", lexeme_list.get_tag(beg_idx)); return false; } // --- evaluating postfix expression cfgVector value; if (!evaluate_rpn(value, rpn, rpn_key, lexeme_list, state.name_space, exe_cntrl)) { printf(" CONFIG:> failed to evaluate 'while' statement expression, expecting bool value (line, %i)\n", lexeme_list.get_tag(beg_idx)); return false; } while_cntrl = false; if (exe_cntrl || (value.is_defined())) { if (!value.get_if_single(&while_cntrl)) { printf(" CONFIG:> failed to evaluate 'while' statement expression, expecting bool value (line, %i)\n", lexeme_list.get_tag(beg_idx)); return false; } } // --- pointer to do code beginning const int do_beg_idx = state.idx; // --- iterations counter int iters = 0; while ( (exe_cntrl && while_cntrl) || (iters == 0)) // --- parsing at least iteration to check syntax and move state { // --- resetting state state.idx = do_beg_idx; if (!parse_block(state, lexeme_list, (exe_cntrl && while_cntrl), pcb)) return false; // --- checking 'while' statement closure if ((state.idx < nlexeme) && (lexeme_list.get_type(state.idx) == Lexeme::IS_KEY_ENDDO)) { state.idx++; // --- in case just checking syntax if ((!exe_cntrl) || (!while_cntrl)) break; // --- checking if infinite loop iters++; if (iters == c_max_iters) { printf(" CONFIG:> max allowed iterations ( = %i) reached for 'while' statement, aborting (line, %i)\n", c_max_iters, lexeme_list.get_tag(beg_idx)); return false; } // --- evaluating while condition // --- evaluating postfix expression cfgVector value; if (!evaluate_rpn(value, rpn, rpn_key, lexeme_list, state.name_space, exe_cntrl)) { printf(" CONFIG:> failed to evaluate 'while' statement expression, expecting bool value (line, %i)\n", lexeme_list.get_tag(beg_idx)); return false; } if (!value.get_if_single(&while_cntrl)) { printf(" CONFIG:> failed to evaluate 'while' statement expression, expecting bool value (line, %i)\n", lexeme_list.get_tag(beg_idx)); return false; } } else { printf(" CONFIG:> unclosed 'while' statement, missing 'enddo' (line, %i)\n", lexeme_list.get_tag(beg_idx)); return false; } } return true; } // -------------------------------------------------------------------------------------------- // bool scm::ConfigParser::add(const cfgVector &ex) { if (!ex.is_defined()) return false; if (!is_valid_name(ex.get_name())) return false; return add_unsafe(ex); } bool scm::ConfigParser::is_valid_name(const char *name) const { int token_length = (int)strlen(name); if (token_length == 0) return false; if ((!isalpha(name[0])) && (name[0] != '_')) return false; for (int i = 1; i < token_length; i++) { if ((!isalnum(name[i])) && (name[i] != '_') && (name[i] != '.')) return false; } if (name[token_length - 1] == '.') return false; return true; } bool scm::ConfigParser::add_unsafe(const cfgVector &ex) { // --- just overwriting variable if already exists for (int k = 0; k < nvars; k++) { if (var[k].is_name_eq(ex)) { var[k] = ex; return true; } } if (nvars >= nalloc_vars) { cfgVector *hvar = new cfgVector[nalloc_vars + c_alloc_vars_init]; for (int i = 0; i < nalloc_vars; i++) { hvar[i] = var[i]; } delete[] var; var = hvar; nalloc_vars += c_alloc_vars_init; } var[nvars] = ex; nvars++; return true; } // -------------------------------------------------------------------------------------------- // int scm::ConfigParser::operator_priority( const Lexeme::TYPE type) { if ((type == Lexeme::IS_OP_LOGICAL_AND) || (type == Lexeme::IS_OP_LOGICAL_OR)) return 1; if ((type == Lexeme::IS_OP_EQ) || (type == Lexeme::IS_OP_NEQ)) return 2; if ((type == Lexeme::IS_OP_LT) || (type == Lexeme::IS_OP_GT) || (type == Lexeme::IS_OP_LEQ) || (type == Lexeme::IS_OP_GEQ)) return 3; if ((type == Lexeme::IS_OP_ADD) || (type == Lexeme::IS_OP_SUB)) return 4; if ((type == Lexeme::IS_OP_MUL) || (type == Lexeme::IS_OP_DIV) || (type == Lexeme::IS_OP_MOD)) return 5; if ((type == Lexeme::IS_OP_PLUS) || (type == Lexeme::IS_OP_MINUS)) return 6; if ((type == Lexeme::IS_OP_EXP)) return 7; return 0; } bool scm::ConfigParser::operator_priority_lt( const Lexeme::TYPE typeA, const Lexeme::TYPE typeB) { return (operator_priority(typeA) < operator_priority(typeB)); } bool scm::ConfigParser::is_operator_binary(const Lexeme::TYPE type) { return ( (type == Lexeme::IS_OP_ADD) || (type == Lexeme::IS_OP_SUB) || (type == Lexeme::IS_OP_MUL) || (type == Lexeme::IS_OP_DIV) || (type == Lexeme::IS_OP_MOD) || (type == Lexeme::IS_OP_EXP) || (type == Lexeme::IS_OP_EQ) || (type == Lexeme::IS_OP_NEQ) || (type == Lexeme::IS_OP_LOGICAL_AND) || (type == Lexeme::IS_OP_LOGICAL_OR) || (type == Lexeme::IS_OP_LT) || (type == Lexeme::IS_OP_GT) || (type == Lexeme::IS_OP_LEQ) || (type == Lexeme::IS_OP_GEQ)); } bool scm::ConfigParser::is_operator_unary(const Lexeme::TYPE type) { return ((type == Lexeme::IS_OP_PLUS) || (type == Lexeme::IS_OP_MINUS)); } bool scm::ConfigParser::is_operator_assoc_right(const Lexeme::TYPE type) { return ((type == Lexeme::IS_OP_EXP) || (type == Lexeme::IS_OP_PLUS) || (type == Lexeme::IS_OP_MINUS)); } bool scm::ConfigParser::is_operator_assoc_left(const Lexeme::TYPE type) { return ( (type == Lexeme::IS_OP_ADD) || (type == Lexeme::IS_OP_SUB) || (type == Lexeme::IS_OP_MUL) || (type == Lexeme::IS_OP_DIV) || (type == Lexeme::IS_OP_MOD) || (type == Lexeme::IS_OP_EQ) || (type == Lexeme::IS_OP_NEQ) || (type == Lexeme::IS_OP_LOGICAL_AND) || (type == Lexeme::IS_OP_LOGICAL_OR) || (type == Lexeme::IS_OP_LT) || (type == Lexeme::IS_OP_GT) || (type == Lexeme::IS_OP_LEQ) || (type == Lexeme::IS_OP_GEQ)); } int scm::ConfigParser::function_nargs(const Lexeme::TYPE type) { if ((type == Lexeme::IS_MIN_FUNCTION) || (type == Lexeme::IS_MAX_FUNCTION) || (type == Lexeme::IS_DOT_PRODUCT_FUNCTION) || (type == Lexeme::IS_UNIRAND_FUNCTION)) return 2; if ((type == Lexeme::IS_VECMIN_FUNCTION) || (type == Lexeme::IS_VECMAX_FUNCTION) || (type == Lexeme::IS_SIN_FUNCTION) || (type == Lexeme::IS_COS_FUNCTION) || (type == Lexeme::IS_TAN_FUNCTION) || (type == Lexeme::IS_LOG_FUNCTION) || (type == Lexeme::IS_SQRT_FUNCTION) || (type == Lexeme::IS_ABS_FUNCTION) || (type == Lexeme::IS_L2NORM_FUNCTION) || (type == Lexeme::IS_CNORM_FUNCTION) || (type == Lexeme::IS_TO_STRING_FUNCTION) || (type == Lexeme::IS_SIZE_FUNCTION) || (type == Lexeme::IS_DEFINED_FUNCTION)) return 1; return 0; } // -------------------------------------------------------------------------------------------- // // * get & check calls * // // -------------------------------------------------------------------------------------------- // bool scm::ConfigParser::is_varname(const char *name) const { for (int i = 0; i < nvars; i++) if (var[i].is_name_eq(name)) return true; return false; } const scm::cfgVector scm::ConfigParser::get_variable(const int idx) const { if ((idx < 0) || (idx >= nvars)) return cfgVector(); return var[idx]; } const scm::cfgVector scm::ConfigParser::get_variable(const char *name) const { for (int k = 0; k < nvars; k++) { if (var[k].is_name_eq(name)) return var[k]; } return cfgVector(); } void scm::ConfigParser::print() const { for (int i = 0; i < nvars; i++) { var[i].print(); getc(stdin); } } bool scm::ConfigParser::get_value(const char *name, int *value) const { cfgVector vec = get_variable(name); if (vec.get_size() > 1) { printf(" CONFIG:> failed to set (int) variable: '%s' -- vector (size > 1)\n", name); return false; } cfgValue var = vec.get(0); cfgValue::VAR_TYPE type = var.get_type(); if (type == cfgValue::IS_INT) return var.get(value); else if (type == cfgValue::IS_DOUBLE) { printf(" CONFIG:> failed to set (int) variable: '%s' - declared as double\n", name); return false; } else if (type == cfgValue::IS_STRING) { printf(" CONFIG:> failed to set (int) variable: '%s' - declared as string\n", name); return false; } else if (type == cfgValue::IS_BOOLEAN) { printf(" CONFIG:> failed to set (int) variable: '%s' - declared as boolean\n", name); return false; } printf(" CONFIG:> failed to set (int) variable: '%s'\n", name); return false; } bool scm::ConfigParser::get_value(const char *name, float *value) const { cfgVector vec = get_variable(name); if (vec.get_size() > 1) { printf(" CONFIG:> failed to set (float) variable: '%s' -- vector (size > 1)\n", name); return false; } cfgValue var = vec.get(0); cfgValue::VAR_TYPE type = var.get_type(); if (type == cfgValue::IS_INT) return var.get(value); else if (type == cfgValue::IS_DOUBLE) return var.get(value); else if (type == cfgValue::IS_STRING) { printf(" CONFIG:> failed to set (float) variable: '%s' - declared as string\n", name); return false; } else if (type == cfgValue::IS_BOOLEAN) { printf(" CONFIG:> failed to set (float) variable: '%s' - declared as boolean\n", name); return false; } printf(" CONFIG:> failed to set (float) variable: '%s' - undefined\n", name); return false; } bool scm::ConfigParser::get_value(const char *name, double *value) const { cfgVector vec = get_variable(name); if (vec.get_size() > 1) { printf(" CONFIG:> failed to set (double) variable: '%s' -- vector (size > 1)\n", name); return false; } cfgValue var = vec.get(0); cfgValue::VAR_TYPE type = var.get_type(); if (type == cfgValue::IS_INT) return var.get(value); else if (type == cfgValue::IS_DOUBLE) return var.get(value); else if (type == cfgValue::IS_STRING) { printf(" CONFIG:> failed to set (double) variable: '%s' - declared as string\n", name); return false; } else if (type == cfgValue::IS_BOOLEAN) { printf(" CONFIG:> failed to set (double) variable: '%s' - declared as boolean\n", name); return false; } printf(" CONFIG:> failed to set (double) variable: '%s' - undefined\n", name); return false; } bool scm::ConfigParser::get_value(const char *name, long double *value) const { cfgVector vec = get_variable(name); if (vec.get_size() > 1) { printf(" CONFIG:> failed to set (double) variable: '%s' -- vector (size > 1)\n", name); return false; } cfgValue var = vec.get(0); cfgValue::VAR_TYPE type = var.get_type(); if (type == cfgValue::IS_INT) var.get(value); else if (type == cfgValue::IS_DOUBLE) var.get(value); else if (type == cfgValue::IS_STRING) { printf(" CONFIG:> failed to set (double) variable: '%s' - declared as string\n", name); return false; } else if (type == cfgValue::IS_BOOLEAN) { printf(" CONFIG:> failed to set (double) variable: '%s' - declared as boolean\n", name); return false; } printf(" CONFIG:> failed to set (double) variable: '%s' - undefined\n", name); return false; } bool scm::ConfigParser::get_value(const char *name, char **value) const { cfgVector vec = get_variable(name); if (vec.get_size() > 1) { printf(" CONFIG:> failed to set (string) variable: '%s' -- vector (size > 1)\n", name); return false; } cfgValue var = vec.get(0); cfgValue::VAR_TYPE type = var.get_type(); if (type == cfgValue::IS_INT) { printf(" CONFIG:> failed to set (string) variable: '%s' - declared as int\n", name); return false; } else if (type == cfgValue::IS_DOUBLE) { printf(" CONFIG:> failed to set (string) variable: '%s' - declared as double\n", name); return false; } else if (type == cfgValue::IS_STRING) return var.get(value); else if (type == cfgValue::IS_BOOLEAN) { printf(" CONFIG:> failed to set (string) variable: '%s' - declared as boolean\n", name); return false; } printf(" CONFIG:> failed to set (string) variable: '%s' - undefined\n", name); return false; } bool scm::ConfigParser::get_value(const char *name, std::string &value) const { cfgVector vec = get_variable(name); if (vec.get_size() > 1) { printf(" CONFIG:> failed to set (string) variable: '%s' -- vector (size > 1)\n", name); return false; } cfgValue var = vec.get(0); cfgValue::VAR_TYPE type = var.get_type(); if (type == cfgValue::IS_INT) { printf(" CONFIG:> failed to set (string) variable: '%s' - declared as int\n", name); return false; } else if (type == cfgValue::IS_DOUBLE) { printf(" CONFIG:> failed to set (string) variable: '%s' - declared as double\n", name); return false; } else if (type == cfgValue::IS_STRING) return var.get(value); else if (type == cfgValue::IS_BOOLEAN) { printf(" CONFIG:> failed to set (string) variable: '%s' - declared as boolean\n", name); return false; } printf(" CONFIG:> failed to set (string) variable: '%s' - undefined\n", name); return false; } bool scm::ConfigParser::get_value(const char *name, bool *value) const { cfgVector vec = get_variable(name); if (vec.get_size() > 1) { printf(" CONFIG:> failed to set (bool) variable: '%s' -- vector (size > 1)\n", name); return false; } cfgValue var = vec.get(0); cfgValue::VAR_TYPE type = var.get_type(); if (type == cfgValue::IS_INT) { printf(" CONFIG:> failed to set (bool) variable: '%s' - declared as int\n", name); return false; } else if (type == cfgValue::IS_DOUBLE) { printf(" CONFIG:> failed to set (bool) variable: '%s' - declared as double\n", name); return false; } else if (type == cfgValue::IS_STRING) { printf(" CONFIG:> failed to set (bool) variable: '%s' - declared as string\n", name); return false; } else if (type == cfgValue::IS_BOOLEAN) return var.get(value); printf(" CONFIG:> failed to set (bool) variable: '%s'\n", name); return false; } // -------------------------------------------------------------------------------------------- //