Intervall parseTermOfIntervals(string input){
    string::iterator it;
    int brackets = 0;
    int closedBrackets = 0;
    if(input=="")
        return 0;
    for(it=input.end();it>=input.begin();it--){
        if(*it=='(')
            brackets++;
        if(*it==')')
            brackets--;
        if(*it=='[')
            closedBrackets++;
        if(*it==']')
            closedBrackets--;
        if(*it=='|' && brackets==0 && closedBrackets==0){
            if(it==input.begin()){
                //Bin‰rem Operator fehlt Operand
                errorWindow("Operand missing!");
                return Intervall(NAN);
            }
            if(it+1==input.end()){
                //Bin‰rem Operator fehlt Operand
                errorWindow("Operand missing!");
                return Intervall(NAN);
            }
            string input1(input.begin(),it);
            string input2(it+1,input.end());
            Intervall result = parseTermOfIntervals(input1)||parseTermOfIntervals(input2);
            if(result.getInf()!=result.getInf()){
                errorWindow("Vereinigung disjunkter Intervalle!");
            }
            return result;
        }
    }
    for(it=input.end();it>=input.begin();it--){
        if(*it=='(')
            brackets++;
        if(*it==')')
            brackets--;
        if(*it=='[')
            closedBrackets++;
        if(*it==']')
            closedBrackets--;
        if(*it=='&' && brackets==0 && closedBrackets==0){
            if(it==input.begin()){
                //Bin‰rem Operator fehlt Operand
                errorWindow("Operand missing!");
                return Intervall(NAN);
            }
            if(it+1==input.end()){
                //Bin‰rem Operator fehlt Operand
                errorWindow("Operand missing!");
                return Intervall(NAN);
            }
            string input1(input.begin(),it);
            string input2(it+1,input.end());
            Intervall result = parseTermOfIntervals(input1)&&parseTermOfIntervals(input2);
            if(result.getInf()!=result.getInf()){
                errorWindow("Schnitt disjunkter Intervalle!");
            }
            return result;
        }
    }
    for(it=input.end();it>=input.begin();it--){
        if(*it=='(')
            brackets++;
        if(*it==')')
            brackets--;
        if(*it=='[')
            closedBrackets++;
        if(*it==']')
            closedBrackets--;
        if(*it=='+' && brackets==0 && closedBrackets==0 && *(it-1)!='/' && *(it-1)!='*' && *(it-1)!='-' && *(it-1)!='+'){
            if(it==input.begin()){
                string input2(it+1,input.end());
                return parseTermOfIntervals(input2);
            }
            if(it+1==input.end()){
                //Bin‰rem Operator fehlt Operand//
                errorWindow("Operand missing!");
                return Intervall(NAN);
            }
            string input1(input.begin(),it);
            string input2(it+1,input.end());
            return parseTermOfIntervals(input1)+parseTermOfIntervals(input2);
        }
        if(*it=='-' && brackets==0 && closedBrackets==0 && *(it-1)!='/' && *(it-1)!='*' && *(it-1)!='-' && *(it-1)!='+'){
            if(it==input.begin()){
                string input2(it+1,input.end());
                return Intervall(0)-parseTermOfIntervals(input2);
            }
            if(it+1==input.end()){
                //Bin‰rem Operator fehlt Operand//
                errorWindow("Operand missing!");
                return Intervall(NAN);
            }
            string input1(input.begin(),it);
            string input2(it+1,input.end());
            return parseTermOfIntervals(input1)-parseTermOfIntervals(input2);
        }
    }
    it=input.begin();
    if(*it=='('){
        brackets++;
        while(brackets>0){
            it++;
            if(*it=='(')
                brackets++;
            if(*it==')')
                brackets--;
        }
        it++;
        if(it==input.end()){
            string input1(input.begin()+1,input.end()-1);
            return parseTermOfIntervals(input1);
        }
        if(*it=='*'){
            string input1(input.begin()+1,it-1);
            if(it+1==input.end()){
                //Bin‰rem Operator fehlt Operand//
                errorWindow("Operand missing!");
                return Intervall(NAN);
            }
            string input2(it+1,input.end());
            return parseTermOfIntervals(input1)*parseTermOfIntervals(input2);
        }
        if(*it=='/'){
            string input1(input.begin()+1,it-1);
            if(it+1==input.end()){
                //Bin‰rem Operator fehlt Operand//
                errorWindow("Operand missing!");
                return Intervall(NAN);
            }
            string input2(it+1,input.end());
            Intervall result2 = parseTermOfIntervals(input2);
            if(result2.getInf()<=0 && result2.getSup()>=0){
                //Teilen durch 0!
                errorWindow("Division by zero!");
                return Intervall(NAN);
            }
            return parseTermOfIntervals(input1)/result2;
        }
    }
    if(*it=='*' || *it=='/'){
        //Bin‰rem Operator fehlt Operand//
        errorWindow("Operand missing!");
        return Intervall(NAN);
    }
    closedBrackets = 0;
    if(*it=='['){
        for(;it<input.end();it++){
            if(*it=='[')
                closedBrackets++;
            if(*it==']')
                closedBrackets--;
            if(*it=='*' && closedBrackets==0){
                string input1(input.begin(),it);
                string input2(it+1,input.end());
                return parseIntervals(input1)*parseTermOfIntervals(input2);
            }
            if(*it=='/' && closedBrackets==0){
                string input1(input.begin(),it);
                string input2(it+1,input.end());
                Intervall result2 = parseTermOfIntervals(input2);
                if(result2.getInf()<=0 && result2.getSup()>=0){
                    //Teilen durch 0!
                    errorWindow("Division by zero!");
                    return Intervall(NAN);
                }
                return parseIntervals(input1)/result2;
            }
        }
        return parseIntervals(input);
    }
    size_t found1 = input.find_first_of("*");
    if(found1!=string::npos){
        string input1 = input.substr(0,found1);
        string input2 = input.substr(found1+1);
        return parseNumbers(input1)*parseTermOfIntervals(input2);
    }
    size_t found2 = input.find_first_of("/");
    if(found2!=string::npos){
        string input1 = input.substr(0,found2);
        string input2 = input.substr(found2+1);
        Intervall result2 = parseTermOfIntervals(input2);
        if(result2.getInf()<=0 && result2.getSup()>=0){
            //Teilen durch 0!
            errorWindow("Division by zero!");
            return Intervall(NAN);
        }
        return parseNumbers(input1)/result2;
    }
    if(found1==string::npos && found2==string::npos){
        return parseNumbers(input);
    }

    errorWindow("42: "+input);
    return Intervall(NAN);
}
int main(int argc, char* argv[]) {

    unsigned int i = 0;
    unsigned int nbIntervals = 0;
    double* intervals = NULL;
    FILE* outputFileFd = NULL;
    gsl_rng* rng = NULL;
    unsigned int nbStates = 0;

    struct arg_file* outputFile = arg_file1("o", NULL, "<file>", "The output file for the generated initial state");
    struct arg_int* n = arg_int1("n", NULL, "<n>", "The number of initial states to generate");
    struct arg_str* s = arg_str1(NULL, "intervals", "<s>", "The intervals for the initial states generation");
    struct arg_end* end = arg_end(4);

    void* argtable[4];

    int nerrors = 0;

    argtable[0] = outputFile;
    argtable[1] = n;
    argtable[2] = s;
    argtable[3] = end;

    if(arg_nullcheck(argtable) != 0) {
        printf("error: insufficient memory\n");
        arg_freetable(argtable, 4);
        return EXIT_FAILURE;
    }

    nerrors = arg_parse(argc, argv, argtable);

    if(nerrors > 0) {
        printf("%s:", argv[0]);
        arg_print_syntax(stdout, argtable, "\n");
        arg_print_errors(stdout, end, argv[0]);
        arg_freetable(argtable, 4);
        return EXIT_FAILURE;
    }

    nbStates = n->ival[0];

    intervals = parseIntervals(s->sval[0], &nbIntervals);

    rng = gsl_rng_alloc(gsl_rng_mt19937);
    gsl_rng_set(rng, time(NULL));

    outputFileFd = fopen(outputFile->filename[0], "w");
    fprintf(outputFileFd, "%u\n", n->ival[0]);

    for(; i < nbStates; i++) {
        unsigned int j = 0;
        for(; j < (nbIntervals - 1); j++)
            fprintf(outputFileFd, "%.15f,", (fabs(intervals[(j * 2) + 1] - intervals[j * 2]) * gsl_rng_uniform(rng)) + intervals[j * 2]);
        fprintf(outputFileFd, "%.15f\n", (fabs(intervals[(j * 2) + 1] - intervals[j * 2]) * gsl_rng_uniform(rng)) + intervals[j * 2]);
    }

    fclose(outputFileFd);
	gsl_rng_free(rng);
    free(intervals);
    arg_freetable(argtable, 4);

    return EXIT_SUCCESS;

}