diff --git a/CMakeLists.txt b/CMakeLists.txt
index 83d6efe68b86491f205aff5173bf7c74410cd02c..1b6e12fbab6213f0133e489c10aab61be9d6c7fd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.20)
 
 project(ehigeneratorsa)
 
-set(SRC_FILES  main.cpp cap.cpp resistor.cpp model.cpp)
+set(SRC_FILES  main.cpp cap.cpp resistor.cpp model.cpp tokenize.cpp)
 
 find_package(PkgConfig REQUIRED)
 pkg_check_modules(SPICE REQUIRED ngspice)
@@ -10,6 +10,6 @@ pkg_check_modules(SPICE REQUIRED ngspice)
 add_executable(${PROJECT_NAME} ${SRC_FILES})
 target_link_libraries(${PROJECT_NAME} ${SPICE_LIBRARIES})
 target_include_directories(${PROJECT_NAME} PUBLIC ${SPICE_CFLAGS} .)
-set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-std=c++20 -Wall -O3 -march=native" LINK_FLAGS "-flto")
+set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-std=c++20 -Wall -O0 -march=native -g" LINK_FLAGS "-flto")
 
 install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
diff --git a/cap.cpp b/cap.cpp
index b5b35b91cfd27f5db18b8afc4bf0cb222a426833..447d5641fcb25ba4efbd34172dfda5ca135f82e5 100644
--- a/cap.cpp
+++ b/cap.cpp
@@ -1,11 +1,53 @@
 #include "cap.h"
+#include "tokenize.h"
+#include <cstdlib>
+#include <math.h>
 
 Cap::Cap(double c): _C(c)
 {
 
 }
 
+Cap::Cap(std::string paramStr)
+{
+	std::vector<std::string> tokens = tokenize(paramStr, ',');
+	if(tokens.empty())
+	{
+		std::cout<<"Warning: to few parameters in "<<__func__<<" parameter string: "<<paramStr<<'\n';
+		_C = 1e-6;
+		return;
+	}
+	else
+	{
+		try
+		{
+			_C = std::stod(tokens[0]);
+		}
+		catch(const std::invalid_argument& ia)
+		{
+			std::cout<<"Warning: cant parse parameter in "<<__func__<<" parameter: "<<tokens[0]<<'\n';
+			_C = 1e3;
+		}
+	}
+}
+
 std::complex<double> Cap::execute(double omega)
 {
 	return std::complex<double>(0, 0.0-(1.0/(_C*omega)));
 }
+
+std::vector<double> Cap::getParam()
+{
+	return std::vector<double>({_C});
+}
+
+void Cap::setParam(const std::vector<double>& param)
+{
+	if(param.empty())
+	{
+		std::cout<<"Warning: invalid parameter list sent to "<<__func__<<'\n';
+		return;
+	}
+
+	_C = param[0];
+}
diff --git a/cap.h b/cap.h
index accff8773824b3cd632c7584c06687ec5f7a1ff5..95c7bb2e6a1797df9525be61eed1817a2cb94326 100644
--- a/cap.h
+++ b/cap.h
@@ -1,5 +1,7 @@
 #pragma once
 #include <complex>
+#include <string>
+#include <vector>
 #include "componant.h"
 
 class Cap: public Componant
@@ -7,6 +9,9 @@ class Cap: public Componant
 private:
 	double _C;
 public:
-	Cap(double c);
+	Cap(std::string paramStr);
+	Cap(double c = 1e-6);
 	virtual std::complex<double> execute(double omega) override;
+	virtual std::vector<double> getParam() override;
+	virtual void setParam(const std::vector<double>& param) override;
 };
diff --git a/componant.h b/componant.h
index e026c9a5002bbb24e6998cbaa7b52c2bd376ce00..c5f3a53b929643d8dea456d3cf10ee7408a6a1ca 100644
--- a/componant.h
+++ b/componant.h
@@ -1,6 +1,7 @@
 #pragma once
 #include <complex>
 #include <iostream>
+#include <vector>
 
 class Componant
 {
@@ -10,4 +11,10 @@ class Componant
 			std::cout<<"warning incompleat model\n";
 			return std::complex<double> (1,0);
 		}
+
+		virtual std::vector<double> getParam()
+		{
+			return std::vector<double>();
+		};
+		virtual void setParam(const std::vector<double>& param){};
 };
