xref: /plan9-contrib/sys/src/cmd/rc/syn.y (revision dbee78772299b06484db59f95f481ad96b19f995)
13e12c5d1SDavid du Colombier %term FOR IN WHILE IF NOT TWIDDLE BANG SUBSHELL SWITCH FN
23e12c5d1SDavid du Colombier %term WORD REDIR DUP PIPE SUB
33e12c5d1SDavid du Colombier %term SIMPLE ARGLIST WORDS BRACE PAREN PCMD PIPEFD /* not used in syntax */
43e12c5d1SDavid du Colombier /* operator priorities -- lowest first */
53e12c5d1SDavid du Colombier %left IF WHILE FOR SWITCH ')' NOT
63e12c5d1SDavid du Colombier %left ANDAND OROR
73e12c5d1SDavid du Colombier %left BANG SUBSHELL
83e12c5d1SDavid du Colombier %left PIPE
93e12c5d1SDavid du Colombier %left '^'
103e12c5d1SDavid du Colombier %right '$' COUNT '"'
113e12c5d1SDavid du Colombier %left SUB
123e12c5d1SDavid du Colombier %{
133e12c5d1SDavid du Colombier #include "rc.h"
143e12c5d1SDavid du Colombier #include "fns.h"
153e12c5d1SDavid du Colombier %}
163e12c5d1SDavid du Colombier %union{
173e12c5d1SDavid du Colombier 	struct tree *tree;
183e12c5d1SDavid du Colombier };
193e12c5d1SDavid du Colombier %type<tree> line paren brace body cmdsa cmdsan assign epilog redir
203e12c5d1SDavid du Colombier %type<tree> cmd simple first word comword keyword words
213e12c5d1SDavid du Colombier %type<tree> NOT FOR IN WHILE IF TWIDDLE BANG SUBSHELL SWITCH FN
223e12c5d1SDavid du Colombier %type<tree> WORD REDIR DUP PIPE
233e12c5d1SDavid du Colombier %%
243e12c5d1SDavid du Colombier rc:				{ return 1;}
253e12c5d1SDavid du Colombier |	line '\n'		{return !compile($1);}
263e12c5d1SDavid du Colombier line:	cmd
273e12c5d1SDavid du Colombier |	cmdsa line		{$$=tree2(';', $1, $2);}
283e12c5d1SDavid du Colombier body:	cmd
293e12c5d1SDavid du Colombier |	cmdsan body		{$$=tree2(';', $1, $2);}
303e12c5d1SDavid du Colombier cmdsa:	cmd ';'
313e12c5d1SDavid du Colombier |	cmd '&'			{$$=tree1('&', $1);}
323e12c5d1SDavid du Colombier cmdsan:	cmdsa
333e12c5d1SDavid du Colombier |	cmd '\n'
343e12c5d1SDavid du Colombier brace:	'{' body '}'		{$$=tree1(BRACE, $2);}
353e12c5d1SDavid du Colombier paren:	'(' body ')'		{$$=tree1(PCMD, $2);}
363e12c5d1SDavid du Colombier assign:	first '=' word		{$$=tree2('=', $1, $3);}
373e12c5d1SDavid du Colombier epilog:				{$$=0;}
383e12c5d1SDavid du Colombier |	redir epilog		{$$=mung2($1, $1->child[0], $2);}
393e12c5d1SDavid du Colombier redir:	REDIR word		{$$=mung1($1, $1->rtype==HERE?heredoc($2):$2);}
403e12c5d1SDavid du Colombier |	DUP
413e12c5d1SDavid du Colombier cmd:				{$$=0;}
423e12c5d1SDavid du Colombier |	brace epilog		{$$=epimung($1, $2);}
433e12c5d1SDavid du Colombier |	IF paren {skipnl();} cmd
443e12c5d1SDavid du Colombier 				{$$=mung2($1, $2, $4);}
453e12c5d1SDavid du Colombier |	IF NOT {skipnl();} cmd	{$$=mung1($2, $4);}
463e12c5d1SDavid du Colombier |	FOR '(' word IN words ')' {skipnl();} cmd
477dd7cddfSDavid du Colombier 	/*
487dd7cddfSDavid du Colombier 	 * if ``words'' is nil, we need a tree element to distinguish between
497dd7cddfSDavid du Colombier 	 * for(i in ) and for(i), the former being a loop over the empty set
507dd7cddfSDavid du Colombier 	 * and the latter being the implicit argument loop.  so if $5 is nil
517dd7cddfSDavid du Colombier 	 * (the empty set), we represent it as "()".  don't parenthesize non-nil
527dd7cddfSDavid du Colombier 	 * functions, to avoid growing parentheses every time we reread the
537dd7cddfSDavid du Colombier 	 * definition.
547dd7cddfSDavid du Colombier 	 */
557dd7cddfSDavid du Colombier 				{$$=mung3($1, $3, $5 ? $5 : tree1(PAREN, $5), $8);}
563e12c5d1SDavid du Colombier |	FOR '(' word ')' {skipnl();} cmd
573e12c5d1SDavid du Colombier 				{$$=mung3($1, $3, (struct tree *)0, $6);}
583e12c5d1SDavid du Colombier |	WHILE paren {skipnl();} cmd
593e12c5d1SDavid du Colombier 				{$$=mung2($1, $2, $4);}
603e12c5d1SDavid du Colombier |	SWITCH word {skipnl();} brace
613e12c5d1SDavid du Colombier 				{$$=tree2(SWITCH, $2, $4);}
623e12c5d1SDavid du Colombier |	simple			{$$=simplemung($1);}
633e12c5d1SDavid du Colombier |	TWIDDLE word words	{$$=mung2($1, $2, $3);}
643e12c5d1SDavid du Colombier |	cmd ANDAND cmd		{$$=tree2(ANDAND, $1, $3);}
653e12c5d1SDavid du Colombier |	cmd OROR cmd		{$$=tree2(OROR, $1, $3);}
663e12c5d1SDavid du Colombier |	cmd PIPE cmd		{$$=mung2($2, $1, $3);}
673e12c5d1SDavid du Colombier |	redir cmd  %prec BANG	{$$=mung2($1, $1->child[0], $2);}
683e12c5d1SDavid du Colombier |	assign cmd %prec BANG	{$$=mung3($1, $1->child[0], $1->child[1], $2);}
693e12c5d1SDavid du Colombier |	BANG cmd		{$$=mung1($1, $2);}
703e12c5d1SDavid du Colombier |	SUBSHELL cmd		{$$=mung1($1, $2);}
713e12c5d1SDavid du Colombier |	FN words brace		{$$=tree2(FN, $2, $3);}
723e12c5d1SDavid du Colombier |	FN words		{$$=tree1(FN, $2);}
733e12c5d1SDavid du Colombier simple:	first
743e12c5d1SDavid du Colombier |	simple word		{$$=tree2(ARGLIST, $1, $2);}
753e12c5d1SDavid du Colombier |	simple redir		{$$=tree2(ARGLIST, $1, $2);}
763e12c5d1SDavid du Colombier first:	comword
773e12c5d1SDavid du Colombier |	first '^' word		{$$=tree2('^', $1, $3);}
787dd7cddfSDavid du Colombier word:	keyword			{lastword=1; $1->type=WORD;}
793e12c5d1SDavid du Colombier |	comword
803e12c5d1SDavid du Colombier |	word '^' word		{$$=tree2('^', $1, $3);}
813e12c5d1SDavid du Colombier comword: '$' word		{$$=tree1('$', $2);}
823e12c5d1SDavid du Colombier |	'$' word SUB words ')'	{$$=tree2(SUB, $2, $4);}
833e12c5d1SDavid du Colombier |	'"' word		{$$=tree1('"', $2);}
843e12c5d1SDavid du Colombier |	COUNT word		{$$=tree1(COUNT, $2);}
853e12c5d1SDavid du Colombier |	WORD
86*dbee7877SDavid du Colombier |	'`' brace		{$$=tree2('`', (struct tree*)0, $2);}
87*dbee7877SDavid du Colombier |	'`' word brace		{$$=tree2('`', $2, $3);}
883e12c5d1SDavid du Colombier |	'(' words ')'		{$$=tree1(PAREN, $2);}
893e12c5d1SDavid du Colombier |	REDIR brace		{$$=mung1($1, $2); $$->type=PIPEFD;}
903e12c5d1SDavid du Colombier keyword: FOR|IN|WHILE|IF|NOT|TWIDDLE|BANG|SUBSHELL|SWITCH|FN
917dd7cddfSDavid du Colombier words:				{$$=(struct tree*)0;}
923e12c5d1SDavid du Colombier |	words word		{$$=tree2(WORDS, $1, $2);}
93