1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
   2: static char rcsid[] = "$Header: gram.c,v 2.5 85/08/22 16:03:16 timo Exp $";
   3: 
   4: /*
   5:  * B editor -- All routines referencing the grammar table are in this file.
   6:  */
   7: 
   8: #include "b.h"
   9: #include "feat.h"
  10: #include "bobj.h"
  11: #include "node.h"
  12: #include "gram.h"
  13: #include "supr.h"
  14: #include "tabl.h"
  15: 
  16: extern bool dflag;
  17: 
  18: #include <ctype.h>
  19: 
  20: 
  21: /*
  22:  * Test whether sym is in the given class.
  23:  */
  24: 
  25: Visible bool
  26: isinclass(sym, ci)
  27:     register int sym;
  28:     struct classinfo *ci;
  29: {
  30:     register classptr cp;
  31: 
  32:     Assert(ci && ci->c_class);
  33:     if (sym == Hole)
  34:         return !isinclass(Optional, ci);
  35:     for (cp = ci->c_class; *cp; ++cp)
  36:         if (sym == *cp)
  37:             return Yes;
  38:     return No;
  39: }
  40: 
  41: 
  42: /*
  43:  * Deliver the representation array for the given node.
  44:  * If the node is actually just a "text" value, construct
  45:  * one in static storage -- which is overwritten at each call.
  46:  * In this case there are two deficiencies: the next call to
  47:  * noderepr which uses the same feature overwrites the reply
  48:  * value of the previous call, AND if the text value itself
  49:  * is changed, the representation may change, too.
  50:  * In practical use this is no problem at all, however.
  51:  */
  52: 
  53: Visible string *
  54: noderepr(n)
  55:     register node n;
  56: {
  57:     register int sym;
  58: 
  59:     if (n && Type(n) == Tex) {
  60:         static string buf[2];
  61:         buf[0] = Str((value)n);
  62:         return buf;
  63:     }
  64:     sym = symbol(n);
  65:     return table[sym].r_repr;
  66: }
  67: 
  68: 
  69: /*
  70:  * Deliver the prototype node for the given symbol.
  71:  */
  72: 
  73: Visible node
  74: gram(sym)
  75:     register int sym;
  76: {
  77:     Assert(sym == 0 || sym > 0 && sym < TABLEN && table[sym].r_symbol);
  78:     return table[sym].r_node;
  79: }
  80: 
  81: #ifdef SAVEBUF
  82: 
  83: /*
  84:  * Deliver the name of a symbol.
  85:  */
  86: 
  87: Visible string
  88: symname(sym)
  89:     int sym;
  90: {
  91:     static char buf[20];
  92: 
  93:     if (sym >= 0 && sym < TABLEN && table[sym].r_name)
  94:         return table[sym].r_name;
  95:     sprintf(buf, "%d", sym);
  96:     return buf;
  97: }
  98: 
  99: 
 100: /*
 101:  * Find the symbol corresponding to a given name.
 102:  * Return -1 if not found.
 103:  */
 104: 
 105: Visible int
 106: nametosym(str)
 107:     register string str;
 108: {
 109:     register int sym;
 110:     register string name;
 111: 
 112:     for (sym = 0; sym < TABLEN; ++sym) {
 113:         name = table[sym].r_name;
 114:         if (name && Strequ(name, str))
 115:             return sym;
 116:     }
 117:     return -1;
 118: }
 119: 
 120: #endif SAVEBUF
 121: 
 122: /*
 123:  * Test whether `sym' may replace the node in the path `p'.
 124:  */
 125: 
 126: Visible bool
 127: allowed(p, sym)
 128:     register path p;
 129:     register int sym;
 130: {
 131:     register path pa = parent(p);
 132:     register int ich = ichild(p);
 133:     register int sympa = pa ? symbol(tree(pa)) : Rootsymbol;
 134: 
 135:     Assert(sympa >= 0 && sympa < TABLEN && ich > 0 && ich <= MAXCHILD);
 136:     return isinclass(sym, table[sympa].r_class[ich-1]);
 137: }
 138: 
 139: 
 140: /*
 141:  * Initialize (and verify) the grammar table.
 142:  */
 143: 
 144: Visible Procedure
 145: initgram()
 146: {
 147:     register int sym;
 148:     register int nch;
 149:     register struct classinfo **cp;
 150:     register struct classinfo *sp;
 151:     node ch[MAXCHILD];
 152: 
 153: #ifndef NDEBUG
 154:     if (dflag)
 155:         fprintf(stderr, "*** initgram();\n\r");
 156: #endif NDEBUG
 157:     /* Set the node pointers in the table and check the representations.
 158: 	   The code assumes Optional and Hole are the last
 159: 	   symbols in the table, i.e. the first processed by the loop. */
 160: 
 161:     for (sym = TABLEN-1; sym >= 0; --sym) {
 162:         if (table[sym].r_symbol != sym) {
 163:             if (sym != Hole && sym != Optional && table[sym].r_symbol == 0)
 164:                 continue; /* Disabled table entry */
 165:             syserr("initgram: table order (%s=%d, should be %d)",
 166:                 table[sym].r_name, table[sym].r_symbol, sym);
 167:         }
 168:         cp = table[sym].r_class;
 169:         for (nch = 0; nch < MAXCHILD && (sp = cp[nch]); ++nch)
 170:             ch[nch] =
 171:                 table[sp->c_class[0] == Optional ?
 172:                     Optional : Hole].r_node;
 173:         table[sym].r_node = newnode(nch, sym, ch);
 174:         fix((value) table[sym].r_node);
 175:     }
 176: 
 177:     initcodes();
 178: #ifdef USERSUGG
 179:     initclasses();
 180: #endif USERSUGG
 181: }
 182: 
 183: 
 184: #ifdef USERSUGG
 185: 
 186: /*
 187:  * Add built-in commands to the suggestion tables.
 188:  */
 189: 
 190: Hidden Procedure
 191: initclasses()
 192: {
 193:     register int i;
 194:     register int j;
 195:     register struct table *tp;
 196: 
 197:     for (i = 0; i < TABLEN; ++i) {
 198:         tp = &table[i];
 199:         if (tp->r_symbol != i || i == Suggestion)
 200:             continue; /* Dead entry */
 201:         for (j = 0; j < MAXCHILD && tp->r_class[j]; ++j) {
 202:             if (isinclass(Suggestion, tp->r_class[j]))
 203:                 makesugg(tp->r_class[j]->c_class);
 204:         }
 205:     }
 206: }
 207: 
 208: 
 209: /*
 210:  * Extract suggestions from class list.
 211:  */
 212: 
 213: Hidden Procedure
 214: makesugg(cp)
 215:     classptr cp;
 216: {
 217:     struct table *tp;
 218:     string *rp;
 219:     char buffer[1000];
 220:     string bp;
 221:     string sp;
 222:     int i;
 223:     int nch;
 224: 
 225:     for (; *cp; ++cp) {
 226:         if (*cp >= TABLEN || *cp < 0)
 227:             continue;
 228:         tp = &table[*cp];
 229:         rp = tp->r_repr;
 230:         if (rp[0] && isupper(rp[0][0])) {
 231:             bp = buffer;
 232:             nch = nchildren(tp->r_node);
 233:             for (i = 0; i <= nch; ++i) {
 234:                 if (rp[i]) {
 235:                     for (sp = rp[i]; *sp >= ' '; ++sp)
 236:                         *bp++ = *sp;
 237:                 }
 238:                 if (i < nch && !isinclass(Optional, tp->r_class[i]))
 239:                     *bp++ = '?';
 240:             }
 241:             if (bp > buffer) {
 242:                 *bp = 0;
 243:                 addsugg(buffer, Yes);
 244:             }
 245:         }
 246:     }
 247: }
 248: 
 249: #endif USERSUGG
 250: 
 251: 
 252: /*
 253:  * Compaction scheme for characters to save space in grammar tables
 254:  * by combining characters with similar properties (digits, l.c. letters).
 255:  */
 256: 
 257: #define RANGE 128 /* ASCII characters are in {0 .. RANGE-1} */
 258: 
 259: Visible char code_array[RANGE];
 260: Visible char invcode_array[RANGE];
 261: Visible int lastcode;
 262: 
 263: Hidden Procedure
 264: initcodes()
 265: {
 266:     register int c;
 267: 
 268:     code_array['\n'] = ++lastcode;
 269:     invcode_array[lastcode] = '\n';
 270:     for (c = ' '; c <= '0'; ++c) {
 271:         code_array[c] = ++lastcode;
 272:         invcode_array[lastcode] = c;
 273:     }
 274:     for (; c <= '9'; ++c)
 275:         code_array[c] = lastcode;
 276:     for (; c <= 'a'; ++c) {
 277:         code_array[c] = ++lastcode;
 278:         invcode_array[lastcode] = c;
 279:     }
 280:     for (; c <= 'z'; ++c)
 281:         code_array[c] = lastcode;
 282:     for (; c < RANGE; ++c) {
 283:         code_array[c] = ++lastcode;
 284:         invcode_array[lastcode] = c;
 285:     }
 286: }
 287: 
 288: 
 289: /*
 290:  * Set the root of the grammar to the given symbol.  It must exist.
 291:  */
 292: 
 293: Visible Procedure
 294: setroot(name)
 295:     string name;
 296: {
 297:     register int k;
 298:     register int i;
 299: 
 300:     for (k = 1; k < TABLEN; ++k) {
 301:         if (table[k].r_name && Strequ(name, table[k].r_name)) {
 302:             table[Rootsymbol].r_symbol = table[k].r_symbol;
 303:             table[Rootsymbol].r_name = table[k].r_name;
 304:             for (i = 0; i < MAXCHILD; ++i) {
 305:                 table[Rootsymbol].r_repr[i] = table[k].r_repr[i];
 306:                 table[Rootsymbol].r_class[i] = table[k].r_class[i];
 307:             }
 308:             table[Rootsymbol].r_repr[i] = table[k].r_repr[i];
 309:             table[Rootsymbol].r_node = table[k].r_node;
 310:             table[Rootsymbol].r_symbol = Rootsymbol;
 311:             return;
 312:         }
 313:     }
 314:     syserr("Can't set root of grammar to <%s>", name);
 315: }
 316: 
 317: 
 318: /*
 319:  * The remainder of this file is specific for the currently used grammar.
 320:  */
 321: 
 322: 
 323: #include "boot.h" /* Has static data, so should be included only once! */
 324: #include "syms.h"
 325: 
 326: Visible struct table *table = b_grammar;
 327: 
 328: 
 329: /*
 330:  * Table indicating which symbols are used to form lists of items.
 331:  * Consulted via predicate 'issublist' in "gram.c".
 332:  */
 333: 
 334: Hidden classelem Asublists[] = {
 335:     E_plus, F_e_plus,
 336:     And, And_kw, Or, Or_kw,
 337:     0,
 338: };
 339: 
 340: Hidden struct classinfo sublists[] = {Asublists};
 341: 
 342: 
 343: /*
 344:  * Predicate telling whether two symbols can form lists together.
 345:  * This is important for list whose elements must alternate in some
 346:  * way, as is the case for [KEYWORD [expression] ]*.
 347:  *
 348:  * This code must be in this file, otherwise the names and values
 349:  * of the symbols would have to be made public.
 350:  */
 351: 
 352: Visible bool
 353: samelevel(sym, sym1)
 354:     register int sym;
 355:     register int sym1;
 356: {
 357:     register int zzz;
 358: 
 359:     if (sym1 == sym)
 360:         return Yes;
 361:     if (sym1 < sym)
 362:         zzz = sym, sym = sym1, sym1 = zzz; /* Ensure sym <= sym1 */
 363:     /* Now always sym < sym1 */
 364:     return sym == Kw_plus && sym1 == E_plus
 365:         || sym == F_kw_plus && sym1 == F_e_plus
 366:         || sym == And && sym1 == And_kw
 367:         || sym == Or && sym1 == Or_kw;
 368: }
 369: 
 370: 
 371: /*
 372:  * Predicate to tell whether a symbol can form chained lists.
 373:  * By definition, all right-recursive symbols can do so;
 374:  * in addition, those listed in the class 'sublists' can do
 375:  * it, too (this is used for lists formed of alternating members
 376:  * such as KW expr KW ...).
 377:  */
 378: 
 379: Visible bool
 380: issublist(sym)
 381:     register int sym;
 382: {
 383:     register int i;
 384:     register string repr;
 385: 
 386:     Assert(sym < TABLEN);
 387:     if (isinclass(sym, sublists))
 388:         return Yes;
 389:     repr = table[sym].r_repr[0];
 390:     if (Fw_positive(repr))
 391:         return No;
 392:     for (i = 0; i < MAXCHILD && table[sym].r_class[i]; ++i)
 393:         ;
 394:     if (i <= 0)
 395:         return No;
 396:     repr = table[sym].r_repr[i];
 397:     if (!Fw_zero(repr))
 398:         return No;
 399:     return isinclass(sym, table[sym].r_class[i-1]);
 400: }

Defined functions

initclasses defined in line 190; used 1 times
initcodes defined in line 263; used 1 times
initgram defined in line 144; used 1 times
isinclass defined in line 25; used 12 times
makesugg defined in line 213; used 1 times
nametosym defined in line 105; used 1 times
setroot defined in line 293; used 4 times

Defined variables

Asublists defined in line 334; used 1 times
code_array defined in line 259; used 7 times
invcode_array defined in line 260; used 5 times
lastcode defined in line 261; used 10 times
rcsid defined in line 2; never used
sublists defined in line 340; used 1 times
table defined in line 326; used 36 times

Defined macros

RANGE defined in line 257; used 3 times
Last modified: 1985-08-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3100
Valid CSS Valid XHTML 1.0 Strict