diff --git a/main.cpp b/main.cpp
index cdd51fafa175cbdc4ae48d3078ba0a930feb8eae..7f83be72605ad92c890f6242f0887e36a0b301c9 100644
--- a/main.cpp
+++ b/main.cpp
@@ -11,12 +11,11 @@ double omegafn(size_t i)
 
 int main(int argc, char** argv)
 {
-	std::vector<double> params = {1.0e3, 1.0e-6, 1.0e3, 1.0e-6};
-	std::string modelStr("r-(c-r)r-(cr-(rc-r))");
+	std::string modelStr("r{1e3}-(c{1e-6}r{1e3})");
 
 	std::vector<Model::DataPoint> results;
 
-	Model model(modelStr, params);
+	Model model(modelStr);
 	auto start = std::chrono::high_resolution_clock::now();
 	for(size_t i = 0; i < 50; ++i)
 		results.push_back(model.execute(omegafn(i)));
diff --git a/model.cpp b/model.cpp
index 017db9c155799b0f4ae66fc714f0ced0c5c42948..375ce2741e37366d16f894e18b911d99c93b2145 100644
--- a/model.cpp
+++ b/model.cpp
@@ -32,11 +32,11 @@ std::complex<double> Model::Serial::execute(double omega)
 	return accum;
 }
 
-size_t Model::opposingBraket(const std::string& str, size_t index)
+size_t Model::opposingBraket(const std::string& str, size_t index, char bracketChar)
 {
 	for(size_t i = index; i < str.size(); ++i)
 	{
-		if(str[i] == ')')
+		if(str[i] == bracketChar)
 			return i;
 	}
 	return std::string::npos;
@@ -62,19 +62,19 @@ size_t Model::deepestBraket(const std::string& str)
 	return deepestPos;
 }
 
-Componant *Model::processBrackets(std::string& str, size_t& bracketCounter, const std::vector<double>& param)
+Componant *Model::processBrackets(std::string& str, size_t& bracketCounter)
 {
 	size_t bracketStart = deepestBraket(str);
 	std::cout<<str<<" bracket start "<<(bracketStart == std::string::npos ? std::string("npos") :  std::to_string(bracketStart))<<'\n';
 
 	if(bracketStart == std::string::npos)
 	{
-		Componant* componant = processBracket(str, param);
+		Componant* componant = processBracket(str);
 		if(!componant)
 		{
-			std::cout<<"Warning: can not create componant for "<<str;
+			std::cout<<"Warning: can not create componant type B for "<<str<<'\n';
 		}
-		return processBracket(str, param);
+		return componant;
 	}
 
 	size_t bracketEnd = opposingBraket(str, bracketStart);
@@ -84,58 +84,83 @@ Componant *Model::processBrackets(std::string& str, size_t& bracketCounter, cons
 		return nullptr;
 	}
 
-	std::string bracket = str.substr(bracketStart+1, bracketEnd-1);
+	std::string bracket = str.substr(bracketStart+1, bracketEnd-1-bracketStart);
 
-	Componant* componant = processBracket(bracket, param);
-	_bracketComponants.push_back(processBracket(bracket, param));
+	Componant* componant = processBracket(bracket);
 	if(!componant)
 	{
-		std::cout<<"Warning: can not create componant for "<<bracket;
+		std::cout<<"Warning: can not create componant type A for "<<bracket<<'\n';
 	}
+	_bracketComponants.push_back(componant);
 
 	str.erase(str.begin()+bracketStart, str.begin()+bracketEnd+1);
 	str.insert(str.begin()+bracketStart, bracketCounter+48);
 	++bracketCounter;
-	return processBrackets(str, bracketCounter, param);
+	return processBrackets(str, bracketCounter);
 }
 
