tforgot this. - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit dda0695dc0e5ff185e096bda7337db59e22165fb
 (DIR) parent 5c34ff9e1c19fd73ccc79c0f702f7c4b964840d1
 (HTM) Author: rsc <devnull@localhost>
       Date:   Sun, 23 Nov 2003 18:11:17 +0000
       
       forgot this.
       
       Diffstat:
         A src/cmd/rc/syn.y                    |      91 +++++++++++++++++++++++++++++++
       
       1 file changed, 91 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/src/cmd/rc/syn.y b/src/cmd/rc/syn.y
       t@@ -0,0 +1,91 @@
       +%term FOR IN WHILE IF NOT TWIDDLE BANG SUBSHELL SWITCH FN
       +%term WORD REDIR DUP PIPE SUB
       +%term SIMPLE ARGLIST WORDS BRACE PAREN PCMD PIPEFD /* not used in syntax */
       +/* operator priorities -- lowest first */
       +%left IF WHILE FOR SWITCH ')' NOT
       +%left ANDAND OROR
       +%left BANG SUBSHELL
       +%left PIPE
       +%left '^'
       +%right '$' COUNT '"'
       +%left SUB
       +%{
       +#include "rc.h"
       +#include "fns.h"
       +%}
       +%union{
       +        struct tree *tree;
       +};
       +%type<tree> line paren brace body cmdsa cmdsan assign epilog redir
       +%type<tree> cmd simple first word comword keyword words
       +%type<tree> NOT FOR IN WHILE IF TWIDDLE BANG SUBSHELL SWITCH FN
       +%type<tree> WORD REDIR DUP PIPE
       +%%
       +rc:                                { return 1;}
       +|        line '\n'                {return !compile($1);}
       +line:        cmd
       +|        cmdsa line                {$$=tree2(';', $1, $2);}
       +body:        cmd
       +|        cmdsan body                {$$=tree2(';', $1, $2);}
       +cmdsa:        cmd ';'
       +|        cmd '&'                        {$$=tree1('&', $1);}
       +cmdsan:        cmdsa
       +|        cmd '\n'
       +brace:        '{' body '}'                {$$=tree1(BRACE, $2);}
       +paren:        '(' body ')'                {$$=tree1(PCMD, $2);}
       +assign:        first '=' word                {$$=tree2('=', $1, $3);}
       +epilog:                                {$$=0;}
       +|        redir epilog                {$$=mung2($1, $1->child[0], $2);}
       +redir:        REDIR word                {$$=mung1($1, $1->rtype==HERE?heredoc($2):$2);}
       +|        DUP
       +cmd:                                {$$=0;}
       +|        brace epilog                {$$=epimung($1, $2);}
       +|        IF paren {skipnl();} cmd
       +                                {$$=mung2($1, $2, $4);}
       +|        IF NOT {skipnl();} cmd        {$$=mung1($2, $4);}
       +|        FOR '(' word IN words ')' {skipnl();} cmd
       +        /*
       +         * if ``words'' is nil, we need a tree element to distinguish between 
       +         * for(i in ) and for(i), the former being a loop over the empty set
       +         * and the latter being the implicit argument loop.  so if $5 is nil
       +         * (the empty set), we represent it as "()".  don't parenthesize non-nil
       +         * functions, to avoid growing parentheses every time we reread the
       +         * definition.
       +         */
       +                                {$$=mung3($1, $3, $5 ? $5 : tree1(PAREN, $5), $8);}
       +|        FOR '(' word ')' {skipnl();} cmd
       +                                {$$=mung3($1, $3, (struct tree *)0, $6);}
       +|        WHILE paren {skipnl();} cmd
       +                                {$$=mung2($1, $2, $4);}
       +|        SWITCH word {skipnl();} brace
       +                                {$$=tree2(SWITCH, $2, $4);}
       +|        simple                        {$$=simplemung($1);}
       +|        TWIDDLE word words        {$$=mung2($1, $2, $3);}
       +|        cmd ANDAND cmd                {$$=tree2(ANDAND, $1, $3);}
       +|        cmd OROR cmd                {$$=tree2(OROR, $1, $3);}
       +|        cmd PIPE cmd                {$$=mung2($2, $1, $3);}
       +|        redir cmd  %prec BANG        {$$=mung2($1, $1->child[0], $2);}
       +|        assign cmd %prec BANG        {$$=mung3($1, $1->child[0], $1->child[1], $2);}
       +|        BANG cmd                {$$=mung1($1, $2);}
       +|        SUBSHELL cmd                {$$=mung1($1, $2);}
       +|        FN words brace                {$$=tree2(FN, $2, $3);}
       +|        FN words                {$$=tree1(FN, $2);}
       +simple:        first
       +|        simple word                {$$=tree2(ARGLIST, $1, $2);}
       +|        simple redir                {$$=tree2(ARGLIST, $1, $2);}
       +first:        comword        
       +|        first '^' word                {$$=tree2('^', $1, $3);}
       +word:        keyword                        {lastword=1; $1->type=WORD;}
       +|        comword
       +|        word '^' word                {$$=tree2('^', $1, $3);}
       +comword: '$' word                {$$=tree1('$', $2);}
       +|        '$' word SUB words ')'        {$$=tree2(SUB, $2, $4);}
       +|        '"' word                {$$=tree1('"', $2);}
       +|        COUNT word                {$$=tree1(COUNT, $2);}
       +|        WORD
       +|        '`' brace                {$$=tree1('`', $2);}
       +|        '(' words ')'                {$$=tree1(PAREN, $2);}
       +|        REDIR brace                {$$=mung1($1, $2); $$->type=PIPEFD;}
       +keyword: FOR|IN|WHILE|IF|NOT|TWIDDLE|BANG|SUBSHELL|SWITCH|FN
       +words:                                {$$=(struct tree*)0;}
       +|        words word                {$$=tree2(WORDS, $1, $2);}