static sl_node_base_t* statements(sl_parse_state_t* ps) { sl_node_seq_t* seq = sl_make_seq_node(ps); sl_node_base_t* node; while(peek_token(ps)->type != SL_TOK_END) { node = statement(ps); if(node) { sl_seq_node_append(ps, seq, node); } } return (sl_node_base_t*)seq; }
static sl_node_base_t* for_expression(sl_parse_state_t* ps) { sl_node_base_t *lval, *expr, *body, *else_body = NULL; sl_node_seq_t* seq_lval; sl_token_t* tok; sl_parse_scope_t scope; expect_token(ps, SL_TOK_FOR); /* save current token to allow rewinding and erroring */ tok = peek_token(ps); lval = call_expression(ps); if(!sl_node_is_lval(lval)) { unexpected(ps, tok); } if(peek_token(ps)->type == SL_TOK_COMMA || peek_token(ps)->type == SL_TOK_FAT_COMMA) { seq_lval = sl_make_seq_node(ps); seq_lval->nodes[seq_lval->node_count++] = lval; while(peek_token(ps)->type == SL_TOK_COMMA || peek_token(ps)->type == SL_TOK_FAT_COMMA) { next_token(ps); if(seq_lval->node_count == seq_lval->node_capacity) { seq_lval->node_capacity *= 2; seq_lval->nodes = sl_realloc(ps->vm->arena, seq_lval->nodes, sizeof(sl_node_base_t*) * seq_lval->node_capacity); } tok = peek_token(ps); lval = call_expression(ps); if(!sl_node_is_lval(lval)) { unexpected(ps, tok); } seq_lval->nodes[seq_lval->node_count++] = lval; } lval = sl_make_array_node(ps, seq_lval->node_count, seq_lval->nodes); } expect_token(ps, SL_TOK_IN); expr = expression(ps); scope.prev = ps->scope; scope.flags = scope.prev->flags | SL_PF_CAN_NEXT_LAST; ps->scope = &scope; body = body_expression(ps); ps->scope = scope.prev; if(scope.flags & SL_PF_SCOPE_CLOSURE) { ps->scope->flags |= SL_PF_SCOPE_CLOSURE; } if(peek_token(ps)->type == SL_TOK_ELSE) { next_token(ps); else_body = body_expression(ps); } return sl_make_for_node(ps, lval, expr, body, else_body); }
static sl_node_base_t* body_expression(sl_parse_state_t* ps) { sl_node_seq_t* seq = sl_make_seq_node(ps); sl_node_base_t* node; expect_token(ps, SL_TOK_OPEN_BRACE); while(peek_token(ps)->type != SL_TOK_CLOSE_BRACE) { node = statement(ps); if(node) { sl_seq_node_append(ps, seq, node); } } expect_token(ps, SL_TOK_CLOSE_BRACE); return (sl_node_base_t*)seq; }
static sl_node_base_t* bracketed_expression(sl_parse_state_t* ps) { sl_node_base_t* node; expect_token(ps, SL_TOK_OPEN_PAREN); node = expression(ps); if(peek_token(ps)->type == SL_TOK_SEMICOLON) { sl_node_seq_t* seq = sl_make_seq_node(ps); sl_seq_node_append(ps, seq, node); while(peek_token(ps)->type == SL_TOK_SEMICOLON) { next_token(ps); sl_seq_node_append(ps, seq, expression(ps)); } node = (sl_node_base_t*)seq; } expect_token(ps, SL_TOK_CLOSE_PAREN); return node; }
static sl_node_base_t* inline_raw(sl_parse_state_t* ps) { sl_node_seq_t* seq = sl_make_seq_node(ps); while(1) { switch(peek_token(ps)->type) { case SL_TOK_OPEN_ECHO_TAG: sl_seq_node_append(ps, seq, echo_tag(ps)); break; case SL_TOK_OPEN_RAW_ECHO_TAG: sl_seq_node_append(ps, seq, echo_raw_tag(ps)); break; case SL_TOK_RAW: sl_seq_node_append(ps, seq, sl_make_raw_node(ps, next_token(ps))); break; case SL_TOK_END: return (sl_node_base_t*)seq; case SL_TOK_OPEN_TAG: return (sl_node_base_t*)seq; default: break; } } }