aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/rc/syntax.y
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/rc/syntax.y')
-rw-r--r--src/cmd/rc/syntax.y147
1 files changed, 147 insertions, 0 deletions
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<tree> line cmds cmdsln body paren block ifbody casebody case assign epilog redir;
+%type<tree> cmd basic executable nonkeyword keyword word words wordsnl atom;
+%type<tree> Tfor Tin Twhile Tif Telse Tswitch Tcase Ttwiddle Tbang Tsubshell Tfunc;
+%type<tree> 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'
+
+%%