home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.lbl.gov / 2014.05.ftp.ee.lbl.gov.tar / ftp.ee.lbl.gov / s2latex.tar.Z / s2latex.tar / s2l.y < prev    next >
Text File  |  1985-02-05  |  14KB  |  551 lines

  1. %{
  2. #ifndef lint
  3. static char *sccsid="@(#)s2l.y    1.2 (LBL) 2/4/85";
  4. #endif
  5. /* scribe-to-latex converter.
  6.  *
  7.  * copyright (c) 1984 by Van Jacobson, Lawrence Berkeley Laboratory
  8.  * This program may be freely redistributed but not for profit.  This
  9.  * comment must remain in the program or any derivative.
  10.  *
  11.  * I would appreciate comments, suggestions, bug fixes, etc.  My
  12.  * mailing addresses are:
  13.  *   van@lbl-csam.arpa or van@lbl-rtsg.arpa (ARPANET or CSNET)
  14.  *   ucbvax!lbl-csam!van  (UUCP)
  15.  *
  16.  * Expect to get 81 shift/reduce & 48 reduce/reduce conflicts when
  17.  * running this thing through yacc.  The grammar does more-or-less
  18.  * what I wanted so I didn't bother to add the precedence & assoc.
  19.  * rules needed to get rid of the confict msgs.
  20.  *
  21.  * Change this grammar with fear & trembling (I do).  No text is
  22.  * kept around by the parser so the order of the reductions is very
  23.  * important.  The reduction that outputs the current token has to
  24.  * happen before the next shift wipes out that token (except in some
  25.  * cases where the parse stack or the production encodes the token).
  26.  *
  27.  * Modifications.
  28.  * --------------
  29.  * 05Feb85, vj    Bug fixes from users: added "comment" to allowed names
  30.  *        in -s file; added "format" as kw in addition to env;
  31.  *        fixed bug in kw->env handling; fixed mis-count of arguments
  32.  *        when "-s" present.
  33.  * 30Dec84, vj    Changed description env to handle null tags.  Added
  34.  *        a few more scribe 2-char control seq. to scanner.
  35.  * 28Dec84, vj    Bug fixes from Richard Furuta
  36.  * 16Aug84    Van Jacobson, written.
  37.  */
  38.  
  39. #include <stdio.h>
  40. #include <ctype.h>
  41. #include <strings.h>
  42. #include "symtab.h"
  43.  
  44. #define    DELBUFLEN 1024    /* "delayed" text buffer length (see comments
  45.              * with routine "dprintf" */
  46.  
  47. static    struct stab *lastsym;    /* result of last "lookup" */
  48. static    int kflag = 0;        /* set to print unrecog keywords */
  49. static    int dirquote = 1;    /* set to covert quotes to directed quotes */
  50. static    int dquote=0;    /* set 1 if we're expecting a closing double quote */
  51. static    int informat=0;    /* set 1 if we're doing a "format" environment */
  52. static    int incomment=0; /* set 1 if we're inside a comment */
  53. static    int delayout=0;    /* set 1 if we have to delay output */
  54. static    char *inputfile;    /* current input file name */
  55. static    inputline=1;        /* line number in input file */
  56. %}
  57. %union {
  58.     int ival;
  59.     struct stab *sval;
  60.     }
  61.  
  62. %token    KW_REP    /* keyword to be replaced */
  63. %token    KW_ENV    /* keyword to be made environment [begin()..end()] */
  64. %token    KW_DEL    /* keyword to be deleted */
  65. %token    KW_COM    /* comment */
  66. %token    KW_FORMAT /* keyword introducing "format" environment */
  67. %token    FONT    /* keyword to be treated like font */
  68. %token    KW_IGN    /* keyword to ignore in @description label */
  69. %token    ITEMIZE DESCRIPT
  70. %type    <sval>    kw_rep
  71. %type    <sval>    kw_env
  72. %type    <sval>    kw_format
  73. %type    <sval>    itemize
  74. %type    <sval>    descrip
  75. %type    <sval>    istart
  76. %type    <sval>    dstart
  77. %token    ENV_REP        /* environment to be renamed */
  78. %token    ENV_DEL        /* environment to be deleted */
  79. %token    ENV_KW        /* environment to be made keyword */
  80. %token    ENV_FORMAT    /* "format" (tabular) environment */
  81. %token    END_ENV
  82. %token    ENV_ITEMIZE
  83. %token    ENV_DESCRIP
  84. %token    ENV_COM        /* comments */
  85. %type    <sval>    env_rep
  86. %type    <sval>    env_kw
  87. %type    <sval>    env_itemize
  88. %type    <sval>    env_descrip
  89. %type    <sval>    env_format
  90. %token    BLANKLINE
  91. %token    INCHES
  92. %token    COMMAND
  93. %token    SUP SUB
  94. %token    TAB RJUST CENTER POINT NPSPACE SETTAB LBREAK STILDE HYPHEN
  95. %token    CHAR
  96. %token    LBRACK RBRACK
  97. %%
  98. sdoc    :    sdoc foo
  99.     |    foo
  100.     ;
  101. foo    :    control
  102.     |    ignore
  103.     |    env
  104.      |    special
  105.      |    text
  106.     |    error '\n'
  107.     ;
  108. control    :    kw_rep balbrack
  109.     |    itemize optnl items RBRACK {
  110.                     dprintf("\\end{%s}",$1->s_reptext);
  111.                     }
  112.     |    itemize optnl items blanklines RBRACK {
  113.                     dprintf("\\end{%s}",$1->s_reptext);
  114.                     }
  115.     |    descrip optnl ditems RBRACK {
  116.                     dprintf("\\end{%s}",$1->s_reptext);
  117.                     }
  118.     |    descrip optnl ditems blanklines RBRACK {
  119.                     dprintf("\\end{%s}",$1->s_reptext);
  120.                     }
  121.     |    kw_del sdoc RBRACK
  122.     |    kw_env LBRACK optnl sdoc RBRACK    {
  123.                     dprintf("\\end{%s}",$1->s_reptext);
  124.                     }
  125.     |    kw_format LBRACK optnl sdoc RBRACK {
  126.                     dprintf("\\end{%s}",$1->s_reptext);
  127.                     informat = 0;
  128.                     }
  129.     |    supsub balbrack        { dprintf( "}$" ); }
  130.     |    font sdoc rbrack
  131.     |    kw_com sdoc RBRACK optnl    { dprintf("}\n"); incomment=0; }
  132.     ;
  133. ignore    :    kw_ign balbrack
  134.     ;
  135. env    :    env_rep sdoc endenv
  136.     |    env_format optnl sdoc endenv    { informat = 0; }
  137.     |    ENV_DEL sdoc END_ENV
  138.     |    env_kw sdoc END_ENV    { dprintf( "}" ); }
  139.     |    env_itemize optnl items endenv
  140.     |    env_itemize optnl items blanklines endenv
  141.     |    env_descrip optnl ditems endenv
  142.     |    env_descrip optnl ditems blanklines endenv
  143.     |    env_com sdoc endenv optnl    { dprintf("\n"); incomment=0; }
  144.     ;
  145. env_rep    :    ENV_REP        { dprintf("\\begin{%s}",lastsym->s_reptext); }
  146.     ;
  147. env_format:    ENV_FORMAT    {
  148.                 dprintf("\\begin{%s}\n",lastsym->s_reptext);
  149.                 informat = 1;
  150.                 }
  151.     ;
  152. endenv    :    END_ENV        { dprintf("\\end{%s}",lastsym->s_reptext); }
  153.     ;
  154. env_kw    :    ENV_KW        { dprintf("\\%s{",lastsym->s_reptext); }
  155.     ;
  156. env_com    :    ENV_COM        {
  157.                 dprintf("%% \\begin{%s}", lastsym->s_reptext);
  158.                 incomment=1;
  159.                 }
  160.     ;
  161. kw_com    :    KW_COM LBRACK    {
  162.                 dprintf("%% \\%s{", lastsym->s_reptext);
  163.                 incomment=1;
  164.                 }
  165.     ;
  166. kw_rep    :    KW_REP        { dprintf("\\%s",lastsym->s_reptext); }
  167.     ;
  168. kw_ign    :    KW_IGN        { dprintf("\\%s",lastsym->s_reptext); }
  169.     ;
  170. kw_del    :    KW_DEL LBRACK optnl
  171.     ;    
  172. kw_env    :    KW_ENV         {
  173.                 dprintf("\\begin{%s}\n",lastsym->s_reptext);
  174.                 $$ = lastsym;
  175.                 }
  176.     ;
  177. kw_format:    KW_FORMAT     {
  178.                 dprintf("\\begin{%s}\n",lastsym->s_reptext);
  179.                 $$ = lastsym;
  180.                 informat = 1;
  181.                 }
  182.     ;
  183. itemize    :    istart LBRACK        {
  184.                     dprintf("\\begin{%s}\n",$1->s_reptext);
  185.                     $$ = $1;
  186.                     }
  187.     ;
  188. istart    :    ITEMIZE            { $$ = lastsym; }
  189.     ;
  190. descrip    :    dstart LBRACK        {
  191.                     dprintf("\\begin{%s}\n",$1->s_reptext);
  192.                     $$ = $1;
  193.                     }
  194.     ;
  195. dstart    :    DESCRIPT        { $$ = lastsym; }
  196.     ;
  197. env_itemize:    ENV_ITEMIZE        {
  198.                     dprintf("\\begin{%s}\n",
  199.                         lastsym->s_reptext);
  200.                     }
  201.     ;
  202. env_descrip:    ENV_DESCRIP        {
  203.                     dprintf("\\begin{%s}\n",
  204.                         lastsym->s_reptext);
  205.                     }
  206.     ;
  207. optnl    :    '\n'
  208.     |    optnl BLANKLINE
  209.     |
  210.     ;
  211. items    :    items blanklines item
  212.     |    item
  213.     ;
  214. item    :    item newline
  215.     |    item line
  216.     |    item ignore
  217.     |    item env
  218.     |    itemstrt
  219.     ;
  220. itemstrt:            { dprintf("\\item "); dquote=0; }
  221.     ;
  222.  
  223. /* these productions describe the list of items for an @description environment.
  224.  * The list is a bunch of items separated by one or more blank lines.  There
  225.  * may also be interspersed keywords like "@index()" which we try to ignore
  226.  * and interspersed environments which couldn't be part of a tag.
  227.  */
  228. ditems    :    ditems blanklines ditem
  229.     |    ditem
  230.     ;
  231. /* A single description item consists of stuff that we ignore, a first line
  232.  * that we search for a tag & other lines.  Or it may consist entirely of
  233.  * stuff we ignore.
  234.  */
  235. ditem    :    dignores dfirstl lines
  236.     |    dignores
  237.     |    error '\n'        { flushout("\\item[] "); }
  238.     ;
  239. dignores:    dignores ignore newline
  240.     |    dignores ignore
  241.     |    dignores env newline
  242.     |    dignores env
  243.     |
  244.     ;
  245. dfirstl    :    ditemstrt line TAB    {
  246.                     flushout("\\item[");
  247.                     dprintf("]    ");
  248.                     }
  249.     |    ditemstrt line '\n'    {
  250.                     flushout("\\item[] ");
  251.                     dprintf("\n");
  252.                     }
  253.     ;
  254. lines    :    lines newline
  255.     |    lines linepart
  256.     |    lines ignore
  257.     |    lines env
  258.     |
  259.     ;
  260.  
  261. /* we think we have the start of an item - delay output until we know
  262.  * whether or not to put a "\item[" in front of it
  263.  */
  264. ditemstrt:            { delayout=1; dquote=0; }
  265.     ;
  266.  
  267. line    :    line linepart
  268.     |    line env
  269.     |    line ignore
  270.     |    linepart
  271.     ;
  272. linepart:    control
  273.     |    special
  274.     |    char
  275.     ;
  276. supsub    :    SUP        { dprintf("$^{\\hbox"); }
  277.     |    SUB        { dprintf("$_{\\hbox"); }
  278.     ;
  279. font    :    FONT LBRACK    { dprintf("{\\%s ", lastsym->s_reptext); }
  280.     ;
  281. balbrack:    lbrack sdoc rbrack
  282.     |    lbrack rbrack
  283.     ;
  284. lbrack    :    LBRACK        { dprintf("{"); }
  285.     ;
  286. rbrack    :    RBRACK        { dprintf("}"); }
  287.     ;
  288. special    :    POINT        { dprintf(".~"); }
  289.     |    NPSPACE        { dprintf("\\ "); }
  290.     |    LBREAK        { dprintf("\\newline{}"); }
  291.     |    STILDE        { dprintf("%%"); }
  292.     |    HYPHEN        { dprintf("\\-"); }
  293.     |    COMMAND        { dprintf("\\%s",&yytext[1]); }
  294.     ;
  295. text    :    text char
  296.     |    char
  297.     |    newline
  298.     |    BLANKLINE    { dprintf(incomment?"\n%% ":"\n"); dquote=0; }
  299.     |    TAB        { dprintf(" & "); }
  300.     |    CENTER        { dprintf(" & "); }
  301.     |    RJUST        { dprintf(" & "); }
  302.     |    SETTAB        { dprintf(" & "); }
  303.     ;
  304. char    :    CHAR        { dprintf(yytext); }
  305.     |    '@'        { dprintf("@"); }
  306.     |    INCHES        { dprintf("in"); }
  307.     |    '{'        { dprintf("\\{"); }
  308.     |    '}'        { dprintf("\\}"); }
  309.     |    '#'        { dprintf("\\#"); }
  310.     |    '$'        { dprintf("\\$"); }
  311.     |    '%'        { dprintf("\\%%"); }
  312.     |    '&'        { dprintf("\\&"); }
  313.     |    '~'        { dprintf("{\\tt\\char`\\~}"); }
  314.     |    '_'        { dprintf("{\\tt\\char`\\_}"); }
  315.     |    '^'        { dprintf("{\\tt\\char`\\^}"); }
  316.     |    '\\'        { dprintf("{\\tt\\char`\\\\}"); }
  317.     |    '<'        { dprintf("{\\tt\\char`\\<}"); }
  318.     |    '>'        { dprintf("{\\tt\\char`\\>}"); }
  319.     |    '|'        { dprintf("{\\tt\\char`\\|}"); }
  320.     |    '"'        { if( dirquote ) {
  321.                     dprintf( dquote? "'":"`");
  322.                     dquote=!dquote;
  323.                   } else
  324.                     dprintf("{\\tt\\char`\\\"}");
  325.                 }
  326.     ;
  327. newline    :    '\n'        {
  328.                 if ( incomment )
  329.                     dprintf("\n%% ");
  330.                 else
  331.                     dprintf(informat?"\\\\\n":"\n");
  332.                 }
  333.     ;
  334. blanklines:    blanklines BLANKLINE
  335.     |    BLANKLINE    { dprintf(incomment?"\n%% ":"\n"); dquote=0; }
  336.     ;
  337. %%
  338.  
  339. main( argc, argv )
  340. char **argv; {
  341.     char *pname = *argv;
  342.     init_st();
  343.     argc--, argv++;
  344.     while( argc > 0 && argv[0][0] == '-' ) {
  345.         if ( strcmp(*argv, "-s")==0 ) {
  346.             if ( argc < 1 ) {
  347.                 fprintf( stderr,
  348.                     "%s: filename must follow -s\n",
  349.                     pname );
  350.                 exit(1);
  351.             }
  352.             argv++;
  353.             argc--;
  354.             read_st( *argv );
  355.         } else {
  356.             if( index( *argv, 'k' ) )
  357.                 kflag++;
  358.             if( index( *argv, 'q' ) )
  359.                 dirquote = 0;
  360.         }
  361.         argv++;
  362.         argc--;
  363.     }
  364.     if ( argc > 0 )
  365.         while ( argc-- > 0 ) {
  366.             if ( freopen( *argv, "r", stdin ) == NULL ) {
  367.                 perror( *argv );
  368.                 exit(1);
  369.             }
  370.             inputfile = *argv;
  371.             inputline = 1;
  372.             yyparse();
  373.             argv++;
  374.         }
  375.     else {
  376.         inputfile = "<stdin>";
  377.         yyparse();
  378.     }
  379. }
  380.  
  381. yyerror( str )
  382. char *str; {
  383.     fprintf( stderr,
  384.          "s2l: %s in %s line %d\n", str, inputfile, inputline );
  385. }
  386.  
  387. /* initialize the keyword symbol table */
  388. init_st() {
  389.  
  390.     /* straight keyword replacement */
  391.     enter("@begin", KW_REP, "begin");
  392.     enter("@end", KW_REP, "end");
  393.     enter("@unnumbered",KW_REP,"chapter*");
  394.     enter("@bigsection",KW_REP,"chapter");
  395.     enter("@blankspace",KW_REP,"vspace");
  396.     enter("@ux",KW_REP,"underline");
  397.  
  398.     /* keywords to turn into environments */
  399.     enter("@example",KW_ENV,"example");
  400.     enter("@center",KW_ENV,"center");
  401.  
  402.     /* keywords that behave like fonts (eg, @i{} -> {\it } */
  403.     enter("@i",FONT,"it");
  404.     enter("@u",FONT,"it");
  405.     enter("@un",FONT,"it");
  406.     enter("@b",FONT,"bf");
  407.     enter("@p",FONT,"bf");
  408.     enter("@t",FONT,"tt");
  409.     enter("@c",FONT,"sc");
  410.     enter("@r",FONT,"rm");
  411.     enter("@w",FONT,"obeyspaces");
  412.  
  413.     /* list environments */
  414.     enter("@itemize",ITEMIZE,"itemize");
  415.     enter("@enumerate",ITEMIZE,"enumerate");
  416.     enter("@description",DESCRIPT,"description");
  417.     enter("@multiple",KW_DEL,"");
  418.  
  419.     /* the begin-end form of list environments */
  420.     enter("itemize",ENV_ITEMIZE,"itemize");
  421.     enter("enumerate",ENV_ITEMIZE,"enumerate");
  422.     enter("description",ENV_DESCRIP,"description");
  423.     enter("multiple",ENV_DEL,"");
  424.  
  425.     /* environments to be renamed */
  426.     enter("@format",KW_FORMAT,"tabular");
  427.     enter("format",ENV_FORMAT,"tabular");
  428.  
  429.     /* comments */
  430.     enter("@comment",KW_COM,"comment");
  431.     enter("comment",ENV_COM,"comment");
  432.  
  433.     /* keywords to "ignore" in description env */
  434.     enter("@tabs",KW_IGN,"tabs");
  435.     enter("@index",KW_IGN,"index");
  436. }
  437.  
  438. /* Read User-specified entries into the symbol table */
  439.  
  440. #define ENTER(txt,typ,rtxt) enter(txt,*txt=='@'?typ,rtxt)
  441.  
  442. read_st( fname )
  443. char *fname;
  444. {
  445.     FILE *stream;
  446.     char text[128], stype[128], reptext[128];
  447.     register int sstat;
  448.  
  449.     if ( (stream = fopen( fname, "r" )) == NULL ) {
  450.         perror( stream );
  451.         exit(1);
  452.     }
  453.  
  454.     while ( (sstat = fscanf( stream, "%s %s %s \n", text, stype, reptext ))
  455.         != EOF ) {
  456.  
  457.         if ( sstat == 3 ) {
  458.             switch( stype[0] ) {
  459.  
  460.             case 'R': case 'r':
  461.                 ENTER( text, KW_REP:ENV_REP, reptext );
  462.                 break;
  463.             case 'D': case 'd':
  464.                 ENTER( text, KW_DEL:ENV_DEL, reptext );
  465.                 break;
  466.             case 'F': case 'f':
  467.                 enter( text, FONT, reptext );
  468.                 break;
  469.             case 'E': case 'e':
  470.                 ENTER( text, KW_ENV:ENV_KW, reptext );
  471.                 break;
  472.             case 'I': case 'i': case 'L': case 'l':
  473.                 ENTER( text, ITEMIZE:ENV_ITEMIZE, reptext );
  474.                 break;
  475.             case 'T': case 't':
  476.                 ENTER( text, DESCRIPT:ENV_DESCRIP, reptext );
  477.                 break;
  478.             case 'A': case 'a':
  479.                 ENTER( text, KW_FORMAT:ENV_FORMAT, reptext );
  480.                 break;
  481.             case 'N': case 'n':
  482.                 enter( text, KW_IGN, reptext );
  483.                 break;
  484.             case 'C': case 'c':
  485.                 ENTER( text, KW_COM:ENV_COM, reptext );
  486.                 break;
  487.             default:
  488.                 fprintf(stderr,"-unknown type `%s'\n",stype);
  489.                 exit(1);
  490.             }
  491.         }
  492.     }
  493.     fclose( stream );
  494. }
  495.  
  496. /* dprintf - a (possibly delayed) printf 
  497.  * This routine is used for all Latex output.  If the flag "delayout"
  498.  * isn't set, it's just a printf.  If delayout is set, an sprintf is done
  499.  * & the text is accumulated in a local buffer.  The buffer is written out
  500.  * when by a call to flushout.  This routine is intended to handle cases
  501.  * where you don't know what text to generate until several tokens later
  502.  * in the input.  In particular, for an "@description" item you don't know
  503.  * whether to put an "\item[" at the beginning of the line until you see a
  504.  * tab or newline.  Because this routine uses a static buffer, it will
  505.  * screw up on things like a description environment inside of a
  506.  * description tag (which I can't imagine happening).  The static buffer
  507.  * is also finite so you can't delay a very large portion of the document.
  508.  */
  509. static char delbuf[DELBUFLEN];    /* buffer for delayed text */
  510. static int  delcnt = 0;        /* count of characters in delbuf */
  511.  
  512. dprintf( fmt, a1, a2, a3, a4 ) 
  513. char *fmt;
  514. {
  515.     if( delayout ) {
  516.         /* we're delaying output text */
  517.         sprintf( &delbuf[delcnt], fmt, a1, a2, a3, a4 );
  518.         delcnt = strlen( delbuf );
  519.         if( delcnt >= (DELBUFLEN-50) ) {
  520.             yyerror( "delayed text buffer overflow" );
  521.             exit(1);
  522.         }
  523.     } else {
  524.         printf( fmt, a1, a2, a3, a4 );
  525.     }
  526. }
  527.  
  528. /* flush the delayed output buffer, inserting the string "prefix"
  529.  * just after the last newline in the buffer.
  530.  */
  531. flushout( prefix )
  532. char *prefix;
  533. {
  534.     char *nlpos;
  535.  
  536.     if( delayout ) {
  537.         if( nlpos = rindex( delbuf, '\n' ) ) {
  538.             *nlpos = '\0';
  539.             printf( "%s", delbuf );
  540.             nlpos++;
  541.             printf( "\n%s%s", prefix, nlpos );
  542.         } else {
  543.             printf( "%s%s", prefix, delbuf );
  544.         }
  545.         delcnt = 0;
  546.         delayout = 0;
  547.     }
  548. }
  549.                 
  550. #include "lex.yy.c"
  551.