~ubuntu-branches/ubuntu/lucid/kaptain/lucid

« back to all changes in this revision

Viewing changes to captain/krule.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Bradley Bell
  • Date: 2001-11-30 11:25:19 UTC
  • Revision ID: james.westby@ubuntu.com-20011130112519-uw4jutplvr0h2mgx
Tags: upstream-0.6
Import upstream version 0.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
                          krule.cpp  -  description
 
3
                             -------------------
 
4
    begin                : Tue Aug 1 2000
 
5
    copyright            : (C) 2000 by Ter�k Zsolt
 
6
    email                : tz124@hszk.bme.hu
 
7
 ***************************************************************************/
 
8
 
 
9
/***************************************************************************
 
10
 *                                                                         *
 
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.                                   *
 
15
 *                                                                         *
 
16
 ***************************************************************************/
 
17
 
 
18
#include "krule.h"
 
19
#include "kgrammar.h"
 
20
#include "kplace.h"
 
21
 
 
22
#include <iostream.h>
 
23
 
 
24
extern KGrammar * gr;
 
25
extern bool verbose_flag;
 
26
 
 
27
KRule::KRule()
 
28
{
 
29
  type=Conjunctive;
 
30
  style=0;
 
31
  specType=0;
 
32
  thisDefault=false;
 
33
  myDefault=1;
 
34
  place=0;
 
35
 
 
36
  align=Qt::AlignLeft;
 
37
  parameters=0;
 
38
  transformers=0;
 
39
  initValue=0;
 
40
  bossRule=0;
 
41
}
 
42
 
 
43
KRule::~KRule()
 
44
{
 
45
}
 
46
 
 
47
/* warning! deletes parameter! */
 
48
void KRule::addAsNewClause(KRule * other)
 
49
{
 
50
  if (other -> isSpecial()) other->saveOut();
 
51
  if (isSpecial()) saveOut();
 
52
 
 
53
  /* If this is conjunctive, has it more than 1 nonterminals on the right side? */
 
54
  if (!isDisjunctive() && !(right.count()==1 && right.first()<0))
 
55
  {
 
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;
 
65
  }
 
66
  /* Has the other just a nonterminal? */
 
67
  if (other->right.count()==1 && (other->right.first()<0))
 
68
  {
 
69
    right.append(other->right.first());
 
70
    if (other->thisDefault) myDefault=right.count();
 
71
    delete other;
 
72
  } else
 
73
  /* the other is disjunuctive */
 
74
  if (other->isDisjunctive())
 
75
  {
 
76
//    if (other->myDefault) myDefault=right.count();
 
77
    right+=other->right;
 
78
    delete other;
 
79
  }
 
80
  else
 
81
  /* This rule has one child yet, surely. The other has several.
 
82
  But the other must be conjunctive */
 
83
  {
 
84
    int tempNum=gr->getNewNonterminal();
 
85
    right.append(tempNum);
 
86
    other->left=tempNum;
 
87
    gr->addRule(other);
 
88
    /* what about default? */
 
89
    if (other->thisDefault) myDefault=right.count();
 
90
  }
 
91
  setDisjunctive();
 
92
}
 
93
        
 
94
void KRule::append(int s)
 
95
{
 
96
  if (isSpecial()) saveOut();
 
97
  right.append(s);
 
98
}
 
99
        
 
100
void KRule::setDefault()
 
101
{
 
102
  thisDefault=true;
 
103
}
 
104
        
 
105
QValueList<int> KRule::children()
 
106
{
 
107
  QValueList<int> ch;
 
108
  QValueList<int>::Iterator it;
 
109
  for (it=right.begin(); it!=right.end(); ++it)
 
110
    if ((*it)<0) ch.append(*it);
 
111
  return ch;
 
112
}
 
113
 
 
114
void KRule::print()
 