-Componant *Model::processBracket(std::string& str, const std::vector<double>& param)
+std::string Model::getParamStr(const std::string& str, size_t index)
 {
-	std::vector<std::string> tokens = tokenize(str, '-');
+	if(str.size()-index < 3 || str[index+1] != '{')
+	{
+		std::cout<<"Warning: missing parameter for "<<str[index]<<'\n';
+		return 0;
+	}
 
-	std::vector<Componant*> nodes;
+	size_t end = opposingBraket(str, index, '}');
+	std::string parameterStr = str.substr(index+2, end-index-2);
+	std::cout<<"param for "<<str[index]<<' '<<parameterStr<<'\n';
+	return parameterStr;
+}
+
+Componant *Model::processBracket(std::string& str)
+{
+	std::cout<<__func__<<'('<<str<<")\n";
+	std::vector<std::string> tokens = tokenize(str, '-', '{', '}');
 
-	size_t paramCounter = 0;
+	std::vector<Componant*> nodes;
 
 	for(const std::string& nodeStr : tokens)
 	{
+		std::cout<<__func__<<" full node str: "<<nodeStr<<'\n';
 		std::vector<Componant*> componants;
-		for(char c : nodeStr)
+		for(size_t i = 0; i < nodeStr.size(); ++i)
 		{
-			if(paramCounter >= param.size())
-				break;
-			switch(c)
+			std::cout<<__func__<<" arg: "<<nodeStr[i]<<'\n';
+			switch(nodeStr[i])
 			{
 				case 'c':
 				case 'C':
-					componants.push_back(new Cap(1e-6));
+					componants.push_back(new Cap(getParamStr(nodeStr, i)));
+					i = opposingBraket(nodeStr, i, '}');
 					break;
 				case 'r':
 				case 'R':
-					componants.push_back(new Resistor(1e3));
+					componants.push_back(new Resistor(getParamStr(nodeStr, i)));
+					i = opposingBraket(nodeStr, i, '}');
+					break;
+				case '{':
+					i = opposingBraket(nodeStr, i, '}');
+				case '}':
+					std::cout<<"Warning: stray "<<nodeStr[i]<<" in model string\n";
 					break;
 				case '0' ... '9':
 				{
-					size_t i = c-48;
-					if(_bracketComponants.size() > i)
-						componants.push_back(_bracketComponants[i]);
+					size_t j = nodeStr[i]-48;
+					if(_bracketComponants.size() > j)
+						componants.push_back(_bracketComponants[j]);
 					break;
 				}
 				default:
 					break;
 			}
 		}
-		nodes.push_back(new Paralell(componants));
+		if(componants.size() > 1)
+			nodes.push_back(new Paralell(componants));
+		else if(componants.size() == 1)
+			nodes.push_back(componants[0]);
+		else
+			std::cout<<"Warning: empty node for "<<nodeStr<<'\n';
 	}
 
 	if(nodes.size() > 1)
@@ -146,11 +171,11 @@ Componant *Model::processBracket(std::string& str, const std::vector<double>& pa
 		return nullptr;
 }
 
-Model::Model(const std::string& str, const std::vector<double>& param)
+Model::Model(const std::string& str): _modelStr(str)
 {
 	size_t bracketCounter = 0;
 	std::string strCpy(str);
-	_model = processBrackets(strCpy, bracketCounter, param);
+	_model = processBrackets(strCpy, bracketCounter);
 }
 
 Model::DataPoint Model::execute(double omega)
@@ -163,6 +188,8 @@ Model::DataPoint Model::execute(double omega)
 		return dataPoint;
 	}
 	else
+	{
 		std::cout<<"Warning: model not ready\n";
+	}
 	return DataPoint({std::complex<double>(0,0), 0});
 }
diff --git a/model.h b/model.h
index 4d6e439ce70451a769593bcccdd921cb06c6c55c..bee488ed2c6a227542ea518f0d7052b86cdc7931 100644
--- a/model.h
+++ b/model.h
@@ -33,16 +33,21 @@ private:
 		virtual std::complex<double> execute(double omaga) override;
 	};
 
-	size_t opposingBraket(const std::string& str, size_t index);
+	size_t opposingBraket(const std::string& str, size_t index, char bracketChar = ')');
 	size_t deepestBraket(const std::string& str);
-	Componant *processBrackets(std::string& str, size_t& bracketCounter, const std::vector<double>& param);
-	Componant *processBracket(std::string& str, const std::vector<double>& param);
+	Componant *processBrackets(std::string& str, size_t& bracketCounter);
+	Componant *processBracket(std::string& str);
+	std::string getParamStr(const std::string& str, size_t index);
 
 private:
 	Componant *_model = nullptr;
 	std::vector<Componant*> _bracketComponants;
+	std::string _modelStr;
+	std::vector<Componant*> _flatComponants;
 
 public:
-	Model(const std::string& str, const std::vector<double>& params);
+	Model(const std::string& str);
 	DataPoint execute(double omaga);
