From 0193d490b88bba3b8eedfb1d1ac8e2157ed9e4ca Mon Sep 17 00:00:00 2001
From: Lizzzka007 <gashchuk2011@mail.ru>
Date: Thu, 21 Dec 2023 01:16:00 +0300
Subject: [PATCH] Add parser

---
 CMakeLists.txt           |    5 +
 parser/CMakeLists.txt    |   54 +
 parser/call_parser.F90   |   87 ++
 parser/call_parser.c     |   38 +
 parser/call_parser.cpp   |   78 ++
 parser/call_parser.h     |   20 +
 parser/cfg-cmd.cpp       |  157 +++
 parser/cfg-cmd.h         |   70 ++
 parser/cfg-value.cpp     | 1092 +++++++++++++++++
 parser/cfg-value.h       |  140 +++
 parser/cfg-vec.cpp       |  816 +++++++++++++
 parser/cfg-vec.h         |  146 +++
 parser/config-parser.cpp | 2382 ++++++++++++++++++++++++++++++++++++++
 parser/config-parser.h   |  191 +++
 parser/io-guts.cpp       |  152 +++
 parser/io-guts.h         |   39 +
 parser/lexeme-list.cpp   |  159 +++
 parser/lexeme-list.h     |   71 ++
 parser/lexeme-parser.cpp |  604 ++++++++++
 parser/lexeme-parser.h   |   49 +
 parser/lexeme.cpp        |  173 +++
 parser/lexeme.h          |  112 ++
 parser/mem-buffer.h      |  148 +++
 parser/scm-mem.h         |  523 +++++++++
 parser/scm-sys.h         |   50 +
 25 files changed, 7356 insertions(+)
 create mode 100644 parser/CMakeLists.txt
 create mode 100644 parser/call_parser.F90
 create mode 100644 parser/call_parser.c
 create mode 100644 parser/call_parser.cpp
 create mode 100644 parser/call_parser.h
 create mode 100644 parser/cfg-cmd.cpp
 create mode 100644 parser/cfg-cmd.h
 create mode 100644 parser/cfg-value.cpp
 create mode 100644 parser/cfg-value.h
 create mode 100644 parser/cfg-vec.cpp
 create mode 100644 parser/cfg-vec.h
 create mode 100644 parser/config-parser.cpp
 create mode 100644 parser/config-parser.h
 create mode 100644 parser/io-guts.cpp
 create mode 100644 parser/io-guts.h
 create mode 100644 parser/lexeme-list.cpp
 create mode 100644 parser/lexeme-list.h
 create mode 100644 parser/lexeme-parser.cpp
 create mode 100644 parser/lexeme-parser.h
 create mode 100644 parser/lexeme.cpp
 create mode 100644 parser/lexeme.h
 create mode 100644 parser/mem-buffer.h
 create mode 100644 parser/scm-mem.h
 create mode 100644 parser/scm-sys.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3a846f6..0261993 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -132,9 +132,14 @@ if(INCLUDE_CXX OR INCLUDE_CUDA)
     set(CMAKE_CUDA_FLAGS " -g ")
 endif(INCLUDE_CXX OR INCLUDE_CUDA)
 
+add_subdirectory(parser/)
+
 add_executable(drag ${SOURCES})
 add_definitions(${RUN_MACRO})
 set_property(TARGET drag PROPERTY LINKER_LANGUAGE Fortran)
