/*----------------------------------------------------------------------*/ static ast_statement_t *parse_statement(parse_state_t *p) { token_t *token; token = peek_token(p); if (token == NULL) { return NULL; } else if (test_token(token, TK_ELSE) || test_token(token, TK_END)) { return NULL; } else if (test_token(token, TK_VAR)) { return parse_declare_var(p); } else if (test_token(token, TK_FUNCTION)) { return parse_define_function(p); } else if (test_token(token, TK_RETURN)) { return parse_return(p); } else if (test_token(token, TK_IF)) { return parse_if(p); } else if (test_token(token, TK_FOR)) { return parse_for(p); } else if (test_token(token, TK_IDENTIFIER)) { return parse_assignment(p); } next_token(p); error(p, "statement expected"); return NULL; /* unreachable */ }
struct instruction *parse_instruction(void) { struct expr *expr; struct instruction *res; switch (lookahead[0]->type) { case WHILE: return parse_while(); case DO: return parse_do(); case IDENTIFIER: case LPAREN: expr = parse_expression(); switch(lookahead[0]->type) { case ASSIGN: return parse_assignment_instr(expr); case EOL: if (expr->exprtype != funcalltype) { if (expr->exprtype == binopexprtype && expr->val.binopexpr.op == EQ) { error(expr->pos, "unexpected =, did you mean <- ?"); exit(1); } else syntaxerror("expected instruction, not expression"); } eat(EOL); res = funcallinstr(expr->val.funcall.fun_ident, expr->val.funcall.args, expr->pos); free(expr); return res; default: next(); syntaxerror("unexpected %s", tok->val); return parse_instruction(); } case RETURN: eat(RETURN); if (lookahead[0]->type == EOL) { eat(EOL); return return_stmt(NULL); } else { expr = parse_expression(); eat(EOL); return return_stmt(expr); } case FOR: return parse_for(); case IF: return parse_if(); case SWITCH: return parse_switch(); case ENDOFFILE: return NULL; default: next(); syntaxerror("expected instruction, not %s", tok->val); return parse_instruction(); } }
/* parse a compound- or a simple-command * (pipeline and lists are done outside this) * ----------------------------------------------------------------------- */ union node *parse_command(struct parser *p, int tempflags) { enum tok_flag tok; union node *command; union node **rptr; tok = parse_gettok(p, tempflags); switch(tok) { /* T_FOR begins an iteration statement */ case T_FOR: command = parse_for(p); break; /* T_IF begins a case match statement */ case T_CASE: command = parse_case(p); break; /* T_IF begins a conditional statement */ case T_IF: command = parse_if(p); break; /* T_WHILE/T_UNTIL begin a for-loop statement */ case T_WHILE: case T_UNTIL: command = parse_loop(p); break; /* T_LP/T_BEGIN start a grouping compound */ case T_LP: case T_BEGIN: p->pushback++; command = parse_grouping(p); break; /* handle simple commands */ case T_NAME: case T_WORD: case T_REDIR: case T_ASSIGN: p->pushback++; command = parse_simple_command(p); break; /* it wasn't a compound command, return now */ default: p->pushback++; return NULL; } if(command) { /* they all can have redirections, so parse these now */ rptr = &command->ncmd.rdir; /* * in the case of a simple command there are maybe already * redirections in the list (because in a simple command they * can appear between arguments), so skip to the end of the list. */ while(*rptr) tree_next(rptr); while(parse_gettok(p, P_DEFAULT) & T_REDIR) tree_move(p->tree, rptr); } p->pushback++; return command; }
/** Parse statement. * * @param parse Parser object. * @return New syntax tree node. */ stree_stat_t *parse_stat(parse_t *parse) { stree_stat_t *stat; stree_vdecl_t *vdecl_s; stree_if_t *if_s; stree_switch_t *switch_s; stree_while_t *while_s; stree_for_t *for_s; stree_raise_t *raise_s; stree_break_t *break_s; stree_return_t *return_s; stree_wef_t *wef_s; stree_exps_t *exp_s; #ifdef DEBUG_PARSE_TRACE printf("Parse statement.\n"); #endif switch (lcur_lc(parse)) { case lc_var: vdecl_s = parse_vdecl(parse); stat = stree_stat_new(st_vdecl); stat->u.vdecl_s = vdecl_s; break; case lc_if: if_s = parse_if(parse); stat = stree_stat_new(st_if); stat->u.if_s = if_s; break; case lc_switch: switch_s = parse_switch(parse); stat = stree_stat_new(st_switch); stat->u.switch_s = switch_s; break; case lc_while: while_s = parse_while(parse); stat = stree_stat_new(st_while); stat->u.while_s = while_s; break; case lc_for: for_s = parse_for(parse); stat = stree_stat_new(st_for); stat->u.for_s = for_s; break; case lc_raise: raise_s = parse_raise(parse); stat = stree_stat_new(st_raise); stat->u.raise_s = raise_s; break; case lc_break: break_s = parse_break(parse); stat = stree_stat_new(st_break); stat->u.break_s = break_s; break; case lc_return: return_s = parse_return(parse); stat = stree_stat_new(st_return); stat->u.return_s = return_s; break; case lc_do: case lc_with: wef_s = parse_wef(parse); stat = stree_stat_new(st_wef); stat->u.wef_s = wef_s; break; default: exp_s = parse_exps(parse); stat = stree_stat_new(st_exps); stat->u.exp_s = exp_s; break; } #ifdef DEBUG_PARSE_TRACE printf("Parsed statement %p\n", stat); #endif return stat; }