#include <TString.h>
#include <TObjString.h>
#include <TObjArray.h>
#include "AliLog.h"
#include "AliExpression.h"
#include "AliTriggerInput.h"
ClassImp( AliExpression )
AliExpression::AliExpression( TString exp ) :
TObject(),
fVname(""),
fArg1(0x0),
fArg2(0x0),
fOperator(0)
{
TObjArray* tokens = Tokenize( exp );
Int_t i = -1;
AliExpression* 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;
}
AliExpression::~AliExpression()
{
if( fArg1 ) delete fArg1;
if( fArg2 ) delete fArg2;
}
AliExpression& AliExpression::operator=(const AliExpression& e)
{
if( this != &e ) {
TObject::operator=(e);
fArg1 = e.fArg1;
fArg2 = e.fArg2;
fOperator = e.fOperator;
fVname = e.fVname;
}
return *this;
}
AliExpression::AliExpression( int op, AliExpression* a, AliExpression* b ) :
TObject(),
fVname(""),
fArg1(a),
fArg2(b),
fOperator(op)
{
}
AliExpression::AliExpression( int op, AliExpression* a ) :
TObject(),
fVname(""),
fArg1(0),
fArg2(a),
fOperator(op)
{
}
Bool_t AliExpression::Value( const TObjArray &vars )
{
if ( ( fArg2 == 0 && fVname.IsNull() ) ||
( fArg2 == 0 && ( fOperator == kOpOR || fOperator == kOpAND || fOperator == kOpNOT ) ) ) {
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 :
{
TObject* dd = vars.FindObject( fVname.Data() );
if( dd == NULL ) {
AliError( fVname + " is undefined" );
return 0;
}
return ((AliTriggerInput*)dd)->GetValue();
}
default:
AliError( "Illegal operator in expression!");
}
return kFALSE;
}
TString AliExpression::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* AliExpression::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;
}
AliExpression* AliExpression::Element( TObjArray &st, Int_t &i )
{
AliExpression* 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 AliVariableExpression( token );
break;
case '(' :
result = Expression(st, i);
if( i < nt-1 ) {
i++;
valt = (TObjString*)st.At( i );
token = valt->String();
}
if( token[0] != ')' ) {
AliErrorGeneral( "AliExpression::Element", "Mismatched parenthesis." );
delete result;
result = new AliExpression;
}
break;
default:
i--;
AliErrorGeneral( "AliExpression::Element", Form("Unexpected symbol on input. %s", token.Data()) );
result = new AliExpression;
}
return result;
}
AliExpression* AliExpression::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 AliExpression( kOpNOT, Primary( st, i ) );
default:
i--;
return Element( st, i );
}
}
AliExpression* AliExpression::Expression( TObjArray &st,Int_t &i )
{
AliExpression* 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 AliExpression( kOpAND, result, Primary( st, i ) );
break;
case '|' :
result = new AliExpression( kOpOR, result, Primary( st, i ) );
break;
default:
done = kTRUE;
i--;
break;
}
}
stack--;
if( stack == 0 && !token.IsNull() && token[0] == ')' ) {
AliErrorGeneral( "AliExpression::Expression", "To many closing parenthesis." );
delete result;
result = new AliExpression;
} else
if( stack == 0 && i< nt-1 ) {
AliErrorGeneral( "AliExpression::Expression", Form( "Unexpected symbol on input. %s", token.Data() ) );
delete result;
result = new AliExpression;
}
return result;
}
ClassImp( AliVariableExpression )
Bool_t AliVariableExpression::Value( const TObjArray& pgm )
{
TObject* dd = pgm.FindObject( fVname.Data() );
if( dd == NULL ) {
AliError( fVname + " is undefined" );
return 0;
}
return ((AliTriggerInput*)dd)->GetValue();
}