9base

revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log | Files | Refs | README | LICENSE

syn.y (3128B)


      1 %term FOR IN WHILE IF NOT TWIDDLE BANG SUBSHELL SWITCH FN
      2 %term WORD REDIR DUP PIPE SUB
      3 %term SIMPLE ARGLIST WORDS BRACE PAREN PCMD PIPEFD /* not used in syntax */
      4 /* operator priorities -- lowest first */
      5 %left IF WHILE FOR SWITCH ')' NOT
      6 %left ANDAND OROR
      7 %left BANG SUBSHELL
      8 %left PIPE
      9 %left '^'
     10 %right '$' COUNT '"'
     11 %left SUB
     12 %{
     13 #include "rc.h"
     14 #include "fns.h"
     15 %}
     16 %union{
     17 	struct tree *tree;
     18 };
     19 %type<tree> line paren brace body cmdsa cmdsan assign epilog redir
     20 %type<tree> cmd simple first word comword keyword words
     21 %type<tree> NOT FOR IN WHILE IF TWIDDLE BANG SUBSHELL SWITCH FN
     22 %type<tree> WORD REDIR DUP PIPE
     23 %%
     24 rc:				{ return 1;}
     25 |	line '\n'		{return !compile($1);}
     26 line:	cmd
     27 |	cmdsa line		{$$=tree2(';', $1, $2);}
     28 body:	cmd
     29 |	cmdsan body		{$$=tree2(';', $1, $2);}
     30 cmdsa:	cmd ';'
     31 |	cmd '&'			{$$=tree1('&', $1);}
     32 cmdsan:	cmdsa
     33 |	cmd '\n'
     34 brace:	'{' body '}'		{$$=tree1(BRACE, $2);}
     35 paren:	'(' body ')'		{$$=tree1(PCMD, $2);}
     36 assign:	first '=' word		{$$=tree2('=', $1, $3);}
     37 epilog:				{$$=0;}
     38 |	redir epilog		{$$=mung2($1, $1->child[0], $2);}
     39 redir:	REDIR word		{$$=mung1($1, $1->rtype==HERE?heredoc($2):$2);}
     40 |	DUP
     41 cmd:				{$$=0;}
     42 |	brace epilog		{$$=epimung($1, $2);}
     43 |	IF paren {skipnl();} cmd
     44 				{$$=mung2($1, $2, $4);}
     45 |	IF NOT {skipnl();} cmd	{$$=mung1($2, $4);}
     46 |	FOR '(' word IN words ')' {skipnl();} cmd
     47 	/*
     48 	 * if ``words'' is nil, we need a tree element to distinguish between 
     49 	 * for(i in ) and for(i), the former being a loop over the empty set
     50 	 * and the latter being the implicit argument loop.  so if $5 is nil
     51 	 * (the empty set), we represent it as "()".  don't parenthesize non-nil
     52 	 * functions, to avoid growing parentheses every time we reread the
     53 	 * definition.
     54 	 */
     55 				{$$=mung3($1, $3, $5 ? $5 : tree1(PAREN, $5), $8);}
     56 |	FOR '(' word ')' {skipnl();} cmd
     57 				{$$=mung3($1, $3, (struct tree *)0, $6);}
     58 |	WHILE paren {skipnl();} cmd
     59 				{$$=mung2($1, $2, $4);}
     60 |	SWITCH word {skipnl();} brace
     61 				{$$=tree2(SWITCH, $2, $4);}
     62 |	simple			{$$=simplemung($1);}
     63 |	TWIDDLE word words	{$$=mung2($1, $2, $3);}
     64 |	cmd ANDAND cmd		{$$=tree2(ANDAND, $1, $3);}
     65 |	cmd OROR cmd		{$$=tree2(OROR, $1, $3);}
     66 |	cmd PIPE cmd		{$$=mung2($2, $1, $3);}
     67 |	redir cmd  %prec BANG	{$$=mung2($1, $1->child[0], $2);}
     68 |	assign cmd %prec BANG	{$$=mung3($1, $1->child[0], $1->child[1], $2);}
     69 |	BANG cmd		{$$=mung1($1, $2);}
     70 |	SUBSHELL cmd		{$$=mung1($1, $2);}
     71 |	FN words brace		{$$=tree2(FN, $2, $3);}
     72 |	FN words		{$$=tree1(FN, $2);}
     73 simple:	first
     74 |	simple word		{$$=tree2(ARGLIST, $1, $2);}
     75 |	simple redir		{$$=tree2(ARGLIST, $1, $2);}
     76 first:	comword	
     77 |	first '^' word		{$$=tree2('^', $1, $3);}
     78 word:	keyword			{lastword=1; $1->type=WORD;}
     79 |	comword
     80 |	word '^' word		{$$=tree2('^', $1, $3);}
     81 comword: '$' word		{$$=tree1('$', $2);}
     82 |	'$' word SUB words ')'	{$$=tree2(SUB, $2, $4);}
     83 |	'"' word		{$$=tree1('"', $2);}
     84 |	COUNT word		{$$=tree1(COUNT, $2);}
     85 |	WORD
     86 |	'`' brace		{$$=tree1('`', $2);}
     87 |	'(' words ')'		{$$=tree1(PAREN, $2);}
     88 |	REDIR brace		{$$=mung1($1, $2); $$->type=PIPEFD;}
     89 keyword: FOR|IN|WHILE|IF|NOT|TWIDDLE|BANG|SUBSHELL|SWITCH|FN
     90 words:				{$$=(struct tree*)0;}
     91 |	words word		{$$=tree2(WORDS, $1, $2);}