115
{
 
116
  if (!verbose_flag) return;
 
117
  cout << gr->getNonterminal(left) << " -> ";
 
118
  if (isSpecial()) cout << "@special"; else
 
119
  if (isEpsilon()) cout << '@';
 
120
  else
 
121
  {
 
122
    QValueList<int>::Iterator i;
 
123
    int num;
 
124
    for (num=1, i=right.begin(); i!=right.end(); ++i, ++num)
 
125
    {
 
126
      if (isDisjunctive() && num!=1)
 
127
        cout << " | ";
 
128
      if (*i<0)
 
129
        cout << gr->getNonterminal(*i) << ' ';
 
130
      else
 
131
        cout << '"' << gr->getTerminal(*i) << "\" ";
 
132
      if (myDefault==num && isDisjunctive()) cout << '!';
 
133
    }
 
134
  }
 
135
  /* extra info */
 
136
//  cout << ';' << style << ':' << type << endl;
 
137
  cout << ';' << endl;
 
138
}
 
139
 
 
140
QString KRule::getTitle() {
 
141
  return title;
 
142
}
 
143
 
 
144
QString KRule::getToolTip() {
 
145
  return toolTip;
 
146
}
 
147
 
 
148
QString KRule::getWhatsThis() {
 
149
  return whatsThis;
 
150
}
 
151
 
 
152
void KRule::setTitle(QString * s) {
 
153
  title=*s;
 
154
}
 
155
 
 
156
void KRule::setToolTip(QString * s) {
 
157
  toolTip=*s;
 
158
}
 
159
 
 
160
void KRule::setWhatsThis(QString * s) {
 
161
  whatsThis=*s;
 
162
}
 
163
 
 
164
void KRule::setParams(QList<param_type> * p)
 
165
{
 
166
  parameters=p;
 
167
}
 
168
 
 
169
void KRule::setTransformers(QList<param_type> * t)
 
170
{
 
171
  transformers=t;
 
172
}
 
173
 
 
174
void KRule::setInitValue(param_type * p)
 
175
{
 
176
  initValue=p;
 
177
}
 
178
 
 
179
/* returns the index of the selected item in case of disjunctive rules */
 
180
int KRule::whichIsSelected()
 
181
{
 
182
  if (isDisjunctive())
 
183
  {
 
184
    if (hasBoss())
 
185
      return bossRule->whichIsSelected();
 
186
    /**************************************/
 
187
    /* determine which choice is selected */
 
188
    /**************************************/
 
189
    QValueList<int>::Iterator ch;
 
190
    int n=1;
 
191
 
 
192
    /* a check box controls this disjunction */
 
193
    if (isCheckBox())
 
194
    {
 
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]);
 
199
 
 
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;
 
205
        else
 
206
          return hasEpsilonChild;
 
207
    } else
 
208
    if (isTristate())
 
209
    {
 
210
      KRule * tristateChild=gr->getRule(right[0]);
 
211
      if (tristateChild && tristateChild->place)
 
212
        /* check box exists */
 
213
        return tristateChild->place->getState();
 
214
      else
 
215
        /* choose default value */
 
216
        {
 
217
          n=myDefault;
 
218
        }
 
219
    } else
 
220
 
 
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())
 
226
          return n;
 
227
        /* if place doesn't exist, choose default */
 
228
        else if (!(gr->getRule(*ch)->place) && n==myDefault)
 
229
          return myDefault;
 
230
  }
 
231
  return 1;
 
232
}
 
233
 
 
234
/* the rule evaluates, returns the generated text by subwidgets */
 
235
QString KRule::evaluate(bool considerNoEval)
 
