Annotation of 43BSD/contrib/B/src/bed/gram.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.