equals_expr() { addsub_expr(); KurumiToken op = get_current_token(); bool loop_flag = true; while (op != null && loop_flag) { switch (op.to_operator_type()) { case KurumiOperatorType.LTHAN: case KurumiOperatorType.GTHAN: case KurumiOperatorType.LOREQ: case KurumiOperatorType.GOREQ: case KurumiOperatorType.NOTEQ: case KurumiOperatorType.EQUAL: next(); addsub_expr(); expression.add(op, storage); break; default: loop_flag = false; break; } op = get_current_token(); } }
keyword_expression(KurumiKeyword keyword) { switch (keyword) { case KurumiKeyword.IF: KurumiNumber stop_p = new KurumiNumber(-1); if_statement(stop_p); break; case KurumiKeyword.ELSE: case KurumiKeyword.ELIF: if (if_statement_count <= 0) { throw new Exception("Keyword 'else' or 'elif' without if statement."); } break; case KurumiKeyword.GOTO: next(); KurumiToken current = get_current_token(); expression.add(new KurumiCommand(KurumiCommandType.JMP)); expression.add(goto_storage.get(current.data)); next(); break; default: break; } }
muldiv_expr() { variable(); KurumiToken op = get_current_token(); bool loop_flag = true; while (op != null && loop_flag) { switch (op.to_operator_type()) { case KurumiOperatorType.MUL: case KurumiOperatorType.DIV: next(); variable(); expression.add(op, storage); break; default: loop_flag = false; break; } op = get_current_token(); } }
parse_any() { if (is_string()) { return(parse_string()); } if (is_digit()) { return(parse_number()); } if (is_name_identifier()) { return(parse_name()); } if (is_operator(current)) { return(parse_operator()); } if (is_endline()) { store_position(); next(); KurumiToken token = new KurumiToken(this, TokenType.Operator); line_position = 1; line += 1; skip_empty_lines(); return(token); } else { next(); } return(null); }
function_call(KurumiToken token, int return_count) { int count = call_args(); expression.add(token, storage); expression.add(new KurumiCommand(KurumiCommandType.CALL)); expression.add(new KurumiNumber(return_count)); expression.add(new KurumiNumber(count)); }
if_statement(KurumiNumber stop_p) { next(); if_statement_count += 1; rexpr(); next(); KurumiNumber next_p = new KurumiNumber(-1); expression.add(new KurumiCommand(KurumiCommandType.JMPIN)); expression.add(next_p); bool additional_branching = false; KurumiToken current = get_current_token(); while (current != null) { KurumiKeyword kw = current.is_keyword(); if (kw == KurumiKeyword.END) { int end_position = expression.size(); stop_p.number = end_position; if (!additional_branching) { next_p.number = end_position; } break; } else if (kw == KurumiKeyword.ELSE) { additional_branching = true; expression.add(new KurumiCommand(KurumiCommandType.JMP)); expression.add(stop_p); next_p.number = expression.size(); next(); } else if (kw == KurumiKeyword.ELIF) { additional_branching = true; expression.add(new KurumiCommand(KurumiCommandType.JMP)); expression.add(stop_p); next_p.number = expression.size(); if_statement(stop_p); break; } else { lexpr(); } current = get_current_token(); } next(); if_statement_count -= 1; }
parse_name() { store_position(); for ( ; !is_end(); next()) { if (!is_letter_or_digit() && current != '_') { break; } } KurumiToken token = new KurumiToken(this, TokenType.Identifier); return(token); }
parse_number() { store_position(); for ( ; !is_end(); next()) { if (!is_digit() && current != '.') { break; } } KurumiToken token = new KurumiToken(this, TokenType.Number); return(token); }
parse_string() { next(); store_position(); for ( ; !is_end(); next()) { if (is_string()) { break; } } KurumiToken token = new KurumiToken(this, TokenType.String); next(); return(token); }
lexpr() { KurumiToken current = get_current_token(); switch (current.type) { case TokenType.Identifier: KurumiKeyword keyword = current.is_keyword(); if (keyword == KurumiKeyword.UNKNOWN) { KurumiToken n = get_current_token(1); if (n == null) { return; } OperatorType type = n.to_operator_type(); if (type == OperatorType.COLON) { KurumiNumber number = goto_storage.get(current.data); number.number = expression.size(); next(); next(); } else if (type == OperatorType.LBRACKET) { function_call(current, 0); } else { rexpr(); } } else { keyword_expression(keyword); } break; case TokenType.Operator: next(); return; default: throw new Exception("Identifier or Keyword is expected in the left-sided expression."); } }
tokenize() { KurumiTokenList list = new KurumiTokenList(); while (!is_end()) { KurumiToken token = parse_any(); if (token != null) { list.Add(token); //Console.WriteLine("{0} {1} {2} {3} {4}", //token.data, token.type, token.line, token.line_position, token.indent); } } return(list); }
rexpr() { KurumiToken current = get_current_token(); while (current != null) { OperatorType type = current.to_operator_type(); bool v1 = current.type == TokenType.Operator && (type == OperatorType.ENDLINE || type == OperatorType.COLON); bool v2 = current.is_keyword() == KurumiKeyword.END; if (v1 || v2) { break; } int assigment_count = 0; assign_expr(ref assigment_count); current = get_current_token(); } }
assign_expr(ref int assigment_count) { equals_expr(); KurumiToken op = get_current_token(); bool loop_flag = true; while (op != null && loop_flag) { switch (op.to_operator_type()) { case KurumiOperatorType.ASSIGN: if (++assigment_count > 1) { expression.dublicate_top(); } next(); assign_expr(ref assigment_count); expression.add(op, storage); break; case KurumiOperatorType.ADDASSIGN: case KurumiOperatorType.SUBASSIGN: case KurumiOperatorType.MULASSIGN: case KurumiOperatorType.DIVASSIGN: if (++assigment_count > 1) { expression.dublicate_top(); } next(); expression.dublicate_top(2); assign_expr(ref assigment_count); expression.add(op, storage); expression.add(new KurumiCommand(KurumiCommandType.ASSIGN)); break; default: loop_flag = false; break; } op = get_current_token(); } }
parse_operator() { store_position(); for (int i = 0; !is_end(); next()) { i++; if (!is_operator(current) || i > 2) { if (!is_valid_operator(substring())) { prev(); } break; } } KurumiToken token = new KurumiToken(this, TokenType.Operator); return(token); }
call_args() { int count = 0; next(); KurumiToken token = get_current_token(); OperatorType t = token.to_operator_type(); while (token != null && t != OperatorType.RBRACKET && t != OperatorType.ENDLINE) { count += 1; equals_expr(); token = get_current_token(); t = token.to_operator_type(); if (t == OperatorType.COMMA) { next(); } } next(); return(count); }
add(KurumiToken token, KurumiStorage storage) { switch (token.type) { case TokenType.String: add(new KurumiString(token.data)); break; case TokenType.Number: add(new KurumiNumber(token.data)); break; case TokenType.Identifier: add(new KurumiCommand(KurumiCommandType.REF)); add(new KurumiNumber(storage.get_index_from_name(token.data))); break; case TokenType.Operator: add(new KurumiCommand(token.optype_to_command())); break; default: break; } }
variable() { KurumiToken token = get_current_token(); switch (token.type) { case TokenType.Operator: { switch (token.to_operator_type()) { case OperatorType.LBRACKET: next(); equals_expr(); KurumiToken rbracket = get_current_token(); if (rbracket == null || rbracket.type != TokenType.Operator || rbracket.to_operator_type() != OperatorType.RBRACKET) { throw new Exception("Expression right bracket not found: " + token.get_token_info()); } next(); break; case OperatorType.ADD: next(); break; case OperatorType.SUB: next(); expression.add(new KurumiNumber(0)); variable(); expression.add(token, storage); break; case OperatorType.ASSIGN: next(); rexpr(); expression.add(token, storage); break; default: throw new Exception("Expression error: " + token.get_token_info()); } break; } case TokenType.Identifier: next(); KurumiToken n = get_current_token(); if (n.to_operator_type() == OperatorType.LBRACKET) { function_call(token, 1); } else { expression.add(token, storage); } break; case TokenType.Number: case TokenType.String: next(); expression.add(token, storage); break; default: throw new Exception("Expression end in unknown token."); } }