First prototype of the trigger classes (E. Lopez Torres)
[u/mrichter/AliRoot.git] / STEER / AliExpression.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 ///////////////////////////////////////////////////////////////////////////////
19 //                                                                           //
20 //  AliExpression Class                                                      //                                                                           //
21 //                                                                           //
22 //  Helper class to evaluate the condition expressions in                    //
23 //  AliTriggerCondition                                                      //
24 //  Implements a simple recursive-descent parser                             //
25 //                                                                           //
26 ///////////////////////////////////////////////////////////////////////////////
27
28 //#include <Riostream.h>
29 #include <TString.h>
30 #include <TObjString.h>
31 #include <TObjArray.h>
32
33 #include "AliLog.h"
34 #include "AliExpression.h"
35 #include "AliTriggerInput.h"
36
37 ClassImp( AliExpression )
38
39 //______________________________________________________________________________
40 AliExpression::AliExpression( TString exp )
41 {
42    // Default constructor
43    TObjArray* tokens = Tokenize( exp );
44
45    Int_t i = -1;
46    AliExpression* e = Expression( *tokens, i );
47    // Copy !!!
48    fArg1 = e->fArg1; e->fArg1 = 0;
49    fArg2 = e->fArg2; e->fArg2 = 0;
50    fOperator = e->fOperator;
51    delete e;
52    delete tokens;
53 }
54
55 //______________________________________________________________________________
56 AliExpression::~AliExpression()
57 {
58    if( fArg1 ) delete fArg1;
59    if( fArg2 ) delete fArg2;
60 }
61
62 //______________________________________________________________________________
63 AliExpression& AliExpression::operator=(const AliExpression& e)
64 {
65    // AliExpression assignment operator.
66
67    if( this != &e ) {
68       TObject::operator=(e);
69       fArg1 = e.fArg1;
70       fArg2 = e.fArg2;
71       fOperator = e.fOperator;
72    }
73    return *this;
74 }
75
76 //______________________________________________________________________________
77 AliExpression::AliExpression( int op, AliExpression* a, AliExpression* b )
78 {
79    // Create a new expression
80    fArg1 = a;
81    fArg2 = b;
82    fOperator = op;
83 }
84
85 //______________________________________________________________________________
86 AliExpression::AliExpression( int op, AliExpression* a )
87 {
88    // Create a unary expression.
89    fArg1 = 0;
90    fArg2 = a;
91    fOperator = op;
92 }
93
94 //______________________________________________________________________________
95 Bool_t AliExpression::Value( TObjArray &vars )
96 {
97    //  Evaluate the expression
98    if ( fArg2 == 0 ) {
99        AliError( "Expression undefined." );
100        return kFALSE;
101    }
102
103    switch (fOperator) {
104
105       case kOpOR :
106           return fArg1->Value(vars) || fArg2->Value(vars);
107
108       case kOpAND :
109           return fArg1->Value(vars) && fArg2->Value(vars);
110
111       case kOpNOT :
112           return !(fArg2->Value(vars));
113
114       default:
115           AliError( "Illegal operator in expression!");
116
117    }
118    return kFALSE;
119 }
120
121
122 //______________________________________________________________________________
123 TString AliExpression::Unparse() const
124 {
125    // Unparse the expression
126
127    TString opVals[4] = { "&", "|","!" };
128    if ( fArg2 == 0 ) {
129        AliError( "Expression undefined." );
130        return "Error";
131    }
132
133    if (fArg1 == 0 && fArg2) {
134        return opVals[fOperator]+fArg2->Unparse();
135    }
136    return "("+fArg1->Unparse()+" "+opVals[fOperator]+" "+fArg2->Unparse()+")";
137 }
138
139 //______________________________________________________________________________
140 TObjArray* AliExpression::Tokenize( TString str ) const
141 {
142    // tokenize the expression
143
144    // Remove spaces
145    TString str1;
146    for( Int_t i=0; i<str.Length(); i++ ) {
147       if( str[i] == ' ' ) continue;
148       str1.Append( str[i] );
149    }
150    // get variable tokens
151    TObjArray* valtok = str1.Tokenize( "!&|()" );
152    // put all variables together
153    Int_t nvt = valtok->GetEntriesFast();
154    TString sumval;
155    for( Int_t i=0; i<nvt; i++ ) {
156       TObjString* val = (TObjString*)valtok->At( i );
157       sumval.Append( val->String() );
158    }
159    // get the operator tokens
160    TObjArray* optok = str1.Tokenize( sumval.Data() );
161    // put all operator in one string
162    TString operators;
163    Int_t nopt = optok->GetEntriesFast();
164    for( Int_t i=0; i<nopt; i++ ) {
165       TObjString* val1 = (TObjString*)optok->At( i );
166       operators.Append( val1->String() );
167    }
168    // add more room to be safe
169    TObjString* blank = new TObjString(" ");
170    operators.Append( " " );
171    valtok->AddLast( blank );
172    // Now put var. and oper. together
173    TObjArray* tokens = new TObjArray( valtok->GetEntriesFast() + operators.Length() );
174    int io = 0,iv = 0;
175    int index = 0;
176    while( 1 ) {
177       TString so = operators[io];
178       int indexO = str1.Index( so, index );
179       TString val2 = ((TObjString*)valtok->At( iv ))->String();
180       int indexV = str1.Index( val2, index );
181       if( (indexO < indexV || indexV < 0) && indexO >=0 ) {
182          tokens->AddLast( new TObjString( so ) );
183          index += so.Length();
184          io++;
185       }
186       if( (indexV < indexO || indexO < 0) && indexV >=0 ) {
187          tokens->AddLast( new TObjString( val2 ) );
188          index += val2.Length();
189          iv++;
190       }
191       if( index >= str1.Length() ) break;
192    }
193
194 //  Debug -> Print the tokens
195 //   Int_t nt = tokens->GetEntriesFast();
196 //   for( Int_t i=0; i<nt; i++ ) {
197 //      TObjString* val3 = (TObjString*)tokens->At( i );
198 //      cout << i << " " << val3->String() << endl;
199 //   }
200    delete valtok;
201    delete optok;
202
203    return tokens;
204 }
205
206
207 //______________________________________________________________________________
208 AliExpression* AliExpression::Element( TObjArray &st, Int_t &i )
209 {
210    // create an element
211    
212    AliExpression* result = 0;
213
214    Int_t nt = st.GetEntriesFast();
215    TString token = "@";
216    TObjString* valt;
217    // next token
218    if( i < nt-1 ) {
219       i++;
220       valt = (TObjString*)st.At( i );
221       token = valt->String();
222    }
223    // token type
224    char ttok = ( token[0]!='|' && token[0]!='&' &&
225                  token[0]!='!' && token[0]!='('&& token[0]!=')') ? 'w' : token[0];
226    switch( ttok ) {
227       case 'w' :
228           result = new AliVariableExpression( token );
229           break;
230       case '(' :
231           result = Expression(st, i);
232             // next token
233           if( i < nt-1 ) {
234              i++;
235              valt = (TObjString*)st.At( i );
236              token = valt->String();
237           }
238           if( token[0] != ')' ) {
239        //       i--; // push back
240               AliErrorGeneral( "AliExpression::Element", "Mismatched parenthesis." );
241               delete result;
242               result = new AliExpression;
243           }
244           break;
245       default:
246           i--; // push back
247           AliErrorGeneral( "AliExpression::Element", Form("Unexpected symbol on input. %s", token.Data()) );
248           if( result ) delete result;
249           result = new AliExpression;
250    }
251    return result;
252 }
253
254 //______________________________________________________________________________
255 AliExpression* AliExpression::Primary( TObjArray &st, Int_t &i )
256 {
257    // create a primary
258    
259    Int_t nt = st.GetEntriesFast();
260    TString token = "@";
261    TObjString* valt;
262    // next token
263    if( i < nt-1 ) {
264       i++;
265       valt = (TObjString*)st.At( i );
266       token = valt->String();
267    }
268
269    switch (token[0]) {
270        case '!' :
271            return new AliExpression( kOpNOT, Primary( st, i ) );
272        default:
273            i--; // push back
274            return Element( st, i );
275    }
276 }
277
278 //______________________________________________________________________________
279 AliExpression* AliExpression::Expression( TObjArray &st,Int_t &i )
280 {
281    // create an expression
282    
283    AliExpression* result = 0;
284    Bool_t done = kFALSE;
285    TString token;
286    TObjString* valt;
287
288    static int stack = 0;
289    stack++;
290    Int_t nt = st.GetEntriesFast();
291
292    result = Primary( st, i );
293 //   cout <<"i "<<i<< "Primary " << result->Unparse() << endl;
294    while (! done) {
295       // next token
296       if( i < nt-1 ) i++;
297       else break;
298       valt = (TObjString*)st.At( i );
299       token = valt->String();
300       switch (token[0]) {
301          case '&' :
302              result = new AliExpression( kOpAND, result, Primary( st, i ) );
303 //   cout <<"i "<<i<< " Expression AND " << result->Unparse() << endl;
304              break;
305          case '|' :
306              result = new AliExpression( kOpOR, result, Primary( st, i ) );
307 //   cout <<"i "<<i<< " Expression OR " << result->Unparse() << endl;
308              break;
309          default:
310              done = kTRUE;
311              i--; // push back
312              break;
313       }
314    }
315    stack--;
316    if( stack == 0 && !token.IsNull() && token[0] == ')' ) {
317       AliErrorGeneral( "AliExpression::Expression", "To many closing parenthesis." );
318       delete result;
319       result = new AliExpression;
320    } else 
321    if( stack == 0 && i< nt-1 ) {
322       AliErrorGeneral( "AliExpression::Expression", Form( "Unexpected symbol on input. %s", token.Data() ) );
323       delete result;
324       result = new AliExpression;
325    }
326    return result;
327 }
328
329 ////////////////////////////////////////////////////////////////////////////////
330
331 ClassImp( AliVariableExpression )
332
333 //______________________________________________________________________________
334 Bool_t AliVariableExpression::Value( TObjArray& pgm )
335 {
336    // return the value
337    TObject* dd = pgm.FindObject( fVname.Data() );
338    if( dd == NULL ) {
339       AliError( fVname + " is undefined" );
340       return 0;
341    }
342    return ((AliTriggerInput*)dd)->GetValue();
343 }
344