OSDN Git Service

Merge branch 'post-2.4.2'
[tjqt4port/tj2qt4.git] / taskjuggler / ExpressionParser.cpp
1 /*
2  * ExpressionParser.cpp - TaskJuggler
3  *
4  * Copyright (c) 2001, 2002, 2003, 2004 by Chris Schlaeger <cs@kde.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of version 2 of the GNU General Public License as
8  * published by the Free Software Foundation.
9  *
10  * $Id$
11  */
12
13 #include "ExpressionParser.h"
14 #include "Project.h"
15 #include "Operation.h"
16 #include "debug.h"
17 #include "ExpressionTree.h"
18 #include "tjlib-internal.h"
19 #include "ExpressionFunctionTable.h"
20
21 Operation*
22 ExpressionParser::parse()
23 {
24     Operation* op( 0 );
25
26     if (tokenizer.open())
27     {
28         op = parseLogicalExpression(0);
29         if (!tokenizer.close())
30         {
31             delete op;
32             op = 0;
33         }
34     }
35     return op;
36 }
37
38 Operation*
39 ExpressionParser::parseLogicalExpression(int precedence)
40 {
41     Operation* op;
42     QString token;
43     TokenType tt;
44
45     tt = tokenizer.nextToken(token);
46     if (DEBUGEX(5))
47         qDebug("parseLogicalExpression(%d): %s", precedence, token.latin1());
48     if (tt == ID || tt == ABSOLUTE_ID)
49     {
50         QString lookAhead;
51         if ((tt = tokenizer.nextToken(lookAhead)) == LBRACKET)
52         {
53             if (EFT.isKnownFunction(token))
54             {
55                 if ((op = parseFunctionCall(token)) == 0)
56                 {
57                     if (DEBUGEX(5))
58                         qDebug("exit after function call");
59                     return 0;
60                 }
61             }
62             else
63             {
64                 errorMessage(i18n("Function '%1' is unknown").arg(token));
65                 return 0;
66             }
67         }
68         else
69         {
70             tokenizer.returnToken(tt, lookAhead);
71             /* We can't test here, whether the ID is known or not. So this has
72              * to be checked at evaluation time. */
73             op = new Operation(Operation::Id, token);
74         }
75     }
76     else if (tt == STRING)
77     {
78         op = new Operation(Operation::String, token);
79     }
80     else if (tt == DATE)
81     {
82         time_t date;
83         if ((date = date2time(token)) == 0)
84         {
85             errorMessage(getUtilityError());
86             return 0;
87         }
88         else
89             op = new Operation(Operation::Date, date);
90     }
91     else if (tt == INTEGER)
92     {
93         op = new Operation(token.toLong());
94     }
95     else if (tt == TILDE)
96     {
97         if ((op = parseLogicalExpression(1)) == 0)
98         {
99             if (DEBUGEX(5))
100                 qDebug("exit after NOT");
101             return 0;
102         }
103         op = new Operation(op, Operation::Not);
104     }
105     else if (tt == LBRACKET)
106     {
107         if ((op = parseLogicalExpression(0)) == 0)
108         {
109             if (DEBUGEX(5))
110                 qDebug("exit after ()");
111             return 0;
112         }
113         if ((tt = tokenizer.nextToken(token)) != RBRACKET)
114         {
115             errorMessage(i18n("')' expected"));
116             delete op;
117             return 0;
118         }
119     }
120     else
121     {
122         errorMessage(i18n("Logical expression expected"));
123         return 0;
124     }
125
126     if (precedence < 1)
127     {
128         tt = tokenizer.nextToken(token);
129         if (DEBUGEX(5))
130             qDebug("Second operator %s", token.latin1());
131         if (tt == AND)
132         {
133             Operation* op2 = parseLogicalExpression(0);
134             op = new Operation(op, Operation::And, op2);
135         }
136         else if (tt == OR)
137         {
138             Operation* op2 = parseLogicalExpression(0);
139             op = new Operation(op, Operation::Or, op2);
140         }
141         else if (tt == GREATER)
142         {
143             Operation* op2 = parseLogicalExpression(0);
144             op = new Operation(op, Operation::Greater, op2);
145         }
146         else if (tt == SMALLER)
147         {
148             Operation* op2 = parseLogicalExpression(0);
149             op = new Operation(op, Operation::Smaller, op2);
150         }
151         else if (tt == EQUAL)
152         {
153             Operation* op2 = parseLogicalExpression(0);
154             op = new Operation(op, Operation::Equal, op2);
155         }
156         else if (tt == GREATEROREQUAL)
157         {
158             Operation* op2 = parseLogicalExpression(0);
159             op = new Operation(op, Operation::GreaterOrEqual, op2);
160         }
161         else if (tt == SMALLEROREQUAL)
162         {
163             Operation* op2 = parseLogicalExpression(0);
164             op = new Operation(op, Operation::SmallerOrEqual, op2);
165         }
166         else
167             tokenizer.returnToken(tt, token);
168      }
169
170     if (DEBUGEX(5))
171         qDebug("exit default");
172     return op;
173 }
174
175 Operation*
176 ExpressionParser::parseFunctionCall(const QString& name)
177 {
178     QString token;
179     TokenType tt;
180
181     QPtrList<Operation> args;
182     for (int i = 0; i < EFT.getArgumentCount(name); i++)
183     {
184         if (DEBUGEX(5))
185             qDebug("Reading function '%s' arg %d", name.latin1(), i);
186         Operation* op;
187         if ((op = parseLogicalExpression(0)) == 0)
188             return 0;
189         args.append(op);
190         if ((i < EFT.getArgumentCount(name) - 1) &&
191             tokenizer.nextToken(token) != COMMA)
192         {
193             errorMessage(i18n("Comma expected. "
194                               "Function '%1' needs %2 arguments.")
195                          .arg(name).arg(EFT.getArgumentCount(name)));
196             return 0;
197         }
198     }
199     if ((tt = tokenizer.nextToken(token)) != RBRACKET)
200     {
201         errorMessage(i18n("')' expected"));
202         return 0;
203     }
204     Operation** argsArr = new Operation*[args.count()];
205     int i = 0;
206     for (QPtrListIterator<Operation> oli(args); *oli != 0; ++oli)
207         argsArr[i++] = *oli;
208     if (DEBUGEX(5))
209         qDebug("function '%s' done", name.latin1());
210     return new Operation(name, argsArr, args.count());
211 }
212
213 void
214 ExpressionParser::errorMessage(const QString& msg)
215 {
216     tokenizer.errorMessage(msg);
217 }