|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.