home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume30 / rc / part05 / parse.y < prev    next >
Encoding:
Text File  |  1992-05-30  |  5.2 KB  |  175 lines

  1. /* parse.y */
  2.  
  3. /*
  4.  * Adapted from rc grammar, v10 manuals, volume 2.
  5.  */
  6.  
  7. %{
  8. #include "rc.h"
  9. #ifndef lint
  10. #define lint        /* hush up gcc -Wall, leave out the dumb sccsid's. */
  11. #endif
  12. static Node *star, *nolist;
  13. Node *parsetree;    /* not using yylval because bison declares it as an auto */
  14. %}
  15.  
  16. %token ANDAND BACKBACK BANG CASE COUNT DUP ELSE END FLAT FN FOR IF IN
  17. %token OROR PIPE REDIR SREDIR SUB SUBSHELL SWITCH TWIDDLE WHILE WORD HUH
  18.  
  19. %left WHILE ')' ELSE
  20. %left ANDAND OROR '\n'
  21. %left BANG SUBSHELL
  22. %left PIPE
  23. %right '$' 
  24. %left SUB
  25. /*
  26. */
  27.  
  28. %union {
  29.     struct Node *node;
  30.     struct Redir redir;
  31.     struct Pipe pipe;
  32.     struct Dup dup;
  33.     struct Word word;
  34.     char *keyword;
  35. }
  36.  
  37. %type <redir> REDIR SREDIR
  38. %type <pipe> PIPE
  39. %type <dup> DUP
  40. %type <word> WORD
  41. %type <keyword> keyword
  42. %type <node> assign body brace case cbody cmd cmdsa cmdsan comword epilog
  43.          first line nlwords paren redir sword simple iftail word words
  44.  
  45. %start rc
  46.  
  47. %%
  48.  
  49. rc    : line end        { parsetree = $1; YYACCEPT; }
  50.     | error end        { yyerrok; parsetree = NULL; YYABORT; }
  51.  
  52. /* an rc line may end in end-of-file as well as newline, e.g., rc -c 'ls' */
  53. end    : END    /* EOF */    { if (!heredoc(1)) YYABORT; } /* flag error if there is a heredoc in the queue */
  54.     | '\n'            { if (!heredoc(0)) YYABORT; } /* get heredoc on \n */
  55.  
  56. /* a cmdsa is a command followed by ampersand or newline (used in "line" and "body") */
  57. cmdsa    : cmd ';'
  58.     | cmd '&'        { $$ = ($1 != NULL ? mk(nNowait,$1) : $1); }
  59.  
  60. /* a line is a single command, or a command terminated by ; or & followed by a line (recursive) */
  61. line    : cmd
  62.     | cmdsa line        { $$ = ($1 != NULL ? mk(nBody,$1,$2) : $2); }
  63.  
  64. /* a body is like a line, only commands may also be terminated by newline */
  65. body    : cmd
  66.     | cmdsan body        { $$ = ($1 == NULL ? $2 : $2 == NULL ? $1 : mk(nBody,$1,$2)); }
  67.  
  68. cmdsan    : cmdsa
  69.     | cmd '\n'        { $$ = $1; if (!heredoc(0)) YYABORT; } /* get h.d. on \n */
  70.  
  71. brace    : '{' body '}'        { $$ = $2; }
  72.  
  73. paren    : '(' body ')'        { $$ = $2; }
  74.  
  75. assign    : first '=' word    { $$ = mk(nAssign,$1,$3); }
  76.  
  77. epilog    :            { $$ = NULL; }
  78.     | redir epilog        { $$ = mk(nEpilog,$1,$2); }
  79.  
  80. /* a redirection is a dup (e.g., >[1=2]) or a file redirection. (e.g., > /dev/null) */
  81. redir    : DUP            { $$ = mk(nDup,$1.type,$1.left,$1.right); }
  82.     | REDIR word        { $$ = mk(nRedir,$1.type,$1.fd,$2);
  83.                   if ($1.type == rHeredoc && !qdoc($2, $$)) YYABORT; /* queue heredocs up */
  84.                 }
  85.     | SREDIR word        { $$ = mk(nRedir,$1.type,$1.fd,$2);
  86.                   if ($1.type == rHeredoc && !qdoc($2, $$)) YYABORT; /* queue heredocs up */
  87.                 }
  88.  
  89. case    : CASE words ';'             { $$ = mk(nCase, $2); }
  90.     | CASE words '\n'             { $$ = mk(nCase, $2); }
  91.  
  92. cbody    : cmd                    { $$ = mk(nCbody, $1, NULL); }
  93.     | case cbody                { $$ = mk(nCbody, $1, $2); }
  94.     | cmdsan cbody                { $$ = mk(nCbody, $1, $2); }
  95.  
  96. iftail    : cmd        %prec ELSE
  97.     | brace ELSE optnl cmd            { $$ = mk(nElse,$1,$4); }
  98.  
  99. cmd    : /* empty */    %prec WHILE        { $$ = NULL; }
  100.     | simple
  101.     | brace epilog                { $$ = mk(nBrace,$1,$2); }
  102.     | IF paren optnl iftail            { $$ = mk(nIf,$2,$4); }
  103.     | FOR '(' word IN words ')' optnl cmd    { $$ = mk(nForin,$3,$5,$8); }
  104.     | FOR '(' word ')' optnl cmd        { $$ = mk(nForin,$3,star,$6); }
  105.     | WHILE paren optnl cmd            { $$ = mk(nWhile,$2,$4); }
  106.     | SWITCH '(' word ')' optnl '{' cbody '}' { $$ = mk(nSwitch,$3,$7); }
  107.     | TWIDDLE optcaret word words        { $$ = mk(nMatch,$3,$4); }
  108.     | cmd ANDAND optnl cmd            { $$ = mk(nAndalso,$1,$4); }
  109.     | cmd OROR optnl cmd            { $$ = mk(nOrelse,$1,$4); }
  110.      | cmd PIPE optnl cmd            { $$ = mk(nPipe,$2.left,$2.right,$1,$4); }
  111.     | redir cmd    %prec BANG        { $$ = ($2 != NULL ? mk(nPre,$1,$2) : $1); }
  112.     | assign cmd    %prec BANG        { $$ = ($2 != NULL ? mk(nPre,$1,$2) : $1); }
  113.     | BANG optcaret cmd            { $$ = mk(nBang,$3); }
  114.     | SUBSHELL optcaret cmd            { $$ = mk(nSubshell,$3); }
  115.     | FN words brace            { $$ = mk(nNewfn,$2,$3); }
  116.     | FN words                { $$ = mk(nRmfn,$2); }
  117.  
  118. optcaret : /* empty */
  119.     | '^'
  120.  
  121. simple    : first
  122.     | simple word            { $$ = ($2 != NULL ? mk(nArgs,$1,$2) : $1); }
  123.     | simple redir            { $$ = mk(nArgs,$1,$2); }
  124.  
  125. first    : comword
  126.     | first '^' sword        { $$ = mk(nConcat,$1,$3); }
  127.  
  128. sword    : comword
  129.     | keyword            { $$ = mk(nWord,$1, NULL); }
  130.  
  131. word    : sword
  132.     | word '^' sword        { $$ = mk(nConcat,$1,$3); }
  133.  
  134. comword    : '$' sword            { $$ = mk(nVar,$2); }
  135.     | '$' sword SUB words ')'    { $$ = mk(nVarsub,$2,$4); }
  136.     | COUNT sword            { $$ = mk(nCount,$2); }
  137.     | FLAT sword            { $$ = mk(nFlat, $2); }
  138.     | '`' sword            { $$ = mk(nBackq,nolist,$2); }
  139.     | '`' brace            { $$ = mk(nBackq,nolist,$2); }
  140.     | BACKBACK word    brace        { $$ = mk(nBackq,$2,$3); }
  141.     | BACKBACK word    sword        { $$ = mk(nBackq,$2,$3); }
  142.     | '(' nlwords ')'        { $$ = $2; }
  143.     | REDIR brace            { $$ = mk(nNmpipe,$1.type,$1.fd,$2); }
  144.     | WORD                { $$ = ($1.w[0] == '\'') ? mk(nQword, $1.w+1, NULL) : mk(nWord,$1.w, $1.m); }
  145.  
  146. keyword    : FOR        { $$ = "for"; }
  147.     | IN        { $$ = "in"; }
  148.     | WHILE        { $$ = "while"; }
  149.     | IF        { $$ = "if"; }
  150.     | SWITCH    { $$ = "switch"; }
  151.     | FN        { $$ = "fn"; }
  152.     | ELSE        { $$ = "else"; }
  153.     | CASE        { $$ = "case"; }
  154.     | TWIDDLE    { $$ = "~"; }
  155.     | BANG        { $$ = "!"; }
  156.     | SUBSHELL    { $$ = "@"; }
  157.  
  158. words    :        { $$ = NULL; }
  159.     | words word    { $$ = ($1 != NULL ? ($2 != NULL ? mk(nLappend,$1,$2) : $1) : $2); }
  160.  
  161. nlwords :        { $$ = NULL; }
  162.     | nlwords '\n'
  163.     | nlwords word    { $$ = ($1 != NULL ? ($2 != NULL ? mk(nLappend,$1,$2) : $1) : $2); }
  164.  
  165. optnl    : /* empty */
  166.     | optnl '\n'
  167.  
  168. %%
  169.  
  170. void initparse() {
  171.     star = treecpy(mk(nVar,mk(nWord,"*",NULL)), ealloc);
  172.     nolist = treecpy(mk(nVar,mk(nWord,"ifs",NULL)), ealloc);
  173. }
  174.  
  175.