BSD 4_4_Lite2 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Thu, 26 Mar 1992 16:31:40 +0000 (08:31 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Thu, 26 Mar 1992 16:31:40 +0000 (08:31 -0800)
Work on file usr/src/contrib/rc-1.4/parse.y

Synthesized-from: CSRG/cd3/4.4BSD-Lite2

usr/src/contrib/rc-1.4/parse.y [new file with mode: 0644]

diff --git a/usr/src/contrib/rc-1.4/parse.y b/usr/src/contrib/rc-1.4/parse.y
new file mode 100644 (file)
index 0000000..f1f5526
--- /dev/null
@@ -0,0 +1,174 @@
+/* parse.y */
+
+/*
+ * Adapted from rc grammar, v10 manuals, volume 2.
+ */
+
+%{
+#include "rc.h"
+#ifndef lint
+#define lint           /* hush up gcc -Wall, leave out the dumb sccsid's. */
+#endif
+static Node *star, *nolist;
+Node *parsetree;       /* not using yylval because bison declares it as an auto */
+%}
+
+%token ANDAND BACKBACK BANG CASE COUNT DUP ELSE END FLAT FN FOR IF IN
+%token OROR PIPE REDIR SREDIR SUB SUBSHELL SWITCH TWIDDLE WHILE WORD HUH
+
+%left WHILE ')' ELSE
+%left ANDAND OROR '\n'
+%left BANG SUBSHELL
+%left PIPE
+%right '$' 
+%left SUB
+/*
+*/
+
+%union {
+       struct Node *node;
+       struct Redir redir;
+       struct Pipe pipe;
+       struct Dup dup;
+       struct Word word;
+       char *keyword;
+}
+
+%type <redir> REDIR SREDIR
+%type <pipe> PIPE
+%type <dup> DUP
+%type <word> WORD
+%type <keyword> keyword
+%type <node> assign body brace case cbody cmd cmdsa cmdsan comword epilog
+            first line nlwords paren redir sword simple iftail word words
+
+%start rc
+
+%%
+
+rc     : line end              { parsetree = $1; YYACCEPT; }
+       | error end             { yyerrok; parsetree = NULL; YYABORT; }
+
+/* an rc line may end in end-of-file as well as newline, e.g., rc -c 'ls' */
+end    : END   /* EOF */       { if (!heredoc(1)) YYABORT; } /* flag error if there is a heredoc in the queue */
+       | '\n'                  { if (!heredoc(0)) YYABORT; } /* get heredoc on \n */
+
+/* a cmdsa is a command followed by ampersand or newline (used in "line" and "body") */
+cmdsa  : cmd ';'
+       | cmd '&'               { $$ = ($1 != NULL ? mk(nNowait,$1) : $1); }
+
+/* a line is a single command, or a command terminated by ; or & followed by a line (recursive) */
+line   : cmd
+       | cmdsa line            { $$ = ($1 != NULL ? mk(nBody,$1,$2) : $2); }
+
+/* a body is like a line, only commands may also be terminated by newline */
+body   : cmd
+       | cmdsan body           { $$ = ($1 == NULL ? $2 : $2 == NULL ? $1 : mk(nBody,$1,$2)); }
+
+cmdsan : cmdsa
+       | cmd '\n'              { $$ = $1; if (!heredoc(0)) YYABORT; } /* get h.d. on \n */
+
+brace  : '{' body '}'          { $$ = $2; }
+
+paren  : '(' body ')'          { $$ = $2; }
+
+assign : first '=' word        { $$ = mk(nAssign,$1,$3); }
+
+epilog :                       { $$ = NULL; }
+       | redir epilog          { $$ = mk(nEpilog,$1,$2); }
+
+/* a redirection is a dup (e.g., >[1=2]) or a file redirection. (e.g., > /dev/null) */
+redir  : DUP                   { $$ = mk(nDup,$1.type,$1.left,$1.right); }
+       | REDIR word            { $$ = mk(nRedir,$1.type,$1.fd,$2);
+                                 if ($1.type == rHeredoc && !qdoc($2, $$)) YYABORT; /* queue heredocs up */
+                               }
+       | SREDIR word           { $$ = mk(nRedir,$1.type,$1.fd,$2);
+                                 if ($1.type == rHeredoc && !qdoc($2, $$)) YYABORT; /* queue heredocs up */
+                               }
+
+case   : CASE words ';'                        { $$ = mk(nCase, $2); }
+       | CASE words '\n'                       { $$ = mk(nCase, $2); }
+
+cbody  : cmd                                   { $$ = mk(nCbody, $1, NULL); }
+       | case cbody                            { $$ = mk(nCbody, $1, $2); }
+       | cmdsan cbody                          { $$ = mk(nCbody, $1, $2); }
+
+iftail : cmd           %prec ELSE
+       | brace ELSE optnl cmd                  { $$ = mk(nElse,$1,$4); }
+
+cmd    : /* empty */   %prec WHILE             { $$ = NULL; }
+       | simple
+       | brace epilog                          { $$ = mk(nBrace,$1,$2); }
+       | IF paren optnl iftail                 { $$ = mk(nIf,$2,$4); }
+       | FOR '(' word IN words ')' optnl cmd   { $$ = mk(nForin,$3,$5,$8); }
+       | FOR '(' word ')' optnl cmd            { $$ = mk(nForin,$3,star,$6); }
+       | WHILE paren optnl cmd                 { $$ = mk(nWhile,$2,$4); }
+       | SWITCH '(' word ')' optnl '{' cbody '}' { $$ = mk(nSwitch,$3,$7); }
+       | TWIDDLE optcaret word words           { $$ = mk(nMatch,$3,$4); }
+       | cmd ANDAND optnl cmd                  { $$ = mk(nAndalso,$1,$4); }
+       | cmd OROR optnl cmd                    { $$ = mk(nOrelse,$1,$4); }
+       | cmd PIPE optnl cmd                    { $$ = mk(nPipe,$2.left,$2.right,$1,$4); }
+       | redir cmd     %prec BANG              { $$ = ($2 != NULL ? mk(nPre,$1,$2) : $1); }
+       | assign cmd    %prec BANG              { $$ = ($2 != NULL ? mk(nPre,$1,$2) : $1); }
+       | BANG optcaret cmd                     { $$ = mk(nBang,$3); }
+       | SUBSHELL optcaret cmd                 { $$ = mk(nSubshell,$3); }
+       | FN words brace                        { $$ = mk(nNewfn,$2,$3); }
+       | FN words                              { $$ = mk(nRmfn,$2); }
+
+optcaret : /* empty */
+       | '^'
+
+simple : first
+       | simple word                   { $$ = ($2 != NULL ? mk(nArgs,$1,$2) : $1); }
+       | simple redir                  { $$ = mk(nArgs,$1,$2); }
+
+first  : comword
+       | first '^' sword               { $$ = mk(nConcat,$1,$3); }
+
+sword  : comword
+       | keyword                       { $$ = mk(nWord,$1, NULL); }
+
+word   : sword
+       | word '^' sword                { $$ = mk(nConcat,$1,$3); }
+
+comword        : '$' sword                     { $$ = mk(nVar,$2); }
+       | '$' sword SUB words ')'       { $$ = mk(nVarsub,$2,$4); }
+       | COUNT sword                   { $$ = mk(nCount,$2); }
+       | FLAT sword                    { $$ = mk(nFlat, $2); }
+       | '`' sword                     { $$ = mk(nBackq,nolist,$2); }
+       | '`' brace                     { $$ = mk(nBackq,nolist,$2); }
+       | BACKBACK word brace           { $$ = mk(nBackq,$2,$3); }
+       | BACKBACK word sword           { $$ = mk(nBackq,$2,$3); }
+       | '(' nlwords ')'               { $$ = $2; }
+       | REDIR brace                   { $$ = mk(nNmpipe,$1.type,$1.fd,$2); }
+       | WORD                          { $$ = ($1.w[0] == '\'') ? mk(nQword, $1.w+1, NULL) : mk(nWord,$1.w, $1.m); }
+
+keyword        : FOR           { $$ = "for"; }
+       | IN            { $$ = "in"; }
+       | WHILE         { $$ = "while"; }
+       | IF            { $$ = "if"; }
+       | SWITCH        { $$ = "switch"; }
+       | FN            { $$ = "fn"; }
+       | ELSE          { $$ = "else"; }
+       | CASE          { $$ = "case"; }
+       | TWIDDLE       { $$ = "~"; }
+       | BANG          { $$ = "!"; }
+       | SUBSHELL      { $$ = "@"; }
+
+words  :               { $$ = NULL; }
+       | words word    { $$ = ($1 != NULL ? ($2 != NULL ? mk(nLappend,$1,$2) : $1) : $2); }
+
+nlwords :              { $$ = NULL; }
+       | nlwords '\n'
+       | nlwords word  { $$ = ($1 != NULL ? ($2 != NULL ? mk(nLappend,$1,$2) : $1) : $2); }
+
+optnl  : /* empty */
+       | optnl '\n'
+
+%%
+
+void initparse() {
+       star = treecpy(mk(nVar,mk(nWord,"*",NULL)), ealloc);
+       nolist = treecpy(mk(nVar,mk(nWord,"ifs",NULL)), ealloc);
+}
+