+target_include_directories(drag PUBLIC ${CMAKE_BINARY_DIR}/modules/)
+target_link_libraries(drag parser_F parser_CXX)
+
 
 #copy data on post build
 add_custom_command(
diff --git a/parser/CMakeLists.txt b/parser/CMakeLists.txt
new file mode 100644
index 0000000..da342d4
--- /dev/null
+++ b/parser/CMakeLists.txt
@@ -0,0 +1,54 @@
+cmake_minimum_required(VERSION 3.0)
+
+# option(INCLUDE_CXX  "CXX build in mode"    OFF)
+
+project(Pars)
+
+enable_language(Fortran)
+enable_language(C)
+enable_language(CXX)
+set(CMAKE_CXX_STANDARD 11)
+
+set(SOURCES_CXX 
+    call_parser.cpp
+    cfg-cmd.cpp  
+    cfg-value.cpp  
+    cfg-vec.cpp   
+    config-parser.cpp  
+    lexeme.cpp 
+    lexeme-list.cpp    
+    io-guts.cpp
+    lexeme-parser.cpp
+)
+set(HEADERS_CXX 
+    call_parser.h
+    cfg-cmd.h
+    cfg-value.h
+    cfg-vec.h
+    config-parser.h
+    lexeme.h  
+    lexeme-list.h
+    scm-mem.h  
+    scm-sys.h
+    io-guts.h
+    mem-buffer.h
+    lexeme-parser.h
+)
+
+set(SOURCES_C
+    call_parser.c
+)
+
+set(SOURCES_F
+    call_parser.F90
+)
+
+set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/modules)
+
+set(SOURCES_CXX ${SOURCES_CXX} ${SOURCES_C})
+set(HEADERS_CXX ${HEADERS_CXX})
+
+add_library(parser_CXX STATIC ${HEADERS_CXX} ${SOURCES_CXX})
+add_library(parser_F STATIC   ${SOURCES_F})
+set_property(TARGET parser_F PROPERTY LINKER_LANGUAGE Fortran)
+target_link_libraries(parser_F parser_CXX)
diff --git a/parser/call_parser.F90 b/parser/call_parser.F90
new file mode 100644
index 0000000..a662050
--- /dev/null
+++ b/parser/call_parser.F90
@@ -0,0 +1,87 @@
+! module C_FUNC_SUB
+!     contains 
+
+!     INTEGER function get_char_len(name) BIND(C)
+!         USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_CHAR
+!         IMPLICIT NONE
+!         CHARACTER (KIND=C_CHAR),    intent(in)    :: name(*)
+!     end function get_char_len
+    
+! end module C_FUNC_SUB
+
+module PARSER_C_FUNC
+
+    INTERFACE
+        SUBROUTINE run(filename) BIND(C)
+            USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_CHAR
+            IMPLICIT NONE
+            CHARACTER (KIND=C_CHAR),  intent(in)  :: filename(*)
+        END SUBROUTINE run
+
+        SUBROUTINE get_int(name, value) BIND(C)
+            USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_CHAR, C_INT
+            IMPLICIT NONE
+            CHARACTER (KIND=C_CHAR),  intent(in)    :: name(*)
+            INTEGER   (KIND=C_INT),   intent(out)   :: value
+        END SUBROUTINE get_int
+
+        SUBROUTINE get_float(name, value) BIND(C)
+            USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_CHAR, C_FLOAT
+            IMPLICIT NONE
+            CHARACTER (KIND=C_CHAR),    intent(in)    :: name(*)
+            REAL      (KIND=C_FLOAT),   intent(out)   :: value
+        END SUBROUTINE get_float
+
+        SUBROUTINE get_double(name, value) BIND(C)
+            USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_CHAR, C_DOUBLE
+            IMPLICIT NONE
+            CHARACTER (KIND=C_CHAR),    intent(in)    :: name(*)
+            REAL      (KIND=C_DOUBLE),  intent(out)   :: value
+        END SUBROUTINE get_double
+
+        ! TODO:
+        SUBROUTINE get_char_len(name, len) BIND(C)
+            USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_CHAR, C_INT
+            IMPLICIT NONE
+            CHARACTER (KIND=C_CHAR),    intent(in)    :: name(*)
+            INTEGER   (KIND=C_INT),     intent(out)   :: len
+        END SUBROUTINE get_char_len
+
+        SUBROUTINE get_charc(name, value) BIND(C)
+            USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_CHAR
+            IMPLICIT NONE
+            CHARACTER (KIND=C_CHAR),    intent(in)    :: name(*)
+            CHARACTER (KIND=C_CHAR),    intent(out)   :: value(*)
+        END SUBROUTINE get_charc
+
+    END INTERFACE  
+end module PARSER_C_FUNC
+
+! TODO:
+
+SUBROUTINE get_char_lenf(name, len) 
+    USE PARSER_C_FUNC
+
+    IMPLICIT NONE
+    CHARACTER, intent(in) :: name(*)
+    INTEGER, intent(out)  :: len
+
+    call get_char_len(name, len)
+END SUBROUTINE get_char_lenf
+
+SUBROUTINE get_charf(name, char_value) 
+    USE PARSER_C_FUNC
+
+    IMPLICIT NONE
+    CHARACTER, allocatable, intent(OUT) :: char_value(:)
+
+    CHARACTER, intent(in) :: name(*)
+    INTEGER :: len
+
+    call get_char_lenf(name, len)
+    
+    write(*, *) 'len = ', len
+
+    ! IF(ALLOCATED(char_value)) DEALLOCATE(char_value)
+    ! allocate(char_value(4))
+END SUBROUTINE get_charf
\ No newline at end of file
diff --git a/parser/call_parser.c b/parser/call_parser.c
new file mode 100644
index 0000000..109668d
--- /dev/null
+++ b/parser/call_parser.c
@@ -0,0 +1,38 @@
+#include "call_parser.h"
+#include <stdio.h>
+#include "ISO_Fortran_binding.h"
+
+int run(const char* filename)
+{
+    return runCXX(filename);
+}
+
+int get_int(const char* name, int* value)
+{
+    return get_intCXX(name, value);
+}
+
+int get_float(const char* name, float* value)
+{
+    return get_floatCXX(name, value);
+}
+
+int get_double(const char* name, double* value)
+{
+    return get_doubleCXX(name, value);
+}
+
+int get_charc(const char* name, char* value) 
+{
+    return get_charCXX(name, value);
+}
+
+void get_char_len(const char* name, int *len) 
+{
+    *len =  get_char_lenCXX(name);
+}
+
+// int get_bool(const char* name, bool* value) 
+// {
+//     return get_valueCXX(name, value);
+// }
\ No newline at end of file
diff --git a/parser/call_parser.cpp b/parser/call_parser.cpp
new file mode 100644
index 0000000..d08a0b9
--- /dev/null
+++ b/parser/call_parser.cpp
@@ -0,0 +1,78 @@
+#include "call_parser.h"
+#include "config-parser.h"
+#include <string>
+
+static scm::ConfigParser Parser;
+
+#ifdef __cplusplus
+extern "C" {  
+#endif  
+
+    int runCXX(const char* filename)
+    {
+        bool res = Parser.run(filename);
+
+        if(res == false) return 0;
+        return 1;
+    }
+
+    int get_intCXX(const char* name, int* value)
+    {
+        bool res = Parser.get_value(name, value);
+
+        if(res == false) return 0;
+        return 1;
+    }
+
+    int get_floatCXX(const char* name, float* value)
+    {
+        bool res = Parser.get_value(name, value);
+
+        if(res == false) return 0;
+        return 1;
+    }
+
+    int get_doubleCXX(const char* name, double* value)
+    {
+        bool res = Parser.get_value(name, value);
+
+        if(res == false) return 0;
+        return 1;
+    }
+
+    int get_char_lenCXX(const char* name) 
+    {
+        std::string target_res;
+        bool res = Parser.get_value(name, target_res);
+
+        return target_res.size();
+    }
+
+    int get_charCXX(const char* name, char* value) 
+    {
+        std::string target_res;
+        bool res = Parser.get_value(name, target_res);
+
+        printf("target_res = %s, len = %d\n", target_res.c_str(), target_res.size());
+
+        const int n = target_res.size();
+
+        for (int i = 0; i < n; i++)
+            value[i] = target_res[i];
+
+        if(res == false) return 0;
+        return 1;
+    }
+
+    // bool get_valueCXX(const char* name, std::string& value) 
+    // {
+    //     return Parser.get_value(name, value);
+    // }
+
+    // bool get_valueCXX(const char* name, bool* value) 
+    // {
+    //     return Parser.get_value(name, value);
+    // }
+#ifdef __cplusplus
+}
+#endif 
\ No newline at end of file
diff --git a/parser/call_parser.h b/parser/call_parser.h
new file mode 100644
index 0000000..567fd60
--- /dev/null
+++ b/parser/call_parser.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {  
+#endif  
+
+    int runCXX(const char* filename);
+    int get_intCXX(const char* name, int* value);
+    int get_floatCXX(const char* name, float* value);
+    int get_doubleCXX(const char* name, double* value);
+    // bool get_valueCXX(const char* name, long double* value);
+
+    int get_char_lenCXX(const char* name);
+    int get_charCXX(const char* name, char* value);
+
+    // bool get_valueCXX(const char* name, bool* value);
+
+#ifdef __cplusplus
+}
+#endif 
diff --git a/parser/cfg-cmd.cpp b/parser/cfg-cmd.cpp
new file mode 100644
index 0000000..1ef0eda
--- /dev/null
+++ b/parser/cfg-cmd.cpp
@@ -0,0 +1,157 @@
+#include "cfg-cmd.h"
+
+#include "scm-mem.h"
+#include <string.h>
+#include <stdio.h>
+
+// -------------------------------------------------------------------------------------------- //
+// * Implementation *
+// -------------------------------------------------------------------------------------------- //
+
+scm::cfgCommand::cfgCommand()
+{
+	nalloc = 0;
+	narg = 0;
+
+	name_memsize = 1;
+	name = new char[name_memsize];
+	*name = '\0';
+}
+
+scm::cfgCommand::~cfgCommand()
+{
+	if (nalloc > 0) delete[] arg;
+	delete[] name;
+
+	narg = 0;
+	nalloc = 0;
+}
+
+scm::cfgCommand::cfgCommand(const cfgCommand& cmd)
+{
+	name_memsize = strlen(cmd.name) + 1;
+	name = new char[name_memsize];
+	strcpy(name, cmd.name);
+
+	narg = cmd.narg;
+	if (narg > 0) {
+		arg = new cfgVector[narg];
+		for (int k = 0; k < narg; k++)
+			arg[k] = cmd.arg[k];
+	}
+
+	nalloc = narg;
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * swap & assignment * //
+// -------------------------------------------------------------------------------------------- //
+const scm::cfgCommand&
+scm::cfgCommand::operator=(cfgCommand cmd)
+{
+	swap(cmd);
+	return (*this);
+}
+
+void scm::cfgCommand::swap(
+	cfgCommand& cmd)
+{
+	scm::swap(narg, cmd.narg);
+	scm::swap(nalloc, cmd.nalloc);
+	scm::swap(arg, cmd.arg);
+
+	scm::swap(name, cmd.name);
+	scm::swap(name_memsize, cmd.name_memsize);
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * add argument * //
+// -------------------------------------------------------------------------------------------- //
+bool scm::cfgCommand::add_arg(const cfgVector& _arg)
+{
+	if (!_arg.is_defined()) return false;
+
+	if (narg == nalloc) {
+
+		cfgVector *arg_list;
+		arg_list = new cfgVector[nalloc + c_nalloc_inc];
+
+		for (int k = 0; k < narg; k++)
+			arg_list[k] = arg[k];
+
+		if (nalloc > 0) delete[] arg;
+		arg = arg_list;
+
+		nalloc += c_nalloc_inc;
+	}
+
+	arg[narg] = _arg;
+	narg++;
+
+	return true;
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * change command name * //
+// -------------------------------------------------------------------------------------------- //
+void scm::cfgCommand::set_name(const char* ex_name)
+{
+	if (ex_name == NULL) return;
+
+	const size_t ex_length = strlen(ex_name) + 1;
+	if (ex_length > name_memsize) {
+		delete[] name;
+
+		name_memsize = ex_length;
+		name = new char[name_memsize];
+	}
+
+	strcpy(name, ex_name);
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * reset command * //
+// -------------------------------------------------------------------------------------------- //
+void scm::cfgCommand::reset()
+{
+	narg = 0;
+	*name = '\0';
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * get & check calls * //
+// -------------------------------------------------------------------------------------------- //
+int scm::cfgCommand::get_narg() const
+{
+	return narg;
+}
+
+scm::cfgVector scm::cfgCommand::get_arg(const int idx) const
+{
+	if ((idx < 0) || (idx >= narg)) return cfgVector();
+	return arg[idx];
+}
+
+bool scm::cfgCommand::is_name_eq(const char* ex_name) const
+{
+	if (ex_name == NULL) return false;
+	return (!strcmp(ex_name, name));
+}
+
+const char* scm::cfgCommand::get_name() const
+{
+	return name;
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * print * //
+// -------------------------------------------------------------------------------------------- //
+void scm::cfgCommand::print() const
+{
+	printf(" > COMMAND '%s', narg = %i\n", name, narg);
+	for (int k = 0; k < narg; k++) {
+		printf(" %i", k);
+		arg[k].print();
+	}
+}
+// -------------------------------------------------------------------------------------------- //
diff --git a/parser/cfg-cmd.h b/parser/cfg-cmd.h
new file mode 100644
index 0000000..77fdad0
--- /dev/null
+++ b/parser/cfg-cmd.h
@@ -0,0 +1,70 @@
+#pragma once
+
+// [cfg-cmd.h]: configurable variable class 'cfgCommand'
+//
+// -------------------------------------------------------------------------------------------- //
+
+#include "cfg-vec.h"
+
+namespace scm
+{
+	class cfgCommand {
+	public:
+
+		// add argument
+		// -------------------------------------------------------------------------------------------- //
+		bool add_arg(const cfgVector& _arg);
+		// -------------------------------------------------------------------------------------------- //
+
+		// change command name
+		// -------------------------------------------------------------------------------------------- //
+		void set_name(const char* _name);
+		// -------------------------------------------------------------------------------------------- //
+		
+		// reset command, narg == 0
+		// -------------------------------------------------------------------------------------------- //
+		void reset();
+		// -------------------------------------------------------------------------------------------- //
+
+		// get & check calls
+		// -------------------------------------------------------------------------------------------- //
+		int get_narg() const;
+		cfgVector get_arg(const int idx) const;
+		
+		bool is_name_eq(const char* ex_name) const;
+
+		const char* get_name() const;
+		// -------------------------------------------------------------------------------------------- //
+
+		// print
+		// -------------------------------------------------------------------------------------------- //
+		void print() const;
+		// -------------------------------------------------------------------------------------------- //
+
+		// swap & assignment
+		// -------------------------------------------------------------------------------------------- //
+		const cfgCommand& operator=(cfgCommand cmd);
+		void swap(cfgCommand& cmd);
+		// -------------------------------------------------------------------------------------------- //
+
+		// -------------------------------------------------------------------------------------------- //
+		cfgCommand();
+		cfgCommand(const cfgCommand& cmd);
+		~cfgCommand();
+		// -------------------------------------------------------------------------------------------- //
+
+	private:
+		// data (private):
+		// -------------------------------------------------------------------------------------------- //
+
+		cfgVector *arg;
+		int narg;
+
+		int nalloc;
+		static const int c_nalloc_inc = 2;
+
+		char* name;
+		size_t name_memsize;
+	};
+}
+// -------------------------------------------------------------------------------------------- //
diff --git a/parser/cfg-value.cpp b/parser/cfg-value.cpp
new file mode 100644
index 0000000..89b6231
--- /dev/null
+++ b/parser/cfg-value.cpp
@@ -0,0 +1,1092 @@
+#include "cfg-value.h"
+
+#define _CRT_SECURE_NO_DEPRECATE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <limits.h>
+
+#include <errno.h>
+
+#include "scm-mem.h"
+#include "io-guts.h"
+
+// -------------------------------------------------------------------------------------------- //
+// * Implementation *
+// -------------------------------------------------------------------------------------------- //
+
+
+// CPP 
+namespace scm {
+
+	// = x^p
+	int ipow(const int x, const int p)
+	{
+		if (p == 0) return 1;
+		if (p == 1) return x;
+
+		int tmp = ipow(x, p / 2);
+		if (p % 2 == 0) return tmp*tmp;
+		else
+			return x*tmp*tmp;
+	}
+}
+
+// -------------------------------------------------------------------------------------------- //
+bool scm::is_integer(const char* token, int* value)
+{
+	const int mode = 10;
+	char* pend;
+
+	if (strlen(token) == 0) return false;
+
+	errno = 0;
+	long lvalue = strtol(token, &pend, mode);
+	if ((errno == ERANGE && (lvalue == LONG_MAX || lvalue == LONG_MIN)) ||
+		(errno != 0 && lvalue == 0)) {
+		return false;
+	}
+	// checking integer bounds //
+	if ((lvalue >= INT_MAX) || (lvalue <= INT_MIN)) return false;
+	if (*pend != '\0') return false;
+
+	*value = (int)lvalue;
+	return true;
+}
+
+bool scm::is_integer(const char* token)
+{
+	int value;
+	return is_integer(token, &value);
+}
+
+bool scm::is_double(const char* token, double* value)
+{
+	char* pend;
+
+	if (strlen(token) == 0) return false;
+
+	errno = 0;
+	*value = strtod(token, &pend);
+	if ((errno == ERANGE && (*value == HUGE_VAL || *value == -HUGE_VAL)) ||
+		(errno != 0 && *value == (double)0)) {
+		return false;
+	}
+
+	if (*pend != '\0') return false;
+	return true;
+}
+
+bool scm::is_double(const char* token)
+{
+	double value;
+	return is_double(token, &value);
+}
+
+bool scm::is_valid_c_name(const char* token)
+{
+	int token_length = (int)strlen(token);
+
+	if (token_length == 0) return false;
+	if ((!isalpha(token[0])) && (token[0] != '_')) return false;
+
+	for (int i = 1; i < token_length; i++) {
+		if ((!isalnum(token[i])) && (token[i] != '_')) return false;
+	}
+
+	return true;
+}
+
+bool scm::is_valid_string(const char* token)
+{
+	int token_length = (int)strlen(token);
+
+	if (token_length <= 1) return false;
+	if ((token[0] != '"') || (token[token_length - 1] != '"')) return false;
+
+	return true;
+}
+
+bool scm::is_boolean(const char* token, bool* value)
+{
+	if (!strcmp(token, "true")) {
+		*value = true;
+		return true;
+	}
+	if (!strcmp(token, "false")) {
+		*value = false;
+		return true;
+	}
+
+	return false;
+}
+
+bool scm::is_boolean(const char* token)
+{
+	bool value;
+	return is_boolean(token, &value);
+}
+
+
+void scm::strcpyrm(char* a, const char* b, const char sym)
+{
+	int i = 0;
+	for (int k = 0; k < (int)strlen(b); k++) {
+		if (b[k] == sym) continue;
+		a[i] = b[k];
+		i++;
+	}
+	a[i] = '\0';
+}
+// -------------------------------------------------------------------------------------------- //
+
+
+// -------------------------------------------------------------------------------------------- //
+// * Implementation *
+// * scm::cfgValue * 
+// -------------------------------------------------------------------------------------------- //
+
+// -------------------------------------------------------------------------------------------- //
+scm::cfgValue::cfgValue() :
+	type(IS_UNDEF),
+	eint(0), edouble((double)0), estring(NULL), ebool(false)
+{
+}
+
+scm::cfgValue::cfgValue(const int x) :
+	type(IS_INT),
+	eint(x), edouble((double)0), estring(NULL), ebool(false)
+{
+}
+
+scm::cfgValue::cfgValue(const float x) :
+	type(IS_DOUBLE),
+	eint(0), edouble((double)x), estring(NULL), ebool(false)
+{
+}
+
+scm::cfgValue::cfgValue(const double x) :
+	type(IS_DOUBLE),
+	eint(0), edouble(x), estring(NULL), ebool(false)
+{
+}
+
+scm::cfgValue::cfgValue(const long double x) :
+	type(IS_DOUBLE),
+	eint(0), edouble((double)x), estring(NULL), ebool(false)
+{
+}
+
+scm::cfgValue::cfgValue(const char* c_str) :
+	type(IS_STRING),
+	eint(0), edouble((double)0), estring(NULL), ebool(false)
+{
+	estring = new char[strlen(c_str) + 1];
+	strcpy(estring, c_str);
+}
+
+scm::cfgValue::cfgValue(const bool x) :
+	type(IS_BOOLEAN),
+	eint(0), edouble((double)0), estring(NULL), ebool(x)
+{
+}
+
+scm::cfgValue::~cfgValue()
+{
+	clear();
+}
+
+scm::cfgValue::cfgValue(const cfgValue& x)
+{
+	type = x.type;
+
+	if (type == IS_INT) eint = x.eint;
+	else if (type == IS_DOUBLE) edouble = x.edouble;
+	else if (type == IS_BOOLEAN) ebool = x.ebool;
+	else if (type == IS_STRING) 
+	{
+		estring = new char[strlen(x.estring) + 1];
+		strcpy(estring, x.estring);
+	}
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * swap & assignment * //
+// -------------------------------------------------------------------------------------------- //
+const scm::cfgValue&
+scm::cfgValue::operator=(cfgValue x)
+{
+	swap(x);
+	return (*this);
+}
+
+void scm::cfgValue::swap(
+	cfgValue& x)
+{
+	scm::swap(type, x.type);
+	scm::swap(eint, x.eint);
+	scm::swap(edouble, x.edouble);
+	scm::swap(estring, x.estring);
+	scm::swap(ebool, x.ebool);
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * make implicit value * //
+// -------------------------------------------------------------------------------------------- //
+scm::cfgValue scm::cfgValue::make_implicit(const char* value_in_string)
+{
+	cfgValue x;
+
+	if (is_integer(value_in_string, &x.eint)) 
+		x.type = IS_INT;
+	else if (is_double(value_in_string, &x.edouble)) 
+		x.type = IS_DOUBLE;
+	else if (is_boolean(value_in_string, &x.ebool))
+		x.type = IS_BOOLEAN;
+	else if (is_valid_string(value_in_string))
+	{
+		x.type = IS_STRING;
+		x.estring = new char[strlen(value_in_string) + 1];
+		strcpyrm(x.estring, value_in_string, '"');
+	}
+
+	return x;
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * clear * //
+// -------------------------------------------------------------------------------------------- //
+void scm::cfgValue::clear()
+{
+	if (type == IS_STRING) {
+		delete[] estring;
+		estring = NULL;
+	}
+
+	type = IS_UNDEF;
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * get and check calls * //
+// -------------------------------------------------------------------------------------------- //
+bool scm::cfgValue::get(int* x) const
+{
+	if (type == IS_INT) {
+		(*x) = eint;
+		return true;
+	}
+
+	return false;
+}
+
+bool scm::cfgValue::get(float* x) const
+{
+	if (type == IS_DOUBLE) {
+		(*x) = (float)edouble;
+		return true;
+	}
+	if (type == IS_INT) {
+		(*x) = (float)eint;
+		return true;
+	}
+
+	return false;
+}
+
+bool scm::cfgValue::get(double* x) const
+{
+	if (type == IS_DOUBLE) {
+		(*x) = edouble;
+		return true;
+	}
+	if (type == IS_INT) {
+		(*x) = (double)eint;
+		return true;
+	}
+
+	return false;
+}
+
+bool scm::cfgValue::get(long double* x) const
+{
+	if (type == IS_DOUBLE) {
+		(*x) = (long double)edouble;
+		return true;
+	}
+	if (type == IS_INT) {
+		(*x) = (long double)eint;
+		return true;
+	}
+
+	return false;
+}
+
+bool scm::cfgValue::get(char** c_str) const
+{
+	if (type == IS_STRING) {
+		(*c_str) = new char[strlen(estring) + 1];
+		strcpy(*c_str, estring);
+		return true;
+	}
+
+	return false;
+}
+
+bool scm::cfgValue::get(std::string& x) const
+{
+	if (type == IS_STRING) {
+		x = std::string(estring);
+		return true;
+	}
+
+	return false;
+}
+
+bool scm::cfgValue::get(bool* x) const
+{
+	if (type == IS_BOOLEAN) {
+		(*x) = ebool;
+		return true;
+	}
+
+	return false;
+}
+
+scm::cfgValue::VAR_TYPE scm::cfgValue::get_type() const 
+{
+	return type;
+}
+
+bool scm::cfgValue::is_defined() const
+{
+	return (type != IS_UNDEF);
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * print * //
+// -------------------------------------------------------------------------------------------- //
+void scm::cfgValue::print() const
+{
+	print(stdout);
+}
+
+void scm::cfgValue::print(FILE *ptr) const
+{
+	if (type == IS_INT)
+		fprintf(ptr, "%i", eint);
+	else if (type == IS_DOUBLE)
+		fprintf(ptr, "%f", edouble);
+	else if (type == IS_BOOLEAN)
+		fprintf(ptr, "%s", ebool ? "true" : "false");
+	else if (type == IS_STRING)
+		fprintf(ptr, "%s", estring);
+	else
+		fprintf(ptr, "(UNDEFINED)");
+}
+
+void scm::cfgValue::print_typed() const
+{
+	if (type == IS_INT)
+		printf("(INT) %i", eint);
+	else if (type == IS_DOUBLE)
+		printf("(DOUBLE) %f", edouble);
+	else if (type == IS_BOOLEAN)
+		printf("(BOOLEAN) %s", ebool ? "true" : "false");
+	else if (type == IS_STRING)
+		printf("(STRING) %s", estring);
+	else 
+		printf("(UNDEFINED)");
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * operators * //
+// -------------------------------------------------------------------------------------------- //
+scm::cfgValue& scm::cfgValue::operator+=(const cfgValue& x)
+{
+	// (int) += (int)
+	// (int) += (double) + conversion to (double)
+	// (double) += (double)
+	// (double) += (int)
+	// (string) += (string)
+	if ((type == IS_INT) && (x.type == IS_INT))
+		eint += x.eint;
+	else if ((type == IS_INT) && (x.type == IS_DOUBLE))
+	{
+		edouble = (double)eint + x.edouble;
+		type = IS_DOUBLE;
+	}
+	else if ((type == IS_DOUBLE) && (x.type == IS_DOUBLE))
+		edouble += x.edouble;
+	else if ((type == IS_DOUBLE) && (x.type == IS_INT))
+		edouble += (double)x.eint;
+	else if ((type == IS_STRING) && (x.type == IS_STRING))
+	{
+		const size_t length = strlen(estring) + strlen(x.estring) + 1;
+		char *buf = new char[length];
+
+		strcpy(buf, estring);
+		strcat(buf, x.estring);
+
+		delete[] estring;
+		estring = buf;
+	}
+	else
+	{
+		clear();	// type:= IS_UNDEF
+	}
+
+	return (*this);
+}
+
+scm::cfgValue& scm::cfgValue::operator-=(const cfgValue& x)
+{
+	// (int) -= (int)
+	// (int) -= (double) + conversion to (double)
+	// (double) -= (double)
+	// (double) -= (int)
+	if ((type == IS_INT) && (x.type == IS_INT))
+		eint -= x.eint;
+	else if ((type == IS_INT) && (x.type == IS_DOUBLE))
+	{
+		edouble = (double)eint - x.edouble;
+		type = IS_DOUBLE;
+	}
+	else if ((type == IS_DOUBLE) && (x.type == IS_DOUBLE))
+		edouble -= x.edouble;
+	else if ((type == IS_DOUBLE) && (x.type == IS_INT))
+		edouble -= (double)x.eint;
+	else
+	{
+		clear();	// type:= IS_UNDEF
+	}
+
+	return (*this);
+}
+
+scm::cfgValue& scm::cfgValue::operator*=(const cfgValue& x)
+{
+	// (int) *= (int)
+	// (int) *= (double) + conversion to (double)
+	// (double) *= (double)
+	// (double) *= (int)
+	if ((type == IS_INT) && (x.type == IS_INT))
+		eint *= x.eint;
+	else if ((type == IS_INT) && (x.type == IS_DOUBLE))
+	{
+		edouble = (double)eint * x.edouble;
+		type = IS_DOUBLE;
+	}
+	else if ((type == IS_DOUBLE) && (x.type == IS_DOUBLE))
+		edouble *= x.edouble;
+	else if ((type == IS_DOUBLE) && (x.type == IS_INT))
+		edouble *= (double)x.eint;
+	else
+	{
+		clear();	// type:= IS_UNDEF
+	}
+
+	return (*this);
+}
+
+scm::cfgValue& scm::cfgValue::operator/=(const cfgValue& x)
+{
+	// (int) /= (int)
+	// (int) /= (double) + conversion to (double)
+	// (double) /= (double)
+	// (double) /= (int)
+	if ((type == IS_INT) && (x.type == IS_INT))
+		eint /= x.eint;
+	else if ((type == IS_INT) && (x.type == IS_DOUBLE))
+	{
+		edouble = (double)eint / x.edouble;
+		type = IS_DOUBLE;
+	}
+	else if ((type == IS_DOUBLE) && (x.type == IS_DOUBLE))
+		edouble /= x.edouble;
+	else if ((type == IS_DOUBLE) && (x.type == IS_INT))
+		edouble /= (double)x.eint;
+	else
+	{
+		clear();	// type:= IS_UNDEF
+	}
+
+	return (*this);
+}
+
+scm::cfgValue& scm::cfgValue::operator%=(const cfgValue& x)
+{
+	// int %= (int)
+	if ((type == IS_INT) && (x.type == IS_INT))
+		eint %= x.eint;
+	else
+	{
+		clear();	// type:= IS_UNDEF
+	}
+
+	return (*this);
+}
+
+scm::cfgValue& scm::cfgValue::operator^=(const cfgValue& x)
+{
+	// (int) ^= (int)
+	// (int) ^= (double) + conversion to (double)
+	// (double) ^= (double)
+	// (double) ^= (int)
+	if ((type == IS_INT) && (x.type == IS_INT))
+		eint = ipow(eint, x.eint);
+	else if ((type == IS_INT) && (x.type == IS_DOUBLE))
+	{
+		edouble = pow((double)eint, x.edouble);
+		type = IS_DOUBLE;
+	}
+	else if ((type == IS_DOUBLE) && (x.type == IS_DOUBLE))
+		edouble = pow(edouble, x.edouble);
+	else if ((type == IS_DOUBLE) && (x.type == IS_INT))
+		edouble = pow(edouble, x.eint);
+	else
+	{
+		clear();	// type:= IS_UNDEF
+	}
+
+	return (*this);
+}
+
+// *: check if we should really use const on return (all operators) ->
+const scm::cfgValue 
+scm::cfgValue::operator+(const cfgValue& x) const
+{
+	return cfgValue(*this) += x;
+}
+
+const scm::cfgValue
+scm::cfgValue::operator-(const cfgValue& x) const
+{
+	return cfgValue(*this) -= x;
+}
+
+const scm::cfgValue
+scm::cfgValue::operator*(const cfgValue& x) const
+{
+	return cfgValue(*this) *= x;
+}
+
+const scm::cfgValue
+scm::cfgValue::operator/(const cfgValue& x) const
+{
+	return cfgValue(*this) /= x;
+}
+
+const scm::cfgValue
+scm::cfgValue::operator%(const cfgValue& x) const
+{
+	return cfgValue(*this) %= x;
+}
+
+const scm::cfgValue
+scm::cfgValue::operator^(const cfgValue& x) const
+{
+	return cfgValue(*this) ^= x;
+}
+
+const scm::cfgValue
+scm::cfgValue::operator==(const cfgValue& x) const
+{
+	cfgValue res;
+
+	if (type == IS_INT) 
+	{
+		if (x.type == IS_INT) 
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (eint == x.eint);
+		}
+		else if (x.type == IS_DOUBLE) 
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (eint == x.edouble);
+		}
+		else if (x.type == IS_BOOLEAN) 
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (eint == (int)x.ebool);
+		}
+	}
+	else if (type == IS_DOUBLE) 
+	{
+		if (x.type == IS_INT)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (edouble == x.eint);
+		}
+		else if (x.type == IS_DOUBLE)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (edouble == x.edouble);
+		}
+		else if (x.type == IS_BOOLEAN)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (edouble == (int)x.ebool);
+		}
+	}
+	else if (type == IS_BOOLEAN)
+	{
+		if (x.type == IS_INT)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = ((int)ebool == x.eint);
+		}
+		else if (x.type == IS_DOUBLE)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = ((int)ebool == x.edouble);
+		}
+		else if (x.type == IS_BOOLEAN)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (ebool == x.ebool);
+		}
+	}
+	else if (type == IS_STRING)
+	{
+		if (x.type == IS_STRING)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (!strcmp(estring, x.estring));
+		}
+	}
+
+	return res;
+}
+
+const scm::cfgValue
+scm::cfgValue::operator!=(const cfgValue& x) const
+{
+	cfgValue res = ((*this) == x);
+	if (res.type == IS_BOOLEAN) res.ebool = (!res.ebool);
+	
+	return res;
+}
+
+const scm::cfgValue
+scm::cfgValue::operator<(const cfgValue& x) const
+{
+	cfgValue res;
+
+	if (type == IS_INT)
+	{
+		if (x.type == IS_INT)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (eint < x.eint);
+		}
+		else if (x.type == IS_DOUBLE)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (eint < x.edouble);
+		}
+		else if (x.type == IS_BOOLEAN)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (eint < (int)x.ebool);
+		}
+	}
+	else if (type == IS_DOUBLE)
+	{
+		if (x.type == IS_INT)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (edouble < x.eint);
+		}
+		else if (x.type == IS_DOUBLE)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (edouble < x.edouble);
+		}
+		else if (x.type == IS_BOOLEAN)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (edouble < (int)x.ebool);
+		}
+	}
+	else if (type == IS_BOOLEAN)
+	{
+		if (x.type == IS_INT)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = ((int)ebool < x.eint);
+		}
+		else if (x.type == IS_DOUBLE)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = ((int)ebool < x.edouble);
+		}
+		else if (x.type == IS_BOOLEAN)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (ebool < x.ebool);
+		}
+	}
+
+	return res;
+}
+
+const scm::cfgValue
+scm::cfgValue::operator>(const cfgValue& x) const
+{
+	cfgValue res;
+
+	if (type == IS_INT)
+	{
+		if (x.type == IS_INT)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (eint > x.eint);
+		}
+		else if (x.type == IS_DOUBLE)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (eint > x.edouble);
+		}
+		else if (x.type == IS_BOOLEAN)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (eint > (int)x.ebool);
+		}
+	}
+	else if (type == IS_DOUBLE)
+	{
+		if (x.type == IS_INT)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (edouble > x.eint);
+		}
+		else if (x.type == IS_DOUBLE)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (edouble > x.edouble);
+		}
+		else if (x.type == IS_BOOLEAN)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (edouble > (int)x.ebool);
+		}
+	}
+	else if (type == IS_BOOLEAN)
+	{
+		if (x.type == IS_INT)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = ((int)ebool > x.eint);
+		}
+		else if (x.type == IS_DOUBLE)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = ((int)ebool > x.edouble);
+		}
+		else if (x.type == IS_BOOLEAN)
+		{
+			res.type = IS_BOOLEAN;
+			res.ebool = (ebool > x.ebool);
+		}
+	}
+
+	return res;
+}
+
+const scm::cfgValue
+scm::cfgValue::operator<=(const cfgValue& x) const
+{
+	cfgValue res = ((*this) > x);
+	if (res.type == IS_BOOLEAN) res.ebool = (!res.ebool);
+
+	return res;
+}
+
+const scm::cfgValue
+scm::cfgValue::operator>=(const cfgValue& x) const
+{
+	cfgValue res = ((*this) < x);
+	if (res.type == IS_BOOLEAN) res.ebool = (!res.ebool);
+
+	return res;
+}
+
+const scm::cfgValue
+scm::cfgValue::operator-() const
+{
+	// -(int)
+	// -(double)
+	cfgValue x;	// default: type:= IS_UNDEF
+
+	if (type == IS_INT) {
+		x = (*this);
+		x.eint = -x.eint;
+	}
+	else if (type == IS_DOUBLE) {
+		x = (*this);
+		x.edouble = -x.edouble;
+	}
+
+	return x;
+}
+
+const scm::cfgValue
+scm::cfgValue::operator+() const
+{
+	// +(int)
+	// +(double)
+	cfgValue x;	// default: type:= IS_UNDEF
+
+	if (type == IS_INT) x = (*this);
+	else if (type == IS_DOUBLE) x = (*this);
+
+	return x;
+}
+
+const scm::cfgValue
+scm::cfgValue::logical_and(const cfgValue& x) const
+{
+	cfgValue res;
+
+	if ((type == IS_BOOLEAN) && (x.type == IS_BOOLEAN))
+	{
+		res.type = IS_BOOLEAN;
+		res.ebool = (ebool && x.ebool);
+	}
+
+	return res;
+}
+
+const scm::cfgValue
+scm::cfgValue::logical_or(const cfgValue& x) const
+{
+	cfgValue res;
+
+	if ((type == IS_BOOLEAN) && (x.type == IS_BOOLEAN))
+	{
+		res.type = IS_BOOLEAN;
+		res.ebool = (ebool || x.ebool);
+	}
+
+	return res;
+}
+
+// <-
+//
+// -------------------------------------------------------------------------------------------- //
+
+// * functions * // 
+// -------------------------------------------------------------------------------------------- //
+const scm::cfgValue 
+scm::cfgValue::cfg_sin(const cfgValue& x)
+{
+	// sin(int)
+	// sin(double)
+	cfgValue y;		// default: type:=IS_UNDEF
+
+	if (x.type == IS_DOUBLE) {
+		y.edouble = sin(x.edouble);
+		y.type = IS_DOUBLE;
+	}
+	else if (x.type == IS_INT) {
+		y.edouble = sin((double)x.eint);
+		y.type = IS_DOUBLE;
+	}
+
+	return y;
+}
+
+const scm::cfgValue 
+scm::cfgValue::cfg_cos(const cfgValue& x)
+{
+	// cos(int)
+	// cos(double)
+	cfgValue y;		// default: type:=IS_UNDEF
+
+	if (x.type == IS_DOUBLE) {
+		y.edouble = cos(x.edouble);
+		y.type = IS_DOUBLE;
+	}
+	else if (x.type == IS_INT) {
+		y.edouble = cos((double)x.eint);
+		y.type = IS_DOUBLE;
+	}
+
+	return y;
+}
+
+const scm::cfgValue 
+scm::cfgValue::cfg_tan(const cfgValue& x)
+{
+	// tan(int)
+	// tan(double)
+	cfgValue y;		// default: type:=IS_UNDEF
+
+	if (x.type == IS_DOUBLE) {
+		y.edouble = tan(x.edouble);
+		y.type = IS_DOUBLE;
+	}
+	else if (x.type == IS_INT) {
+		y.edouble = tan((double)x.eint);
+		y.type = IS_DOUBLE;
+	}
+
+	return y;
+}
+
+const scm::cfgValue 
+scm::cfgValue::cfg_log(const cfgValue& x)
+{
+	// log(int)
+	// log(double)
+	cfgValue y;		// default: type:=IS_UNDEF
+
+	if (x.type == IS_DOUBLE) {
+		y.edouble = log(x.edouble);
+		y.type = IS_DOUBLE;
+	}
+	else if (x.type == IS_INT) {
+		y.edouble = log((double)x.eint);
+		y.type = IS_DOUBLE;
+	}
+
+	return y;
+}
+
+const scm::cfgValue 
+scm::cfgValue::cfg_sqrt(const cfgValue& x)
+{
+	// sqrt(int)
+	// sqrt(double)
+	cfgValue y;		// default: type:=IS_UNDEF
+
+	if (x.type == IS_DOUBLE) {
+		y.edouble = sqrt(x.edouble);
+		y.type = IS_DOUBLE;
+	}
+	else if (x.type == IS_INT) {
+		y.edouble = sqrt((double)x.eint);
+		y.type = IS_DOUBLE;
+	}
+
+	return y;
+}
+
+const scm::cfgValue 
+scm::cfgValue::cfg_abs(const cfgValue& x)
+{
+	// sqrt(int)
+	// sqrt(double)
+
+	cfgValue y;		// default: type:=IS_UNDEF
+
+	if (x.type == IS_DOUBLE) {
+		y.edouble = (x.edouble < (double)0) ?
+			-x.edouble : x.edouble;
+		y.type = IS_DOUBLE;
+	}
+	else if (x.type == IS_INT) {
+		y.eint = (x.eint < 0) ?
+			-x.eint : x.eint;
+		y.type = IS_INT;
+	}
+
+	return y;
+}
+
+const scm::cfgValue 
+scm::cfgValue::cfg_to_string(const cfgValue& x)
+{
+	// string(int)
+	// string(double)
+	// string(string)
+	// string(boolean)
+	cfgValue y;		// default: type:=IS_UNDEF
+
+	if (x.type == IS_INT)
+	{
+		y.type = IS_STRING;
+		std::string val_string = convert_to_string(x.eint);
+		y.estring = new char[strlen(val_string.c_str()) + 1];
+		strcpy(y.estring, val_string.c_str());
+	}
+	else if (x.type == IS_DOUBLE)
+	{
+		y.type = IS_STRING;
+		std::string val_string = convert_to_string(x.edouble);
+		y.estring = new char[strlen(val_string.c_str()) + 1];
+		strcpy(y.estring, val_string.c_str());
+	}
+	else if (x.type == IS_BOOLEAN)
+	{
+		y.type = IS_STRING;
+		std::string val_string;
+		val_string = (x.ebool) ? "true" : "false";
+		y.estring = new char[strlen(val_string.c_str()) + 1];
+		strcpy(y.estring, val_string.c_str());
+	}
+	else if (x.type == IS_STRING) y = x;
+
+	return y;
+}
+
+const scm::cfgValue 
+scm::cfgValue::cfg_min(const cfgValue& a, const cfgValue& b)
+{
+	// min(int, int)
+	// min(double, double)
+	// min(int, double)
+	// min(double, int)
+	cfgValue _min;		// default: type:=IS_UNDEF
+
+	if ((a.type == IS_DOUBLE) && (b.type == IS_DOUBLE))
+		_min = (a.edouble < b.edouble) ? a : b;
+	else if ((a.type == IS_DOUBLE) && (b.type == IS_INT)) 
+	{
+		_min.edouble = (a.edouble < (double)b.eint) ?
+			a.edouble : (double)b.eint;
+		_min.type = IS_DOUBLE;
+	}
+	else if ((a.type == IS_INT) && (b.type == IS_DOUBLE)) 
+	{
+		_min.edouble = ((double)a.eint < b.edouble) ?
+			(double)a.eint : b.edouble;
+		_min.type = IS_DOUBLE;
+	}
+	else if ((a.type == IS_INT) && (b.type == IS_INT)) 
+		_min = (a.eint < b.eint) ? a : b;
+
+	return _min;
+}
+
+const scm::cfgValue 
+scm::cfgValue::cfg_max(const cfgValue& a, const cfgValue& b)
+{
+	// max(int, int)
+	// max(double, double)
+	// max(int, double)
+	// max(double, int)
+	cfgValue _max;		// default: type:=IS_UNDEF
+
+	if ((a.type == IS_DOUBLE) && (b.type == IS_DOUBLE))
+		_max = (a.edouble > b.edouble) ? a : b;
+	else if ((a.type == IS_DOUBLE) && (b.type == IS_INT))
+	{
+		_max.edouble = (a.edouble > (double)b.eint) ?
+			a.edouble : (double)b.eint;
+		_max.type = IS_DOUBLE;
+	}
+	else if ((a.type == IS_INT) && (b.type == IS_DOUBLE))
+	{
+		_max.edouble = ((double)a.eint > b.edouble) ?
+			(double)a.eint : b.edouble;
+		_max.type = IS_DOUBLE;
+	}
+	else if ((a.type == IS_INT) && (b.type == IS_INT))
+		_max = (a.eint > b.eint) ? a : b;
+
+	return _max;
+}
+// -------------------------------------------------------------------------------------------- //
diff --git a/parser/cfg-value.h b/parser/cfg-value.h
new file mode 100644
index 0000000..9479a5b
--- /dev/null
+++ b/parser/cfg-value.h
@@ -0,0 +1,140 @@
+#pragma once
+
+// [cfg-var.h]: 
+// -------------------------------------------------------------------------------------------- //
+// configurable variable class 'cfgValue'
+// -------------------------------------------------------------------------------------------- //
+
+#define _CRT_SECURE_NO_WARNINGS
+#include <string>
+
+
+namespace scm
+{
+	bool is_integer(const char* token, int* value);
+	bool is_integer(const char* token);
+
+	bool is_double(const char* token, double* value);
+	bool is_double(const char* token);
+
+	bool is_valid_c_name(const char* token);
+	bool is_valid_string(const char* string);
+
+	bool is_boolean(const char* token, bool* value);
+	bool is_boolean(const char* token);
+
+	// --- copy a = b and remove [sym]
+	void strcpyrm(char* a, const char* b, const char sym);
+	// -------------------------------------------------------------------------------------------- //
+
+	class cfgValue {
+	public:
+
+		enum VAR_TYPE { IS_UNDEF, IS_INT, IS_DOUBLE, IS_STRING, IS_BOOLEAN };
+
+		// -------------------------------------------------------------------------------------------- //
+		cfgValue();
+		cfgValue(const int x);
+		cfgValue(const float x);
+		cfgValue(const double x);
+		cfgValue(const long double x);
+		cfgValue(const char* c_str);
+		cfgValue(const bool x);
+		~cfgValue();
+		// -------------------------------------------------------------------------------------------- //
+
+		// -------------------------------------------------------------------------------------------- //
+		cfgValue(const cfgValue& x);
+		const cfgValue& operator=(cfgValue x);
+		void swap(cfgValue& x);
+		// -------------------------------------------------------------------------------------------- //
+
+		// --- assuming that string should be in double quotation marks ""
+		static cfgValue make_implicit(const char* x_in_string);
+		// -------------------------------------------------------------------------------------------- //
+
+		// clear --> type = IS_UNDEF
+		// -------------------------------------------------------------------------------------------- //
+		void clear();
+		// -------------------------------------------------------------------------------------------- //
+
+		// get & check calls
+		// -------------------------------------------------------------------------------------------- //
+		bool get(int* x) const;
+		bool get(float* x) const;
+		bool get(double* x) const;
+		bool get(long double* x) const;
+		bool get(char** c_str) const;
+		bool get(std::string& x) const;
+		bool get(bool* x) const;
+
+		VAR_TYPE get_type() const;
+
+		// : type != IS_UNDEF
+		bool is_defined() const;	
+		// -------------------------------------------------------------------------------------------- //
+
+		// print
+		// -------------------------------------------------------------------------------------------- //
+		void print(FILE *ptr) const;
+		void print() const;
+		void print_typed() const;
+		// -------------------------------------------------------------------------------------------- //
+
+		// operators
+		// -------------------------------------------------------------------------------------------- //
+		cfgValue& operator+=(const cfgValue& x);
+		cfgValue& operator-=(const cfgValue& x);
+		cfgValue& operator*=(const cfgValue& x);
+		cfgValue& operator/=(const cfgValue& x);
+		cfgValue& operator%=(const cfgValue& x);
+		cfgValue& operator^=(const cfgValue& x);
+
+		const cfgValue operator+(const cfgValue& x) const;
+		const cfgValue operator-(const cfgValue& x) const;
+		const cfgValue operator*(const cfgValue& x) const;
+		const cfgValue operator/(const cfgValue& x) const;
+		const cfgValue operator%(const cfgValue& x) const;
+		const cfgValue operator^(const cfgValue& x) const;
+
+		const cfgValue operator==(const cfgValue& x) const;
+		const cfgValue operator!=(const cfgValue& x) const;
+		const cfgValue operator<(const cfgValue& x) const;
+		const cfgValue operator>(const cfgValue& x) const;
+		const cfgValue operator<=(const cfgValue& x) const;
+		const cfgValue operator>=(const cfgValue& x) const;
+
+		const cfgValue operator-() const;
+		const cfgValue operator+() const;
+
+		const cfgValue logical_and(const cfgValue& x) const;	// no short-circuit
+		const cfgValue logical_or(const cfgValue& y) const;		// no short-circuit
+		// -------------------------------------------------------------------------------------------- //
+
+		// functions 
+		// -------------------------------------------------------------------------------------------- //
+		static const cfgValue cfg_sin(const cfgValue& x);
+		static const cfgValue cfg_cos(const cfgValue& x);
+		static const cfgValue cfg_tan(const cfgValue& x);
+		static const cfgValue cfg_log(const cfgValue& x);
+		static const cfgValue cfg_sqrt(const cfgValue& x);
+		static const cfgValue cfg_abs(const cfgValue& x);
+		static const cfgValue cfg_to_string(const cfgValue& x);
+
+		static const cfgValue cfg_min(const cfgValue& a, const cfgValue& b);
+		static const cfgValue cfg_max(const cfgValue& a, const cfgValue& b);
+		// -------------------------------------------------------------------------------------------- //
+
+	private:
+		// data (private):
+		// -------------------------------------------------------------------------------------------- //
+
+		VAR_TYPE type;
+
+		int eint;
+		double edouble;
+		char *estring;
+		bool ebool;
+	};
+}
+// -------------------------------------------------------------------------------------------- //
diff --git a/parser/cfg-vec.cpp b/parser/cfg-vec.cpp
new file mode 100644
index 0000000..0c546d6
--- /dev/null
+++ b/parser/cfg-vec.cpp
@@ -0,0 +1,816 @@
+#include "cfg-vec.h"
+
+#include "scm-mem.h"
+#include <string.h>
+#include <stdio.h>
+
+// -------------------------------------------------------------------------------------------- //
+// * Implementation *
+// -------------------------------------------------------------------------------------------- //
+
+
+scm::cfgVector::cfgVector() :
+	size(0), nalloc(0)
+{
+	name_memsize = 1;
+	name = new char[name_memsize];
+	*name = '\0';
+}
+
+scm::cfgVector::cfgVector(const cfgValue& _value) :
+	size(1), nalloc(1)
+{
+	value = new cfgValue[nalloc];
+	*value = _value;
+
+	name_memsize = 1;
+	name = new char[name_memsize];
+	*name = '\0';
+}
+
+scm::cfgVector::~cfgVector()
+{
+	if (nalloc > 0) delete[] value;
+	delete[] name;
+}
+
+scm::cfgVector::cfgVector(const cfgVector& x) :
+	size(x.size), nalloc(size)
+{
+	if (nalloc > 0) {
+		value = new cfgValue[nalloc];
+		for (int k = 0; k < size; k++)
+			value[k] = x.value[k];
+	}
+
+	name_memsize = strlen(x.name) + 1;
+	name = new char[name_memsize];
+	strcpy(name, x.name);
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * swap & assignment * //
+// -------------------------------------------------------------------------------------------- //
+const scm::cfgVector& scm::cfgVector::operator=(cfgVector x)
+{
+	swap(x);
+	return (*this);
+}
+
+void scm::cfgVector::swap(cfgVector& x)
+{
+	scm::swap(size, x.size);
+	scm::swap(nalloc, x.nalloc);
+	scm::swap(value, x.value);
+
+	scm::swap(name_memsize, x.name_memsize);
+	scm::swap(name, x.name);
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * set & add calls * //
+// -------------------------------------------------------------------------------------------- //
+void scm::cfgVector::set(const cfgValue& _value)
+{
+	if (nalloc == 0) 
+	{
+		nalloc = 1;
+		value = new cfgValue[nalloc];
+	}
+
+	size = 1;
+	*value = _value;
+}
+
+void scm::cfgVector::set(const cfgValue& _value, const int _size)
+{
+	if (nalloc < _size)
+	{
+		if (nalloc > 0) delete[] value;
+
+		nalloc = max(nalloc + c_nalloc_inc, _size);
+		value = new cfgValue[nalloc];
+	}
+
+	size = _size;
+	for (int k = 0; k < size; k++)
+		value[k] = _value;
+}
+
+void scm::cfgVector::set(const int* x, const int _size)
+{
+	if (nalloc < _size)
+	{
+		if (nalloc > 0) delete[] value;
+
+		nalloc = max(nalloc + c_nalloc_inc, _size);
+		value = new cfgValue[nalloc];
+	}
+
+	size = _size;
+	for (int k = 0; k < size; k++)
+		value[k] = cfgValue(x[k]);
+}
+
+void scm::cfgVector::set(const float* x, const int _size)
+{
+	if (nalloc < _size)
+	{
+		if (nalloc > 0) delete[] value;
+
+		nalloc = max(nalloc + c_nalloc_inc, _size);
+		value = new cfgValue[nalloc];
+	}
+
+	size = _size;
+	for (int k = 0; k < size; k++)
+		value[k] = cfgValue(x[k]);
+}
+
+void scm::cfgVector::set(const double* x, const int _size)
+{
+	if (nalloc < _size)
+	{
+		if (nalloc > 0) delete[] value;
+
+		nalloc = max(nalloc + c_nalloc_inc, _size);
+		value = new cfgValue[nalloc];
+	}
+
+	size = _size;
+	for (int k = 0; k < size; k++)
+		value[k] = cfgValue(x[k]);
+}
+
+void scm::cfgVector::set(const long double* x, const int _size)
+{
+	if (nalloc < _size)
+	{
+		if (nalloc > 0) delete[] value;
+
+		nalloc = max(nalloc + c_nalloc_inc, _size);
+		value = new cfgValue[nalloc];
+	}
+
+	size = _size;
+	for (int k = 0; k < size; k++)
+		value[k] = cfgValue(x[k]);
+}
+
+bool scm::cfgVector::change(const int idx, const cfgValue& _value)
+{
+	if ((idx < 0) || (idx >= size)) return false;
+	
+	value[idx] = _value;
+	return true;
+}
+
+void scm::cfgVector::append(const cfgValue& _value)
+{
+	if (size == nalloc)
+	{
+		if (nalloc == 0) 
+		{
+			set(_value);
+			return;
+		}
+
+		cfgValue *hvalue;
+		hvalue = new cfgValue[nalloc + c_nalloc_inc];
+
+		for (int k = 0; k < size; k++) {
+			hvalue[k].swap(value[k]);
+		}
+
+		delete[] value;	// size > 0
+		value = hvalue;
+
+		nalloc += c_nalloc_inc;
+	}
+
+	value[size] = _value;
+	size++;
+}
+
+void scm::cfgVector::set_name(const char* ex_name)
+{
+	if (ex_name == NULL) return;	// keeping old name
+
+	const size_t ex_size = strlen(ex_name) + 1;
+	if (ex_size > name_memsize) {
+		delete[] name;
+
+		name_memsize = ex_size;
+		name = new char[name_memsize];
+	}
+
+	strcpy(name, ex_name);
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * get calls * //
+// -------------------------------------------------------------------------------------------- //
+const scm::cfgValue scm::cfgVector::get(const int idx) const
+{
+	if ((idx < 0) || (idx >= size)) return cfgValue();
+	return value[idx];
+}
+
+bool scm::cfgVector::get(const int idx, int* _value) const
+{
+	if ((idx < 0) || (idx >= size)) return false;
+
+	return value[idx].get(_value);
+}
+
+bool scm::cfgVector::get(const int idx, float* _value) const
+{
+	if ((idx < 0) || (idx >= size)) return false;
+
+	return value[idx].get(_value);
+}
+
+bool scm::cfgVector::get(const int idx, double* _value) const
+{
+	if ((idx < 0) || (idx >= size)) return false;
+
+	return value[idx].get(_value);
+}
+
+bool scm::cfgVector::get(const int idx, long double* _value) const
+{
+	if ((idx < 0) || (idx >= size)) return false;
+
+	return value[idx].get(_value);
+}
+
+bool scm::cfgVector::get(const int idx, char** c_str) const
+{
+	if ((idx < 0) || (idx >= size)) return false;
+
+	return value[idx].get(c_str);
+}
+
+bool scm::cfgVector::get(const int idx, std::string& _value) const
+{
+	if ((idx < 0) || (idx >= size)) return false;
+
+	return value[idx].get(_value);
+}
+
+bool scm::cfgVector::get(const int idx, bool* _value) const
+{
+	if ((idx < 0) || (idx >= size)) return false;
+
+	return value[idx].get(_value);
+}
+
+bool scm::cfgVector::get_if_single(int* _value) const
+{
+	if (size == 1) return (*value).get(_value);
+	return false;
+}
+
+bool scm::cfgVector::get_if_single(float* _value) const
+{
+	if (size == 1) return (*value).get(_value);
+	return false;
+}
+
+bool scm::cfgVector::get_if_single(double* _value) const
+{
+	if (size == 1) return (*value).get(_value);
+	return false;
+}
+
+bool scm::cfgVector::get_if_single(long double* _value) const
+{
+	if (size == 1) return (*value).get(_value);
+	return false;
+}
+
+bool scm::cfgVector::get_if_single(char** c_str) const
+{
+	if (size == 1) return (*value).get(c_str);
+	return false;
+}
+
+bool scm::cfgVector::get_if_single(std::string& _value) const
+{
+	if (size == 1) return (*value).get(_value);
+	return false;
+}
+
+bool scm::cfgVector::get_if_single(bool* _value) const
+{
+	if (size == 1) return (*value).get(_value);
+	return false;
+}
+
+int scm::cfgVector::get_size() const
+{
+	return size;
+}
+
+const char* scm::cfgVector::get_name() const
+{
+	return name;
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * check calls * //
+// -------------------------------------------------------------------------------------------- //
+bool scm::cfgVector::is_defined() const
+{
+	for (int k = 0; k < size; k++) {
+		if (value[k].get_type() == cfgValue::IS_UNDEF) 
+			return false;
+	}
+
+	return (!is_empty());
+}
+
+bool scm::cfgVector::is_empty() const
+{
+	return (size == 0);
+}
+
+bool scm::cfgVector::is_single() const
+{
+	return (size == 1);
+}
+
+bool scm::cfgVector::is_name_empty() const
+{
+	return ((*name) == '\0');
+}
+
+bool scm::cfgVector::is_name_eq(const cfgVector& x) const
+{
+	return (!strcmp(name, x.name));
+}
+
+bool scm::cfgVector::is_name_eq(const char* _name) const
+{
+	if (_name == NULL) return false;
+	return (!strcmp(name, _name));
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * print * //
+// -------------------------------------------------------------------------------------------- //
+void scm::cfgVector::print() const
+{
+	printf(" > '%s'[%i] = ", name, get_size());
+
+	for (int k = 0; k < get_size(); k++)
+	{
+		value[k].print_typed();
+		if (k < get_size() - 1) printf(", ");
+	}
+	printf("\n");
+}
+
+void scm::cfgVector::print_value() const
+{
+	if (size == 0) return;
+	if (size == 1) {
+		(*value).print();
+		return;
+	}
+
+	printf("[");
+	(*value).print();
+
+	for (int k = 1; k < get_size(); k++)
+	{
+		printf(", ");
+		value[k].print();
+	}
+	printf("]");
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * operators * //
+// -------------------------------------------------------------------------------------------- //
+scm::cfgVector& scm::cfgVector::operator+=(const cfgVector& x)
+{
+	if (size == x.size)
+	{
+		for (int k = 0; k < size; k++)
+			value[k] += x.value[k];
+	}
+	else
+		size = 0;	// setting null vector
+
+	return (*this);
+}
+scm::cfgVector& scm::cfgVector::operator-=(const cfgVector& x)
+{
+	if (size == x.size)
+	{
+		for (int k = 0; k < size; k++)
+			value[k] -= x.value[k];
+	}
+	else
+		size = 0;	// setting null vector
+
+	return (*this);
+}
+
+scm::cfgVector& scm::cfgVector::operator*=(const cfgVector& x)
+{
+	if (size == x.size)
+	{
+		for (int k = 0; k < size; k++)
+			value[k] *= x.value[k];
+	}
+	else
+		size = 0;	// setting null vector
+
+	return (*this);
+}
+
+scm::cfgVector& scm::cfgVector::operator/=(const cfgVector& x)
+{
+	if (size == x.size)
+	{
+		for (int k = 0; k < size; k++)
+			value[k] /= x.value[k];
+	}
+	else
+		size = 0;	// setting null vector
+
+	return (*this);
+}
+
+scm::cfgVector& scm::cfgVector::operator%=(const cfgVector& x)
+{
+	if (size == x.size)
+	{
+		for (int k = 0; k < size; k++)
+			value[k] %= x.value[k];
+	}
+	else
+		size = 0;	// setting null vector
+	
+	return (*this);
+}
+
+scm::cfgVector& scm::cfgVector::operator^=(const cfgVector& x)
+{
+	if (size == x.size)
+	{
+		for (int k = 0; k < size; k++)
+			value[k] ^= x.value[k];
+	}
+	else
+		size = 0;	// setting null vector
+
+	return (*this);
+}
+
+const scm::cfgVector scm::cfgVector::operator+(const cfgVector& x) const
+{
+	return cfgVector(*this) += x;
+}
+const scm::cfgVector scm::cfgVector::operator-(const cfgVector& x) const
+{
+	return cfgVector(*this) -= x;
+}
+const scm::cfgVector scm::cfgVector::operator*(const cfgVector& x) const
+{
+	return cfgVector(*this) *= x;
+}
+const scm::cfgVector scm::cfgVector::operator/(const cfgVector& x) const
+{
+	return cfgVector(*this) /= x;
+}
+const scm::cfgVector scm::cfgVector::operator%(const cfgVector& x) const
+{
+	return cfgVector(*this) %= x;
+}
+const scm::cfgVector scm::cfgVector::operator^(const cfgVector& x) const
+{
+	return cfgVector(*this) ^= x;
+}
+
+const scm::cfgVector scm::cfgVector::operator==(const cfgVector& x) const
+{
+	cfgVector res;
+	if (size == x.size)
+	{
+		res.set(cfgValue(), size);
+		for (int k = 0; k < size; k++) 
+			res.value[k] = (value[k] == x.value[k]);
+	}
+
+	return res;
+}
+const scm::cfgVector scm::cfgVector::operator!=(const cfgVector& x) const
+{
+	cfgVector res;
+	if (size == x.size)
+	{
+		res.set(cfgValue(), size);
+		for (int k = 0; k < size; k++)
+			res.value[k] = (value[k] != x.value[k]);
+	}
+
+	return res;
+}
+const scm::cfgVector scm::cfgVector::operator<(const cfgVector& x) const
+{
+	cfgVector res;
+	if (size == x.size)
+	{
+		res.set(cfgValue(), size);
+		for (int k = 0; k < size; k++)
+			res.value[k] = (value[k] < x.value[k]);
+	}
+
+	return res;
+}
+const scm::cfgVector scm::cfgVector::operator>(const cfgVector& x) const
+{
+	cfgVector res;
+	if (size == x.size)
+	{
+		res.set(cfgValue(), size);
+		for (int k = 0; k < size; k++)
+			res.value[k] = (value[k] > x.value[k]);
+	}
+
+	return res;
+}
+const scm::cfgVector scm::cfgVector::operator<=(const cfgVector& x) const
+{
+	cfgVector res;
+	if (size == x.size)
+	{
+		res.set(cfgValue(), size);
+		for (int k = 0; k < size; k++)
+			res.value[k] = (value[k] <= x.value[k]);
+	}
+
+	return res;
+}
+const scm::cfgVector scm::cfgVector::operator>=(const cfgVector& x) const
+{
+	cfgVector res;
+	if (size == x.size)
+	{
+		res.set(cfgValue(), size);
+		for (int k = 0; k < size; k++)
+			res.value[k] = (value[k] >= x.value[k]);
+	}
+
+	return res;
+}
+
+const scm::cfgVector scm::cfgVector::operator-() const
+{
+	cfgVector res((*this));;
+	for (int k = 0; k < size; k++) 
+		res.value[k] = -value[k];
+
+	return res;
+}
+const scm::cfgVector scm::cfgVector::operator+() const
+{
+	cfgVector res((*this));;
+	for (int k = 0; k < size; k++)
+		res.value[k] = +value[k];
+
+	return res;
+}
+
+const scm::cfgVector scm::cfgVector::logical_and(const cfgVector& x) const
+{
+	cfgVector res;
+	if (size == x.size)
+	{
+		res.set(cfgValue(), size);
+		for (int k = 0; k < size; k++)
+			res.value[k] = value[k].logical_and(x.value[k]);
+	}
+
+	return res;
+}
+
+const scm::cfgVector scm::cfgVector::logical_or(const cfgVector& x) const
+{
+	cfgVector res;
+	if (size == x.size)
+	{
+		res.set(cfgValue(), size);
+		for (int k = 0; k < size; k++)
+			res.value[k] = value[k].logical_or(x.value[k]);
+	}
+
+	return res;
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * functions * //
+// -------------------------------------------------------------------------------------------- //
+const scm::cfgVector 
+scm::cfgVector::cfg_sin(const cfgVector& x)
+{
+	cfgVector y;
+	y.set(cfgValue(), x.size);
+
+	for (int k = 0; k < y.size; k++)
+		y.value[k] = cfgValue::cfg_sin(x.value[k]);
+
+	return y;
+}
+
+const scm::cfgVector 
+scm::cfgVector::cfg_cos(const cfgVector& x)
+{
+	cfgVector y;
+	y.set(cfgValue(), x.size);
+
+	for (int k = 0; k < y.size; k++)
+		y.value[k] = cfgValue::cfg_cos(x.value[k]);
+
+	return y;
+}
+
+const scm::cfgVector 
+scm::cfgVector::cfg_tan(const cfgVector& x)
+{
+	cfgVector y;
+	y.set(cfgValue(), x.size);
+
+	for (int k = 0; k < y.size; k++)
+		y.value[k] = cfgValue::cfg_tan(x.value[k]);
+
+	return y;
+}
+
+const scm::cfgVector 
+scm::cfgVector::cfg_log(const cfgVector& x)
+{
+	cfgVector y;
+	y.set(cfgValue(), x.size);
+
+	for (int k = 0; k < y.size; k++)
+		y.value[k] = cfgValue::cfg_log(x.value[k]);
+
+	return y;
+}
+
+const scm::cfgVector 
+scm::cfgVector::cfg_sqrt(const cfgVector& x)
+{
+	cfgVector y;
+	y.set(cfgValue(), x.size);
+
+	for (int k = 0; k < y.size; k++)
+		y.value[k] = cfgValue::cfg_sqrt(x.value[k]);
+
+	return y;
+}
+
+const scm::cfgVector 
+scm::cfgVector::cfg_abs(const cfgVector& x)
+{
+	cfgVector y;
+	y.set(cfgValue(), x.size);
+
+	for (int k = 0; k < y.size; k++)
+		y.value[k] = cfgValue::cfg_abs(x.value[k]);
+
+	return y;
+}
+
+const scm::cfgVector 
+scm::cfgVector::cfg_to_string(const cfgVector& x)
+{
+	cfgVector y;
+	y.set(cfgValue(), x.size);
+
+	for (int k = 0; k < y.size; k++)
+		y.value[k] = cfgValue::cfg_to_string(x.value[k]);
+
+	return y;
+}
+
+const scm::cfgVector
+scm::cfgVector::cfg_vecmin(const cfgVector& x)
+{
+	if (x.size > 0)
+	{
+		cfgValue _min = x.value[0];
+		for (int k = 1; k < x.size; k++) 
+		{
+			cfgValue cmp = (x.value[k] < _min);
+			
+			bool is_less;
+			if (!cmp.get(&is_less)) return cfgVector();
+
+			if (is_less) _min = x.value[k];
+		}
+		return cfgVector(_min);
+	}
+	else
+		return cfgVector();
+}
+
+const scm::cfgVector
+scm::cfgVector::cfg_vecmax(const cfgVector& x)
+{
+	if (x.size > 0)
+	{
+		cfgValue _max = x.value[0];
+		for (int k = 1; k < x.size; k++)
+		{
+			cfgValue cmp = (x.value[k] > _max);
+
+			bool is_greater;
+			if (!cmp.get(&is_greater)) return cfgVector();
+
+			if (is_greater) _max = x.value[k];
+		}
+		return cfgVector(_max);
+	}
+	else
+		return cfgVector();
+}
+
+const scm::cfgVector 
+scm::cfgVector::cfg_min(const cfgVector& a, const cfgVector& b)
+{
+	cfgVector _min;
+	if (a.size == b.size)
+	{
+		_min.set(cfgValue(), a.size);
+		for (int k = 0; k < _min.size; k++)
+			_min.value[k] = cfgValue::cfg_min(a.value[k], b.value[k]);
+	}
+
+	return _min;
+}
+
+const scm::cfgVector 
+scm::cfgVector::cfg_max(const cfgVector& a, const cfgVector& b)
+{
+	cfgVector _max;
+	if (a.size == b.size)
+	{
+		_max.set(cfgValue(), a.size);
+		for (int k = 0; k < _max.size; k++)
+			_max.value[k] = cfgValue::cfg_max(a.value[k], b.value[k]);
+	}
+
+	return _max;
+}
+
+const scm::cfgVector 
+scm::cfgVector::cfg_dot_product(const cfgVector& a, const cfgVector& b)
+{
+	if ((a.size == b.size) && (a.size > 0))
+	{
+		cfgValue dp(0);
+		for (int k = 0; k < a.size; k++)
+			dp += a.value[k] * b.value[k];
+
+		return cfgVector(dp);
+	}
+	else
+		return cfgVector();
+}
+
+const scm::cfgVector 
+scm::cfgVector::cfg_l2norm(const cfgVector& x)
+{
+	if (x.size == 0) return cfgVector();
+
+	cfgValue norm((double)0);
+	for (int k = 0; k < x.size; k++)
+		norm += x.value[k] * x.value[k];
+
+	return cfgVector(cfgValue::cfg_sqrt(norm));
+}
+
+const scm::cfgVector 
+scm::cfgVector::cfg_cnorm(const cfgVector& x)
+{
+	if (x.size == 0) return cfgVector();
+
+	cfgValue norm(cfgValue::cfg_abs(x.value[0]));
+	for (int k = 1; k < x.size; k++)
+	{
+		cfgValue cfg_is_max = (cfgValue::cfg_abs(x.value[k]) > norm);
+		bool is_max;
+		if (!cfg_is_max.get(&is_max))
+			return cfgVector();
+
+		if (is_max) norm = cfgValue::cfg_abs(x.value[k]);
+	}
+
+	return cfgVector(norm);
+}
+// -------------------------------------------------------------------------------------------- //
diff --git a/parser/cfg-vec.h b/parser/cfg-vec.h
new file mode 100644
index 0000000..fe2d643
--- /dev/null
+++ b/parser/cfg-vec.h
@@ -0,0 +1,146 @@
+#pragma once
+
+#include "cfg-value.h"
+
+namespace scm
+{
+	class cfgVector
+	{
+	public:
+		
+		// set & add calls
+		// -------------------------------------------------------------------------------------------- //
+		void set(const cfgValue& value);
+		void set(const cfgValue& value, const int size);
+
+		void set(const int* x, const int size);
+		void set(const float* x, const int size);
+		void set(const double* x, const int size);
+		void set(const long double* x, const int size);
+
+		bool change(const int idx, const cfgValue& value);
+		void append(const cfgValue& value);
+
+		void set_name(const char* name);
+		//		*: name == NULL - not changing vector name
+		// -------------------------------------------------------------------------------------------- //
+		
+		// get calls
+		// -------------------------------------------------------------------------------------------- //
+		const cfgValue get(const int idx) const;
+		
+		bool get(const int idx, int* value) const;
+		bool get(const int idx, float* value) const;
+		bool get(const int idx, double* value) const;
+		bool get(const int idx, long double* value) const;
+		bool get(const int idx, char** c_str) const;
+		bool get(const int idx, std::string& value) const;
+		bool get(const int idx, bool* value) const;
+
+		bool get_if_single(int* value) const;
+		bool get_if_single(float* value) const;
+		bool get_if_single(double* value) const;
+		bool get_if_single(long double* value) const;
+		bool get_if_single(char** c_str) const;
+		bool get_if_single(std::string& value) const;
+		bool get_if_single(bool* value) const;
+
+		int get_size() const;
+		const char* get_name() const;
+		// -------------------------------------------------------------------------------------------- //
+
+		// check calls
+		// -------------------------------------------------------------------------------------------- //
+		bool is_defined() const;
+		//		*: size != 0 && all values defined
+		bool is_empty() const;
+		//		*: size == 0 
+		bool is_name_empty() const;
+		//		*: name = "\0";
+		bool is_name_eq(const cfgVector& x) const;
+		bool is_name_eq(const char* name) const;
+		bool is_single() const;
+		//		*: size == 1
+		// -------------------------------------------------------------------------------------------- //
+
+		// print
+		// -------------------------------------------------------------------------------------------- //
+		void print() const;
+		void print_value() const;
+		// -------------------------------------------------------------------------------------------- //
+
+		// operators
+		// -------------------------------------------------------------------------------------------- //
+		cfgVector& operator+=(const cfgVector& x);
+		cfgVector& operator-=(const cfgVector& x);
+		cfgVector& operator*=(const cfgVector& x);
+		cfgVector& operator/=(const cfgVector& x);
+		cfgVector& operator%=(const cfgVector& x);
+		cfgVector& operator^=(const cfgVector& x);
+
+		const cfgVector operator+(const cfgVector& x) const;
+		const cfgVector operator-(const cfgVector& x) const;
+		const cfgVector operator*(const cfgVector& x) const;
+		const cfgVector operator/(const cfgVector& x) const;
+		const cfgVector operator%(const cfgVector& x) const;
+		const cfgVector operator^(const cfgVector& x) const;
+
+		const cfgVector operator==(const cfgVector& x) const;
+		const cfgVector operator!=(const cfgVector& x) const;
+		const cfgVector operator<(const cfgVector& x) const;
+		const cfgVector operator>(const cfgVector& x) const;
+		const cfgVector operator<=(const cfgVector& x) const;
+		const cfgVector operator>=(const cfgVector& x) const;
+
+		const cfgVector operator-() const;
+		const cfgVector operator+() const;
+
+		const cfgVector logical_and(const cfgVector& x) const;	// no short-circuit
+		const cfgVector logical_or(const cfgVector& y) const;	// no short-circuit
+		// -------------------------------------------------------------------------------------------- //
+
+		// functions
+		// -------------------------------------------------------------------------------------------- //
+		static const cfgVector cfg_sin(const cfgVector& x);
+		static const cfgVector cfg_cos(const cfgVector& x);
+		static const cfgVector cfg_tan(const cfgVector& x);
+		static const cfgVector cfg_log(const cfgVector& x);
+		static const cfgVector cfg_sqrt(const cfgVector& x);
+		static const cfgVector cfg_abs(const cfgVector& x);
+		static const cfgVector cfg_to_string(const cfgVector& x);
+		static const cfgVector cfg_vecmin(const cfgVector& x);
+		static const cfgVector cfg_vecmax(const cfgVector& x);
+
+		static const cfgVector cfg_min(const cfgVector& a, const cfgVector& b);
+		static const cfgVector cfg_max(const cfgVector& a, const cfgVector& b);
+
+		static const cfgVector cfg_dot_product(const cfgVector& a, const cfgVector& b);
+		static const cfgVector cfg_l2norm(const cfgVector& x);
+		static const cfgVector cfg_cnorm(const cfgVector& x);
+		// -------------------------------------------------------------------------------------------- //
+		
+		// -------------------------------------------------------------------------------------------- //
+		cfgVector();
+		cfgVector(const cfgValue& value);
+		~cfgVector();
+
+		cfgVector(const cfgVector& x);
+		const cfgVector& operator=(cfgVector x);
+		void swap(cfgVector& x);
+		// -------------------------------------------------------------------------------------------- //
+
+	private:
+		// data (private):
+		// -------------------------------------------------------------------------------------------- //
+
+		int size;
+		int nalloc;
+		static const int c_nalloc_inc = 8;
+
+		cfgValue *value;
+
+		char* name;	// default name = empty string = "\0"
+		size_t name_memsize;		// memory handler for name string
+	};
+}
+
diff --git a/parser/config-parser.cpp b/parser/config-parser.cpp
new file mode 100644
index 0000000..00e1dbe
--- /dev/null
+++ b/parser/config-parser.cpp
@@ -0,0 +1,2382 @@
+#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 (%i) 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;
+}
+// -------------------------------------------------------------------------------------------- //
diff --git a/parser/config-parser.h b/parser/config-parser.h
new file mode 100644
index 0000000..7ae3494
--- /dev/null
+++ b/parser/config-parser.h
@@ -0,0 +1,191 @@
+#pragma once
+
+// [config-parser.h]: configuration file parser
+//
+// -------------------------------------------------------------------------------------------- //
+
+#include "cfg-value.h"
+#include "cfg-cmd.h"
+#include "cfg-vec.h"
+
+#include "lexeme-list.h"
+#include "mem-buffer.h"
+
+#include <stack>
+
+namespace scm
+{
+	// call back default
+	// -------------------------------------------------------------------------------------------- //
+	class parserCallBack {
+	public:
+
+		virtual bool call_back(const cfgCommand& cmd) { return true; }
+
+		parserCallBack() {}
+		virtual ~parserCallBack() {}
+	};
+	// -------------------------------------------------------------------------------------------- //
+
+	class ConfigParser {
+	public:
+
+		// -------------------------------------------------------------------------------------------- //
+		ConfigParser();
+		~ConfigParser();
+		// -------------------------------------------------------------------------------------------- //
+
+		// run
+		// -------------------------------------------------------------------------------------------- //
+		bool run(const char* filename);
+		bool run(const char* filename, parserCallBack& pcb);
+		// -------------------------------------------------------------------------------------------- //
+
+		// get & check calls
+		// -------------------------------------------------------------------------------------------- //
+		bool is_varname(const char* name) const;
+		const cfgVector get_variable(const int idx) const;
+		const cfgVector get_variable(const char* name) const;
+
+		bool get_value(const char* name, int* value) const;
+		bool get_value(const char* name, float* value) const;
+		bool get_value(const char* name, double* value) const;
+		bool get_value(const char* name, long double* value) const;
+
+		bool get_value(const char* name, char** value) const;
+		bool get_value(const char* name, std::string& value) const;
+
+		bool get_value(const char* name, bool* value) const;
+		// -------------------------------------------------------------------------------------------- //
+
+		// adding variable
+		// -------------------------------------------------------------------------------------------- //
+		bool add(const cfgVector& rvalue);
+
+		bool is_valid_name(const char* name) const;
+		// -------------------------------------------------------------------------------------------- //
+
+		// print
+		// -------------------------------------------------------------------------------------------- //
+		void print() const;
+		// -------------------------------------------------------------------------------------------- //
+
+	private:
+		// datatypes
+		// -------------------------------------------------------------------------------------------- //
+
+		// --- helper struct to control parsing state
+		// -------------------------------------------------------------------------------------------- //
+		struct parserState {
+
+			parserState();
+			parserState(const parserState& state);
+			~parserState();
+
+			void truncate_name_space();
+			void append_name_space(const char* name);
+
+			const char* get_global_name(const char* varname);
+
+			int idx;			// lexeme index
+			char *name_space;	// current namespace
+
+		private:	// allocation data
+			int nalloc;
+			static const int c_alloc_init = 64;
+
+			char *name_buf;
+			int name_buf_nalloc;
+		};
+		// -------------------------------------------------------------------------------------------- //
+
+	private:
+		// processing (private)
+		// -------------------------------------------------------------------------------------------- //
+
+		// --- expression rpn evaluation
+		bool get_rpn(
+			mem_buffer<int>& rpn,
+			mem_buffer<int>& rpn_key,
+			const LexemeList& lexeme_list,
+			const int lex_beg, const int lex_end) const;
+
+		bool evaluate_rpn(
+			std::stack<cfgVector>& dyn_expr,
+			const mem_buffer< int >& rpn,
+			const mem_buffer<int>& rpn_key,
+			const int rpn_beg, const int rpn_end,
+			const LexemeList& lexeme_list,
+			const char* name_space,
+			const bool exe_cntrl) const;
+		bool 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;
+		// -------------------------------------------------------------------------------------------- //
+
+		// --- command setup 
+		bool set_command(
+			cfgCommand& cmd,
+			const mem_buffer< int >& rpn,
+			const mem_buffer< int >& fun_narg,
+			const LexemeList& lexeme_list,
+			const bool exe_cntrl) const;
+		// -------------------------------------------------------------------------------------------- //
+
+		// --- syntax analysis
+		bool parse_syntax(const LexemeList& lexeme_list, const bool exe_cntrl, parserCallBack& pcb);
+
+		bool parse_block(
+			parserState& state, const LexemeList& lexeme_list, const bool exe_cntrl, parserCallBack& pcb);
+		bool parse_command(
+			parserState& state, const LexemeList& lexeme_list, const bool exe_cntrl, parserCallBack& pcb);
+		bool parse_if_statement(
+			parserState& state, const LexemeList& lexeme_list, const bool exe_cntrl, parserCallBack& pcb);
+		bool parse_while_statement(
+			parserState& state, const LexemeList& lexeme_list, const bool exe_cntrl, parserCallBack& pcb);
+		bool parse_name_space(
+			parserState& state, const LexemeList& lexeme_list, const bool exe_cntrl, parserCallBack& pcb);
+		bool parse_assignment(
+			parserState& state, const LexemeList& lexeme_list, const bool exe_cntrl, parserCallBack& pcb);
+		bool parse_address_assignment(
+			parserState& state, const LexemeList& lexeme_list, const bool exe_cntrl, parserCallBack& pcb);
+		// -------------------------------------------------------------------------------------------- //
+
+		// --- add variable (no additional checks) 
+		bool add_unsafe(const cfgVector& rvalue);
+		// -------------------------------------------------------------------------------------------- //
+
+	private:
+		// static (private)
+		// -------------------------------------------------------------------------------------------- //
+
+		// +,-		[priority=1, assoc.=left]
+		// *,/,%	[priority=2, assoc.=left]
+		// +,-		[priority=3, assoc.=right]
+		// ^		[priority=4, assoc.=right]
+		static int operator_priority(const Lexeme::TYPE type);
+		static bool operator_priority_lt(
+			const Lexeme::TYPE typeA, const Lexeme::TYPE typeB);
+
+		static int function_nargs(const Lexeme::TYPE type);
+
+		static bool is_operator_binary(const Lexeme::TYPE type);
+		static bool is_operator_unary(const Lexeme::TYPE type);
+		static bool is_operator_assoc_left(const Lexeme::TYPE type);
+		static bool is_operator_assoc_right(const Lexeme::TYPE type);
+
+	private:
+		// data (private)
+		// -------------------------------------------------------------------------------------------- //
+
+		int nvars;
+		int nalloc_vars;
+		static const int c_alloc_vars_init = 64;
+		cfgVector *var;
+	};
+	// -------------------------------------------------------------------------------------------- //
+}
diff --git a/parser/io-guts.cpp b/parser/io-guts.cpp
new file mode 100644
index 0000000..d85ca8b
--- /dev/null
+++ b/parser/io-guts.cpp
@@ -0,0 +1,152 @@
+
+// [io-guts.cpp]
+// -------------------------------------------------------------------------------------------- //
+// input/output tech subroutines
+// -------------------------------------------------------------------------------------------- //
+
+#define _CRT_SECURE_NO_DEPRECATE
+#include "io-guts.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <sstream>
+
+// --- including for directory operations
+#ifdef _WIN32
+#include <direct.h>
+#else
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#endif
+#include <errno.h>
+
+
+// -------------------------------------------------------------------------------------------- //
+// * Implementation *
+// -------------------------------------------------------------------------------------------- //
+
+// * append index * //
+// -------------------------------------------------------------------------------------------- //
+const std::string scm::append_index(
+	const std::string& name, const int index)
+{
+	std::ostringstream sidx;
+	sidx << index;
+
+	const int ext_pos = name.find_last_of(".");
+	std::string app_name = name;
+	if (ext_pos == std::string::npos)
+		app_name.append(sidx.str());
+	else
+		app_name.insert(ext_pos, sidx.str());
+
+	return app_name;
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * create dir * //
+// -------------------------------------------------------------------------------------------- //
+bool scm::create_dir(const std::string& path)
+{
+	// empty path is OK	[local DIR]
+	if (path.empty()) return true;
+
+	char *c_path;
+	c_path = new char[path.length() + 1];
+	strcpy(c_path, path.c_str());
+
+	int status;
+	char *ptr = c_path + 1;		// not empty string
+	while (*ptr != '\0')
+	{
+		if (*ptr == '/')
+		{
+			*ptr = '\0';
+#ifdef _WIN32
+			status = _mkdir(c_path);
+#else
+			status = mkdir(c_path, S_IRWXU);	// add group?: S_IRWXG
+#endif
+			if (!((status == 0) ||
+				((status == -1) && (errno == EEXIST))))
+			{
+				delete[] c_path;
+				return false;
+			}
+
+			*ptr = '/';
+		}
+		ptr++;
+	}
+
+
+#ifdef _WIN32
+	status = _mkdir(c_path);
+#else
+	status = mkdir(c_path, S_IRWXU);	// add group?: S_IRWXG
+#endif
+
+	delete[] c_path;
+
+	return ((status == 0) ||
+		((status == -1) && (errno == EEXIST)));
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * getline * //
+// -------------------------------------------------------------------------------------------- //
+char* scm::getline(char** buf, int* size, FILE* ptr)
+{
+	const int c_min_size = 512;
+
+	if (*size < c_min_size) {
+		if (*size > 0) delete[](*buf);
+
+		*size = c_min_size;
+		*buf = new char[*size];
+	}
+
+	if (fgets(&(*buf)[0], *size, ptr) == NULL) return NULL;
+	int bidx = strlen(*buf);
+
+	while (!feof(ptr) && ((*buf)[bidx - 1] != '\n'))
+	{
+		// --- reading more ...
+
+		// --- allocating additional memory
+		*size += c_min_size;
+		char *hbuf = new char[*size];
+		strcpy(hbuf, *buf);
+
+		// --- pointing buf to new memory
+		delete[](*buf);
+		*buf = hbuf;
+
+		// --- reading & removing termination character
+		if (fgets(&(*buf)[bidx], *size - bidx, ptr) == NULL) {
+			if (!feof(ptr)) return NULL;
+		}
+		bidx = strlen(*buf);
+	}
+
+	return *buf;
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * convert to string * //
+// -------------------------------------------------------------------------------------------- //
+std::string scm::convert_to_string(const int value)
+{
+	std::ostringstream stream;
+	stream << value;
+	return stream.str();
+}
+
+std::string scm::convert_to_string(const double value)
+{
+	std::ostringstream stream;
+	stream << value;
+	return stream.str();
+}
+// -------------------------------------------------------------------------------------------- //
diff --git a/parser/io-guts.h b/parser/io-guts.h
new file mode 100644
index 0000000..7075f43
--- /dev/null
+++ b/parser/io-guts.h
@@ -0,0 +1,39 @@
+#pragma once
+
+// [io-guts.h]
+// -------------------------------------------------------------------------------------------- //
+// input/output tech subroutines
+// -------------------------------------------------------------------------------------------- //
+
+#include <string>
+
+
+
+namespace scm
+{
+	// append index to string before last '.'
+	// -------------------------------------------------------------------------------------------- //
+	const std::string append_index(const std::string& name, const int index);
+	// -------------------------------------------------------------------------------------------- //
+
+	// create all directories in path
+	// --- returns <true> on create and if exists
+	// -------------------------------------------------------------------------------------------- //
+	bool create_dir(const std::string& path);
+	// -------------------------------------------------------------------------------------------- //
+
+
+	// fgets() for arbitrary line length
+	// --- <buf> - pointer to buffer memory (input/output)
+	// --- <size> - buffer memory size (input/output)
+	// -------------------------------------------------------------------------------------------- //
+	char* getline(char** buf, int* size, FILE* ptr);
+	// -------------------------------------------------------------------------------------------- //
+
+	// convert int to string
+	// *: implemented due to problems with std::to_string on some gcc compilers
+	// -------------------------------------------------------------------------------------------- //
+	std::string convert_to_string(const int value);
+	std::string convert_to_string(const double value);
+	// -------------------------------------------------------------------------------------------- //
+}
diff --git a/parser/lexeme-list.cpp b/parser/lexeme-list.cpp
new file mode 100644
index 0000000..76d1312
--- /dev/null
+++ b/parser/lexeme-list.cpp
@@ -0,0 +1,159 @@
+#include "lexeme-list.h"
+
+#include <string.h>
+
+#include "scm-mem.h"
+
+// -------------------------------------------------------------------------------------------- //
+// * Implementation *
+// -------------------------------------------------------------------------------------------- //
+
+scm::LexemeList::LexemeList()
+{
+	size = 0;
+	nalloc = 0;
+}
+
+scm::LexemeList::~LexemeList()
+{
+	clear();
+}
+
+scm::LexemeList::LexemeList(const LexemeList& list)
+{
+	size = list.size;
+	
+	if (size > 0) {
+		lexeme = new Lexeme[size];
+		for (int k = 0; k < size; k++)
+			lexeme[k] = list.lexeme[k];
+	}
+
+	nalloc = size;
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * swap & assignment * //
+// -------------------------------------------------------------------------------------------- //
+const scm::LexemeList& scm::LexemeList::operator=(LexemeList list)
+{
+	swap(list);
+	return (*this);
+}
+
+void scm::LexemeList::swap(LexemeList& list)
+{
+	scm::swap(lexeme, list.lexeme);
+	scm::swap(size, list.size);
+	scm::swap(nalloc, list.nalloc);
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * add calls * //
+// -------------------------------------------------------------------------------------------- //
+void scm::LexemeList::add(const char* token, const Lexeme::TYPE type, const int tag)
+{
+	if (size == nalloc) 
+	{
+		Lexeme *cp_list;
+		cp_list = new Lexeme[nalloc + c_nalloc_inc];
+
+		for (int k = 0; k < size; k++)
+			cp_list[k].swap(lexeme[k]);
+
+		if (nalloc > 0) delete[] lexeme;
+		lexeme = cp_list;
+
+		nalloc += c_nalloc_inc;
+	}
+
+	lexeme[size].set(token, type, tag);
+	size++;
+}
+
+void scm::LexemeList::add(const char* token, const Lexeme::TYPE type)
+{
+	add(token, type, 0);
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * get calls * //
+// -------------------------------------------------------------------------------------------- //
+int scm::LexemeList::get_size() const
+{
+	return size;
+}
+
+const scm::Lexeme scm::LexemeList::get_lexeme(const int idx) const
+{
+	if ((idx < 0) || (idx >= size)) return Lexeme();
+
+	return lexeme[idx];
+}
+
+const char* scm::LexemeList::get_token(const int idx) const
+{
+	if ((idx < 0) || (idx >= size)) return NULL;
+
+	return lexeme[idx].get_token();
+}
+
+scm::Lexeme::TYPE scm::LexemeList::get_type(const int idx) const
+{
+	if ((idx < 0) || (idx >= size)) return Lexeme::IS_INVALID;
+
+	return lexeme[idx].get_type();
+}
+
+int scm::LexemeList::get_tag(const int idx) const
+{
+	if ((idx < 0) || (idx >= size)) return 0;
+
+	return lexeme[idx].get_tag();
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * check lexeme type * //
+// -------------------------------------------------------------------------------------------- //
+bool scm::LexemeList::is_operator(const int idx) const
+{
+	if ((idx < 0) || (idx >= size)) return false;
+
+	return lexeme[idx].is_operator();
+}
+bool scm::LexemeList::is_function(const int idx) const
+{
+	if ((idx < 0) || (idx >= size)) return false;
+
+	return lexeme[idx].is_function();
+}
+bool scm::LexemeList::is_ctor(const int idx) const
+{
+	if ((idx < 0) || (idx >= size)) return false;
+
+	return lexeme[idx].is_ctor();
+}
+bool scm::LexemeList::is_value(const int idx) const
+{
+	if ((idx < 0) || (idx >= size)) return false;
+
+	return lexeme[idx].is_value();
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * clear & reset * //
+// -------------------------------------------------------------------------------------------- //
+void scm::LexemeList::clear()
+{
+	if (nalloc > 0)
+		delete[] lexeme;
+
+	size = 0;
+	nalloc = 0;
+}
+
+void scm::LexemeList::reset()
+{
+	size = 0;
+}
+// -------------------------------------------------------------------------------------------- //
\ No newline at end of file
diff --git a/parser/lexeme-list.h b/parser/lexeme-list.h
new file mode 100644
index 0000000..f7c0883
--- /dev/null
+++ b/parser/lexeme-list.h
@@ -0,0 +1,71 @@
+#pragma once
+
+// [lexeme-list.h]
+// -------------------------------------------------------------------------------------------- //
+// lexeme list
+// -------------------------------------------------------------------------------------------- //
+
+#include "lexeme.h"
+
+
+namespace scm
+{
+
+	class LexemeList {
+	public:
+
+		// add calls
+		// -------------------------------------------------------------------------------------------- //
+		void add(const char* token, const Lexeme::TYPE type, const int tag);
+		void add(const char* token, const Lexeme::TYPE type);
+		// -------------------------------------------------------------------------------------------- //
+
+		// get calls
+		// -------------------------------------------------------------------------------------------- //
+		int get_size() const;
+
+		const Lexeme get_lexeme(const int idx) const;
+
+		const char* get_token(const int idx) const;
+		Lexeme::TYPE get_type(const int idx) const;
+		int get_tag(const int idx) const;
+		// -------------------------------------------------------------------------------------------- //
+
+		// check lexeme type
+		// -------------------------------------------------------------------------------------------- //
+		bool is_operator(const int idx) const;
+		bool is_function(const int idx) const;
+		bool is_ctor(const int idx) const;
+		bool is_value(const int idx) const;
+		// -------------------------------------------------------------------------------------------- //
+
+		// clear & reset
+		// -------------------------------------------------------------------------------------------- //
+		void clear();
+		void reset();
+		// -------------------------------------------------------------------------------------------- //
+
+		// swap & assignment
+		// -------------------------------------------------------------------------------------------- //
+		const LexemeList& operator=(LexemeList list);
+		void swap(LexemeList& list);
+		// -------------------------------------------------------------------------------------------- //
+
+		// -------------------------------------------------------------------------------------------- //
+		LexemeList();
+		LexemeList(const LexemeList& list);
+		~LexemeList();
+		// -------------------------------------------------------------------------------------------- //
+
+	private:
+		// data (private):
+		// -------------------------------------------------------------------------------------------- //
+
+		Lexeme *lexeme;
+		int size;
+
+		int nalloc;
+		static const int c_nalloc_inc = 256;
+	};
+}
+// -------------------------------------------------------------------------------------------- //
diff --git a/parser/lexeme-parser.cpp b/parser/lexeme-parser.cpp
new file mode 100644
index 0000000..c7a5330
--- /dev/null
+++ b/parser/lexeme-parser.cpp
@@ -0,0 +1,604 @@
+#include "lexeme-parser.h"
+
+#define _CRT_SECURE_NO_WARNINGS
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "mem-buffer.h"
+
+// -------------------------------------------------------------------------------------------- //
+// * Implementation *
+// -------------------------------------------------------------------------------------------- //
+
+scm::LexemeParser::LexemeParser()
+{
+}
+
+scm::LexemeParser::~LexemeParser()
+{
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * run * //
+// -------------------------------------------------------------------------------------------- //
+bool scm::LexemeParser::run(const char* filename, LexemeList& list)
+{
+	// --- resetting list
+	list.reset();
+	// ----------------------------------------------------- //
+
+	// --- opening file
+	FILE *ptr = fopen(filename, "rt");
+	if (ptr == NULL) {
+		printf(" LEX-PARSE:> failed to open file: '%s'\n", filename);
+		return false;
+	}
+	// ----------------------------------------------------- //
+
+	// --- setting token buffer
+	mem_buffer< char > token_buf;
+	token_buf.reset();
+	// ----------------------------------------------------- //
+	
+	int nline = 1, fsym;
+	STATE state = IS_NULL;
+	bool hold_sym = false;
+	bool status = true;
+	// ----------------------------------------------------- //
+
+	// --- reading file
+	while (!feof(ptr))
+	{
+		// --- reading char from file
+		if (!hold_sym) fsym = fgetc(ptr);
+		else
+			hold_sym = false;
+
+		// --- processing null state
+		if (state == IS_NULL) 
+		{
+			// --- EOF
+			if (fsym == EOF) continue;
+			// --- newline
+			if (fsym == '\n') {
+				nline++;
+				continue;
+			}
+			// --- spaces
+			if (isspace(fsym)) continue;
+			// --- comment line symbol
+			if (fsym == '#') {
+				state = IS_COMMENT_LINE;
+				continue;
+			}
+			// --- string
+			if (fsym == '"') {
+				state = IS_STRING;
+				token_buf.append(fsym);
+				continue;
+			}
+			// --- '='
+			if (fsym == '=') {
+				state = IS_ASSIGNMENT;
+				token_buf.append(fsym);
+				continue;
+			}
+			// --- '!'
+			if (fsym == '!') {
+				state = IS_NOT_EQUAL;
+				token_buf.append(fsym);
+				continue;
+			}
+			// --- '&'
+			if (fsym == '&') {
+				state = IS_LOGICAL_AND;
+				token_buf.append(fsym);
+				continue;
+			}
+			// --- '|'
+			if (fsym == '|') {
+				state = IS_LOGICAL_OR;
+				token_buf.append(fsym);
+				continue;
+			}
+			// --- '<'
+			if (fsym == '<') {
+				state = IS_LESS_THAN;
+				token_buf.append(fsym);
+				continue;
+			}
+			// --- '>'
+			if (fsym == '>') {
+				state = IS_GREATER_THAN;
+				token_buf.append(fsym);
+				continue;
+			}
+			// --- '{','}'
+			if (fsym == '{') {
+				list.add("{", Lexeme::IS_BRACE_OPEN, nline);
+				continue;
+			}
+			if (fsym == '}') {
+				list.add("}", Lexeme::IS_BRACE_CLOSE, nline);
+				continue;
+			}
+			// --- '(', ')'
+			if (fsym == '(') {
+				list.add("(", Lexeme::IS_PAREN_OPEN, nline);
+				continue;
+			}
+			if (fsym == ')') {
+				list.add(")", Lexeme::IS_PAREN_CLOSE, nline);
+				continue;
+			}
+			// --- '[', ']'
+			if (fsym == '[') {
+				list.add("[", Lexeme::IS_BRACKET_OPEN, nline);
+				continue;
+			}
+			if (fsym == ']') {
+				list.add("]", Lexeme::IS_BRACKET_CLOSE, nline);
+				continue;
+			}
+			// --- ';'
+			if (fsym == ';') {
+				list.add(";", Lexeme::IS_SEMICOLON, nline);
+				continue;
+			}
+			// --- ','
+			if (fsym == ',') {
+				list.add(",", Lexeme::IS_COMMA, nline);
+				continue;
+			}
+			// --- '+'
+			if (fsym == '+') {
+				// --- checking for unary '+'
+				if (list.get_size() == 0) list.add("+", Lexeme::IS_OP_PLUS, nline);
+				else
+				{
+					if ((list.is_value(list.get_size() - 1)) ||
+						(list.get_type(list.get_size() - 1) == Lexeme::IS_NAME) ||
+						(list.get_type(list.get_size() - 1) == Lexeme::IS_PAREN_CLOSE) ||
+						(list.get_type(list.get_size() - 1) == Lexeme::IS_BRACKET_CLOSE))
+					{
+						list.add("+", Lexeme::IS_OP_ADD, nline);
+					}
+					else
+						list.add("+", Lexeme::IS_OP_PLUS, nline);
+				}
+				continue;
+			}
+			// --- '-'
+			if (fsym == '-') {
+				// --- checking for unary '-'
+				if (list.get_size() == 0) list.add("-", Lexeme::IS_OP_MINUS, nline);
+				else
+				{
+					if ((list.is_value(list.get_size() - 1)) ||
+						(list.get_type(list.get_size() - 1) == Lexeme::IS_NAME) ||
+						(list.get_type(list.get_size() - 1) == Lexeme::IS_PAREN_CLOSE) ||
+						(list.get_type(list.get_size() - 1) == Lexeme::IS_BRACKET_CLOSE))
+					{
+						list.add("-", Lexeme::IS_OP_SUB, nline);
+					}
+					else
+						list.add("-", Lexeme::IS_OP_MINUS, nline);
+				}
+				continue;
+			}
+			// --- '*'
+			if (fsym == '*') {
+				list.add("*", Lexeme::IS_OP_MUL, nline);
+				continue;
+			}
+			// --- '/'
+			if (fsym == '/') {
+				list.add("/", Lexeme::IS_OP_DIV, nline);
+				continue;
+			}
+			// --- '%'
+			if (fsym == '%') {
+				list.add("%", Lexeme::IS_OP_MOD, nline);
+				continue;
+			}
+			// --- '^'
+			if (fsym == '^') {
+				list.add("^", Lexeme::IS_OP_EXP, nline);
+				continue;
+			}
+			// --- name
+			if (isalpha(fsym) || fsym == '_')
+			{
+				state = IS_NAME;
+				token_buf.append(fsym);
+				continue;
+			}
+			// --- number
+			if (isdigit(fsym))
+			{
+				state = IS_NUMBER;
+				token_buf.append(fsym);
+				continue;
+			}
+
+			// --- unknown symbol
+			printf(" PARSE:> invalid symbol: '%c' (line, %i)\n", fsym, nline);
+			status = false;
+			break;
+		}
+		// ----------------------------------------------------- //
+
+		// --- assignment || comparsion (==)
+		if (state == IS_ASSIGNMENT)
+		{
+			if (fsym == '=') {
+				// found '=='
+				token_buf.append(fsym);
+				token_buf.append('\0');
+				list.add(token_buf.get_ptr(), Lexeme::IS_OP_EQ, nline);
+			}
+			else {
+				// found '='
+				token_buf.append('\0');
+				list.add(token_buf.get_ptr(), Lexeme::IS_ASSIGNMENT, nline);
+
+				hold_sym = true;
+			}
+
+			token_buf.reset();
+
+			state = IS_NULL;
+			continue;
+		}
+		// ----------------------------------------------------- //
+
+		// --- comparison (!=)
+		if (state == IS_NOT_EQUAL)
+		{
+			if (fsym == '=') {
+				// found '!='
+				token_buf.append(fsym);
+				token_buf.append('\0');
+				list.add(token_buf.get_ptr(), Lexeme::IS_OP_NEQ, nline);
+
+				token_buf.reset();
+				state = IS_NULL;
+				continue;
+			}
+
+			// --- unknown symbol
+			printf(" PARSE:> invalid symbol: '%c', expecting '=' (line, %i)\n", fsym, nline);
+			status = false;
+			break;
+		}
+		// ----------------------------------------------------- //
+
+		// --- logical (&&)
+		if (state == IS_LOGICAL_AND)
+		{
+			if (fsym == '&') {
+				// found '&&'
+				token_buf.append(fsym);
+				token_buf.append('\0');
+				list.add(token_buf.get_ptr(), Lexeme::IS_OP_LOGICAL_AND, nline);
+
+				token_buf.reset();
+				state = IS_NULL;
+				continue;
+			}
+
+			// --- unknown symbol
+			printf(" PARSE:> invalid symbol: '%c', expecting '&' (line, %i)\n", fsym, nline);
+			status = false;
+			break;
+		}
+		// ----------------------------------------------------- //
+
+		// --- logical (||)
+		if (state == IS_LOGICAL_OR)
+		{
+			if (fsym == '|') {
+				// found '||'
+				token_buf.append(fsym);
+				token_buf.append('\0');
+				list.add(token_buf.get_ptr(), Lexeme::IS_OP_LOGICAL_OR, nline);
+
+				token_buf.reset();
+				state = IS_NULL;
+				continue;
+			}
+
+			// --- unknown symbol
+			printf(" PARSE:> invalid symbol: '%c', expecting '|' (line, %i)\n", fsym, nline);
+			status = false;
+			break;
+		}
+		// ----------------------------------------------------- //
+
+		// --- comparison (<) || (<=)
+		if (state == IS_LESS_THAN)
+		{
+			if (fsym == '=') {
+				// found '<='
+				token_buf.append(fsym);
+				token_buf.append('\0');
+				list.add(token_buf.get_ptr(), Lexeme::IS_OP_LEQ, nline);
+			}
+			else {
+				// found '<'
+				token_buf.append('\0');
+				list.add(token_buf.get_ptr(), Lexeme::IS_OP_LT, nline);
+
+				hold_sym = true;
+			}
+
+			token_buf.reset();
+
+			state = IS_NULL;
+			continue;
+		}
+		// ----------------------------------------------------- //
+
+		// --- comparison (>) || (>=)
+		if (state == IS_GREATER_THAN)
+		{
+			if (fsym == '=') {
+				// found '>='
+				token_buf.append(fsym);
+				token_buf.append('\0');
+				list.add(token_buf.get_ptr(), Lexeme::IS_OP_GEQ, nline);
+			}
+			else {
+				// found '>'
+				token_buf.append('\0');
+				list.add(token_buf.get_ptr(), Lexeme::IS_OP_GT, nline);
+
+				hold_sym = true;
+			}
+
+			token_buf.reset();
+
+			state = IS_NULL;
+			continue;
+		}
+		// ----------------------------------------------------- //
+
+		// --- processing comment line
+		if (state == IS_COMMENT_LINE) 
+		{
+			// --- EOF
+			if (fsym == EOF) {
+				state = IS_NULL;
+				continue;
+			}
+			// --- new line
+			if (fsym == '\n') {
+				nline++;
+				state = IS_NULL;
+				continue;
+			}
+
+			// --- skipping all symbols
+			continue;
+		}
+		// ----------------------------------------------------- //
+
+		// --- processing string
+		if (state == IS_STRING) 
+		{
+			// --- EOF
+			if (fsym == EOF) {
+				// --- unknown symbol
+				token_buf.append('\0');
+				printf(" PARSE:> missing closing quotation mark (\") in string: '%s' (line, %i)\n", 
+					token_buf.get_ptr(), nline);
+				status = false;
+				break;
+			}
+			// --- adding all symbols
+			token_buf.append(fsym);
+			// --- closing string
+			if (fsym == '"')
+			{
+				token_buf.append('\0');
+
+				list.add(token_buf.get_ptr(), Lexeme::IS_STRING, nline);
+				token_buf.reset();
+				state = IS_NULL;
+			}
+			continue;
+		}
+		// ----------------------------------------------------- //
+
+		// --- processing name
+		if (state == IS_NAME) 
+		{
+			// --- adding alpha, numerals, '_' and '.'
+			if (isalnum(fsym) || (fsym == '_') || (fsym == '.')) {
+				token_buf.append(fsym);
+				continue;
+			}
+			// --- checking if last element is dot
+			if (token_buf.get_value(token_buf.get_size() - 1) == '.') 
+			{
+				token_buf.append('\0');
+				printf(" PARSE:> invalid name ending with '.': '%s' (line, %i)\n",
+					token_buf.get_ptr(), nline);
+				status = false;
+				break;
+			}
+			// --- closing name
+			token_buf.append('\0');
+
+			if ((!strcmp(token_buf.get_ptr(), "true")) ||
+				(!strcmp(token_buf.get_ptr(), "false")))
+			{
+				list.add(token_buf.get_ptr(), Lexeme::IS_BOOL, nline);
+			}
+			else if (!strcmp(token_buf.get_ptr(), "if"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_KEY_IF, nline);
+			else if (!strcmp(token_buf.get_ptr(), "then"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_KEY_THEN, nline);
+			else if (!strcmp(token_buf.get_ptr(), "else"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_KEY_ELSE, nline);
+			else if (!strcmp(token_buf.get_ptr(), "endif"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_KEY_ENDIF, nline);
+			else if (!strcmp(token_buf.get_ptr(), "while"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_KEY_WHILE, nline);
+			else if (!strcmp(token_buf.get_ptr(), "do"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_KEY_DO, nline);
+			else if (!strcmp(token_buf.get_ptr(), "enddo"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_KEY_ENDDO, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__sin"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_SIN_FUNCTION, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__cos"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_COS_FUNCTION, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__tan"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_TAN_FUNCTION, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__log"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_LOG_FUNCTION, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__sqrt"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_SQRT_FUNCTION, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__min"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_MIN_FUNCTION, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__max"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_MAX_FUNCTION, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__vecmin"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_VECMIN_FUNCTION, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__vecmax"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_VECMAX_FUNCTION, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__abs"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_ABS_FUNCTION, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__unirand"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_UNIRAND_FUNCTION, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__dot"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_DOT_PRODUCT_FUNCTION, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__l2norm"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_L2NORM_FUNCTION, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__cnorm"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_CNORM_FUNCTION, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__to_string"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_TO_STRING_FUNCTION, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__size"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_SIZE_FUNCTION, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__defined"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_DEFINED_FUNCTION, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__vector"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_VECTOR_CTOR, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__vector_const"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_VECTOR_CONST_CTOR, nline);
+			else if (!strcmp(token_buf.get_ptr(), "__vector_unirand"))
+				list.add(token_buf.get_ptr(), Lexeme::IS_VECTOR_UNIRAND_CTOR, nline);
+			else
+			{
+				if (!strncmp(token_buf.get_ptr(), "__", 2)) {
+					list.add(token_buf.get_ptr(), Lexeme::IS_COMMAND, nline);
+				}
+				else
+					list.add(token_buf.get_ptr(), Lexeme::IS_NAME, nline);
+			}
+
+			token_buf.reset();
+			state = IS_NULL;
+			hold_sym = true;
+			continue;
+		}
+		// ----------------------------------------------------- //
+
+		// --- processing number
+		if (state == IS_NUMBER) 
+		{
+			// --- adding digits
+			if (isdigit(fsym)) {
+				token_buf.append(fsym);
+				continue;
+			}
+			// --- changing state to fractional part
+			if (fsym == '.') {
+				token_buf.append(fsym);
+				state = IS_FRAC_NUMBER;
+				continue;
+			}
+			// --- changing state to exponent
+			if ((fsym == 'e') || (fsym == 'E')) {
+				token_buf.append(fsym);
+				state = IS_EXP_NUMBER;
+				continue;
+			}
+
+			// --- closing integer
+			token_buf.append('\0');
+			list.add(token_buf.get_ptr(), Lexeme::IS_INTEGER, nline);
+			
+			token_buf.reset();
+			state = IS_NULL;
+			hold_sym = true;
+			continue;
+		}
+		// ----------------------------------------------------- //
+
+		// --- processing fractional part
+		if (state == IS_FRAC_NUMBER)
+		{
+			// --- adding digits
+			if (isdigit(fsym)) {
+				token_buf.append(fsym);
+				continue;
+			}
+			// --- changing state to exponent
+			if ((fsym == 'e') || (fsym == 'E')) {
+				token_buf.append(fsym);
+				state = IS_EXP_NUMBER;
+				continue;
+			}
+			// --- closing floating point
+			token_buf.append('\0');
+			list.add(token_buf.get_ptr(), Lexeme::IS_FLOAT, nline);
+			
+			token_buf.reset();
+			state = IS_NULL;
+			hold_sym = true;
+			continue;
+		}
+
+		// --- processing exponent
+		if (state == IS_EXP_NUMBER)
+		{
+			// --- adding digits
+			if (isdigit(fsym)) {
+				token_buf.append(fsym);
+				continue;
+			}
+			// --- handing exponent sign
+			if (((fsym == '+') || (fsym == '-')) &&
+				((token_buf.get_value(token_buf.get_size() - 1) == 'e') ||
+				(token_buf.get_value(token_buf.get_size() - 1) == 'E')))
+			{
+				token_buf.append(fsym);
+				continue;
+			}
+			// --- closing floating point
+			token_buf.append('\0');
+			list.add(token_buf.get_ptr(), Lexeme::IS_FLOAT, nline);
+			
+			token_buf.reset();
+			state = IS_NULL;
+			hold_sym = true;
+			continue;
+		}
+
+		// unknown state
+		token_buf.append('\0');
+		printf(" PARSE:> invalid parser state: '%s' (line, %i)\n",
+			token_buf.get_ptr(), nline);
+		status = false;
+		break;
+	}
+
+
+	fclose(ptr);
+	return status;
+}
+// -------------------------------------------------------------------------------------------- //
diff --git a/parser/lexeme-parser.h b/parser/lexeme-parser.h
new file mode 100644
index 0000000..0bdc0e4
--- /dev/null
+++ b/parser/lexeme-parser.h
@@ -0,0 +1,49 @@
+#pragma once
+
+// [lexeme-parser.h]
+// -------------------------------------------------------------------------------------------- //
+// lexeme parser static class
+// -------------------------------------------------------------------------------------------- //
+
+#include "lexeme-list.h"
+
+
+namespace scm
+{
+
+	class LexemeParser {
+	public:
+		
+		// run --> get lexeme list
+		// -------------------------------------------------------------------------------------------- //
+		static bool run(const char* filename, LexemeList& list);
+		// -------------------------------------------------------------------------------------------- //
+
+	private:
+
+		// parser state
+		// -------------------------------------------------------------------------------------------- //
+		enum STATE {
+			IS_NULL,
+			IS_COMMENT_LINE,
+			IS_STRING,
+			IS_NAME,
+			IS_NUMBER,
+			IS_FRAC_NUMBER,
+			IS_EXP_NUMBER,
+			IS_ASSIGNMENT,
+			IS_LESS_THAN,
+			IS_GREATER_THAN,
+			IS_NOT_EQUAL,
+			IS_LOGICAL_AND,
+			IS_LOGICAL_OR,
+		};
+		// -------------------------------------------------------------------------------------------- //
+
+		// -------------------------------------------------------------------------------------------- //
+		LexemeParser();
+		~LexemeParser();
+		// -------------------------------------------------------------------------------------------- //
+	};
+}
+// -------------------------------------------------------------------------------------------- //
diff --git a/parser/lexeme.cpp b/parser/lexeme.cpp
new file mode 100644
index 0000000..08f781c
--- /dev/null
+++ b/parser/lexeme.cpp
@@ -0,0 +1,173 @@
+#include "lexeme.h"
+
+#define _CRT_SECURE_NO_WARNINGS
+#include <string.h>
+
+#include "scm-mem.h"
+
+// -------------------------------------------------------------------------------------------- //
+// * Implementation * //
+// -------------------------------------------------------------------------------------------- //
+
+scm::Lexeme::Lexeme()
+{
+	token = NULL;
+	type = IS_INVALID;
+	tag = 0;
+}
+
+scm::Lexeme::~Lexeme()
+{
+	clear();
+}
+
+scm::Lexeme::Lexeme(const Lexeme& lexeme)
+{
+	if (lexeme.token == NULL) token = NULL;
+	else
+	{
+		token = new char[strlen(lexeme.token) + 1];
+		strcpy(token, lexeme.token);
+	}
+
+	type = lexeme.type;
+	tag = lexeme.tag;
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * swap & assignment * //
+// -------------------------------------------------------------------------------------------- //
+const scm::Lexeme& scm::Lexeme::operator=(Lexeme lexeme)
+{
+	swap(lexeme);
+	return (*this);
+}
+
+void scm::Lexeme::swap(Lexeme& lexeme)
+{
+	scm::swap(token, lexeme.token);
+	scm::swap(type, lexeme.type);
+	scm::swap(tag, lexeme.tag);
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * set calls * //
+// -------------------------------------------------------------------------------------------- //
+void scm::Lexeme::set(const char* _token, const TYPE _type, const int _tag)
+{
+	clear();
+	if ((_token == NULL) || (_type == IS_INVALID)) return;
+
+	token = new char[strlen(_token) + 1];
+	strcpy(token, _token);
+
+	type = _type;
+	tag = _tag;
+}
+
+void scm::Lexeme::set(const char* _token, const TYPE _type)
+{
+	set(_token, _type, 0);
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * get calls * //
+// -------------------------------------------------------------------------------------------- //
+const char* scm::Lexeme::get_token() const
+{
+	return token;
+}
+
+scm::Lexeme::TYPE scm::Lexeme::get_type() const
+{
+	return type;
+}
+
+int scm::Lexeme::get_tag() const
+{
+	return tag;
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * clear * //
+// -------------------------------------------------------------------------------------------- //
+void scm::Lexeme::clear()
+{
+	if (token != NULL) delete[] token;
+
+	token = NULL;
+	type = IS_INVALID;
+	tag = 0;
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * check lexeme type * //
+// -------------------------------------------------------------------------------------------- //
+bool scm::Lexeme::is_operator() const
+{
+	return is_operator(type);
+}
+
+bool scm::Lexeme::is_function() const
+{
+	return is_function(type);
+}
+
+bool scm::Lexeme::is_ctor() const
+{
+	return is_ctor(type);
+}
+
+bool scm::Lexeme::is_value() const
+{
+	return is_value(type);
+}
+
+bool scm::Lexeme::is_operator(const Lexeme::TYPE type)
+{
+	return (
+		(type == IS_OP_ADD) || (type == IS_OP_SUB) ||
+		(type == IS_OP_MUL) || (type == IS_OP_DIV) || (type == IS_OP_MOD) ||
+		(type == IS_OP_PLUS) || (type == IS_OP_MINUS) ||
+		(type == IS_OP_EXP) ||
+		(type == IS_OP_EQ) || (type == IS_OP_NEQ) ||
+		(type == IS_OP_LOGICAL_AND)  || (type == IS_OP_LOGICAL_OR) ||
+		(type == IS_OP_LT) || (type == IS_OP_GT) ||
+		(type == IS_OP_LEQ) || (type == IS_OP_GEQ)
+		);
+}
+
+bool scm::Lexeme::is_function(const Lexeme::TYPE type)
+{
+	return (
+		(type == IS_SIN_FUNCTION) || (type == IS_COS_FUNCTION) ||
+		(type == IS_TAN_FUNCTION) || (type == IS_LOG_FUNCTION) ||
+		(type == IS_SQRT_FUNCTION) ||
+		(type == IS_MIN_FUNCTION) || (type == IS_MAX_FUNCTION) ||
+		(type == IS_VECMIN_FUNCTION) || (type == IS_VECMAX_FUNCTION) ||
+		(type == IS_ABS_FUNCTION) || (type == IS_UNIRAND_FUNCTION) ||
+		(type == IS_DOT_PRODUCT_FUNCTION) ||
+		(type == IS_L2NORM_FUNCTION) || (type == IS_CNORM_FUNCTION) ||
+		(type == IS_TO_STRING_FUNCTION) ||
+		(type == IS_SIZE_FUNCTION) || (type == IS_DEFINED_FUNCTION)
+		);
+}
+
+bool scm::Lexeme::is_ctor(const Lexeme::TYPE type)
+{
+	return (
+		(type == IS_VECTOR_CTOR) || 
+		(type == IS_VECTOR_CONST_CTOR) ||
+		(type == IS_VECTOR_UNIRAND_CTOR))
+		;
+}
+
+bool scm::Lexeme::is_value(const Lexeme::TYPE type)
+{
+	return (
+		(type == IS_INTEGER) || (type == IS_FLOAT) ||
+		(type == IS_BOOL) ||
+		(type == IS_STRING)
+		);
+}
+// -------------------------------------------------------------------------------------------- //
diff --git a/parser/lexeme.h b/parser/lexeme.h
new file mode 100644
index 0000000..60da98d
--- /dev/null
+++ b/parser/lexeme.h
@@ -0,0 +1,112 @@
+#pragma once
+
+// [lexeme.h]
+// -------------------------------------------------------------------------------------------- //
+// lexeme data class
+// -------------------------------------------------------------------------------------------- //
+
+namespace scm
+{
+	class Lexeme {
+	public:
+
+		// lexeme types
+		// -------------------------------------------------------------------------------------------- //
+		enum TYPE {
+			IS_INVALID,
+			IS_NAME,								// 
+			IS_ASSIGNMENT,							// =
+			IS_BRACE_OPEN, IS_BRACE_CLOSE,			// {}
+			IS_PAREN_OPEN, IS_PAREN_CLOSE,			// ()
+			IS_BRACKET_OPEN, IS_BRACKET_CLOSE,		// []
+			IS_SEMICOLON,							// ;
+			IS_COMMA,								// ,
+			IS_INTEGER, IS_FLOAT, IS_BOOL,			// 
+			IS_STRING,								//
+			IS_OP_ADD, IS_OP_SUB,					// +,-
+			IS_OP_MUL, IS_OP_DIV, IS_OP_MOD,		// *,/,%
+			IS_OP_PLUS, IS_OP_MINUS,				// +,-
+			IS_OP_EXP,								// ^
+			IS_OP_EQ, IS_OP_NEQ,					// ==, !=
+			IS_OP_LT, IS_OP_GT,						// <, >
+			IS_OP_LEQ, IS_OP_GEQ,					// <=, >=
+			IS_OP_LOGICAL_AND, IS_OP_LOGICAL_OR,	// &&, ||
+			IS_SIN_FUNCTION, IS_COS_FUNCTION,		// __sin, __cos
+			IS_TAN_FUNCTION,						// __tan
+			IS_LOG_FUNCTION,						// __log
+			IS_SQRT_FUNCTION,						// __sqrt
+			IS_MIN_FUNCTION, IS_MAX_FUNCTION,		// __min, __max
+			IS_VECMIN_FUNCTION, IS_VECMAX_FUNCTION,	// __vecmin, __vecmax
+			IS_ABS_FUNCTION,						// __abs
+			IS_UNIRAND_FUNCTION,					// __unirand
+			IS_DOT_PRODUCT_FUNCTION,				// __dot
+			IS_L2NORM_FUNCTION, IS_CNORM_FUNCTION,	// __l2norm, __cnorm
+			IS_TO_STRING_FUNCTION,					// __to_string
+			IS_SIZE_FUNCTION,						// __size
+			IS_DEFINED_FUNCTION,					// __defined
+			IS_COMMAND,								// __$
+			IS_VECTOR_CTOR,							// __vector
+			IS_VECTOR_CONST_CTOR,					// __vector_const
+			IS_VECTOR_UNIRAND_CTOR,					// __vector_unirand
+			IS_KEY_IF, IS_KEY_THEN,					// 'if', 'then'
+			IS_KEY_ELSE, IS_KEY_ENDIF,				// 'else', 'endif'
+			IS_KEY_WHILE,							// 'while'
+			IS_KEY_DO, IS_KEY_ENDDO					// 'do', 'enddo'
+		};
+		// -------------------------------------------------------------------------------------------- //
+
+	public:
+
+		// set calls
+		// -------------------------------------------------------------------------------------------- //
+		void set(const char* _token, const TYPE _type, const int _tag);
+		void set(const char* _token, const TYPE _type);
+		// -------------------------------------------------------------------------------------------- //
+
+		// get calls
+		// -------------------------------------------------------------------------------------------- //
+		const char* get_token() const;
+		TYPE get_type() const;
+		int get_tag() const;
+		// -------------------------------------------------------------------------------------------- //
+
+		// check lexeme type
+		// -------------------------------------------------------------------------------------------- //
+		bool is_operator() const;
+		bool is_function() const;
+		bool is_ctor() const;
+		bool is_value() const;
+
+		static bool is_operator(const Lexeme::TYPE type);
+		static bool is_function(const Lexeme::TYPE type);
+		static bool is_ctor(const Lexeme::TYPE type);
+		static bool is_value(const Lexeme::TYPE type);
+		// -------------------------------------------------------------------------------------------- //
+
+		// clear
+		// -------------------------------------------------------------------------------------------- //
+		void clear();
+		// -------------------------------------------------------------------------------------------- //
+
+		// swap & assignment
+		// -------------------------------------------------------------------------------------------- //
+		const Lexeme& operator=(Lexeme lexeme);
+		void swap(Lexeme& lexeme);
+		// -------------------------------------------------------------------------------------------- //
+
+		// -------------------------------------------------------------------------------------------- //
+		Lexeme();
+		Lexeme(const Lexeme& lexeme);
+		~Lexeme();
+		// -------------------------------------------------------------------------------------------- //
+
+	private:
+		// data (private):
+		// -------------------------------------------------------------------------------------------- //
+
+		char *token;
+		TYPE type;
+		int tag;
+	};
+	// -------------------------------------------------------------------------------------------- //
+}
diff --git a/parser/mem-buffer.h b/parser/mem-buffer.h
new file mode 100644
index 0000000..042e7b0
--- /dev/null
+++ b/parser/mem-buffer.h
@@ -0,0 +1,148 @@
+#pragma once
+
+// [mem-buffer.h]
+// -------------------------------------------------------------------------------------------- //
+// fast memory buffer for c primary data types
+// -------------------------------------------------------------------------------------------- //
+
+#include "scm-mem.h"
+
+#include <string.h>
+
+namespace scm
+{
+	template< typename T >
+	class mem_buffer {
+	public:
+
+		// append value
+		// -------------------------------------------------------------------------------------------- //
+		void append(const T value);
+		void append(const T* value, const int n);
+		// -------------------------------------------------------------------------------------------- //
+		
+		// reset
+		// -------------------------------------------------------------------------------------------- //
+		void reset();
+		// -------------------------------------------------------------------------------------------- //
+
+		// get calls
+		// -------------------------------------------------------------------------------------------- //
+		const T* get_ptr() const;
+		T get_value(const int idx) const;
+		int get_size() const;
+		// -------------------------------------------------------------------------------------------- //
+
+		// -------------------------------------------------------------------------------------------- //
+		mem_buffer();
+		~mem_buffer();
+		// -------------------------------------------------------------------------------------------- //
+
+	private:
+		// data (private):
+		// -------------------------------------------------------------------------------------------- //
+
+		T *buf;
+		int size;
+		int nalloc;
+
+		static const int c_nalloc_inc = 256;
+	};
+}
+// -------------------------------------------------------------------------------------------- //
+
+// -------------------------------------------------------------------------------------------- //
+// * Implementation *
+// -------------------------------------------------------------------------------------------- //
+
+template< typename T >
+scm::mem_buffer< T >::mem_buffer()
+{
+	size = 0;
+	nalloc = 0;
+}
+
+template< typename T >
+scm::mem_buffer< T >::~mem_buffer()
+{
+	if (nalloc > 0)
+		deallocate(buf);
+
+	nalloc = 0;
+	size = 0;
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * append * //
+// -------------------------------------------------------------------------------------------- //
+template< typename T >
+void scm::mem_buffer< T >::append(const T value)
+{
+	if (size == nalloc) {
+		T *lbuf;
+		allocate(&lbuf, nalloc + c_nalloc_inc);
+		if (size > 0) {
+			memcpy(lbuf, buf, size * sizeof(T));
+			deallocate(buf);
+		}
+
+		buf = lbuf;
+		nalloc += c_nalloc_inc;
+	}
+
+	buf[size] = value;
+	size++;
+}
+
+template< typename T >
+void scm::mem_buffer< T >::append(const T* value, const int n)
+{
+	if ((size - 1) + n >= nalloc) {
+		T *lbuf;
+		allocate(&lbuf, nalloc + max(c_nalloc_inc, size + n - nalloc));
+		if (size > 0) {
+			memcpy(lbuf, buf, size * sizeof(T));
+			deallocate(buf);
+		}
+
+		buf = lbuf;
+		nalloc += max(c_nalloc_inc, size + n - nalloc);
+	}
+
+	memcpy(&buf[size], value, n);
+	size += n;
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * reset * //
+// -------------------------------------------------------------------------------------------- //
+template< typename T >
+void scm::mem_buffer< T >::reset()
+{
+	size = 0;
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * get calls * //
+// -------------------------------------------------------------------------------------------- //
+template< typename T >
+const T* scm::mem_buffer< T >::get_ptr() const
+{
+	return buf;
+}
+
+template< typename T >
+T scm::mem_buffer< T >::get_value(const int idx) const
+{
+	if ((idx >= 0) && (idx < size))
+		return buf[idx];
+
+	return (T)0;
+}
+
+template< typename T >
+int scm::mem_buffer< T >::get_size() const
+{
+	return size;
+}
+// -------------------------------------------------------------------------------------------- //
diff --git a/parser/scm-mem.h b/parser/scm-mem.h
new file mode 100644
index 0000000..f80e349
--- /dev/null
+++ b/parser/scm-mem.h
@@ -0,0 +1,523 @@
+#pragma once
+
+// [scm-mem.h]
+// -------------------------------------------------------------------------------------------- //
+// memory handling, array ops & simple math
+// -------------------------------------------------------------------------------------------- //
+
+
+#include <stdlib.h>
+#include <math.h>
+#if defined(_OPENMP)
+#include <omp.h>
+#endif
+#include <time.h>
+#include "scm-sys.h"
+
+
+namespace scm
+{
+	// * memory (de)allocation * // 
+	// -------------------------------------------------------------------------------------------- //
+	template< typename T >
+	bool allocate(T** x, const int n);
+	template< typename T >
+	bool allocate(T** x, T** y, const int n);
+	template< typename T >
+	bool allocate(T** x, T** y, T** z, const int n);
+
+	template< typename T >
+	void deallocate(T* x);
+	template< typename T >
+	void deallocate(T* x, T* y);
+	template< typename T >
+	void deallocate(T* x, T* y, T* z);
+
+	template< typename T >
+	bool allocate_preset(T** x, const T value, const int n);
+	template< typename T >
+	bool allocate_preset(T** x, T** y, const T value, const int n);
+	template< typename T >
+	bool allocate_preset(T** x, T** y, T** z, const T value, const int n);
+	// -------------------------------------------------------------------------------------------- //
+
+	// * swap * //
+	template< typename T >
+	void swap(T& a, T& b);
+	// -------------------------------------------------------------------------------------------- //
+
+	// * math & vector operations * //
+	// -------------------------------------------------------------------------------------------- //
+	template< typename T >
+	T min(const T a, const T b);
+	template< typename T >
+	T max(const T a, const T b);
+	template< typename T >
+	T min(const T a, const T b, const T c);
+	template< typename T >
+	T max(const T a, const T b, const T c);
+	template< typename T >
+	T min(const T a, const T b, const T c, const T d);
+	template< typename T >
+	T max(const T a, const T b, const T c, const T d);
+
+	template< typename T >
+	T sgn(const T a);
+
+	template< typename T >
+	void assign(T* _RESTRICT x, const T value, const int n);
+	template< typename T >
+	void null(T* _RESTRICT x, const int n);
+	template< typename T >
+	void null(T* _RESTRICT x, T* _RESTRICT y, const int n);
+	template< typename T >
+	void null(T* _RESTRICT x, T* _RESTRICT y, T* _RESTRICT z, const int n);
+
+	template< typename T >
+	T max(const T* _RESTRICT x, const int n);
+	template< typename T >
+	T min(const T* _RESTRICT x, const int n);
+	template< typename T >
+	T avg(const T* _RESTRICT x, const int n);
+	template< typename T >
+	T intsum(const T* _RESTRICT f, const T* _RESTRICT dx, const int n);
+
+	template< typename T >
+	T interp(const T* _RESTRICT X, const T* _RESTRICT z, const int n, const T pz);
+	// -------------------------------------------------------------------------------------------- //
+	
+	// * vector checks * //
+	// -------------------------------------------------------------------------------------------- //
+	template< typename T >
+	bool is_finite(const T* _RESTRICT x, const int n);
+	// -------------------------------------------------------------------------------------------- //
+
+	// * timer * //
+	// -------------------------------------------------------------------------------------------- //
+	double get_sys_time();
+	// -------------------------------------------------------------------------------------------- //
+}
+
+
+// -------------------------------------------------------------------------------------------- //
+// * Implementation *
+// -------------------------------------------------------------------------------------------- //
+
+// * memory (de)allocation * //
+// -------------------------------------------------------------------------------------------- //
+template< typename T >
+inline bool scm::allocate(
+	T** x, const int n)
+{
+#ifndef ALIGN_ALLOCATION
+	(*x) = new T[n];
+#else
+#if defined(__INTEL_COMPILER)
+	(*x) = (T*)_mm_malloc(n * sizeof(T), ALIGN_ALLOCATION);
+	if (*x == NULL) return false;
+
+#elif defined(_MSC_VER)
+	(*x) = (T*)_aligned_malloc(n * sizeof(T), ALIGN_ALLOCATION);
+	if (*x == NULL) return false;
+
+#else // die or use posix //
+	if (posix_memalign((void**)x, ALIGN_ALLOCATION, n * sizeof(T)) != 0)
+		return false;
+#endif
+#endif
+
+	return true;
+}
+
+template< typename T >
+inline bool scm::allocate(
+	T** x, T** y, const int n)
+{
+	if (!allocate(x, n)) return false;
+	if (!allocate(y, n)) {
+		deallocate(*x);
+		return false;
+	}
+
+	return true;
+}
+
+template< typename T >
+inline bool scm::allocate(
+	T** x, T** y, T** z, const int n)
+{
+	if (!allocate(x, n)) return false;
+	if (!allocate(y, n)) {
+		deallocate(*x);
+		return false;
+	}
+	if (!allocate(z, n)) {
+		deallocate(*x);
+		deallocate(*y);
+		return false;
+	}
+
+	return true;
+}
+
+template< typename T >
+inline void scm::deallocate(
+	T* x)
+{
+#ifndef ALIGN_ALLOCATION
+	delete[] x;
+#else
+#if defined(__INTEL_COMPILER)
+	_mm_free((void*)x);
+#elif defined(_MSC_VER)
+	_aligned_free((void*)x);
+#else	// die or use posix //
+	free((void*)x);
+#endif
+#endif
+}
+
+template< typename T >
+inline void scm::deallocate(
+	T* x, T* y)
+{
+	deallocate(x);
+	deallocate(y);
+}
+
+template< typename T >
+inline void scm::deallocate(
+	T* x, T* y, T* z)
+{
+	deallocate(x);
+	deallocate(y);
+	deallocate(z);
+}
+
+template< typename T >
+inline bool scm::allocate_preset(
+	T** x, const T value, const int n)
+{
+	if (!allocate(x, n)) return false;
+
+	assign((*x), value, n);
+	return true;
+}
+
+template< typename T >
+inline bool scm::allocate_preset(
+	T** x, T** y, const T value, const int n)
+{
+	if (!allocate(x, y, n)) return false;
+
+	assign((*x), value, n);
+	assign((*y), value, n);
+	return true;
+}
+
+template< typename T >
+inline bool scm::allocate_preset(
+	T** x, T** y, T** z, const T value, const int n)
+{
+	if (!allocate(x, y, z, n)) return false;
+
+	assign((*x), value, n);
+	assign((*y), value, n);
+	assign((*z), value, n);
+	return true;
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * swap * //
+// -------------------------------------------------------------------------------------------- //
+template< typename T >
+inline void scm::swap(T& a, T& b)
+{
+	T c = a; a = b; b = c;
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * math & vector operations * //
+// -------------------------------------------------------------------------------------------- //
+template< typename T >
+inline T scm::min(
+	const T a, const T b)
+{
+	return (a < b) ? a : b;
+}
+
+template< typename T >
+inline T scm::max(
+	const T a, const T b)
+{
+	return (a > b) ? a : b;
+}
+
+template< typename T >
+inline T scm::min(
+	const T a, const T b, const T c)
+{
+	return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c);
+}
+
+template< typename T >
+inline T scm::max(
+	const T a, const T b, const T c)
+{
+	return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
+}
+
+template< typename T >
+inline T scm::min(
+	const T a, const T b, const T c, const T d)
+{
+	return min(min(a, b, c), d);
+}
+
+template< typename T >
+inline T scm::max(
+	const T a, const T b, const T c, const T d)
+{
+	return max(max(a, b, c), d);
+}
+
+template< typename T >
+inline T scm::sgn(
+	const T a)
+{
+	if (a < (T)0) return (T)-1.0;
+	if (a > (T)0) return (T)1.0;
+
+	return (T)0;
+}
+
+template< typename T >
+inline void scm::assign(
+	T* _RESTRICT x, const T value, const int n)
+{
+#pragma omp parallel shared( x )
+	{
+		int i;
+
+#pragma omp for nowait
+		for (i = 0; i < n - (n % 4); i += 4) {
+			x[i] = value;
+			x[i + 1] = value;
+			x[i + 2] = value;
+			x[i + 3] = value;
+		}
+
+#pragma omp single nowait
+		for (i = n - (n % 4); i < n; i++)
+			x[i] = value;
+	}
+}
+
+template< typename T >
+inline void scm::null(
+	T* _RESTRICT x, const int n)
+{
+#pragma omp parallel shared( x )
+	{
+		int i;
+
+#pragma omp for nowait
+		for (i = 0; i < n - (n % 4); i += 4) {
+			x[i] = (T)0;
+			x[i + 1] = (T)0;
+			x[i + 2] = (T)0;
+			x[i + 3] = (T)0;
+		}
+
+#pragma omp single nowait
+		for (i = n - (n % 4); i < n; i++)
+			x[i] = (T)0;
+	}
+}
+
+template< typename T >
+inline void scm::null(
+	T* _RESTRICT x, T* _RESTRICT y, const int n)
+{
+	null(x, n);
+	null(y, n);
+}
+
+template< typename T >
+inline void scm::null(
+	T* _RESTRICT x, T* _RESTRICT y, T* _RESTRICT z, const int n)
+{
+	null(x, n);
+	null(y, n);
+	null(z, n);
+}
+
+template< typename T >
+inline T scm::min(
+	const T* _RESTRICT const x, const int n)
+{
+	if (n <= 0) return (T)0;
+
+	int i;
+	T _min = (T)(*x);
+
+	T _min_local = (T)(*x);
+
+#pragma omp parallel firstprivate(_min_local) private(i) shared(_min)
+	{
+#pragma omp for nowait
+		for (i = 1; i < n; i++) {
+			if (x[i] < _min_local) _min_local = x[i];
+		}
+
+#pragma omp critical
+		{
+			if (_min_local < _min) _min = _min_local;
+		}
+	}
+
+	return _min;
+}
+
+template< typename T >
+inline T scm::max(
+	const T* _RESTRICT const x, const int n)
+{
+	if (n <= 0) return (T)0;
+
+	int i;
+	T _max = (T)(*x);
+
+	T _max_local = (T)(*x);
+
+#pragma omp parallel firstprivate(_max_local) private(i) shared(_max)
+	{
+#pragma omp for nowait
+		for (i = 1; i < n; i++) {
+			if (x[i] > _max_local) _max_local = x[i];
+		}
+
+#pragma omp critical
+		{
+			if (_max_local > _max) _max = _max_local;
+		}
+	}
+
+	return _max;
+}
+
+template< typename T >
+inline T scm::avg(
+	const T* _RESTRICT const x, const int n)
+{
+	if (n <= 0) return (T)0;
+
+	int i;
+	T _sum = (T)0;
+
+#pragma omp parallel for private( i ) reduction( + : _sum )
+	for (i = 0; i < n - (n % 4); i += 4) {
+		_sum += x[i] + x[i + 1] + x[i + 2] + x[i + 3];
+	}
+
+	for (i = n - (n % 4); i < n; i++)
+		_sum += x[i];
+
+	return _sum / n;
+}
+
+template< typename T >
+inline T scm::intsum(
+	const T* _RESTRICT const f, 
+	const T* _RESTRICT const dx,
+	const int n)
+{
+	if (n <= 0) return (T)0;
+
+	int i;
+	T _sum = (T)0;
+
+#pragma omp parallel for private( i ) reduction( + : _sum )
+	for (i = 0; i < n - (n % 4); i += 4) {
+		_sum += 
+			f[i] * dx[i] + f[i + 1] * dx[i + 1] + 
+			f[i + 2] * dx[i + 2] + f[i + 3] * dx[i + 3];
+	}
+
+	for (i = n - (n % 4); i < n; i++)
+		_sum += f[i] * dx[i];
+
+	return _sum;
+}
+
+template< typename T >
+inline T scm::interp(
+	const T* _RESTRICT X, 
+	const T* _RESTRICT z, const int n, 
+	const T pz)
+{
+	if (n == 0) return (T)0;
+	if (n == 1) return X[0];
+
+	int k;
+
+	k = 0;
+	if (pz < z[k]) {
+		// --- extrapolation, [zpos, zpos + dz/2):
+		T alpha = (z[k + 1] - pz) / (z[k + 1] - z[k]);
+		return alpha * X[k] + ((T)1.0 - alpha) * X[k + 1];
+	}
+
+	k = n - 1;
+	if (pz > z[k]) {
+		// --- extrapolation, (zpos + height - dz/2, zpos + height]
+		T alpha = (z[k] - pz) / (z[k] - z[k - 1]);
+		return alpha * X[k - 1] + ((T)1.0 - alpha) * X[k];
+	}
+
+	for (k = 0; k < n - 1; k++) {
+		if ((pz >= z[k]) && (pz <= z[k + 1]))
+		{
+			T alpha = (z[k + 1] - pz) / (z[k + 1] - z[k]);
+			return alpha * X[k] + ((T)1.0 - alpha) * X[k + 1];
+		}
+	}
+
+	return (T)0;
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * vector checks * //
+// -------------------------------------------------------------------------------------------- //
+template< typename T >
+inline bool scm::is_finite(
+	const T* _RESTRICT x, const int n)
+{
+	int i;
+	int num_inf = 0;
+
+#pragma omp parallel for private( i ) reduction( + : num_inf )
+	for (i = 0; i < n - (n % 4); i += 4) {
+		if ((!isfinite(x[i])) || (!isfinite(x[i + 1])) ||
+			(!isfinite(x[i + 2])) || (!isfinite(x[i + 3]))) num_inf++;
+	}
+
+	for (i = n - (n % 4); i < n; i++)
+		if (!isfinite(x[i])) num_inf++;
+
+	return (num_inf == 0);
+}
+// -------------------------------------------------------------------------------------------- //
+
+// * timer * //
+// -------------------------------------------------------------------------------------------- //
+inline double scm::get_sys_time()
+{
+#if defined(_OPENMP)
+	return omp_get_wtime();
+#else
+	return ((double)clock() / CLOCKS_PER_SEC);
+#endif
+}
+// -------------------------------------------------------------------------------------------- //
+
diff --git a/parser/scm-sys.h b/parser/scm-sys.h
new file mode 100644
index 0000000..2a982ba
--- /dev/null
+++ b/parser/scm-sys.h
@@ -0,0 +1,50 @@
+#pragma once
+
+// [scm-sys.h]
+// -------------------------------------------------------------------------------------------- //
+// system definitions
+// -------------------------------------------------------------------------------------------- //
+
+
+// : data type
+// -------------------------------------------------------------------------------------------- //
+#define Real double 
+// -------------------------------------------------------------------------------------------- //
+
+// : enable 'restrict' keyword
+// -------------------------------------------------------------------------------------------- //
+#define USE_RESTRICT_KEY  
+// -------------------------------------------------------------------------------------------- //
+
+// : aligned allocation, alignment defined in bytes (2^n values)
+// -------------------------------------------------------------------------------------------- //
+#define ALIGN_ALLOCATION	64
+// -------------------------------------------------------------------------------------------- //
+
+// : force number of OpenMP threads
+// :	else number of threads is determined by OMP_NUM_THREADS
+// -------------------------------------------------------------------------------------------- //
+#define SET_OPENMP_THREADS	1
+// -------------------------------------------------------------------------------------------- //
+
+// : NaN & Inf checks
+// -------------------------------------------------------------------------------------------- //
+#define SCM_CHECK_FINITE
+// -------------------------------------------------------------------------------------------- //
+
+// _RESTRICT definition 
+// -------------------------------------------------------------------------------------------- //
+#if defined(USE_RESTRICT_KEY)
+#if defined(__INTEL_COMPILER)
+#define _RESTRICT restrict
+#elif defined(__GNUC__) && !defined(_WIN32) && !defined(_CYGWIN32__)
+#define _RESTRICT __restrict__
+#elif defined(_MSC_VER)
+#define _RESTRICT __restrict
+#else
+#define _RESTRICT
+#endif
+#else
+#define _RESTRICT
+#endif
+// -------------------------------------------------------------------------------------------- //
-- 
GitLab