From ce05175372a9ddca1a225db0765ace1127a39293 Mon Sep 17 00:00:00 2001 From: Nicholas Date: Fri, 12 Nov 2021 09:22:01 -0800 Subject: chore: simplified organizational structure --- src/cmd/rc/syntax.y | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 src/cmd/rc/syntax.y (limited to 'src/cmd/rc/syntax.y') diff --git a/src/cmd/rc/syntax.y b/src/cmd/rc/syntax.y new file mode 100644 index 0000000..0bdc776 --- /dev/null +++ b/src/cmd/rc/syntax.y @@ -0,0 +1,147 @@ +%token Tfor Tin Twhile Tif Telse Tswitch Tcase Tcasebody Ttwiddle Tbang Tsubshell Tfunc +%token Tredir Tdup Tpipe Tindex +%token Tbasic Targs Tword Twords Tparen Tblock + +%define parse.error verbose + +%{ + #include "rc.h" + + int yylex(void); + void yyerror(const char *); +%} + +/* operator precendence: lowest first */ +%left Tif Tfor Tswitch Tcase ')' Twhile Telse +%left Tandand Toror '\n' +%left Tbang Tsubshell +%left Tpipe; +%left '^'; +%right '$' Tcount Tjoin +%left Tindex + +/* semantic types */ +%union{ + struct Tree *tree; +} +%type line cmds cmdsln body paren block ifbody casebody case assign epilog redir; +%type cmd basic executable nonkeyword keyword word words wordsnl atom; +%type Tfor Tin Twhile Tif Telse Tswitch Tcase Ttwiddle Tbang Tsubshell Tfunc; +%type Tword Tredir Tpipe Tdup; + +/* grammar */ + +%start rc + +%% +rc: +/*empty*/ { return 0; } +| line '\n' { return compile($1); } + +line: + cmd +| cmds line { $$ = maketree2(';', $1, $2); } + +body: + cmd +| cmdsln body { $$ = maketree2(';', $1, $2); } + +paren: + '(' body ')' { $$ = maketree1(Tparen, $2); } + +block: + '{' body '}' { $$ = maketree1(Tblock, $2); } + +cmds: + cmd ';' +| cmd '&' { $$ = maketree1('&', $1); } + +cmdsln: + cmds +| cmd '\n' + +ifbody: + cmd %prec Telse { $$ = maketree2(Tif, nil, $1); } +| block Telse nl cmd { $$ = maketree3(Tif, nil, $1, $2); } + +case: + Tcase words ';' { $$ = hangchild1($1, $2, 0); } +| Tcase words '\n' { $$ = hangchild1($1, $2, 0); } + +casebody: + cmd { $$ = maketree2(Tcasebody, $1, nil); } +| case casebody { $$ = maketree2(Tcasebody, $1, $2); } +| cmdsln casebody { $$ = maketree2(Tcasebody, $1, $2); } + +assign: + executable '=' word { $$ = maketree2('=', $1, $3); } + +redir: + Tdup +| Tredir word { $$ = hangchild1($1, $2, 0); } + +epilog: +/* empty */ { $$ = nil; } +| redir epilog { $$ = hangchild1($1, $2, 1); } + +cmd: +/* empty */ %prec Twhile { $$ = nil; } +| basic { $$ = maketree1(Tbasic, $1); } +| block epilog { $$ = hangepilog($1, $2); } +| cmd Tpipe nl cmd { $$ = hangchild2($2, $1, 0, $4, 1); } +| cmd Tandand nl cmd { $$ = maketree2(Tandand, $1, $4); } +| cmd Toror nl cmd { $$ = maketree2(Toror, $1, $4); } +| redir cmd %prec Tbang { $$ = hangchild1($1, $2, 1); } +| assign cmd %prec Tbang { $$ = hangchild1($1, $2, 2); } +| Tbang cmd { $$ = maketree1(Tbang, $2); } +| Tsubshell cmd { $$ = maketree1(Tsubshell, $2); } +| Tfor '(' word ')' nl cmd { $$ = hangchild3($1, $3, nil, $6); } +| Tfor '(' word Tin words ')' nl cmd { $$ = hangchild3($1, $3, $5, $8); } +| Twhile paren nl cmd { $$ = hangchild2($1, $2, 0, $4, 1); } +| Tif paren nl ifbody { $$ = hangchild1($2, $1, 0); } +| Tswitch '(' word ')' nl '{' casebody '}' { $$ = hangchild2($1, $3, 0, $7, 1); } + +basic: + executable +| basic word { $$ = maketree2(Targs, $1, $2); } +| basic redir { $$ = maketree2(Targs, $1, $2); } + +atom: + nonkeyword +| keyword { $$ = maketree1(Tword, $1); } + +word: + atom +| word '^' atom { $$ = maketree2('^', $1, $3); } + +executable: + nonkeyword +| executable '^' atom { $$ = maketree2('^', $1, $3); } + +nonkeyword: + Tword +| '$' atom { $$ = maketree1('$', $2); } +| '$' atom Tindex words ')' { $$ = maketree2(Tindex, $2, $4); } +| '(' wordsnl ')' { $$ = $2; } +| Tcount atom { $$ = maketree1(Tcount, $2); } +| Tjoin atom { $$ = maketree1(Tjoin, $2); } +| '`' block { $$ = maketree1('`', $2); } +//| Tredir block { $$ = hangchild1($1, $2, 0); $$->type = Tpipefd; } + +keyword: + Tfor|Tin|Twhile|Tif|Telse|Tswitch|Tcase|Tbang|Tsubshell|Tfunc + +words: +/* empty */ { $$ = nil; } +| words word { $$ = maketree2(Twords, $1, $2); } + +wordsnl: +/* empty */ { $$ = nil; } +| wordsnl '\n' /* empty */ +| wordsnl word {$$ = (!$1) ? ((!$2) ? nil : $2) : ((!$2) ? $1 : maketree2(Twords, $1, $2)); } + +nl: +/*empty*/ +| nl '\n' + +%% -- cgit v1.2.1