home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 173_01 / lex.y < prev    next >
Text File  |  1979-12-31  |  18KB  |  748 lines

  1. /*
  2.   HEADER:              CUG  nnn.nn;
  3.   TITLE:               LEX - A Lexical Analyser Generator
  4.   VERSION:             1.1 for IBM-PC
  5.   DATE:                Jan 30, 1985
  6.   DESCRIPTION:         A Lexical Analyser Generator. From UNIX
  7.   KEYWORDS:            Lexical Analyser Generator YACC C PREP
  8.   SYSTEM:              IBM-PC and Compatiables
  9.   FILENAME:            LEX.Y
  10.   WARNINGS:            This program is not for the casual user. It will
  11.                        be useful primarily to expert developers.
  12.                        This file must be processed by YACC with the -d
  13.                        option.
  14.   CRC:                 N/A
  15.   SEE-ALSO:            YACC and PREP
  16.   AUTHORS:             Charles H. Forsyth
  17.                        Scott Guthery 11100 leafwood lane Austin, TX 78750
  18.                        Andrew M. Ward, Jr.  Houston, Texas (Modifications)
  19.   COMPILERS:           LATTICE C
  20.   REFERENCES:          UNIX Systems Manuals -- Lex Manual on distribution disks
  21. */
  22. /*
  23.  * Copyright (c) 1978 Charles H. Forsyth
  24.  *
  25.  *
  26.  * Modified 22-Jun-86 Andrew Ward -- Modified code to compile under Lattice C
  27.  *                                 version 3.0h.  Corrected several errors
  28.  *                                 from the assumption that pointers and
  29.  *                                 integers are the same size.     
  30.  *                                 New debug code for LATTICE C using assert
  31.  *                                 to test for wild pointers.  Using a proper
  32.  *                                 YACC this will produce a ytab.c file that
  33.  *                   does not need hand modification.     
  34.  */
  35.  
  36. /*
  37.  * lex -- grammar/lexical analyser
  38.  */
  39.  
  40. %{
  41. #include <stdio.h>
  42. #include <assert.h>
  43. #include <stdlib.h>
  44. #include <string.h>
  45. #include "lexlex.h"
  46.  
  47.  
  48. char    ccl[ (NCHARS+1) / NBPC ];
  49. int  sz_ccl = (NCHARS+1) / NBPC;
  50.     char *yysterm[] = {
  51.        "error",
  52.        "NAME",
  53.        "CCLASS",
  54.        "STRING",
  55.        "CONCAT",
  56.        0     };
  57.     extern char *progname;
  58.     extern char *breakc;
  59.     extern char *ignore;
  60.     extern char *illeg;
  61.     extern int  nlook;
  62.     char *lalloc();
  63.     struct des {
  64.        struct nfa *d_start;
  65.        struct nfa *d_final;
  66.     };
  67.     struct nlist {
  68.        struct  nlist   *nl_next;
  69.        struct  nfa     *nl_base;
  70.        struct  nfa     *nl_end;
  71.        struct  nfa     *nl_start;
  72.        struct  nfa     *nl_final;
  73.        char    *nl_name;
  74.     }
  75.     *nlist;
  76.     extern  int str_len;
  77.     extern  struct  nfa     *nfap;
  78.     extern  struct  nfa     *elem(int, char *);
  79.     extern  struct  des     *newdp(struct nfa *, struct nfa *);
  80.     extern  struct  nlist   *lookup(char *);
  81.     extern int     mapc(int);
  82.     extern int     cclass(void);
  83.     extern void    name(int);
  84.     extern void    action(void);
  85.     extern void    skipstr(int);
  86.     extern void    copycode(void);
  87.     extern void    string(int);
  88.     extern void    copynfa(struct nlist *, struct nfa *, struct des *);
  89.     extern void    spccl(char *, char *, struct des *, char **);
  90.     extern void    unget( int );
  91.     extern void    copy(char *, char *, int);
  92.     extern void    errmsg(char *);
  93.     extern void    yyerror(char *, char *);
  94.     extern void    newcase(int);
  95.     extern void    llactr(void);
  96.     extern void    setline(void);
  97.     extern void    cclprint(char *);
  98.     extern int     yyline;
  99.     %}
  100. %union {
  101.     char   *buff;
  102.     struct nlist *list;
  103.     struct des   *des_ptr;
  104.     struct nfa   *elem_ptr;
  105. }
  106. %term NAME CCLASS STRING CONCAT
  107. %token <buff>  STRING NAME CCLASS
  108. %type <buff> NAME CCLASS
  109. %type <list> namedef name
  110. %type <des_ptr> pattern regexp
  111. %left ';'
  112. %left '='
  113. %left '/'
  114. %left '|'
  115. %left '(' NAME STRING CCLASS
  116. %left CONCAT
  117. %left '*'
  118. %%
  119. %{
  120.     struct nfa *np, *nbase;
  121.     char *cp;
  122.     struct des *dp, *dp1;
  123.     struct trans *tp;
  124.     struct nlist *nl;
  125.     int i, c;
  126.     %}
  127. lexfile:
  128. auxiliary_section translation_section
  129. |
  130.  
  131. ;
  132.  
  133. auxiliary_section:
  134. auxiliaries '%' '%'
  135. |       '%' '%'
  136. ;
  137.  
  138. auxiliaries:
  139. auxiliaries auxiliary
  140. |       auxiliary
  141. ;
  142.  
  143. auxiliary:
  144. namedef '=' regexp ';' ={
  145.     dp = $3;
  146.     nl = $1;
  147.     np = nl->nl_base;
  148.     nl->nl_start = dp->d_start;
  149.     nl->nl_final = dp->d_final;
  150.     nl->nl_end = nfap;
  151. #ifdef DEBUG
  152.     printf("NFA for %s\n", nl->nl_name);
  153.     nfaprint(dp->d_start, nl->nl_base);
  154. #endif
  155.     i = nl->nl_end - nl->nl_base;
  156.     nbase = (struct nfa *)lalloc(i, sizeof(struct nfa), "nfa storage");
  157.     copynfa(nl, nbase, dp);
  158.     nl->nl_start = dp->d_start;
  159.     nl->nl_final = dp->d_final;
  160.     nl->nl_end = nbase+i;
  161.     nl->nl_base = nbase;
  162.     nfap = np;
  163.     spccl(nl->nl_name, "ignore", dp, &ignore);
  164.     spccl(nl->nl_name, "break", dp, &breakc);
  165.     spccl(nl->nl_name, "illegal", dp, &illeg);
  166. }
  167. |       '%' '{'         ={
  168.     copycode();
  169. }
  170. ;
  171.  
  172. namedef:
  173. NAME    ={
  174.     $$ = lookup($1);
  175.     $$->nl_base = nfap;
  176.     if ($$->nl_start)
  177.        yyerror("%s redefined", $$->nl_name);
  178. }
  179. ;
  180.  
  181. name:
  182. NAME    = {
  183.     $$ = lookup($1);
  184. }
  185. ;
  186.  
  187. regexp:
  188. CCLASS = {
  189.     np = elem(CCL, $1);
  190.     $$ = newdp(np, (np->n_succ[0] = elem(FIN, (char *)NULL ) ) );
  191. }
  192. |       STRING ={
  193.     cp = $1;
  194.     if (str_len == 0) {
  195.        np = elem(EPSILON, (char *)NULL );
  196.        $$ = newdp(np, (np->n_succ[0] = elem(FIN, (char *)NULL ) ) );
  197.        /* return(0);*/ /* AMW: the return here appears in error */
  198.        }
  199.     else /* AMW: else stmt added 1 May 1986 $$->d_start added */
  200.        {
  201.        $$->d_start = np = elem(*cp++, (char *)NULL);
  202.        while(--str_len > 0)
  203.            np = np->n_succ[0] = elem(*cp++,(char *)NULL);
  204.        $$ = newdp($$->d_start, ( np->n_succ[0] = elem( FIN, (char *)NULL ) ) );
  205.        }
  206.     }
  207.     |       name    ={
  208.        if ((nl = $1)->nl_end == NULL)
  209.        {
  210.            yyerror("%s not defined", nl->nl_name);
  211.            nl->nl_base = nl->nl_end = elem(FIN, (char *)NULL);
  212.            nl->nl_start = nl->nl_final = nl->nl_base;
  213.        }
  214.        $$ = dp = (struct des *)lalloc(1, sizeof(struct des), "dfa input");
  215.        nbase = nfap;
  216.        i = nl->nl_end - nl->nl_base;
  217.        if ((nfap += i) >= &nfa[MAXNFA]) {
  218.            errmsg("Out of NFA nodes");
  219.            exit(1);
  220.        }
  221.        copynfa(nl, nbase, dp);
  222.     }
  223.     |       regexp '*' ={
  224.        $$ = dp = $1;
  225.        dp->d_start = newnfa(EPSILON, (np = dp->d_start), (struct nfa *)NULL);
  226.        dp->d_final->n_char = EPSILON;
  227.        dp->d_final->n_succ[0] = np;
  228.        dp->d_final->n_succ[1] = np = elem(FIN, (char *)NULL);
  229.        dp->d_start->n_succ[1] = np;
  230.        dp->d_final = np;
  231.     }
  232.     |       regexp '|' regexp ={
  233.        $$ = dp = $1;
  234.        dp->d_start = newnfa(EPSILON, dp->d_start, $3->d_start);
  235.        dp->d_final->n_char = EPSILON;
  236.        dp->d_final = dp->d_final->n_succ[0] = np = elem(FIN, (char *)NULL );
  237.        dp = $3;
  238.        dp->d_final->n_char = EPSILON;
  239.        dp->d_final->n_succ[0] = np;
  240. #ifdef DEBUG
  241.        assert( isdata( (char *)$3, sizeof( struct des) ) );
  242. #endif
  243.        free((char *)$3);
  244.     }
  245.     |       regexp regexp %prec CONCAT ={
  246.        $$ = $1;
  247.        dp = $2;
  248.        np = $$->d_final;
  249.        $$->d_final = dp->d_final;
  250.        np->n_char = dp->d_start->n_char;
  251.        np->n_ccl = dp->d_start->n_ccl;
  252.        np->n_succ[0] = dp->d_start->n_succ[0];
  253.        np->n_succ[1] = dp->d_start->n_succ[1];
  254. #ifdef DEBUG
  255.        assert( isdata( (char *)$2, sizeof( struct nlist) ) );
  256. #endif
  257.        free((char *)$2);
  258.     }
  259.     |       '(' regexp ')' ={
  260.        $$ = $2;
  261.     }
  262.     ;
  263.  
  264. translation_section:
  265.     translations ={
  266.        ending();
  267. trans1:
  268.  
  269.        printf("\nNFA for complete syntax\n");
  270.        printf("state 0\n");
  271.        for (tp = trans; tp < transp; tp++)
  272.            printf("\tepsilon\t%d\n", tp->t_start-nfa);
  273.        for (tp = trans; tp < transp; tp++)
  274.            nfaprint(tp->t_start, nfa);
  275.        ;
  276.     }
  277.     |       ={
  278.        goto trans1;
  279.     }
  280.     ;
  281.  
  282. translations:
  283.     translations translation
  284.        |       llactr translation
  285.        ;
  286.  
  287. llactr:
  288.     ={
  289.        llactr();
  290.     }
  291.     ;
  292.  
  293. translation:
  294.     pattern action ={
  295.        dp = $1;
  296.        newtrans(dp->d_start, dp->d_final);
  297.     }
  298.     |       '%' '{'         ={
  299.        copycode();
  300.     }
  301.     |       '%' '%'         ={
  302.        ending();
  303.        while ((c = get()) != EOF)
  304.            putc(c, llout);
  305.     }
  306.     ;
  307.  
  308. action:
  309.     '{'     ={
  310.        action();
  311.     }
  312.     ;
  313.  
  314. pattern:
  315.     regexp '/' regexp ={
  316.        if (nlook >= NBPW)
  317.            yyerror("More than %d translations with lookahead",NBPW);
  318.        $$ = dp = $1;
  319.        np = dp->d_final;
  320.        np->n_char = EPSILON;
  321.        np->n_flag |= LOOK;
  322.        np->n_succ[0] = $3->d_start;
  323.        dp->d_final = $3->d_final;
  324.        np->n_look = nlook;
  325.        dp->d_final->n_look = nlook++;
  326.        dp->d_final->n_flag |= FLOOK;
  327. #ifdef DEBUG
  328.        assert( isdata( (char *)$3, sizeof( struct des) ) );
  329. #endif
  330.        free((char *)$3);
  331.     }
  332.     |       regexp
  333.        ;
  334.  
  335. %%
  336.     /*
  337.  * Lexical analyser
  338.  * (it isn't done with lex...)
  339.  */
  340.        char    buffer[150];
  341.  
  342. int yylex()
  343.     {
  344.  
  345.        int c;
  346.        /*      char *cp; */
  347.        int lno;
  348.  
  349.        if (yyline == 0)
  350.            yyline++;
  351. loop:
  352.        c = get();
  353.        if (isupper(c)) {
  354.            name(c);
  355.            yylval.buff = strlwr( yylval.buff );
  356.            return(STRING);
  357.        }
  358.        else if (islower(c) || c == '_') {
  359.            name(c);
  360.            return(NAME);
  361.        }
  362.        switch (c) {
  363.        case EOF:
  364.            return(0);
  365.  
  366.        case '[':
  367.            return(cclass());
  368.  
  369.        case '(':
  370.        case ')':
  371.        case '{':
  372.        case '}':
  373.        case '*':
  374.        case '|':
  375.        case '=':
  376.        case ';':
  377.        case '%':
  378.            return(c);
  379.  
  380.        case '/':
  381.            if ((c = get()) != '*') {
  382.                unget(c);
  383.                return('/');
  384.            }
  385.            lno = yyline;
  386.            for (; c != EOF; c = get())
  387.                if (c == '*')
  388.                    if ((c = get()) == '/')
  389.                        goto loop;
  390.                    else
  391.                        unget(c);
  392.            yyline = lno;
  393.            errmsg("End of file in comment");
  394.  
  395.        case '\'':
  396.        case '"':
  397.            yylval.buff = buffer;
  398.            string(c);
  399.            return(STRING);
  400.  
  401.        case '\n':
  402.        case '\r':
  403.        case ' ':
  404.        case '\t':
  405.            goto loop;
  406.  
  407.        default:
  408.  
  409.            yylval.buff = buffer;
  410. /*         if (c == '\\') {
  411.                unget(c);
  412.                c = mapch(EOF);
  413.            }
  414. */
  415.            buffer[0] = c;
  416.            buffer[1] = '\0';
  417.            str_len = 1;
  418.            return(STRING);
  419.        }
  420.     }
  421.  
  422.  
  423. int cclass()
  424.     {
  425.        int c, i, lc;
  426.        int compl;
  427.  
  428.        compl = 0;
  429.        /* Zero the ccl array */
  430.        for (i = 0; i < sz_ccl; i++)  ccl[i] = '\0';
  431.        /* Check if exclusion definition */
  432.        if ((c = get()) == '^') compl++;
  433.        else  unget(c);
  434.  
  435.        lc = -1;
  436.        while( ( c = mapc(']') ) != EOF)
  437.        {
  438.            if (c == '-' && lc >= 0)
  439.            {
  440.                if((c = mapc(']')) == EOF)   break;
  441.                /* Map 'c' into bit pattern */
  442.                for(i = lc; i <= c; i++)  ccl[ i / NBPC ] |= 1 << (i % NBPC);
  443.                lc = -1;
  444.                continue;
  445.            }
  446.  
  447.            ccl[ c / NBPC ] |= 1 << ( c % NBPC );
  448.            lc = c;
  449.        }
  450.  
  451.        if (compl) {
  452.            for (i = 0; i < sz_ccl; i++)
  453.                ccl[i] ^= -1;
  454.            if (aflag == 0)
  455.                for (i = 0200; i < ( 1 << NBPC ); i++)
  456.                    ccl[i/NBPC] &= ~(1 << (i%NBPC));
  457.        }
  458.        yylval.buff = newccl( ccl );
  459.        return(CCLASS);
  460.     }
  461.  
  462. void string(ec)
  463. int ec;
  464.     {
  465.        char *cp;
  466.        int c;
  467.        extern int str_len;
  468.        for(cp = buffer; (c = mapc(ec)) != EOF;)
  469.            *cp++ = c;
  470.        *cp = '\0';
  471.        str_len = strlen( buffer );
  472.     }
  473.  
  474. int mapc(ec)
  475.        int ec;
  476.     {
  477.  
  478.        int c, v, i;
  479.  
  480.        if((c = get()) == ec)  return(EOF);
  481.        switch(c) {
  482.        case EOF:
  483.            errmsg("End of file in string");
  484.            return(c);
  485.  
  486.        case '\\':
  487.            if ((c = get()) >= '0' && c <= '7') {
  488.                i = 0;
  489.                for (v = 0; c>='0' && c<='7' && i++<3; c = get())
  490.                    v = v*010 + c-'0';
  491.                unget(c);
  492.                return(v&CMASK);
  493.            }
  494.            switch (c) {
  495.            case 'n':
  496.                return('\n');
  497.  
  498.            case 't':
  499.                return('\t');
  500.  
  501.            case 'b':
  502.                return('\b');
  503.  
  504.            case 'r':
  505.                return('\r');
  506.  
  507.            case '\n':
  508.                yyline++;
  509.                return(mapc(ec));
  510.            }
  511.  
  512.        default:
  513.            return(c);
  514.        }
  515.     }
  516.  
  517. void name(c)
  518.        int c;
  519.     {
  520.        char *cp;
  521.  
  522.        for (yylval.buff=cp=buffer; isalpha(c) || isdigit(c) || c=='_'; c=get())
  523.            *cp++ = c;
  524.        *cp = '\0';
  525.        str_len = strlen( buffer );
  526.        unget(c);
  527.     }
  528.  
  529. /*
  530.  * Miscellaneous functions
  531.  * used only by lex.y
  532.  */
  533. struct nfa *elem(k, v)
  534. int k;
  535. char *v;
  536.     {
  537.        struct nfa *fp;
  538.        fp = newnfa(k, (struct nfa *)NULL, (struct nfa *)NULL);
  539.  
  540.        if (k == CCL)
  541.            fp->n_ccl = v;
  542.        return(fp);
  543.     }
  544.  
  545. struct des *newdp(st, fi)
  546.     struct nfa *st, *fi;
  547.     {
  548.        struct des *dp;
  549.  
  550.        dp = (struct des *)lalloc(1, sizeof(struct des), "dfa input");
  551. #ifdef DEBUG
  552.        if( st != NULL) assert( isdata( (char *)st, sizeof( struct nfa ) ) );
  553.        if( fi != NULL) assert( isdata( (char *)fi, sizeof( struct nfa ) ) );
  554. #endif
  555.        dp->d_start = st;
  556.        dp->d_final = fi;
  557.        return(dp);
  558.     }
  559.  
  560. void action()
  561.     {
  562.        int c;
  563.        int lno, lev;
  564.  
  565.        newcase(transp-trans);
  566.        lno = yyline;
  567.        lev = 0;
  568.        for (; (c = get()) != EOF && (c != '}' || lev); putc(c, llout))
  569.            if (c == '{')
  570.                lev++;
  571.            else if (c == '}')
  572.                lev--;
  573.            else if (c == '\'' || c == '"') {
  574.                putc(c, llout);
  575.                skipstr(c);
  576.            }
  577.        fprintf(llout, "\n\tbreak;\n");
  578.        if (c == EOF) {
  579.            yyline = lno;
  580.            errmsg("End of file in action");
  581.        }
  582.     }
  583.  
  584. void skipstr(ec)
  585.        int ec;
  586.     {
  587.        int c;
  588.  
  589.        while ((c = get()) != ec && c != EOF) {
  590.            putc(c, llout);
  591.            if (c == '\\' && (c = get()) != EOF)
  592.                putc(c, llout);
  593.        }
  594.     }
  595.  
  596.  
  597. void copycode()
  598.     {
  599.        int lno;
  600.        int c;
  601.  
  602.        setline();
  603.        lno = yyline;
  604.        for (; (c = get()) != EOF; putc(c, llout))
  605.            if (c == '%')
  606.            {
  607.                if ((c = get()) == '}')
  608.                    return;
  609.                unget(c);
  610.                c = '%';
  611.            }
  612.        yyline = lno;
  613.        errmsg("Incomplete %{ declaration");
  614.        exit(1);
  615.     }
  616.  
  617. struct nlist *lookup(s)
  618.        char *s;
  619.     {
  620.        struct nlist *nl;
  621.        char *cp;
  622.  
  623.        for (nl = nlist; nl; nl = nl->nl_next)
  624.            if (!strcmp(s, nl->nl_name))
  625.                return(nl);
  626.        nl = (struct nlist *)lalloc(1, sizeof(struct nlist), "namelist");
  627.        nl->nl_start = nl->nl_end = nl->nl_base = nl->nl_final = (struct nfa *)NULL;
  628.        nl->nl_next = nlist;
  629.        nlist = nl;
  630.        nl->nl_name = cp = strdup( s );
  631.        return(nl);
  632.     }
  633.  
  634. void copynfa(nl, nbase, dp)
  635.        struct nlist *nl;
  636.        struct des *dp;
  637.        struct nfa *nbase;
  638. {
  639.        struct nfa *np, *ob;
  640.        int j;
  641.        int i;
  642.  
  643.        ob = nl->nl_base;
  644.        i = nl->nl_end - ob;
  645.  
  646. #ifdef DEBUG
  647.        fprintf(stdout, "\nCOPYNFA: index i = %d",i);
  648. #endif
  649.        np = nbase;
  650.        copy((char *)np, (char *)ob, sizeof(struct nfa)*i);
  651.        for (np = nbase; i-- > 0; np++) {
  652.            np->n_flag &= ~NPRT;
  653.            for (j = 0; j < 2; j++)
  654.                if (np->n_succ[j])
  655.                    np->n_succ[j] = nbase + (np->n_succ[j] - ob);
  656.        }
  657.        dp->d_start = nbase + (int)(nl->nl_start-ob);
  658.        dp->d_final = nbase + (int)(nl->nl_final-ob);
  659. }
  660.  
  661. void spccl(nm, isit, dp, where)
  662.     char       *nm, *isit;
  663.     struct des *dp;
  664.     char       **where;
  665.     {
  666.        if (!strcmp(nm, isit))
  667.        {
  668.             if(*where != 0 )
  669.                  yyerror("redefinition of %s class", isit);
  670.             if (dp->d_start->n_char == CCL &&
  671.                  dp->d_start->n_succ[0] == dp->d_final)
  672.                  *where = dp->d_start->n_ccl;
  673.             else
  674.                  yyerror("Illegal %s class", isit);
  675.        }
  676.     }
  677.  
  678. int get()
  679.     {
  680.        int c;
  681.  
  682.        if ((c = getc(lexin)) == '\n')
  683.            yyline++;
  684.        return(c);
  685.     }
  686.  
  687. void unget(c)
  688.     int c;
  689.     {
  690.        if (c == '\n')
  691.            yyline--;
  692.        ungetc(c, lexin);
  693.     }
  694.  
  695. void errmsg(s)
  696.        char *s;
  697.     {
  698.        if (yyline)
  699.            fprintf(stderr, "%d: ", yyline);
  700.        fprintf(stderr, "%r", &s);
  701.        if (yychar > 256)
  702.            fprintf(stderr, " near `%s'", yysterm[yychar-256]);
  703.        else if (yychar < 256 && yychar > 0)
  704.            fprintf(stderr, " near `%c'", yychar);
  705.        fprintf(stderr, "\n");
  706.     }
  707.  
  708. void copy(out, in, count)
  709. char   *out;
  710. char   *in;
  711. int    count;
  712. {
  713.         while (--count >= 0)
  714.                 *out++ = *in++;
  715. }
  716.  
  717. void yyerror(format, value)
  718. char *format, *value;
  719. {
  720.         if (yyline)
  721.                 fprintf(stderr, "%d: ", yyline);
  722.         fprintf(stderr, format, value);
  723.         if (yychar > 256)
  724.                 fprintf(stderr, " near '%s'", yysterm[yychar-256]);
  725.         else if (yychar < 256 && yychar > 0)
  726.                 fprintf(stderr, " near '%c'", yychar);
  727.         fprintf(stderr, "\n");
  728. }
  729. int nterms = 15;
  730. int nnonter = 13;
  731. int nstate = 41;
  732.  
  733. char *yysnter[14] = {
  734. "$accept",
  735. "lexfile",
  736. "auxiliary_section",
  737. "translation_section",
  738. "auxiliaries",
  739. "auxiliary",
  740. "namedef",
  741. "regexp",
  742. "name",
  743. "translations",
  744. "translation",
  745. "llactr",
  746. "pattern",
  747. "action" };
  748.