mod std; type_alias Tok: struct { type: string, value: string, }; fn lex(text: string) -> [Tok] { let i = 0; let len = std::string_length(text); let toks = std::array_new::(); while i < len { if std::string_contains(" \t\n", text[i]) { i += 1; if i >= len { break; } } if text[i] >= '1' and text[i] <= '9' { let value = std::ctos(text[i]); i += 1; while i < len and text[i] >= '0' and text[i] <= '9' { value = std::string_push_char(value, text[i]); i += 1; } let tok = struct { type: "int", value: value }; std::array_push(toks, tok); } else if text[i] == '0' { i += 1; let tok = struct { type: "int", value: "0" }; std::array_push(toks, tok); } else if text[i] == '+' { i += 1; let tok = struct { type: "+", value: "+" }; std::array_push(toks, tok); } else if text[i] == '-' { i += 1; let tok = struct { type: "-", value: "-" }; std::array_push(toks, tok); } else if text[i] == '*' { i += 1; let tok = struct { type: "*", value: "*" }; std::array_push(toks, tok); } else if text[i] == '/' { i += 1; let tok = struct { type: "/", value: "/" }; std::array_push(toks, tok); } else if text[i] == '(' { i += 1; let tok = struct { type: "(", value: "(" }; std::array_push(toks, tok); } else if text[i] == ')' { i += 1; let tok = struct { type: ")", value: ")" }; std::array_push(toks, tok); } else { std::println("error: illegal character '" + std::ctos(text[i]) + "'"); i += 1; } } toks } type_alias Calc: struct { toks: [Tok], toks_len: int, i: int, }; fn calc_new(text: string) -> Calc { let toks = lex(text); let toks_len = std::array_length(toks); struct { toks: toks, toks_len: toks_len, i: 0 } } fn calc_expr(self: Calc) -> int { calc_add_sub(self) } fn calc_add_sub(self: Calc) -> int { let left = calc_mul_div(self); loop { if self.toks[self.i].type == "+" { self.i += 1; let right = calc_mul_div(self); left = left + right; } else if self.toks[self.i].type == "-" { self.i += 1; let right = calc_mul_div(self); left = left - right; } else { break; } } left } fn calc_mul_div(self: Calc) -> int { let left = calc_unary(self); loop { if self.toks[self.i].type == "*" { self.i += 1; let right = calc_unary(self); left = left * right; } else if self.toks[self.i].type == "/" { self.i += 1; let right = calc_unary(self); left = left / right; } else { break; } } left } fn calc_unary(self: Calc) -> int { if self.toks[self.i].type == "-" { self.i += 1; let subject = calc_unary(self); -subject } else { calc_operand(self) } } fn calc_operand(self: Calc) -> int { if self.i >= self.toks_len { std::println("error: expected expr"); 0 } else if self.toks[self.i].type == "int" { let val = std::stoi(self.toks[self.i].value); self.i += 1; val } else if self.toks[self.i].type == "(" { self.i += 1; let val = calc_expr(self); if self.i >= self.toks_len or self.toks[self.i].type != ")" { std::println("error: missing ')'"); return 0; } self.i += 1; val } else { std::println("error: expected expr"); self.i += 1; 0 } } fn main() { loop { let line = std::input("> "); if line == "exit" { break; } let calc = calc_new(line); let val = calc_expr(calc); std::println(line); } }