Doxygen
Toggle main menu visibility
Loading...
Searching...
No Matches
condparser.cpp
Go to the documentation of this file.
1
/**
2
* Copyright (C) 1997-2015 by Dimitri van Heesch.
3
*
4
* Permission to use, copy, modify, and distribute this software and its
5
* documentation under the terms of the GNU General Public License is hereby
6
* granted. No representations are made about the suitability of this software
7
* for any purpose. It is provided "as is" without express or implied warranty.
8
* See the GNU General Public License for more details.
9
*
10
* Documents produced by Doxygen are derivative works derived from the
11
* input used in their production; they are not affected by this license.
12
*
13
* C++ Expression parser for ENABLED_SECTIONS in Doxygen
14
*
15
* Features used:
16
* Operators:
17
* && AND operator
18
* || OR operator
19
* ! NOT operator
20
*/
21
22
#include <algorithm>
23
24
#include "
condparser.h
"
25
#include "
config.h
"
26
#include "
message.h
"
27
28
// declarations
29
30
/**
31
* parses and evaluates the given expression.
32
* @returns
33
* - On error, an error message is returned.
34
* - On success, the result of the expression is either "1" or "0".
35
*/
36
bool
CondParser::parse
(
const
QCString
&fileName,
int
lineNr,
const
QCString
&expr)
37
{
38
if
(expr.
isEmpty
())
return
false
;
39
m_expr
= expr;
40
m_tokenType
=
NOTHING
;
41
42
// initialize all variables
43
m_e
=
m_expr
.data();
// let m_e point to the start of the expression
44
45
bool
answer=
false
;
46
getToken
();
47
if
(
m_tokenType
==
DELIMITER
&&
m_token
.isEmpty())
48
{
49
// empty expression: answer==FALSE
50
}
51
else
if
(
m_err
.isEmpty())
52
{
53
answer =
parseLevel1
();
54
}
55
if
(!
m_err
.isEmpty())
56
{
57
warn
(fileName,lineNr,
"problem evaluating expression '{}': {}"
, expr,
m_err
);
58
}
59
//printf("expr='%s' answer=%d\n",expr,answer);
60
return
answer;
61
}
62
63
64
/**
65
* checks if the given char c is a delimiter
66
* minus is checked apart, can be unary minus
67
*/
68
static
bool
isDelimiter
(
const
char
c)
69
{
70
return
c==
'&'
|| c==
'|'
|| c==
'!'
;
71
}
72
73
/**
74
* checks if the given char c is a letter or underscore
75
*/
76
static
bool
isAlpha
(
const
char
c)
77
{
78
return
(c>=
'A'
&& c<=
'Z'
) || (c>=
'a'
&& c<=
'z'
) || c==
'_'
;
79
}
80
81
static
bool
isAlphaNumSpec
(
const
char
c)
82
{
83
return
isAlpha
(c) || (c>=
'0'
&& c<=
'9'
) || c==
'-'
|| c==
'.'
|| (
static_cast<
unsigned
char
>
(c)>=0x80);
84
}
85
86
/**
87
* returns the id of the given operator
88
* returns -1 if the operator is not recognized
89
*/
90
int
CondParser::getOperatorId
(
const
QCString
&opName)
91
{
92
// level 2
93
if
(opName==
"&&"
) {
return
AND
; }
94
if
(opName==
"||"
) {
return
OR
; }
95
96
// not operator
97
if
(opName==
"!"
) {
return
NOT
; }
98
99
return
UNKNOWN_OP
;
100
}
101
102
/**
103
* Get next token in the current string expr.
104
* Uses the data in m_expr pointed to by m_e to
105
* produce m_tokenType and m_token, set m_err in case of an error
106
*/
107
void
CondParser::getToken
()
108
{
109
m_tokenType
=
NOTHING
;
110
m_token
.clear();
111
112
//printf("\tgetToken e:{%c}, ascii=%i, col=%i\n", *e, *e, e-expr);
113
114
// skip over whitespaces
115
while
(*
m_e
==
' '
|| *
m_e
==
'\t'
|| *
m_e
==
'\n'
)
// space or tab or newline
116
{
117
m_e
++;
118
}
119
120
// check for end of expression
121
if
(*
m_e
==
'\0'
)
122
{
123
// token is still empty
124
m_tokenType
=
DELIMITER
;
125
return
;
126
}
127
128
// check for parentheses
129
if
(*
m_e
==
'('
|| *
m_e
==
')'
)
130
{
131
m_tokenType
=
DELIMITER
;
132
m_token
+= *
m_e
++;
133
return
;
134
}
135
136
// check for operators (delimiters)
137
if
(
isDelimiter
(*
m_e
))
138
{
139
m_tokenType
=
DELIMITER
;
140
while
(
isDelimiter
(*
m_e
))
141
{
142
m_token
+= *
m_e
++;
143
}
144
return
;
145
}
146
147
// check for variables
148
if
(
isAlpha
(*
m_e
))
149
{
150
m_tokenType
=
VARIABLE
;
151
while
(
isAlphaNumSpec
(*
m_e
))
152
{
153
m_token
+= *
m_e
++;
154
}
155
return
;
156
}
157
158
// something unknown is found, wrong characters -> a syntax error
159
m_tokenType
=
UNKNOWN
;
160
while
(*
m_e
)
161
{
162
m_token
+= *
m_e
++;
163
}
164
m_err
=
QCString
(
"Syntax error in part '"
)+
m_token
+
"'"
;
165
return
;
166
}
167
168
169
/**
170
* conditional operators AND and OR
171
*/
172
bool
CondParser::parseLevel1
()
173
{
174
bool
ans =
parseLevel2
();
175
int
opId =
getOperatorId
(
m_token
);
176
177
while
(opId==
AND
|| opId==
OR
)
178
{
179
getToken
();
180
ans =
evalOperator
(opId, ans,
parseLevel2
());
181
opId =
getOperatorId
(
m_token
);
182
}
183
184
return
ans;
185
}
186
187
/**
188
* NOT
189
*/
190
bool
CondParser::parseLevel2
()
191
{
192
int
opId =
getOperatorId
(
m_token
);
193
if
(opId ==
NOT
)
194
{
195
getToken
();
196
return
!
parseLevel3
();
197
}
198
else
199
{
200
return
parseLevel3
();
201
}
202
}
203
204
205
/**
206
* parenthesized expression or variable
207
*/
208
bool
CondParser::parseLevel3
()
209
{
210
// check if it is a parenthesized expression
211
if
(
m_tokenType
==
DELIMITER
)
212
{
213
if
(
m_token
==
"("
)
214
{
215
getToken
();
216
bool
ans =
parseLevel1
();
217
if
(
m_tokenType
!=
DELIMITER
||
m_token
!=
")"
)
218
{
219
m_err
=
"Parenthesis ) missing"
;
220
return
FALSE
;
221
}
222
getToken
();
223
return
ans;
224
}
225
}
226
227
// if not parenthesized then the expression is a variable
228
return
parseVar
();
229
}
230
231
232
bool
CondParser::parseVar
()
233
{
234
bool
ans =
false
;
235
switch
(
m_tokenType
)
236
{
237
case
VARIABLE
:
238
// this is a variable
239
ans =
evalVariable
(
m_token
);
240
getToken
();
241
break
;
242
243
default
:
244
// syntax error or unexpected end of expression
245
if
(
m_token
.isEmpty())
246
{
247
m_err
=
"Unexpected end of expression"
;
248
return
FALSE
;
249
}
250
else
251
{
252
m_err
=
"Value expected"
;
253
return
FALSE
;
254
}
255
break
;
256
}
257
return
ans;
258
}
259
260
/**
261
* evaluate an operator for given values
262
*/
263
bool
CondParser::evalOperator
(
int
opId,
bool
lhs,
bool
rhs)
264
{
265
switch
(opId)
266
{
267
// level 2
268
case
AND
:
return
lhs && rhs;
269
case
OR
:
return
lhs || rhs;
270
}
271
272
m_err
=
"Internal error unknown operator: id="
+
QCString
().
setNum
(opId);
273
return
FALSE
;
274
}
275
276
/**
277
* evaluate a variable
278
*/
279
bool
CondParser::evalVariable
(
const
QCString
&varName)
280
{
281
const
StringVector
&list =
Config_getList
(ENABLED_SECTIONS);
282
return
std::find(list.begin(),list.end(),varName.
str
())!=list.end();
283
}
284
CondParser::m_token
QCString m_token
holds the token
Definition
condparser.h:58
CondParser::parseLevel2
bool parseLevel2()
NOT.
Definition
condparser.cpp:190
CondParser::m_err
QCString m_err
error state
Definition
condparser.h:54
CondParser::UNKNOWN
@ UNKNOWN
Definition
condparser.h:41
CondParser::VARIABLE
@ VARIABLE
Definition
condparser.h:40
CondParser::DELIMITER
@ DELIMITER
Definition
condparser.h:39
CondParser::NOTHING
@ NOTHING
Definition
condparser.h:38
CondParser::OR
@ OR
Definition
condparser.h:47
CondParser::NOT
@ NOT
Definition
condparser.h:48
CondParser::AND
@ AND
Definition
condparser.h:46
CondParser::UNKNOWN_OP
@ UNKNOWN_OP
Definition
condparser.h:45
CondParser::m_tokenType
TOKENTYPE m_tokenType
type of the token
Definition
condparser.h:59
CondParser::evalVariable
bool evalVariable(const QCString &varName)
evaluate a variable
Definition
condparser.cpp:279
CondParser::parseLevel1
bool parseLevel1()
conditional operators AND and OR
Definition
condparser.cpp:172
CondParser::getToken
void getToken()
Get next token in the current string expr.
Definition
condparser.cpp:107
CondParser::m_expr
QCString m_expr
holds the expression
Definition
condparser.h:55
CondParser::evalOperator
bool evalOperator(const int opId, bool lhs, bool rhs)
evaluate an operator for given values
Definition
condparser.cpp:263
CondParser::m_e
const char * m_e
points to a character in expr
Definition
condparser.h:56
CondParser::parseVar
bool parseVar()
Definition
condparser.cpp:232
CondParser::parse
bool parse(const QCString &fileName, int lineNr, const QCString &expr)
Copyright (C) 1997-2015 by Dimitri van Heesch.
Definition
condparser.cpp:36
CondParser::parseLevel3
bool parseLevel3()
parenthesized expression or variable
Definition
condparser.cpp:208
CondParser::getOperatorId
int getOperatorId(const QCString &opName)
returns the id of the given operator returns -1 if the operator is not recognized
Definition
condparser.cpp:90
QCString
This is an alternative implementation of QCString.
Definition
qcstring.h:101
QCString::isEmpty
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition
qcstring.h:163
QCString::str
const std::string & str() const
Definition
qcstring.h:552
QCString::setNum
QCString & setNum(short n)
Definition
qcstring.h:459
isDelimiter
static bool isDelimiter(const char c)
checks if the given char c is a delimiter minus is checked apart, can be unary minus
Definition
condparser.cpp:68
isAlphaNumSpec
static bool isAlphaNumSpec(const char c)
Definition
condparser.cpp:81
isAlpha
static bool isAlpha(const char c)
checks if the given char c is a letter or underscore
Definition
condparser.cpp:76
condparser.h
config.h
Config_getList
#define Config_getList(name)
Definition
config.h:38
StringVector
std::vector< std::string > StringVector
Definition
containers.h:33
message.h
warn
#define warn(file, line, fmt,...)
Definition
message.h:97
FALSE
#define FALSE
Definition
qcstring.h:34
src
condparser.cpp
Generated by
1.17.0