ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
parseCore.c
Go to the documentation of this file.
1
18
19/*
20 Some aspects of Boolean Formula Parser:
21
22 1) The names in the boolean formulas can be any strings of symbols
23 that start with char or underscore and contain chars, digits
24 and underscores: For example: 1) a&b <+> c'&d => a + b;
25 2) a1 b2 c3' dummy' + (a2+b2')c3 dummy
26 2) Constant values 0 and 1 can be used just like normal variables
27 3) Any boolean operator (listed below) and parentheses can be used
28 any number of times provided there are equal number of opening
29 and closing parentheses.
30 4) By default, absence of an operator between vars and before and
31 after parentheses is taken for AND.
32 5) Both complementation prefix and complementation suffix can be
33 used at the same time (but who needs this?)
34 6) Spaces (tabs, end-of-lines) may be inserted anywhere,
35 except between characters of the operations: <=>, =>, <=, <+>
36 7) The stack size is defined by macro STACKSIZE and is used by the
37 stack constructor.
38*/
39
43
44#include "parseInt.h"
45
47
48
49// the list of operation symbols to be used in expressions
50#define PARSE_SYM_OPEN '(' // opening parenthesis
51#define PARSE_SYM_CLOSE ')' // closing parenthesis
52#define PARSE_SYM_LOWER '[' // shifts one rank down
53#define PARSE_SYM_RAISE ']' // shifts one rank up
54#define PARSE_SYM_CONST0 '0' // constant 0
55#define PARSE_SYM_CONST1 '1' // constant 1
56#define PARSE_SYM_NEGBEF1 '!' // negation before the variable
57#define PARSE_SYM_NEGBEF2 '~' // negation before the variable
58#define PARSE_SYM_NEGAFT '\'' // negation after the variable
59#define PARSE_SYM_AND1 '&' // logic AND
60#define PARSE_SYM_AND2 '*' // logic AND
61#define PARSE_SYM_XOR1 '<' // logic EXOR (the 1st symbol)
62#define PARSE_SYM_XOR2 '+' // logic EXOR (the 2nd symbol)
63#define PARSE_SYM_XOR3 '>' // logic EXOR (the 3rd symbol)
64#define PARSE_SYM_XOR '^' // logic XOR
65#define PARSE_SYM_OR1 '+' // logic OR
66#define PARSE_SYM_OR2 '|' // logic OR
67#define PARSE_SYM_EQU1 '<' // equvalence (the 1st symbol)
68#define PARSE_SYM_EQU2 '=' // equvalence (the 2nd symbol)
69#define PARSE_SYM_EQU3 '>' // equvalence (the 3rd symbol)
70#define PARSE_SYM_FLR1 '=' // implication (the 1st symbol)
71#define PARSE_SYM_FLR2 '>' // implication (the 2nd symbol)
72#define PARSE_SYM_FLL1 '<' // backward imp (the 1st symbol)
73#define PARSE_SYM_FLL2 '=' // backward imp (the 2nd symbol)
74// PARSE_SYM_FLR1 and PARSE_SYM_FLR2 should be the same as PARSE_SYM_EQU2 and PARSE_SYM_EQU3!
75
76// the list of opcodes (also specifying operation precedence)
77#define PARSE_OPER_NEG 10 // negation
78#define PARSE_OPER_AND 9 // logic AND
79#define PARSE_OPER_XOR 8 // logic EXOR (a'b | ab')
80#define PARSE_OPER_OR 7 // logic OR
81#define PARSE_OPER_EQU 6 // equvalence (a'b'| ab )
82#define PARSE_OPER_FLR 5 // implication ( a' | b )
83#define PARSE_OPER_FLL 4 // backward imp ( 'b | a )
84#define PARSE_OPER_MARK 1 // OpStack token standing for an opening parenthesis
85
86// these are values of the internal Flag
87#define PARSE_FLAG_START 1 // after the opening parenthesis
88#define PARSE_FLAG_VAR 2 // after operation is received
89#define PARSE_FLAG_OPER 3 // after operation symbol is received
90#define PARSE_FLAG_ERROR 4 // when error is detected
91
92#define STACKSIZE 1000
93
94static DdNode * Parse_ParserPerformTopOp( DdManager * dd, Parse_StackFn_t * pStackFn, int Oper );
95
99
116DdNode * Parse_FormulaParser( FILE * pOutput, char * pFormulaInit, int nVars, int nRanks,
117 char * ppVarNames[], DdManager * dd, DdNode * pbVars[] )
118{
119 char * pFormula;
120 Parse_StackFn_t * pStackFn;
121 Parse_StackOp_t * pStackOp;
122 DdNode * bFunc, * bTemp;
123 char * pTemp;
124 int nParans, fFound, Flag;
125 int Oper, Oper1, Oper2;
126 int i, fLower;
127 int v = -1; // Suppress "might be used uninitialized"
128
129 // make sure that the number of vars and ranks is correct
130 if ( nVars * (nRanks + 1) > dd->size )
131 {
132 printf( "Parse_FormulaParser(): The BDD manager does not have enough variables.\n" );
133 return NULL;
134 }
135
136 // make sure that the number of opening and closing parentheses is the same
137 nParans = 0;
138 for ( pTemp = pFormulaInit; *pTemp; pTemp++ )
139 if ( *pTemp == '(' )
140 nParans++;
141 else if ( *pTemp == ')' )
142 nParans--;
143 if ( nParans != 0 )
144 {
145 fprintf( pOutput, "Parse_FormulaParser(): Different number of opening and closing parentheses ().\n" );
146 return NULL;
147 }
148
149 nParans = 0;
150 for ( pTemp = pFormulaInit; *pTemp; pTemp++ )
151 if ( *pTemp == '[' )
152 nParans++;
153 else if ( *pTemp == ']' )
154 nParans--;
155 if ( nParans != 0 )
156 {
157 fprintf( pOutput, "Parse_FormulaParser(): Different number of opening and closing brackets [].\n" );
158 return NULL;
159 }
160
161 // copy the formula
162 pFormula = ABC_ALLOC( char, strlen(pFormulaInit) + 3 );
163 sprintf( pFormula, "(%s)", pFormulaInit );
164
165 // start the stacks
166 pStackFn = Parse_StackFnStart( STACKSIZE );
167 pStackOp = Parse_StackOpStart( STACKSIZE );
168
169 Flag = PARSE_FLAG_START;
170 fLower = 0;
171 for ( pTemp = pFormula; *pTemp; pTemp++ )
172 {
173 switch ( *pTemp )
174 {
175 // skip all spaces, tabs, and end-of-lines
176 case ' ':
177 case '\t':
178 case '\r':
179 case '\n':
180 continue;
181
182 // treat Constant 0 as a variable
183 case PARSE_SYM_CONST0:
184 Parse_StackFnPush( pStackFn, b0 ); Cudd_Ref( b0 );
185 if ( Flag == PARSE_FLAG_VAR )
186 {
187 fprintf( pOutput, "Parse_FormulaParser(): No operation symbol before constant 0.\n" );
188 Flag = PARSE_FLAG_ERROR;
189 break;
190 }
191 Flag = PARSE_FLAG_VAR;
192 break;
193
194 // the same for Constant 1
195 case PARSE_SYM_CONST1:
196 Parse_StackFnPush( pStackFn, b1 ); Cudd_Ref( b1 );
197 if ( Flag == PARSE_FLAG_VAR )
198 {
199 fprintf( pOutput, "Parse_FormulaParser(): No operation symbol before constant 1.\n" );
200 Flag = PARSE_FLAG_ERROR;
201 break;
202 }
203 Flag = PARSE_FLAG_VAR;
204 break;
205
208 if ( Flag == PARSE_FLAG_VAR )
209 {// if NEGBEF follows a variable, AND is assumed
211 Flag = PARSE_FLAG_OPER;
212 }
214 break;
215
216 case PARSE_SYM_NEGAFT:
217 if ( Flag != PARSE_FLAG_VAR )
218 {// if there is no variable before NEGAFT, it is an error
219 fprintf( pOutput, "Parse_FormulaParser(): No variable is specified before the negation suffix.\n" );
220 Flag = PARSE_FLAG_ERROR;
221 break;
222 }
223 else // if ( Flag == PARSE_FLAG_VAR )
224 Parse_StackFnPush( pStackFn, Cudd_Not( Parse_StackFnPop(pStackFn) ) );
225 break;
226
227 case PARSE_SYM_AND1:
228 case PARSE_SYM_AND2:
229 case PARSE_SYM_OR1:
230 case PARSE_SYM_OR2:
231 case PARSE_SYM_XOR:
232 if ( Flag != PARSE_FLAG_VAR )
233 {
234 fprintf( pOutput, "Parse_FormulaParser(): There is no variable before AND, EXOR, or OR.\n" );
235 Flag = PARSE_FLAG_ERROR;
236 break;
237 }
238 if ( *pTemp == PARSE_SYM_AND1 || *pTemp == PARSE_SYM_AND2 )
240 else if ( *pTemp == PARSE_SYM_OR1 || *pTemp == PARSE_SYM_OR2 )
241 Parse_StackOpPush( pStackOp, PARSE_OPER_OR );
242 else //if ( Str[Pos] == PARSE_SYM_XOR )
244 Flag = PARSE_FLAG_OPER;
245 break;
246
247 case PARSE_SYM_EQU1:
248 if ( Flag != PARSE_FLAG_VAR )
249 {
250 fprintf( pOutput, "Parse_FormulaParser(): There is no variable before Equivalence or Implication\n" );
251 Flag = PARSE_FLAG_ERROR; break;
252 }
253 if ( pTemp[1] == PARSE_SYM_EQU2 )
254 { // check what is the next symbol in the string
255 pTemp++;
256 if ( pTemp[1] == PARSE_SYM_EQU3 )
257 {
258 pTemp++;
259 Parse_StackOpPush( pStackOp, PARSE_OPER_EQU );
260 }
261 else
262 {
263 Parse_StackOpPush( pStackOp, PARSE_OPER_FLL );
264 }
265 }
266 else if ( pTemp[1] == PARSE_SYM_XOR2 )
267 {
268 pTemp++;
269 if ( pTemp[1] == PARSE_SYM_XOR3 )
270 {
271 pTemp++;
272 Parse_StackOpPush( pStackOp, PARSE_OPER_XOR );
273 }
274 else
275 {
276 fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c%c\"\n", PARSE_SYM_EQU1, PARSE_SYM_XOR2 );
277 Flag = PARSE_FLAG_ERROR;
278 break;
279 }
280 }
281 else
282 {
283 fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c\"\n", PARSE_SYM_EQU1 );
284 Flag = PARSE_FLAG_ERROR;
285 break;
286 }
287 Flag = PARSE_FLAG_OPER;
288 break;
289
290 case PARSE_SYM_EQU2:
291 if ( Flag != PARSE_FLAG_VAR )
292 {
293 fprintf( pOutput, "Parse_FormulaParser(): There is no variable before Reverse Implication\n" );
294 Flag = PARSE_FLAG_ERROR;
295 break;
296 }
297 if ( pTemp[1] == PARSE_SYM_EQU3 )
298 {
299 pTemp++;
300 Parse_StackOpPush( pStackOp, PARSE_OPER_FLR );
301 }
302 else
303 {
304 fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c\"\n", PARSE_SYM_EQU2 );
305 Flag = PARSE_FLAG_ERROR;
306 break;
307 }
308 Flag = PARSE_FLAG_OPER;
309 break;
310
311 case PARSE_SYM_LOWER:
312 case PARSE_SYM_OPEN:
313 if ( Flag == PARSE_FLAG_VAR )
316 // after an opening bracket, it feels like starting over again
317 Flag = PARSE_FLAG_START;
318 break;
319
320 case PARSE_SYM_RAISE:
321 fLower = 1;
322 case PARSE_SYM_CLOSE:
323 if ( !Parse_StackOpIsEmpty( pStackOp ) )
324 {
325 while ( 1 )
326 {
327 if ( Parse_StackOpIsEmpty( pStackOp ) )
328 {
329 fprintf( pOutput, "Parse_FormulaParser(): There is no opening parenthesis\n" );
330 Flag = PARSE_FLAG_ERROR;
331 break;
332 }
333 Oper = Parse_StackOpPop( pStackOp );
334 if ( Oper == PARSE_OPER_MARK )
335 break;
336
337 // perform the given operation
338 if ( Parse_ParserPerformTopOp( dd, pStackFn, Oper ) == NULL )
339 {
340 fprintf( pOutput, "Parse_FormulaParser(): Unknown operation\n" );
341 ABC_FREE( pFormula );
342 return NULL;
343 }
344 }
345
346 if ( fLower )
347 {
348 bFunc = (DdNode *)Parse_StackFnPop( pStackFn );
349 bFunc = Extra_bddMove( dd, bTemp = bFunc, -nVars ); Cudd_Ref( bFunc );
350 Cudd_RecursiveDeref( dd, bTemp );
351 Parse_StackFnPush( pStackFn, bFunc );
352 }
353 }
354 else
355 {
356 fprintf( pOutput, "Parse_FormulaParser(): There is no opening parenthesis\n" );
357 Flag = PARSE_FLAG_ERROR;
358 break;
359 }
360 if ( Flag != PARSE_FLAG_ERROR )
361 Flag = PARSE_FLAG_VAR;
362 fLower = 0;
363 break;
364
365
366 default:
367 // scan the next name
368/*
369 fFound = 0;
370 for ( i = 0; pTemp[i] && pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n'; i++ )
371 {
372 for ( v = 0; v < nVars; v++ )
373 if ( strncmp( pTemp, ppVarNames[v], i+1 ) == 0 && strlen(ppVarNames[v]) == (unsigned)(i+1) )
374 {
375 pTemp += i;
376 fFound = 1;
377 break;
378 }
379 if ( fFound )
380 break;
381 }
382*/
383 // bug fix by SV (9/11/08)
384 fFound = 0;
385 for ( i = 0; pTemp[i] && pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' &&
386 pTemp[i] != PARSE_SYM_AND1 && pTemp[i] != PARSE_SYM_AND2 && pTemp[i] != PARSE_SYM_XOR1 &&
387 pTemp[i] != PARSE_SYM_XOR2 && pTemp[i] != PARSE_SYM_XOR3 && pTemp[i] != PARSE_SYM_XOR &&
388 pTemp[i] != PARSE_SYM_OR1 && pTemp[i] != PARSE_SYM_OR2 && pTemp[i] != PARSE_SYM_CLOSE &&
389 pTemp[i] != PARSE_SYM_NEGAFT;
390 i++ )
391 {}
392 for ( v = 0; v < nVars; v++ )
393 {
394 if ( strncmp( pTemp, ppVarNames[v], i ) == 0 && strlen(ppVarNames[v]) == (unsigned)(i) )
395 {
396 pTemp += i-1;
397 fFound = 1;
398 break;
399 }
400 }
401
402 if ( !fFound )
403 {
404 fprintf( pOutput, "Parse_FormulaParser(): The parser cannot find var \"%s\" in the input var list.\n", pTemp );
405 Flag = PARSE_FLAG_ERROR;
406 break;
407 }
408 // assume operation AND, if vars follow one another
409 if ( Flag == PARSE_FLAG_VAR )
411 Parse_StackFnPush( pStackFn, pbVars[v] ); Cudd_Ref( pbVars[v] );
412 Flag = PARSE_FLAG_VAR;
413 break;
414 }
415
416 if ( Flag == PARSE_FLAG_ERROR )
417 break; // error exit
418 else if ( Flag == PARSE_FLAG_START )
419 continue; // go on parsing
420 else if ( Flag == PARSE_FLAG_VAR )
421 while ( 1 )
422 { // check if there are negations in the OpStack
423 if ( Parse_StackOpIsEmpty(pStackOp) )
424 break;
425 Oper = Parse_StackOpPop( pStackOp );
426 if ( Oper != PARSE_OPER_NEG )
427 {
428 Parse_StackOpPush( pStackOp, Oper );
429 break;
430 }
431 else
432 {
433 Parse_StackFnPush( pStackFn, Cudd_Not(Parse_StackFnPop(pStackFn)) );
434 }
435 }
436 else // if ( Flag == PARSE_FLAG_OPER )
437 while ( 1 )
438 { // execute all the operations in the OpStack
439 // with precedence higher or equal than the last one
440 Oper1 = Parse_StackOpPop( pStackOp ); // the last operation
441 if ( Parse_StackOpIsEmpty(pStackOp) )
442 { // if it is the only operation, push it back
443 Parse_StackOpPush( pStackOp, Oper1 );
444 break;
445 }
446 Oper2 = Parse_StackOpPop( pStackOp ); // the operation before the last one
447 if ( Oper2 >= Oper1 )
448 { // if Oper2 precedence is higher or equal, execute it
449// Parse_StackPush( pStackFn, Operation( FunStack.Pop(), FunStack.Pop(), Oper2 ) );
450 if ( Parse_ParserPerformTopOp( dd, pStackFn, Oper2 ) == NULL )
451 {
452 fprintf( pOutput, "Parse_FormulaParser(): Unknown operation\n" );
453 ABC_FREE( pFormula );
454 return NULL;
455 }
456 Parse_StackOpPush( pStackOp, Oper1 ); // push the last operation back
457 }
458 else
459 { // if Oper2 precedence is lower, push them back and done
460 Parse_StackOpPush( pStackOp, Oper2 );
461 Parse_StackOpPush( pStackOp, Oper1 );
462 break;
463 }
464 }
465 }
466
467 if ( Flag != PARSE_FLAG_ERROR )
468 {
469 if ( !Parse_StackFnIsEmpty(pStackFn) )
470 {
471 bFunc = (DdNode *)Parse_StackFnPop(pStackFn);
472 if ( Parse_StackFnIsEmpty(pStackFn) )
473 if ( Parse_StackOpIsEmpty(pStackOp) )
474 {
475 Parse_StackFnFree(pStackFn);
476 Parse_StackOpFree(pStackOp);
477 Cudd_Deref( bFunc );
478 ABC_FREE( pFormula );
479 return bFunc;
480 }
481 else
482 fprintf( pOutput, "Parse_FormulaParser(): Something is left in the operation stack\n" );
483 else
484 fprintf( pOutput, "Parse_FormulaParser(): Something is left in the function stack\n" );
485 }
486 else
487 fprintf( pOutput, "Parse_FormulaParser(): The input string is empty\n" );
488 }
489 ABC_FREE( pFormula );
490 return NULL;
491}
492
504DdNode * Parse_ParserPerformTopOp( DdManager * dd, Parse_StackFn_t * pStackFn, int Oper )
505{
506 DdNode * bArg1, * bArg2, * bFunc;
507 // perform the given operation
508 bArg2 = (DdNode *)Parse_StackFnPop( pStackFn );
509 bArg1 = (DdNode *)Parse_StackFnPop( pStackFn );
510 if ( Oper == PARSE_OPER_AND )
511 bFunc = Cudd_bddAnd( dd, bArg1, bArg2 );
512 else if ( Oper == PARSE_OPER_XOR )
513 bFunc = Cudd_bddXor( dd, bArg1, bArg2 );
514 else if ( Oper == PARSE_OPER_OR )
515 bFunc = Cudd_bddOr( dd, bArg1, bArg2 );
516 else if ( Oper == PARSE_OPER_EQU )
517 bFunc = Cudd_bddXnor( dd, bArg1, bArg2 );
518 else if ( Oper == PARSE_OPER_FLR )
519 bFunc = Cudd_bddOr( dd, Cudd_Not(bArg1), bArg2 );
520 else if ( Oper == PARSE_OPER_FLL )
521 bFunc = Cudd_bddOr( dd, Cudd_Not(bArg2), bArg1 );
522 else
523 return NULL;
524 Cudd_Ref( bFunc );
525 Cudd_RecursiveDeref( dd, bArg1 );
526 Cudd_RecursiveDeref( dd, bArg2 );
527 Parse_StackFnPush( pStackFn, bFunc );
528 return bFunc;
529}
530
531
536
#define ABC_ALLOC(type, num)
Definition abc_global.h:264
#define ABC_FREE(obj)
Definition abc_global.h:267
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define b0
Definition bbrImage.c:96
#define b1
Definition bbrImage.c:97
DdNode * Extra_bddMove(DdManager *dd, DdNode *bF, int nVars)
#define PARSE_OPER_EQU
Definition parseCore.c:81
#define PARSE_SYM_EQU3
Definition parseCore.c:69
#define PARSE_SYM_NEGBEF2
Definition parseCore.c:57
#define PARSE_OPER_AND
Definition parseCore.c:78
#define STACKSIZE
Definition parseCore.c:92
#define PARSE_FLAG_OPER
Definition parseCore.c:89
#define PARSE_OPER_MARK
Definition parseCore.c:84
#define PARSE_SYM_OPEN
DECLARATIONS ///.
Definition parseCore.c:50
#define PARSE_SYM_AND1
Definition parseCore.c:59
#define PARSE_SYM_NEGBEF1
Definition parseCore.c:56
#define PARSE_SYM_OR1
Definition parseCore.c:65
#define PARSE_OPER_OR
Definition parseCore.c:80
#define PARSE_SYM_XOR2
Definition parseCore.c:62
#define PARSE_SYM_XOR
Definition parseCore.c:64
#define PARSE_OPER_NEG
Definition parseCore.c:77
#define PARSE_SYM_OR2
Definition parseCore.c:66
#define PARSE_FLAG_ERROR
Definition parseCore.c:90
#define PARSE_SYM_NEGAFT
Definition parseCore.c:58
#define PARSE_SYM_AND2
Definition parseCore.c:60
#define PARSE_FLAG_VAR
Definition parseCore.c:88
#define PARSE_SYM_XOR3
Definition parseCore.c:63
#define PARSE_SYM_LOWER
Definition parseCore.c:52
#define PARSE_OPER_FLR
Definition parseCore.c:82
#define PARSE_OPER_XOR
Definition parseCore.c:79
#define PARSE_FLAG_START
Definition parseCore.c:87
#define PARSE_SYM_EQU1
Definition parseCore.c:67
#define PARSE_SYM_EQU2
Definition parseCore.c:68
#define PARSE_SYM_XOR1
Definition parseCore.c:61
#define PARSE_SYM_CONST0
Definition parseCore.c:54
#define PARSE_SYM_RAISE
Definition parseCore.c:53
DdNode * Parse_FormulaParser(FILE *pOutput, char *pFormulaInit, int nVars, int nRanks, char *ppVarNames[], DdManager *dd, DdNode *pbVars[])
FUNCTION DEFINITIONS ///.
Definition parseCore.c:116
#define PARSE_SYM_CONST1
Definition parseCore.c:55
#define PARSE_OPER_FLL
Definition parseCore.c:83
#define PARSE_SYM_CLOSE
Definition parseCore.c:51
struct ParseStackOpStruct Parse_StackOp_t
Definition parseInt.h:42
Parse_StackFn_t * Parse_StackFnStart(int nDepth)
GLOBAL VARIABLES ///.
Definition parseStack.c:57
void * Parse_StackFnPop(Parse_StackFn_t *p)
Definition parseStack.c:115
void Parse_StackFnFree(Parse_StackFn_t *p)
Definition parseStack.c:136
void Parse_StackFnPush(Parse_StackFn_t *p, void *bFunc)
Definition parseStack.c:94
Parse_StackOp_t * Parse_StackOpStart(int nDepth)
Definition parseStack.c:156
int Parse_StackOpIsEmpty(Parse_StackOp_t *p)
Definition parseStack.c:177
typedefABC_NAMESPACE_HEADER_START struct ParseStackFnStruct Parse_StackFn_t
INCLUDES ///.
Definition parseInt.h:41
void Parse_StackOpPush(Parse_StackOp_t *p, int Oper)
Definition parseStack.c:193
int Parse_StackFnIsEmpty(Parse_StackFn_t *p)
Definition parseStack.c:78
int Parse_StackOpPop(Parse_StackOp_t *p)
Definition parseStack.c:214
void Parse_StackOpFree(Parse_StackOp_t *p)
Definition parseStack.c:235
int strncmp()
int strlen()
char * sprintf()