236
{
 
237
  QString result;
 
238
  /* check if it is marked not to evaluate */
 
239
  if (isNoEval() && considerNoEval) return result;
 
240
  /* conjunctive : all children */
 
241
  if (isConjunctive())
 
242
  {
 
243
    QValueList<int>::Iterator ch;
 
244
    for (ch=right.begin(); ch!=right.end(); ++ch)
 
245
    if ((*ch)>=0)
 
246
      result+=gr->getTerminal(*ch);
 
247
    else
 
248
      if (gr->getRule(*ch))
 
249
        result+=gr->getRule(*ch)->evaluate(considerNoEval);
 
250
  }
 
251
  /* disjunctive: the first selected child */
 
252
  if (isDisjunctive())
 
253
  {
 
254
/*    QValueList<int>::Iterator ch;
 
255
    int n=1;
 
256
 
 
257
     * a check box controls this disjunction
 
258
    if (isCheckBox())
 
259
    {
 
260
      int hasEpsilonChild=whichEpsilonChild();
 
261
      KRule * noEpsRule=gr->getRule(right[2-hasEpsilonChild]),
 
262
            * epsRule=gr->getRule(right[hasEpsilonChild-1]);
 
263
 
 
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);
 
269
        else
 
270
          result=epsRule->evaluate(considerNoEval);
 
271
    } else
 
272
 
 
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())
 
278
        {
 
279
          result=gr->getRule(*ch)->evaluate(considerNoEval);
 
280
          break;
 
281
        }
 
282
        * if place doesn't exist, choose default *
 
283
        else if (!(gr->getRule(*ch)->place) && n==myDefault)
 
284
        {
 
285
          result=gr->getRule(*ch)->evaluate(considerNoEval);
 
286
          break;
 
287
        } */
 
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]);
 
292
    if (selectedRule)
 
293
      result=selectedRule->evaluate(considerNoEval);
 
294
  }
 
295
  /* a special */
 
296
  if (isSpecial())
 
297
    if (place) result=place->evaluate();
 
298
    else result=evalSpecial(considerNoEval);
 
299
 
 
300
  QString result2;
 
301
  param_type * t;
 
302
  /* now preform all the transformations */
 
303
  if (transformers)
 
304
  for (t=transformers->last(); t; t=transformers->prev())
 
305
  {
 
306
    if (t->type==4) /* substitution */
 
307
    {
 
308
      substitute(*t->strsData[0], result, *t->strsData[1], result2, t->strsData[2]!=NULL);
 
309
      result=result2;
 
310
    }
 
311
    if (t->type==5) /* translation */
 
312
    {
 
313
      translate(*t->strsData[0], *t->strsData[1], result, result2);
 
314
      result=result2;
 
315
    }
 
316
  }
 
317
  return result;
 
318
}
 
319
 
 
320
/* find the child for discarding if interpreted as a check box  */
 
321
int KRule::whichEpsilonChild()
 
322
{
 
323
  QValueList<int>::Iterator ch;
 
324
  int n=1, hasEpsilonChild=0;
 
325
  if (isDisjunctive() && right.count()==2)
 
326
  {
 
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 */
 
330
    n=1;
 
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())
 
335
          hasEpsilonChild=n;
 
336
  }
 
337
  return hasEpsilonChild;
 
338
}
 
339
 
 
340
bool KRule::isTristate()
 
341
{
 
342
  if (isDisjunctive() && children().count()==3)
 
343
  {
 
344
    if (gr->getRule(right[1])->isSimple() && gr->getRule(right[2])->isSimple())
 
345
      return true;
 
346
  }
 
347
  return false;
 
348
}
 
349
 
 
350
/* detect is a double disjunction shoulb be treated as a check box */
 
351
bool KRule::isCheckBox()
 
352
{
 
353
  return whichEpsilonChild()!=0;
 
354
}
 
355
 
 
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()
 
359
{
 
360
  /* specials beside a check box or radio button should be aligned to the right */
 
361
  if (isBeside() && children().count()==1)
 
362
  {
 
363
    KRule * spec=gr->getRule(children()[0]);
 
364
    if (spec && spec->isSpecial()) spec->align=Qt::AlignRight;
 
365
  }
 
366
 
 
367
  if ((isCheckBox() || isTristate()) && !hasBoss())
 
368
  {
 
369
    int hasEpsilonChild=whichEpsilonChild();
 
370
    KRule * only;
 
371
    /* find the only child */
 
372
    if (hasEpsilonChild || isTristate())
 
373
    {
 
374
      if (hasEpsilonChild)
 
375
        only=gr->getRule(right[2-hasEpsilonChild]); /* checkboxes */
 
376
      else
 
377
        only=gr->getRule(right[0]); /* tristates */
 
378
      if (only)
 
379
      {
 
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(); }
 
383
      }
 
384
    }
 
385
  }
 
