| syn.y - 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?he… | |
| 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 be… | |
| 49 * for(i in ) and for(i), the former being a loop over the empty… | |
| 50 * and the latter being the implicit argument loop. so if $5 is… | |
| 51 * (the empty set), we represent it as "()". don't parenthesize… | |
| 52 * functions, to avoid growing parentheses every time we reread … | |
| 53 * definition. | |
| 54 */ | |
| 55 {$$=mung3($1, $3, $5 ? $5 : tree1(PAREN,… | |
| 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->ch… | |
| 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);} |