aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/rc/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cmd/rc/parse.c')
-rw-r--r--sys/cmd/rc/parse.c496
1 files changed, 0 insertions, 496 deletions
diff --git a/sys/cmd/rc/parse.c b/sys/cmd/rc/parse.c
deleted file mode 100644
index b61ac3c..0000000
--- a/sys/cmd/rc/parse.c
+++ /dev/null
@@ -1,496 +0,0 @@
-#include "rc.h"
-
-/* TODO: better error messages */
-
-// -----------------------------------------------------------------------
-// global data
-
-static int lastt, nextt=EOF;
-static Tree *node; /* if token was lexed as a tree node (redirs and words), its here */
-
-/* anything that is not listed will automatically terminate parsing the given command */
-static uchar prectab[256] = {
- [Tif] = 1, [Tfor] = 1, [Tswitch] = 1, /* NOTE: we give else lower precedence than if [Telse] = 1, */
- [Tandand] = 2, [Toror] = 2,
- [Tbang] = 3, [Tsubshell] = 3,
- [Tpipe] = 4,
- [Tcarot] = 5,
- [Tdol] = 6, [Tcount] = 6, [Tquote] = 6,
- [Tsub] = 7,
-};
-
-// -----------------------------------------------------------------------
-// helpers
-
-static
-int
-lookahead(void)
-{
- int tok;
-
- if (nextt != EOF)
- return nextt;
-
- tok = lex(&node);
- return nextt = tok;
-}
-
-static
-int
-advance(void)
-{
- int tok = lookahead();
- lastt = nextt, nextt = EOF;
- node = nil;
-
- return tok;
-}
-
-static
-int
-nextis(int tok)
-{
- if (lookahead() == tok) {
- advance();
- return 1;
- }
- return 0;
-}
-
-// -----------------------------------------------------------------------
-// subparsers
-
-/* forward declarations */
-static Tree *word(void);
-static Tree *words(void);
-static Tree* body(int c);
-static Tree *comword(void);
-static Tree *cmd(int prec);
-
-/* implementations */
-
-/*
- * TODO:
- * i don't like all this branching.
- * think of a better way
- */
-
-static
-Tree*
-case_or_cmd(int c)
-{
- Tree *t;
- if (!c || !nextis(Tcase))
- return cmd(1);
-
- t = words();
- if (!nextis(';') && !nextis('\n'))
- rcerror("case: missing terminator: recieved %d", nextt);
-
- t = tree2(Tcase, t, body(0));
- pfmt(errio, "%t\n", t);
-
- return t;
-}
-
-static
-Tree*
-body(int c)
-{
- int tok;
- Tree *l, *r;
-
- skipnl();
- l = case_or_cmd(c);
-loop:
- switch((tok=lookahead())){
- case '&':
- l = tree1('&', l);
- /* fallthrough */
- case ';': case '\n':
- advance();
- /* fallthrough */
- case Tcase:
- if ((r = case_or_cmd(c))) {
- l = tree2(';', l, r);
- goto loop;
- }
- /* fallthrough */
- default:
- ;
- }
-
- return l;
-}
-
-static
-Tree*
-brace(int c)
-{
- Tree *t;
-
- if (!nextis('{'))
- rcerror("brace: expected { found: %c", nextt);
- t = tree1(Tbrace, body(c));
- if (!nextis('}'))
- rcerror("brace: expected } found: %c", nextt);
-
- return t;
-}
-
-static
-Tree*
-paren(void)
-{
- Tree *t;
-
- if (!nextis('('))
- rcerror("not a paren");
- t = tree1(Tparen, body(0));
- if (!nextis(')'))
- rcerror("unmatched paren");
-
- return t;
-}
-
-/* TODO: fill in */
-static
-Tree*
-heredoc(Tree* t)
-{
- return t;
-}
-
-static
-Tree*
-redir(void)
-{
- int tok;
- Tree *t;
-
- switch (tok = lookahead()) {
- case Tdup:
- t = node;
- advance();
- break;
- case Tredir:
- t = node;
- advance();
- t = hang1(t, (t->redir.type == Rhere) ? heredoc(word()) : word());
- break;
- default:
- t = nil;
- }
-
- return t;
-}
-
-static
-Tree*
-epilog(void)
-{
- Tree *t, *tt;
-
- t = redir();
- while((tt = redir()))
- t = hang2(t, t->child[0], tt);
-
- return t;
-}
-
-static
-Tree*
-sword(void)
-{
- int tok;
- if (Kstart < (tok=lookahead()) && tok < Kend)
- return node;
-
- return comword();
-}
-
-static
-Tree*
-word(void)
-{
- int tok;
- Tree *t;
-
- t = sword();
- while(nextis('^'))
- t = tree2('^', t, sword());
-
- return t;
-}
-
-
-static
-Tree*
-words(void)
-{
- Tree *t, *tt;
- t = word();
- while((tt=word()))
- t = tree2(Twords, t, tt);
-
- return t;
-}
-
-/*
- * NOTE: we divergence from Duff's yacc grammar here.
- * he has [dol|count|"]->word, we have [dol|count]->sword
- * calling sword ensures we don't cat strings
- * this was done in Tom's version by setting precedence
- */
-static
-Tree*
-comword(void)
-{
- int tok;
- Tree *t, *tt;
-
- switch(tok=lookahead()){
- case Tdol:
- advance();
- t = sword();
- if(nextis('(')) {
- t = tree2(Tsub, t, words());
- if (!nextis(')'))
- rcerror("malformed index expression");
- }
- return tree1(Tdol, t);
- case Tquote:
- return tree1(Tquote, sword());
- case Tcount:
- advance();
- return tree1(Tcount, sword());
- case Ttick:
- advance();
- return tree1(Ttick, brace(0));
- case Tlparen:
- return paren();
- case Tredir:
- advance();
- t = hang1(node, brace(0));
- t->type = Tpipefd;
- return t;
- case Tword:
- t = node;
- advance();
- return t;
- }
- return nil;
-}
-
-static
-Tree*
-first(void)
-{
- int tok;
- Tree *t;
-
- t = comword();
- while(nextis('^')) {
- t = tree2('^', t, word());
- }
-
- return t;
-}
-
-/* simple _or_ assignment */
-static
-Tree*
-simple_or_assign(void)
-{
- int tok;
- Tree *t, *tt;
-
- /* can't continue */
- if (!(t = first()))
- return nil;
-
- /* is an assignment */
-assign:
- if(nextis('=')) {
- tt = word();
- return tree3(Teq, t, tt, cmd(prectab[Tbang]));
- }
-
- /* is a 'simple' */
-simple:
- switch ((tok=lookahead())) {
- case Tredir:
- case Tdup:
- t = tree2(Targs, t, redir());
- goto simple;
- default:
- if ((tt = word())) {
- t = tree2(Targs, t, tt);
- goto simple;
- }
- /* fallthrough */
- }
-
- return simplehang(t);
-}
-
-static
-Tree*
-opand(void)
-{
- int tok;
- Tree *t, *tt;
-
- switch(tok=lookahead()) {
- case Tif:
- advance();
- t = paren();
- skipnl();
- tt = cmd(prectab[Tif]);
- if (nextis(Telse)) {
- skipnl();
- t = tree3(Tif, t, tt, cmd(prectab[Tif]));
- } else
- t = tree3(Tif, t, tt, nil);
- return t;
- case Telse:
- rcerror("invalid hanging else");
- break;
-
- case Tswitch:
- advance();
- t = word();
- skipnl();
- tt = brace(1);
- t = tree2(Tswitch, t, tt);
- return t;
-
- case Tfor:
- advance();
-
- if (!nextis('('))
- rcerror("for: missing opening paren");
- t = word();
- if (nextis(Tin)) {
- advance();
- tt = words();
- t = tree3(Tfor, t, tt, nil);
- } else
- t = tree3(Tfor, t, nil, nil);
- if (!nextis(')'))
- rcerror("for: missing closing paren");
-
- skipnl();
- tt = cmd(prectab[Tfor]);
- t->child[2] = tt;
- return t;
-
- case Twhile:
- advance();
- t = paren();
- skipnl();
- tt = cmd(1);
- return tree2(Twhile, t, tt);
-
- case Tfunc:
- advance();
- t = words();
- if ((tok=lookahead()) == '{') {
- tt = brace(0);
- t = tree2(Tfunc, t, tt);
- } else
- t = tree1(Tfunc, t);
- return t;
-
- case Tsubshell:
- advance();
- t = tree1(Tsubshell, cmd(prectab[Tsubshell]));
- return t;
-
- case Tbang:
- advance();
- t = tree1(Tbang, cmd(prectab[Tbang]));
- return t;
-
- case Ttwiddle:
- advance();
- tt = word();
- t = tree2(Ttwiddle, tt, words());
- return t;
-
- case Tlbrace:
- t = brace(0);
- tt = epilog();
- return epihang(t, tt);
-
- case Tredir: /* fallthrough */
- case Tdup:
- t = redir();
- tt = cmd(prectab[Tbang]);
- t = hang2(t, t->child[0], tt);
- return t;
- }
-
- return simple_or_assign();
-}
-
-static
-Tree *
-cmd(int prec)
-{
- int np, tok;
- Tree *l, *r, *p;
-
- if (!(l = opand()))
- return nil;
-
- for(;;) {
- tok = lookahead();
- np = prectab[tok];
- if (np < prec)
- break;
- p = node;
- advance();
- r = cmd(np+1);
- if (tok == Tpipe)
- l = hang2(p, l, r);
- else
- l = tree2(tok, l, r);
- }
-
- return l;
-}
-
-// -----------------------------------------------------------------------
-// main function
-
-int
-parse(void)
-{
- int tok;
- Tree *t, *tt;
-
- t = cmd(1);
-loop:
- switch(tok=lookahead()) {
- case '&':
- t = tree1('&', t);
- /* fallthrough */
- case ';':
- advance();
- tt = cmd(1);
- t = tree2(';', t, tt);
- goto loop;
- case '\n':
- advance();
- case EOF:
- pfmt(errio, "%t\n", t);
- break;
- default:
- if (tok > 0x20)
- rcerror("unrecognized token: %c[%d]", tok, tok);
- else
- rcerror("unrecognized token: %d", tok, tok);
- }
- return tok != EOF;
-}