+	std::string getModelStr();
+	std::vector<Componant*> getFlatComponants();
 };
diff --git a/resistor.cpp b/resistor.cpp
index 6db453f1ba5b04ff746e657f90465ca586e14110..d9b33b32a3235ff3b2f21487b42020b0097bed39 100644
--- a/resistor.cpp
+++ b/resistor.cpp
@@ -1,10 +1,52 @@
 #include "resistor.h"
+#include "tokenize.h"
+#include <vector>
+#include <math.h>
 
 Resistor::Resistor(double r): _R(r)
 {}
 
+Resistor::Resistor(std::string paramStr)
+{
+	std::vector<std::string> tokens = tokenize(paramStr, ',');
+	if(tokens.empty())
+	{
+		std::cout<<"Warning: to few parameters in "<<__func__<<" parameter string: "<<paramStr<<'\n';
+		_R = 1e3;
+		return;
+	}
+	else
+	{
+		try
+		{
+			_R = std::stod(tokens[0]);
+		}
+		catch(const std::invalid_argument& ia)
+		{
+			std::cout<<"Warning: cant parse parameter in "<<__func__<<" parameter: "<<tokens[0]<<'\n';
+			_R = 1e3;
+		}
+	}
+}
+
 std::complex<double> Resistor::execute(double omega)
 {
 	(void)omega;
 	return std::complex<double>(_R, 0);
 }
+
+std::vector<double> Resistor::getParam()
+{
+	return std::vector<double>({_R});
+}
+
+void Resistor::setParam(const std::vector<double>& param)
+{
+	if(param.empty())
+	{
+		std::cout<<"Warning: invalid parameter list sent to "<<__func__<<'\n';
+		return;
+	}
+
+	_R = param[0];
+}
diff --git a/resistor.h b/resistor.h
index dd9a500f1406c0306bcea8729e95dcf6097bd4c8..0f9d2cd2c73e723ddd5274264d3090127fb991fd 100644
--- a/resistor.h
+++ b/resistor.h
@@ -1,5 +1,6 @@
 #pragma once
 #include "componant.h"
+#include <string>
 
 class Resistor: public Componant
 {
@@ -8,5 +9,8 @@ private:
 
 public:
 	Resistor(double r);
+	Resistor(std::string paramStr);
 	virtual std::complex<double> execute(double omega)  override;
+	virtual std::vector<double> getParam() override;
+	virtual void setParam(const std::vector<double>& param) override;
 };
diff --git a/tokenize.cpp b/tokenize.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f09da75ba3233d51c0501535cae2281c8d3f9c13
--- /dev/null
+++ b/tokenize.cpp
@@ -0,0 +1,30 @@
+#include "tokenize.h"
+
+std::vector<std::string> tokenize(const std::string& str, const char delim, const char ignBracketStart, const char ignBracketEnd)
+{
+	std::stringstream ss(str);
+	std::vector<std::string> tokens;
+
+	std::string token;
+	size_t bracketCounter = 0;
+	for(char ch : str)
+	{
+		if(ch == delim && bracketCounter == 0)
+		{
+			tokens.push_back(token);
+			token.clear();
+		}
+		else
+		{
+			token.push_back(ch);
+		}
+
+		if(ignBracketStart == ch)
+			++bracketCounter;
+		else if(ignBracketEnd == ch)
+			--bracketCounter;
+	}
+	if(bracketCounter == 0)
+		tokens.push_back(token);
+	return tokens;
+}
diff --git a/tokenize.h b/tokenize.h
index b0af8346b945a164fa384d0771a4d6117d9c07d1..5f36a46bfc73ef851a72abb638c739f8c27839cf 100644
--- a/tokenize.h
+++ b/tokenize.h
@@ -1,14 +1,6 @@
+#pragma once
 #include <string>
 #include <vector>
 #include <sstream>
 
-std::vector<std::string> tokenize(const std::string& str, const char delim = ' ')
-{
-	std::stringstream ss(str);
-	std::vector<std::string> tokens;
-
-	std::string token;
-	while(getline(ss, token, delim))
-		tokens.push_back(token);
-	return tokens;
-}
+std::vector<std::string> tokenize(const std::string& str, const char delim = ' ', const char ignBracketStart = '\0', const char ignBracketEnd = '\0');