static struct ast_node* if_expr(void *opaque) { struct ast_node_if *if_node; struct ast_node_stub *stub_node; struct ast_node *expr; struct ast_node *stmt_node; struct ast_node *_else; struct scope_ctx helper; if (!match(TOKEN_LPARENTH)) { error_msg("error: `(' expected after if"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } expr = or_expr(); if (expr == NULL) { error_msg("error: expression expected after `('"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } if (!match(TOKEN_RPARENTH)) { error_msg("error: `)' expected after exprssion"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } if (opaque == NULL) { memset(&helper, 0, sizeof(helper)); helper.is_cond++; } else { helper = *(struct scope_ctx *)opaque; helper.is_cond++; } stmt_node = stmt(&helper); if (stmt_node == NULL) { error_msg("error: statment expected after `)'"); stub_node = ast_node_stub(); return AST_NODE(stub_node); } _else = NULL; if (match(TOKEN_ELSE)) _else = stmt(&helper); if_node = ast_node_if(expr, stmt_node, _else); helper.is_cond--; return AST_NODE(if_node); }
struct ast_node* process_function(void *opaque) { char *name; struct ast_node_stub *stub_node; if (!match(TOKEN_ID)) { error_msg("error: function name expected after `function'"); sync_stream(); goto exit; } name = ustrdup(lex_prev.id); if (current_token != TOKEN_LPARENTH) { error_msg("error: `(' expected"); sync_stream(); goto exit; } process_args(name); exit: stub_node = ast_node_stub(); return AST_NODE(stub_node); }
static struct ast_node* continue_expr(void *opaque) { struct ast_node_continue *continue_node; struct ast_node_stub *stub_node; struct scope_ctx helper; if (opaque == NULL) { error_msg("error: `continue' outside loop"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } helper = *(struct scope_ctx *)opaque; if (!helper.is_cycle) { error_msg("error: `continue' outside loop`"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } continue_node = ast_node_continue(); return AST_NODE(continue_node); }
static struct ast_node* break_expr(void *opaque) { struct ast_node_stub *stub_node; struct ast_node_break *break_node; struct scope_ctx *helper; if (opaque == NULL) { error_msg("error: `break' outside loop"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } helper = (struct scope_ctx *)opaque; if (!helper->is_cycle) { error_msg("error: `break' outside loop"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } break_node = ast_node_break(); return AST_NODE(break_node); }
static void list_expr(void) { number res; start: while (token.type == TOKEN_INTEGER ||token.type == TOKEN_LPARENTH || token.type == TOKEN_EOL || token.type == TOKEN_EOF) { if (token.type == TOKEN_EOL) { get_next_token(); continue; } if (token.type == TOKEN_EOF) { return ; } add_expr(); if (err == SYN_ERR || err == MEM_ERR) { if (err == SYN_ERR) printf("syntax error\n"); if (err == MEM_ERR) printf("memory error\n"); sync_stream(); sp.n = 0; err = 0; goto start; } pop_item(&sp, &res); print_value(res); } printf("syntax error\n"); sync_stream(); goto start; }
static struct ast_node* while_expr(void *opaque) { struct ast_node_stub *stub_node; struct ast_node_while *while_node; struct ast_node *expr; struct ast_node *_stmt; struct scope_ctx helper; if (!match(TOKEN_LPARENTH)) { error_msg("errorr: `(' expected after while"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } expr = or_expr(); if (expr == NULL) { error_msg("error: NULL expression in while()"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } if (!match(TOKEN_RPARENTH)) { error_msg("error: `)' expected after while("); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } if (opaque) { helper = *(struct scope_ctx *)opaque; helper.is_cycle++; } else { memset(&helper, 0, sizeof(helper)); helper.is_cycle++; } _stmt = stmt(&helper); if (_stmt == NULL) { error_msg("error: statmet expected after while()"); stub_node = ast_node_stub(); return AST_NODE(stub_node); } while_node = ast_node_while(expr, _stmt); helper.is_cycle--; return AST_NODE(while_node); }
static void process_args(char *name) { struct function *func; struct symbol *arg; /*(*/ consume_token(); func = function_table_lookup(name); /* Delete an old function and make a new one */ if (func != NULL) function_table_delete_function(name); func = function_new(name); while (!match(TOKEN_RPARENTH)) { if (match(TOKEN_EOL)) { error_msg("error: new line in function definition"); return; } if (!match(TOKEN_ID)) { error_msg("error: unexpected symbol in definition"); sync_stream(); ufree(func); return; } arg = symbol_new(lex_prev.id, VALUE_TYPE_UNKNOWN); function_add_arg(func, arg); if (current_token != TOKEN_RPARENTH && !match(TOKEN_COMMA)) { error_msg("error: comma expected"); sync_stream(); return; } } switch(current_token) { case TOKEN_LBRACE: function_table_insert(func); process_function_body(name); break; default: error_msg("error: `{' expected"); sync_stream(); break; } }
static struct ast_node* access_node(char *name) { struct ast_node_stub *stub_node; struct ast_node_access *ac_node; struct ast_node *idx; struct symbol *sym; sym = symbol_table_lookup_all(name); if (sym == NULL) { error_msg("error: no such symbol"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } /* `[' */ consume_token(); ac_node = ast_node_access(sym->v_type, sym->name); do { idx = or_expr(); if (idx == NULL) { error_msg("error: empty index"); sync_stream(); goto ac_error; } ast_node_access_add(ac_node, idx); if (current_token != TOKEN_RBRACKET) { error_msg("error: missed `]'"); sync_stream(); goto ac_error; } /* `]' */ consume_token(); } while (match(TOKEN_LBRACKET)); return AST_NODE(ac_node); ac_error: ast_node_unref(AST_NODE(ac_node)); stub_node = ast_node_stub(); return AST_NODE(stub_node); }
static struct ast_node* rest_or(struct ast_node *node) { struct ast_node *ret_node; struct ast_node *left; struct ast_node *right; ret_node = node; while (TRUE) { switch(current_token) { case TOKEN_OR : consume_token(); left = ret_node; right = and_expr(); if (right == NULL) { error_msg("error: expression expected after ||"); right = (struct ast_node *)ast_node_stub(); sync_stream(); } ret_node = (struct ast_node *)ast_node_logic_op(OPCODE_OR, left, right); continue; default: goto exit_or; } } exit_or: return ret_node; }
static struct ast_node* process_scope(void *opaque) { struct ast_node *stmt; struct ast_node_stub *stub_node; struct scope_ctx *helper; if (opaque == NULL) { error_msg("error: unexpected symbol"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } helper = (struct scope_ctx *)opaque; if (!helper->is_cycle && !helper->is_cond) { error_msg("error: scope outside context"); stub_node = ast_node_stub(); return AST_NODE(stub_node); } stmt = stmts(opaque); return stmt; }
static struct ast_node* rest_and(struct ast_node *node) { struct ast_node *ret_node; struct ast_node *left; struct ast_node *right; ret_node = node; while (TRUE) { switch (current_token) { case TOKEN_AND: consume_token(); left = ret_node; right = rel_expr(); if (right == NULL) { error_msg("error: missed expression"); right = (struct ast_node *)ast_node_stub(); sync_stream(); } ret_node = (struct ast_node *)ast_node_logic_op(OPCODE_AND, left, right); continue; default: goto exit_and; } } exit_and: return ret_node; }
static struct ast_node* rel_expr(void) { struct ast_node *left; struct ast_node *right; struct ast_node_op *op_node; opcode_type_t opcode; left = sum_expr(); if (left == NULL) return NULL; switch(current_token) { case TOKEN_EQ: consume_token(); opcode = OPCODE_EQ; break; case TOKEN_LT: consume_token(); opcode = OPCODE_LT; break; case TOKEN_GT: consume_token(); opcode = OPCODE_GT; break; case TOKEN_LE: consume_token(); opcode = OPCODE_LE; break; case TOKEN_GE: consume_token(); opcode = OPCODE_GE; break; case TOKEN_NE: consume_token(); opcode = OPCODE_NE; break; default: return left; } right = sum_expr(); if (right == NULL) { error_msg("error: expression expected"); right = (struct ast_node *)ast_node_stub(); sync_stream(); } op_node = ast_node_rel_op(opcode, left, right); return AST_NODE(op_node); }
struct ast_node* process_local_declaration(void *opaque) { struct scope_ctx helper; struct ast_node_stub *stub_node; struct symbol *var; if (opaque == NULL) { error_msg("error: `local' outside function"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } helper = *(struct scope_ctx *)opaque; if (!helper.is_func) { error_msg("error: `local' outside function"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } while (!match(TOKEN_EOL)) { if (match(TOKEN_ID)) { var = symbol_new(lex_prev.id, VALUE_TYPE_UNKNOWN); symbol_table_put_symbol(var); } if (current_token != TOKEN_EOL && !match(TOKEN_COMMA)) { error_msg("error: `,' expected after variable"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } } stub_node = ast_node_stub(); return AST_NODE(stub_node); }
static struct ast_node* unknown_expr(void *opaque) { struct ast_node_stub *node; error_msg("error: unknown expression"); sync_stream(); node = ast_node_stub(); return AST_NODE(node); }
static struct ast_node* expr(void) { struct ast_node *lvalue; struct ast_node *rvalue; struct ast_node_assign *assign; lvalue = or_expr(); if (current_token != TOKEN_EQUALITY) return lvalue; /* `=' */ consume_token(); switch(lvalue->type) { case NODE_TYPE_ID: case NODE_TYPE_ACCESS: break; default: error_msg("error: rvalue assignmet"); sync_stream(); return lvalue; } rvalue = or_expr(); if (!rvalue) { error_msg("error: expression expected `='"); sync_stream(); rvalue = (struct ast_node *)ast_node_stub(); } assign = ast_node_assign(lvalue, rvalue); return AST_NODE(assign); }
static struct ast_node* other_expr(void *opaque) { struct ast_node *node; struct ast_node_stub *stub_node; node = expr(); if (node == NULL) { if (current_token != TOKEN_EOL) { error_msg("error: unexpected symbol"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } } return node; }
struct ast_node* process_return_node(void *opaque) { struct ast_node *ret_val; struct ast_node_return *_return; if (!opaque) { error_msg("error: return outside function"); sync_stream(); ret_val = (struct ast_node *)ast_node_stub(); return AST_NODE(ret_val); } ret_val = sum_expr(); _return = ast_node_return(ret_val); return AST_NODE(_return); }
static struct ast_node* rest_exp(struct ast_node *node) { struct ast_node *expr_node; struct ast_node *prev_node; struct ast_node *ret_node; char op; prev_node = node; while(TRUE) { switch(current_token) { case TOKEN_CARET: op = '^'; break; default: goto exit_exp; } consume_token(); expr_node = term_expr(); if (expr_node == NULL) { error_msg("error: syntax error"); expr_node = (struct ast_node *)ast_node_stub(); sync_stream(); goto exit_exp; } prev_node = (struct ast_node *)ast_node_op(op, prev_node, expr_node); } exit_exp: ret_node = prev_node; return ret_node; }
static struct ast_node* process_matrix(void) { struct ast_node_stub *stub_node; struct ast_node **elem; struct ast_node *node; int row, col, len; int prev_col; int i; elem = NULL; node = NULL; row = col = 1; len = prev_col = 0; while (TRUE) { node = or_expr(); if (node == NULL) { error_msg("expr expected"); sync_stream(); goto err; } elem = urealloc(elem, ++len*sizeof(struct ast_node *)); elem[len - 1] = node; switch(current_token) { case TOKEN_COMMA: consume_token(); col++; continue; case TOKEN_SEMICOLON: consume_token(); if (prev_col == 0) prev_col = col; else if (prev_col != col) { error_msg("incompatible column count"); sync_stream(); goto err; } col = 1; row++; continue; case TOKEN_RBRACKET: consume_token(); break; default: error_msg("syntax error"); sync_stream(); goto err; } break; } if (row == 1 || col == 1) node = (struct ast_node *)ast_node_vector(elem, len); else node = (struct ast_node *) ast_node_matrix(elem, row, col); return node; err: if (node != NULL) ast_node_unref(node); if (elem != NULL) for (i = 0; i < len; i++) ast_node_unref(elem[i]); stub_node = ast_node_stub(); return AST_NODE(stub_node); }
static struct ast_node* function_call(char *name) { struct function *func_ctx; struct ast_node_func_call *func_call; struct ast_node_stub *stub_node; struct ast_node *arg; int nargs = 0; func_ctx = function_table_lookup(name); consume_token(); if (func_ctx == NULL) { error_msg("unknown function"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } func_call = ast_node_func_call(func_ctx->name); while (!match(TOKEN_RPARENTH)) { if (match(TOKEN_EOL)) { error_msg("EOL in function call"); sync_stream(); goto free; } arg = or_expr(); if (arg == NULL) { error_msg("error: function argument expected"); sync_stream(); goto free; } nargs++; ast_node_func_call_add_arg(func_call, arg); if (current_token != TOKEN_RPARENTH && !match(TOKEN_COMMA)) { error_msg("error: missed comma"); sync_stream(); goto free; } } if (func_ctx->nargs != nargs) { error_msg("error: unmatched arguments count"); sync_stream(); goto free; } return AST_NODE(func_call); free: ast_node_unref(AST_NODE(func_call)); stub_node = ast_node_stub(); return AST_NODE(stub_node); }
static struct ast_node* for_expr(void *opaque) { struct ast_node_for *for_node; struct ast_node_stub *stub_node; struct ast_node *expr1; struct ast_node *expr2; struct ast_node *expr3; struct ast_node *_stmt; struct scope_ctx helper; if (!match(TOKEN_LPARENTH)) { error_msg("error: `(' expected after for"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } expr1 = expr(); if (!match(TOKEN_SEMICOLON)) { error_msg("error: `;' expected after for("); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } expr2 = or_expr(); if (!match(TOKEN_SEMICOLON)) { error_msg("error: `;' expected after for(;"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } expr3 = expr(); if (!match(TOKEN_RPARENTH)) { error_msg("error: `)' expected after for(;;"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } if (opaque) { helper = *(struct scope_ctx *)opaque; helper.is_cycle++; } else { memset(&helper, 0, sizeof(helper)); helper.is_cycle++; } _stmt = stmt(&helper); if (_stmt == NULL) { error_msg("error: stmt expected after for(;;)"); sync_stream(); stub_node = ast_node_stub(); return AST_NODE(stub_node); } for_node = ast_node_for(expr1, expr2, expr3, _stmt); helper.is_cycle--; return AST_NODE(for_node); }