#include <TString.h>
#include <TObjString.h>
#include <TObjArray.h>
#include "AliLog.h"
#include "AliRsnVariableExpression.h"
#include "AliRsnExpression.h"
ClassImp(AliRsnExpression)
AliRsnCutSet *AliRsnExpression::fgCutSet = 0;
AliRsnExpression::AliRsnExpression(TString exp) :
TObject(),
fVname(""),
fArg1(0x0),
fArg2(0x0),
fOperator(0)
{
TObjArray *tokens = Tokenize(exp);
Int_t i = -1;
AliRsnExpression *e = Expression(*tokens, i);
fArg1 = e->fArg1; e->fArg1 = 0;
fArg2 = e->fArg2; e->fArg2 = 0;
fOperator = e->fOperator;
fVname = e->fVname;
delete e;
delete tokens;
}
AliRsnExpression::~AliRsnExpression()
{
if (fArg1) delete fArg1;
if (fArg2) delete fArg2;
}
AliRsnExpression::AliRsnExpression(const AliRsnExpression &exp) : TObject(exp),
fVname(exp.fVname),
fArg1(exp.fArg1),
fArg2(exp.fArg2),
fOperator(exp.fOperator)
{}
AliRsnExpression &AliRsnExpression::operator= (const AliRsnExpression &e)
{
if (this != &e) {
TObject::operator= (e);
fArg1 = e.fArg1;
fArg2 = e.fArg2;
fOperator = e.fOperator;
fVname = e.fVname;
}
return *this;
}
AliRsnExpression::AliRsnExpression(int op, AliRsnExpression *a, AliRsnExpression *b) :
TObject(),
fVname(""),
fArg1(a),
fArg2(b),
fOperator(op)
{
}
AliRsnExpression::AliRsnExpression(int op, AliRsnExpression *a) :
TObject(),
fVname(""),
fArg1(0),
fArg2(a),
fOperator(op)
{
}
Bool_t AliRsnExpression::Value(TObjArray &vars)
{
if (fArg2 == 0 && fVname.IsNull()) {
AliError("Expression undefined.");
return kFALSE;
}
switch (fOperator) {
case kOpOR :
return fArg1->Value(vars) || fArg2->Value(vars);
case kOpAND :
return fArg1->Value(vars) && fArg2->Value(vars);
case kOpNOT :
return !(fArg2->Value(vars));
case 0 : {
AliDebug(AliLog::kDebug, Form("Vname %s", fVname.Data()));
return fgCutSet->GetBoolValue(fVname.Atoi());
}
default:
AliError("Illegal operator in expression!");
}
return kFALSE;
}
TString AliRsnExpression::Unparse() const
{
TString opVals[4] = { "", "&", "|", "!" };
if (fArg2 == 0 && fVname.IsNull()) {
AliError("Expression undefined.");
return "Error";
}
if (fArg2 == 0 && !fVname.IsNull()) return fVname;
if (fArg1 == 0 && fArg2) {
return opVals[fOperator] + fArg2->Unparse();
}
return "(" + fArg1->Unparse() + " " + opVals[fOperator] + " " + fArg2->Unparse() + ")";
}
TObjArray *AliRsnExpression::Tokenize(TString str) const
{
TString str1;
for (Int_t i = 0; i < str.Length(); i++) {
if (str[i] == ' ') continue;
str1.Append(str[i]);
}
TObjArray *valtok = str1.Tokenize("!&|()");
Int_t nvt = valtok->GetEntriesFast();
TString sumval;
for (Int_t i = 0; i < nvt; i++) {
TObjString *val = (TObjString *) valtok->At(i);
sumval.Append(val->String());
}
TObjArray *optok = str1.Tokenize(sumval.Data());
TString operators;
Int_t nopt = optok->GetEntriesFast();
for (Int_t i = 0; i < nopt; i++) {
TObjString *val1 = (TObjString *) optok->At(i);
operators.Append(val1->String());
}
TObjString *blank = new TObjString(" ");
operators.Append(" ");
valtok->AddLast(blank);
TObjArray *tokens = new TObjArray(valtok->GetEntriesFast() + operators.Length());
int io = 0, iv = 0;
int index = 0;
while (1) {
TString so = operators[io];
int indexO = str1.Index(so, index);
TString val2 = ((TObjString *) valtok->At(iv))->String();
int indexV = str1.Index(val2, index);
if ((indexO < indexV || indexV < 0) && indexO >= 0) {
tokens->AddLast(new TObjString(so));
index += so.Length();
io++;
}
if ((indexV < indexO || indexO < 0) && indexV >= 0) {
tokens->AddLast(new TObjString(val2));
index += val2.Length();
iv++;
}
if (index >= str1.Length()) break;
}
delete valtok;
delete optok;
return tokens;
}
AliRsnExpression *AliRsnExpression::Element(TObjArray &st, Int_t &i)
{
AliRsnExpression *result = 0;
Int_t nt = st.GetEntriesFast();
TString token = "@";
TObjString *valt;
if (i < nt - 1) {
i++;
valt = (TObjString *) st.At(i);
token = valt->String();
}
char ttok = (token[0] != '|' && token[0] != '&' &&
token[0] != '!' && token[0] != '(' && token[0] != ')') ? 'w' : token[0];
switch (ttok) {
case 'w' : {
result = new AliRsnVariableExpression(token);
break;
}
case '(' :
result = Expression(st, i);
if (i < nt - 1) {
i++;
valt = (TObjString *) st.At(i);
token = valt->String();
}
if (token[0] != ')') {
AliErrorGeneral("AliRsnExpression::Element", "Mismatched parenthesis.");
delete result;
result = new AliRsnExpression;
}
break;
default:
i--;
AliErrorGeneral("AliRsnExpression::Element", Form("Unexpected symbol on input. %s", token.Data()));
result = new AliRsnExpression;
}
return result;
}
AliRsnExpression *AliRsnExpression::Primary(TObjArray &st, Int_t &i)
{
Int_t nt = st.GetEntriesFast();
TString token = "@";
TObjString *valt;
if (i < nt - 1) {
i++;
valt = (TObjString *) st.At(i);
token = valt->String();
}
switch (token[0]) {
case '!' :
return new AliRsnExpression(kOpNOT, Primary(st, i));
default:
i--;
return Element(st, i);
}
}
AliRsnExpression *AliRsnExpression::Expression(TObjArray &st, Int_t &i)
{
AliRsnExpression *result = 0;
Bool_t done = kFALSE;
TString token;
TObjString *valt;
static int stack = 0;
stack++;
Int_t nt = st.GetEntriesFast();
result = Primary(st, i);
while (! done) {
if (i < nt - 1) i++;
else break;
valt = (TObjString *) st.At(i);
token = valt->String();
switch (token[0]) {
case '&' :
result = new AliRsnExpression(kOpAND, result, Primary(st, i));
break;
case '|' :
result = new AliRsnExpression(kOpOR, result, Primary(st, i));
break;
default:
done = kTRUE;
i--;
break;
}
}
stack--;
if (stack == 0 && !token.IsNull() && token[0] == ')') {
AliErrorGeneral("AliRsnExpression::Expression", "To many closing parenthesis.");
delete result;
result = new AliRsnExpression;
} else if (stack == 0 && i < nt - 1) {
AliErrorGeneral("AliRsnExpression::Expression", Form("Unexpected symbol on input. %s", token.Data()));
delete result;
result = new AliRsnExpression;
}
return result;
}