386
}
 
387
 
 
388
void KRule::saveOut()
 
389
{
 
390
  if (isSpecial())
 
391
  {
 
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);
 
400
    gr->addRule(save);
 
401
  }
 
402
}
 
403
 
 
404
/* evaluate special to the default value if no place is present for it */
 
405
QString KRule::evalSpecial(bool considerNoEval)
 
406
{
 
407
  param_type * p=getInitValue();
 
408
  QList<param_type> * params=getParams();
 
409
  QString result("");
 
410
  switch (getSpecType())
 
411
  {
 
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);
 
416
      break;
 
417
 
 
418
    // string initial value
 
419
    case 1: /* @string */
 
420
    case 3: /* @float */
 
421
    case 5: /* @regexp */
 
422
    case 6:  /* @infile */
 
423
    case 7:  /* @outfile */
 
424
    case 8:  /* @directory */
 
425
    case 13: /* @edit */
 
426
    case 24: /* @password */
 
427
      if (p && p->type==0) result= *(p->strData);
 
428
      break;
 
429
 
 
430
    // initial value choosen from the list
 
431
    case 2:  /* @list */
 
432
    case 9:  /* @combo */
 
433
    case 14: /* @combow */
 
434
    {
 
435
      int n=0;
 
436
      /* which item is initially selected? */
 
437
      if (p && p->type==1)
 
438
        n=p->intData-1;
 
439
      /* split parameters the way every line is a different element in the listbox */
 
440
      QStringList lines;
 
441
      if (params)
 
442
      {
 
443
        for (p=params->first(); p; p=params->next())
 
444
          if (p->type==0)
 
445
            lines+=QStringList::split(QChar('\n'),*(p->strData));
 
446
        result=lines[n];
 
447
      }
 
448
      break;
 
449
    }
 
450
 
 
451
    // initial value is an other nonterminal
 
452
    case 4:  /* @button */
 
453
    {
 
454
      if (params)
 
455
      {
 
456
        p=params->first();
 
457
        if (p && p->type==2)
 
458
          result=gr->getRule(p->intData)->evaluate(considerNoEval);
 
459
      }
 
460
      break;
 
461
    }
 
462
    case 27: /* @multicol */
 
463
    {
 
464
      int n=0;
 
465
      /* which item is initially selected? */
 
466
      if (p && p->type==1)
 
467
        n=p->intData-1;
 
468
      /* split parameters the way every line is a different element in the listbox */
 
469
      QStringList lines;
 
470
      if (params)
 
471
      {
 
472
        for (p=params->first(); p; p=params->next())
 
473
          if (p->type==0)
 
474
            lines+=QStringList::split(QChar('\n'),*(p->strData));
 
475
        result=lines[n+1]; /* +1: assuming header line */
 
476
      }
 
477
      break;
 
478
    }
 
479
    // no evaluation
 
480
    case 10: /* @container */
 
481
    case 11: /* @close */
 
482
    case 12: /* @action */
 
483
    case 15: /* @exec */
 
484
    case 16: /* @echo */
 
485
    case 17: /* @icon */
 
486
    case 18: /* @text */
 
487
    case 19: /* @execclose */
 
488
    case 20: /* @execbuffer */
 
489
    case 21: /* @dump */
 
490
    case 22: /* @preview */
 
491
    case 23: /* @size */
 
492
    case 25: /* @fork */
 
493
    case 26: /* @fill */
 
494
    default:
 
495
      break;
 
496
  }
 
497
  return result;
 
498
}
 
499
 
 
500
void KRule::setConstraint(KRule * boss)
 
501
{
 
502
  bossRule=boss;
 
503
}
 
 
b'\\ No newline at end of file'