1
/***************************************************************************
2
krule.cpp - description
5
copyright : (C) 2000 by Ter�k Zsolt
6
email : tz124@hszk.bme.hu
7
***************************************************************************/
9
/***************************************************************************
11
* This program is free software; you can redistribute it and/or modify *
12
* it under the terms of the GNU General Public License as published by *
13
* the Free Software Foundation; either version 2 of the License, or *
14
* (at your option) any later version. *
16
***************************************************************************/
25
extern bool verbose_flag;
47
/* warning! deletes parameter! */
48
void KRule::addAsNewClause(KRule * other)
50
if (other -> isSpecial()) other->saveOut();
51
if (isSpecial()) saveOut();
53
/* If this is conjunctive, has it more than 1 nonterminals on the right side? */
54
if (!isDisjunctive() && !(right.count()==1 && right.first()<0))
56
int tempNum=gr->getNewNonterminal();
57
KRule * tempRule=new KRule();
58
tempRule->left=tempNum;
59
tempRule->right=right;
60
right=QValueList<int>();
61
right.append(tempNum);
62
gr->addRule(tempRule);
63
/* the content becomes the first child */
64
if (thisDefault) myDefault=1;
66
/* Has the other just a nonterminal? */
67
if (other->right.count()==1 && (other->right.first()<0))
69
right.append(other->right.first());
70
if (other->thisDefault) myDefault=right.count();
73
/* the other is disjunuctive */
74
if (other->isDisjunctive())
76
// if (other->myDefault) myDefault=right.count();
81
/* This rule has one child yet, surely. The other has several.
82
But the other must be conjunctive */
84
int tempNum=gr->getNewNonterminal();
85
right.append(tempNum);
88
/* what about default? */
89
if (other->thisDefault) myDefault=right.count();
94
void KRule::append(int s)
96
if (isSpecial()) saveOut();
100
void KRule::setDefault()
105
QValueList<int> KRule::children()
108
QValueList<int>::Iterator it;
109
for (it=right.begin(); it!=right.end(); ++it)
110
if ((*it)<0) ch.append(*it);
116
if (!verbose_flag) return;
117
cout << gr->getNonterminal(left) << " -> ";
118
if (isSpecial()) cout << "@special"; else
119
if (isEpsilon()) cout << '@';
122
QValueList<int>::Iterator i;
124
for (num=1, i=right.begin(); i!=right.end(); ++i, ++num)
126
if (isDisjunctive() && num!=1)
129
cout << gr->getNonterminal(*i) << ' ';
131
cout << '"' << gr->getTerminal(*i) << "\" ";
132
if (myDefault==num && isDisjunctive()) cout << '!';
136
// cout << ';' << style << ':' << type << endl;
140
QString KRule::getTitle() {
144
QString KRule::getToolTip() {
148
QString KRule::getWhatsThis() {
152
void KRule::setTitle(QString * s) {
156
void KRule::setToolTip(QString * s) {
160
void KRule::setWhatsThis(QString * s) {
164
void KRule::setParams(QList<param_type> * p)
169
void KRule::setTransformers(QList<param_type> * t)
174
void KRule::setInitValue(param_type * p)
179
/* returns the index of the selected item in case of disjunctive rules */
180
int KRule::whichIsSelected()
185
return bossRule->whichIsSelected();
186
/**************************************/
187
/* determine which choice is selected */
188
/**************************************/
189
QValueList<int>::Iterator ch;
192
/* a check box controls this disjunction */
195
int hasEpsilonChild=whichEpsilonChild();
196
if (hasEpsilonChild==0) return 1;
197
KRule * noEpsRule=gr->getRule(right[2-hasEpsilonChild]);//
198
// * epsRule=gr->getRule(right[hasEpsilonChild-1]);
200
/* if checkbox exists, choose selected; *
201
* if not, choose default */
202
if ( noEpsRule->place && noEpsRule->place->isSelected()
203
|| !(noEpsRule->place) && (myDefault==3-hasEpsilonChild) )
204
return 3-hasEpsilonChild;
206
return hasEpsilonChild;
210
KRule * tristateChild=gr->getRule(right[0]);
211
if (tristateChild && tristateChild->place)
212
/* check box exists */
213
return tristateChild->place->getState();
215
/* choose default value */
221
/* all children are nonterminals, have radio buttons */
222
for (ch=right.begin(), n=1; ch!=right.end(); ++ch, n++)
223
if (gr->getRule(*ch))
224
/* find selected child */
225
if (gr->getRule(*ch)->place && gr->getRule(*ch)->place->isSelected())
227
/* if place doesn't exist, choose default */
228
else if (!(gr->getRule(*ch)->place) && n==myDefault)
234
/* the rule evaluates, returns the generated text by subwidgets */
235
QString KRule::evaluate(bool considerNoEval)
238
/* check if it is marked not to evaluate */
239
if (isNoEval() && considerNoEval) return result;
240
/* conjunctive : all children */
243
QValueList<int>::Iterator ch;
244
for (ch=right.begin(); ch!=right.end(); ++ch)
246
result+=gr->getTerminal(*ch);
248
if (gr->getRule(*ch))
249
result+=gr->getRule(*ch)->evaluate(considerNoEval);
251
/* disjunctive: the first selected child */
254
/* QValueList<int>::Iterator ch;
257
* a check box controls this disjunction
260
int hasEpsilonChild=whichEpsilonChild();
261
KRule * noEpsRule=gr->getRule(right[2-hasEpsilonChild]),
262
* epsRule=gr->getRule(right[hasEpsilonChild-1]);
264
* if checkbox exists, choose selected; *
265
* if not, choose default
266
if ( noEpsRule->place && noEpsRule->place->isSelected()
267
|| !(noEpsRule->place) && (myDefault==2-hasEpsilonChild) )
268
result=noEpsRule->evaluate(considerNoEval);
270
result=epsRule->evaluate(considerNoEval);
273
* all children are nonterminals, have radio buttons *
274
for (ch=right.begin(), n=1; ch!=right.end(); ++ch, n++)
275
if (gr->getRule(*ch))
276
* find selected child *
277
if (gr->getRule(*ch)->place && gr->getRule(*ch)->place->isSelected())
279
result=gr->getRule(*ch)->evaluate(considerNoEval);
282
* if place doesn't exist, choose default *
283
else if (!(gr->getRule(*ch)->place) && n==myDefault)
285
result=gr->getRule(*ch)->evaluate(considerNoEval);
288
int ruleNum=whichIsSelected()-1;
289
if (ruleNum<0) ruleNum=0;
290
if (ruleNum>=right.count()) ruleNum=right.count()-1;
291
KRule * selectedRule=gr->getRule(right[ruleNum]);
293
result=selectedRule->evaluate(considerNoEval);
297
if (place) result=place->evaluate();
298
else result=evalSpecial(considerNoEval);
302
/* now preform all the transformations */
304
for (t=transformers->last(); t; t=transformers->prev())
306
if (t->type==4) /* substitution */
308
substitute(*t->strsData[0], result, *t->strsData[1], result2, t->strsData[2]!=NULL);
311
if (t->type==5) /* translation */
313
translate(*t->strsData[0], *t->strsData[1], result, result2);
320
/* find the child for discarding if interpreted as a check box */
321
int KRule::whichEpsilonChild()
323
QValueList<int>::Iterator ch;
324
int n=1, hasEpsilonChild=0;
325
if (isDisjunctive() && right.count()==2)
327
for (ch=right.begin(); ch!=right.end(); ++ch, n++)
328
if (gr->getRule(*ch)->isEpsilon()) hasEpsilonChild=n;
329
/* if there is no epsilon child, but there is at least a child with no nonterminals */
331
if (hasEpsilonChild==0)
332
for (ch=right.begin(); ch!=right.end(); ++ch, n++)
333
// if (gr->getRule(*ch)->children().count()==0 && gr->getRule(*ch)->isConjunctive())
334
if (gr->getRule(*ch)->isSimple())
337
return hasEpsilonChild;
340
bool KRule::isTristate()
342
if (isDisjunctive() && children().count()==3)
344
if (gr->getRule(right[1])->isSimple() && gr->getRule(right[2])->isSimple())
350
/* detect is a double disjunction shoulb be treated as a check box */
351
bool KRule::isCheckBox()
353
return whichEpsilonChild()!=0;
356
/* Labels for checkboxes usually appear one level higher in grammars.
357
Detect it if so, and put labels to the logically correct place. */
358
void KRule::correctCheckBox()
360
/* specials beside a check box or radio button should be aligned to the right */
361
if (isBeside() && children().count()==1)
363
KRule * spec=gr->getRule(children()[0]);
364
if (spec && spec->isSpecial()) spec->align=Qt::AlignRight;
367
if ((isCheckBox() || isTristate()) && !hasBoss())
369
int hasEpsilonChild=whichEpsilonChild();
371
/* find the only child */
372
if (hasEpsilonChild || isTristate())
375
only=gr->getRule(right[2-hasEpsilonChild]); /* checkboxes */
377
only=gr->getRule(right[0]); /* tristates */
380
if (only->title.isEmpty()) { only->title=title; title=QString(); only->style|=style & Beside; }
381
if (only->toolTip.isEmpty()) { only->toolTip=toolTip; toolTip=QString(); }
382
if (only->whatsThis.isEmpty()) { only->whatsThis=whatsThis; whatsThis=QString(); }
388
void KRule::saveOut()
392
KRule * save=new KRule();
393
save->type=type; type=Conjunctive;
394
save->specType=specType; specType=0;
395
save->parameters=parameters; parameters=0;
396
save->initValue=initValue; initValue=0;
397
/* no style at this phase */
398
save->left=gr->getNewNonterminal();
399
right.append(save->left);
404
/* evaluate special to the default value if no place is present for it */
405
QString KRule::evalSpecial(bool considerNoEval)
407
param_type * p=getInitValue();
408
QList<param_type> * params=getParams();
410
switch (getSpecType())
412
// integer initial value
413
case 0: /* @integer */
414
if (p && p->type==1) result=QString::number(p->intData);
415
else result=QString::number(0);
418
// string initial value
419
case 1: /* @string */
421
case 5: /* @regexp */
422
case 6: /* @infile */
423
case 7: /* @outfile */
424
case 8: /* @directory */
426
case 24: /* @password */
427
if (p && p->type==0) result= *(p->strData);
430
// initial value choosen from the list
433
case 14: /* @combow */
436
/* which item is initially selected? */
439
/* split parameters the way every line is a different element in the listbox */
443
for (p=params->first(); p; p=params->next())
445
lines+=QStringList::split(QChar('\n'),*(p->strData));
451
// initial value is an other nonterminal
452
case 4: /* @button */
458
result=gr->getRule(p->intData)->evaluate(considerNoEval);
462
case 27: /* @multicol */
465
/* which item is initially selected? */
468
/* split parameters the way every line is a different element in the listbox */
472
for (p=params->first(); p; p=params->next())
474
lines+=QStringList::split(QChar('\n'),*(p->strData));
475
result=lines[n+1]; /* +1: assuming header line */
480
case 10: /* @container */
481
case 11: /* @close */
482
case 12: /* @action */
487
case 19: /* @execclose */
488
case 20: /* @execbuffer */
490
case 22: /* @preview */
500
void KRule::setConstraint(KRule * boss)
b'\\ No newline at end of file'