Operand (const Operand &cp) {
     action = cp.GetAction();
     variable = cp.GetVariable();
     time = cp.GetTime();
     location = cp.GetLocation();
     if (cp.GetTimeRange() != NULL) {
         time_range = new string[2];
         time_range[0] = cp.GetTimeRange()[0];
         time_range[1] = cp.GetTimeRange()[1];
     } else
         time_range = NULL;
     if (cp.GetNodeRange() != NULL) {
         node_range = new string[2];
         node_range[0] = cp.GetNodeRange()[0];
         node_range[1] = cp.GetNodeRange()[1];
     } else
         node_range = NULL;
 }
void SetVariable(string word,
                 Operand *&currod,
                 queue<Operand*> &ods,
                 stack<string> &bucket,
                 int *currop,
                 int *opcount,
                 register int &bracket_ct,
                 register int &currop_ind) {
    if (currod->GetVariable() == DefaultComponent) {
        currod->SetVariable(word);
    } else {
        Operand *od = new Operand(*currod);
        if (od->GetVariable() != DefaultComponent) {
            ods.push(od);
            opcount[currop_ind] += 1;
            if (opcount[currop_ind] == currop[currop_ind]) {
                FixMissingEntriesAndFillTheBucket(ods, bucket);
                bucket.push(OpenBracket);currop_ind--;opcount[currop_ind] += 1;bracket_ct--;
            }
        }
        ResetCurrentOperand(currod, word, DefaultAction, DefaultWhen, DefaultLocation, NULL, NULL);
    }
}
int main() {
    stack<string> tree_bucket;
    char command[100];
    gets(command);
    vector<string> words;
    stack<string> bucket;
    string nx_command = EmptyString;
    queue<Operand*> ods;
    queue<Operand*> temp;

    string cmd = command;
    cmd = ReplaceCommaBySpaceAnd(cmd);

    istringstream iss(cmd);
    while (getline(iss, cmd, ' '))
        words.push_back(cmd);

    string word;
    Operand *currod = new Operand();
    register int is_op, bracket_ct = 0, first_time = 0, currop_ind = -1;
    int currop[100];
    int opcount[100] = {0};

    for(register int i = 0; i < words.size(); i++) {
        word = words[i];
        //Set NX Command
        SetNXCmd(word, nx_command);
        //Check for operator
        is_op = IsPresentInOperators(word);
        if(is_op != -1) {
            bucket.push(ClosedBracket);bracket_ct++;
            bucket.push(operators[is_op][1]);
            currop[++currop_ind] = IsWhichOperator(operators[is_op][1]);
            //Check for subtraction if between/from interpretation
            CheckForAbnormalOperators(operators[is_op][1], i, words, bucket);
            //Find its operands
            i++;
            while (i < words.size()) {
                word = words[i];
                //Set NX Command
                SetNXCmd(word, nx_command);
                is_op = IsPresentInOperators(word);
                if (is_op != -1) {
                    if (((currod->GetVariable() != DefaultComponent) || (currod->GetAction() != DefaultAction)) && ((opcount[currop_ind]+1) == currop[currop_ind])) {

                    } else if (i != 0) {
                        if ((IsPartOfOperand(words[i-1])) || (IsStringANumber(words[i-1]))) {
                            bucket.push(ClosedBracket);bracket_ct++;
                            FillTheBucket(currod, bucket);
                            ResetCurrentOperand(currod);
                            bucket.push(operators[is_op][1]);
                            currop[++currop_ind] = IsWhichOperator(operators[is_op][1]);
                            opcount[currop_ind] += 1;
                            break;
                        }
                    }
                    Operand *od = new Operand(*currod);
                    ods.push(od);
                    opcount[currop_ind] += 1;
                    bool inside = FixMissingEntriesAndFillTheBucket(ods, bucket);
                    ResetCurrentOperand(currod);
                    if (inside == 1) {
                        if (opcount[currop_ind] == currop[currop_ind]) {
                            bucket.push(OpenBracket);
                            bucket.push(BlankSpace);
                            currop_ind--;bracket_ct--;
                            currop[++currop_ind] = IsWhichOperator(operators[is_op][1]);
                            if (currop[currop_ind] != 1) {
                                //Bracket resolution for this particular condition
                                PushBracketBackWhenOperator(bracket_ct, bucket);
                                //Bracket resolution is done
                                bucket.push(operators[is_op][1]);
                                CheckForAbnormalOperators(operators[is_op][1], i, words, bucket);
                            } else {
                                bucket.push(ClosedBracket);bracket_ct++;
                                bucket.push(operators[is_op][1]);
                                CheckForAbnormalOperators(operators[is_op][1], i, words, bucket);
                            }
                        } else {
                            bucket.push(BlankSpace);
                            i--;
                        }
                    }
                    else {
                            opcount[currop_ind] -= 1;
                            bucket.push(BlankSpace);
                            i--;
                    }
                    break;
                }
                if (IsVariable(word)) {
                    SetVariable(word, currod, ods, bucket, currop, opcount, bracket_ct, currop_ind);
                } else if (IsAction(word)) {
                    SetAction(word, currod, ods, bucket, currop, opcount, bracket_ct, currop_ind);
                } else if (IsLocation(word)) {
                    SetLocation(word, currod, words, i);
                } else if (IsTime(word)) {
                    SetTime(word, currod, words, i);
                }
                i++;
            }
        } else if(IsPartOfOperand(word)) {
            if ((currop_ind == -1) && (first_time == 0)) {
                bucket.push(ClosedBracket);bracket_ct++;first_time = 1;
            }
            //do operand part similar to above block. No need to check is empty or something
            if (IsVariable(word)) {
                SetVariable(word, currod, ods, bucket, currop, opcount, bracket_ct, currop_ind);
            } else if(IsAction(word)) {
                SetAction(word, currod, ods, bucket, currop, opcount, bracket_ct, currop_ind);
            } else if (IsLocation(word)) {
                SetLocation(word, currod, words, i);
            } else if (IsTime(word)) {
                SetTime(word, currod, words, i);
            }
        }
    }
    Operand *od = new Operand(*currod);
    ods.push(od);
    opcount[currop_ind] += 1;
    bool inside = FixMissingEntriesAndFillTheBucket(ods, bucket);
    if (inside == 0)
        opcount[currop_ind] -= 1;
    bucket.push(OpenBracket);bracket_ct--;
    if (bracket_ct > 0) {
        while (bracket_ct != 0) {
            bucket.push(OpenBracket);
            bracket_ct--;
        }
    }

    tree_bucket = bucket;
    /* Suppress Printing To Console */
    cout<<"---------------------------------------------------------------------------"<<endl;
    cout<<"NX Command: "<<nx_command<<endl;
    cout<<"Parsed Statement"<<endl;
    while (bucket.size() > 0) {
        cout<<bucket.top();
        bucket.pop();
    }
    cout<<endl<<"---------------------------------------------------------------------------"<<endl;
    cout<<endl<<endl;

    //Convert stack to tree
    tree_expression *root = new tree_expression();
    TreeConverter(tree_bucket, root);

    //Checking tree formation
    cout<<"Checking tree formation\n\n";
    CheckTreeFormation(root);

    return 0;
}
bool FixMissingEntriesAndFillTheBucket(queue<Operand*> &ods, stack<string> &bucket) {
    //Fix missing entries
    queue<Operand*> temp;
    register bool inside = 0;
    temp = ods;
    while (ods.size() != 1)
        ods.pop();
    Operand *tmpod = new Operand(*(ods.front()));
    string *rt = tmpod->GetTimeRange();
    string *rl = tmpod->GetNodeRange();
    string tact = tmpod->GetAction();
    string rtime = tmpod->GetTime();
    string rloc = tmpod->GetLocation();
    ods = temp;
    //pop entire queue
    string when = BlankSpace, loc = BlankSpace;
    while (ods.size() != 0) {
        when = BlankSpace, loc = BlankSpace;
        Operand *t = new Operand(*(ods.front()));
        when.append(t->GetTime());when.append(BlankSpace);
        loc.append(t->GetLocation()); loc.append(BlankSpace);
        if (t->GetTimeRange() == NULL) {
            t->SetTimeRange(rt);
        }
        if (t->GetNodeRange() == NULL)
            t->SetNodeRange(rl);
        if (t->GetAction() == DefaultAction)
            t->SetAction(tact);
        if (t->GetTime() == DefaultWhen)
            t->SetTime(rtime);
        if (t->GetLocation() == DefaultLocation)
            t->SetLocation(rloc);
        if (t->GetTimeRange() != NULL) {
            when.append(t->GetTimeRange()[0]);
            if (t->GetTimeRange()[1] != EmptyString) {
                when.append(ToKeyword);
                when.append(t->GetTimeRange()[1]);
            }
        } else {
            when.append(DefaultWhenValue);
        }
        if (t->GetNodeRange() != NULL) {
            loc.append(t->GetNodeRange()[0]);
            if (t->GetNodeRange()[1] != EmptyString) {
                loc.append(ToKeyword);
                loc.append(t->GetNodeRange()[1]);
            }
        } else {
            loc.append(DefaultLocationValue);
        }
        if ((t->GetVariable() != DefaultComponent) || (t->GetAction() != DefaultAction)) {
            inside = 1;
            bucket.push(BlankSpace);
            bucket.push(when);
            bucket.push(loc);
            bucket.push(t->GetAction());
            bucket.push(BlankSpace);
            bucket.push(t->GetVariable());
        }
        ods.pop();
    }
    return inside;
}