Решение на Basic BASIC от Станислав Христов

Обратно към всички решения

Към профила на Станислав Христов

Резултати

  • 17 точки от тестове
  • 0 бонус точки
  • 17 точки общо
  • 13 успешни тест(а)
  • 2 неуспешни тест(а)

Код

use std::io::{self, Write, Read};
use std::io::BufReader;
use std::io::BufRead;
use std::collections::HashMap;
#[derive(Debug)]
pub enum InterpreterError {
IoError(io::Error),
UnknownVariable { name: String },
NotANumber { value: String },
SyntaxError { code: String },
RuntimeError { line_number: u16, message: String },
}
pub struct Line {
number: u16,
tokens: Vec<String>
}
impl Line {
pub fn new(number: u16, tokens: Vec<String>) -> Self {
Line { number: number, tokens: tokens }
}
}
pub struct Interpreter<'a, R: Read, W: Write> {
input: BufReader<R>,
output: &'a mut W,
lines: HashMap<u16, Line>,
curr_line: u16,
variables: HashMap<String, u16>
}
impl<'a, R: Read, W: Write> Interpreter<'a, R, W> {
pub fn new(input: R, output: &'a mut W) -> Self {
Interpreter { input: BufReader::new(input),
output: output,
lines: HashMap::new(),
curr_line: 0,
variables: HashMap::new()
}
}
}
impl<'a, R: Read, W: Write> Interpreter<'a, R, W> {
pub fn add(&mut self, code: &str) -> Result<(), InterpreterError> {
let mut tokenized_str = code.split_whitespace();
let curr_line: u16;
let mut code_tokens: Vec<String> = Vec::new();
// Get the line number
match tokenized_str.next() {
Some(num_str) => {
match num_str.parse::<u16>() {
Ok(num) => { curr_line = num },
Err(_err) => { return Err(InterpreterError::SyntaxError { code: String::from(code) })}
}
},
None => { return Err(InterpreterError::SyntaxError { code: String::from(code) }) }
}
// Get command
match tokenized_str.next() {
Some(command) => {
if command == "IF" || command == "GOTO" || command == "PRINT" || command == "READ" {
code_tokens.push(String::from(command));
} else {
return Err(InterpreterError::SyntaxError { code: String::from(code) })
}
},
None => { return Err(InterpreterError::SyntaxError { code: String::from(code) })}
}
// Push rest of tokens
for token in tokenized_str {
code_tokens.push(String::from(token));
}
// Validations
// Check for too many arguments for PRINT and READ
if code_tokens[0] == "PRINT" || code_tokens[0] == "READ" {
if code_tokens.len() != 2 {
return Err(InterpreterError::SyntaxError { code: String::from(code) })
}
// Check if variable starts with upper case
if code_tokens[0] == "READ" {
if !code_tokens[1].chars().next().unwrap().is_uppercase() {
return Err(InterpreterError::SyntaxError { code: String::from(code) })
}
}
}
// Check for GOTO
if code_tokens[0] == "GOTO" {
if code_tokens.len() != 2 {
return Err(InterpreterError::SyntaxError { code: String::from(code) })
}
// let mut chars = code_tokens[1].chars();
// chars.next_back();
// code_tokens[1] = String::from(chars.as_str());
match code_tokens[1].parse::<u16>() {
Ok(_num) => {},
Err(_err) => { return Err(InterpreterError::SyntaxError { code: String::from(code) })}
}
}
// Check for IF
if code_tokens[0] == "IF" {
if code_tokens.len() != 6 {
println!("len");
return Err(InterpreterError::SyntaxError { code: String::from(code) })
}
if code_tokens[4] != "GOTO" {
println!("goto");
return Err(InterpreterError::SyntaxError { code: String::from(code) })
}
// let mut chars = code_tokens[5].chars();
// chars.next_back();
// code_tokens[5] = String::from(chars.as_str());
match code_tokens[5].parse::<u16>() {
Ok(_num) => {},
Err(_err) => { println!("parse error"); return Err(InterpreterError::SyntaxError { code: String::from(code) })}
}
}
let line = Line {number: curr_line, tokens: code_tokens};
// If first time inserting line with such number, insert a placeholder and update the line after that.
// If line with the same line number already exists, this will return a mutable refence, which we can update.
*self.lines.entry(curr_line).or_insert(Line {number: 0, tokens: Vec::new()}) = line;
Ok(())
}
}
impl<'a, R: Read, W: Write> Interpreter<'a, R, W> {
pub fn eval_value(&self, value: &str) -> Result<u16, InterpreterError> {
if value.chars().next().unwrap().is_uppercase() {
if self.variables.contains_key(value) {
// Safe unwrap, since we check that the key is there
let val = self.variables.get(value).unwrap();
return Ok(*val);
} else {
return Err(InterpreterError::UnknownVariable { name: String::from(value) })
}
} else {
match value.parse::<u16>() {
Ok(num) => { return Ok(num); },
Err(_err) => { return Err(InterpreterError::NotANumber { value: String::from(value) })}
}
}
}
}
impl<'a, R: Read, W: Write> Interpreter<'a, R, W> {
fn check_command(&self, line: &Line) -> Result<String, InterpreterError> {
let code = line.tokens.join(" ");
if line.tokens[0] != "PRINT" && line.tokens[0] != "READ" &&
line.tokens[0] != "GOTO" && line.tokens[0] != "IF" {
return Err(InterpreterError::SyntaxError { code: code })
}
Ok(line.tokens[0].clone())
}
fn command_print(&mut self, line: &Line) -> Result<(), InterpreterError>{
if line.tokens[0] != "PRINT" {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("PRINT was called on the wrong line") })
}
if line.tokens.len() != 2 {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("Malformed line. Incorrect number of arguments") })
}
// Check if variable
if line.tokens[1].chars().next().unwrap().is_uppercase() {
let res = self.eval_value(line.tokens[1].as_str());
match res {
Ok(num) => {
match write!(self.output, "{}\n", num) {
Ok(_) => return Ok(()),
Err(err) => return Err(InterpreterError::IoError(err))
}
},
Err(err) => {
return Err(err);
}
}
} else {
// Check if number
match line.tokens[1].parse::<u16>() {
Ok(num) => {
match write!(self.output, "{}\n", num) {
Ok(_) => return Ok(()),
Err(err) => return Err(InterpreterError::IoError(err))
}
},
Err(_err) => {
// If not number, print as string
match write!(self.output, "{}\n", line.tokens[1]) {
Ok(_) => return Ok(()),
Err(err) => return Err(InterpreterError::IoError(err))
}
}
}
}
}
fn command_read(&mut self, line: &Line) -> Result<(), InterpreterError> {
if line.tokens[0] != "READ" {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("READ was called on the wrong line") })
}
if line.tokens.len() != 2 {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("Malformed line. Incorrect number of arguments") })
}
// Check if variable name starts with capital letter
if line.tokens[1].chars().next().unwrap().is_uppercase() {
let mut str_line = String::new();
let len = self.input.read_line(&mut str_line);
// Remove newline
let mut chars = str_line.chars();
chars.next_back();
str_line = String::from(chars.as_str());
//println!("READ LINE: {}\n", str_line);
match len {
Ok(_) => {
match str_line.parse::<u16>() {
Ok(num) => {
//print!("PARSE READ LINE {}\n", num);
self.variables.insert(line.tokens[1].clone(), num);
return Ok(())
},
Err(_err) => {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("We expect to read a u16 with READ") })
}
}
},
Err(err) => return Err(InterpreterError::IoError(err))
}
} else {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("Variables should start with an uppercase letter") })
}
}
fn command_goto(&mut self, line: &Line) -> Result<u16, InterpreterError> {
if line.tokens[0] != "GOTO" {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("GOTO was called on the wrong line") })
}
if line.tokens.len() != 2 {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("Malformed line. Incorrect number of arguments") })
}
match line.tokens[1].parse::<u16>() {
Ok(num) => {
if self.lines.contains_key(&num) {
return Ok(num);
} else {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("Invalid line passed to GOTO") })
}
},
Err(_err) => {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("The value passed to GOTO should be a valid u16") })
}
}
}
fn command_if(&mut self, line: &Line) -> Result<(), InterpreterError> {
if line.tokens[0] != "IF" {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("IF was called on the wrong line") })
}
if line.tokens.len() != 6 {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("Malformed line. Incorrect number of arguments") })
}
if line.tokens[4] != "GOTO" {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("Malformed line. 4th argument should be GOTO") })
}
if line.tokens[2] != "<" && line.tokens[2] != ">" && line.tokens[2] != "==" {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("Invalid operator. Possible operators are '>', '<', '=='") })
}
let first_var = self.eval_value(line.tokens[1].as_str())?;
let second_var = self.eval_value(line.tokens[3].as_str())?;
let should_goto: bool;
if line.tokens[2] == "<" {
should_goto = first_var < second_var;
} else if line.tokens[2] == ">" {
should_goto = first_var > second_var;
} else {
should_goto = first_var == second_var;
}
if should_goto {
let mut goto_tokens: Vec<String> = line.tokens.clone().into_iter().rev().take(2).collect();
goto_tokens = goto_tokens.into_iter().rev().collect();
let new_line = Line {number: line.number, tokens: goto_tokens};
let new_current_line = self.command_goto(&new_line)?;
self.curr_line = new_current_line;
}
Ok(())
}
}
impl<'a, R: Read, W: Write> Interpreter<'a, R, W> {
pub fn run(&mut self) -> Result<(), InterpreterError> {
let mut finished: bool = false;
// Get a sorted vector from the lines hashmap
let mut sorted_vector: Vec<(u16, Line)> = Vec::new();
for (key, value) in self.lines.iter() {
sorted_vector.push((*key, Line {number: *key, tokens: value.tokens.clone()}));
}
sorted_vector.sort_by_key(|a| a.0);
let last_line = sorted_vector.iter().next_back().unwrap();
while !finished {
for (key, value) in sorted_vector.iter().skip(self.curr_line as usize) { //.skip(self.curr_line as usize) {
self.curr_line = *key;
println!("{}", self.curr_line);
let str: String = self.check_command(value).unwrap();
if str == "PRINT" {
self.command_print(value)?;
continue;
}
if str == "READ" {
self.command_read(value)?;
continue;
}
if str == "GOTO" {
let line_number = self.command_goto(value)?;
let index = sorted_vector.iter().position(|a| a.0 == line_number).unwrap();
self.curr_line = index as u16;
break;
}
if str == "IF" {
let old_line = self.curr_line;
self.command_if(value)?;
if self.curr_line != old_line {
let index = sorted_vector.iter().position(|a| a.0 == self.curr_line).unwrap();
self.curr_line = index as u16;
break;
}
}
}
if self.curr_line == last_line.0 {
finished = true;
}
}
Ok(())
}
}

Лог от изпълнението

Compiling solution v0.1.0 (/tmp/d20230111-3772066-1jz44se/solution)
    Finished test [unoptimized + debuginfo] target(s) in 1.64s
     Running tests/solution_test.rs (target/debug/deps/solution_test-0edbea2040daef01)

running 15 tests
test solution_test::test_basic_if ... ok
test solution_test::test_basic_goto ... ok
test solution_test::test_basic_print ... ok
test solution_test::test_basic_input ... ok
test solution_test::test_erroring_goto ... ok
test solution_test::test_basic_read ... ok
test solution_test::test_io_error_read ... ok
test solution_test::test_io_error_write ... ok
test solution_test::test_full_program ... FAILED
test solution_test::test_line_order_and_overwriting ... ok
test solution_test::test_print_vars_and_strings ... ok
test solution_test::test_print_cyrillic ... ok
test solution_test::test_runtime_errors ... FAILED
test solution_test::test_syntax_errors_2 ... ok
test solution_test::test_syntax_errors_1 ... ok

failures:

---- solution_test::test_full_program stdout ----
10
20
30
200
210
10
20
100
110
10
20
30
40
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: RuntimeError { line_number: 40, message: "Invalid operator. Possible operators are '>', '<', '=='" }', tests/solution_test.rs:245:31
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'solution_test::test_full_program' panicked at 'called `Result::unwrap()` on an `Err` value: RuntimeError { line_number: 40, message: "Invalid operator. Possible operators are '>', '<', '=='" }', tests/solution_test.rs:230:5

---- solution_test::test_runtime_errors stdout ----
10
11
thread '<unnamed>' panicked at 'Expression Err(UnknownVariable { name: "A" }) does not match the pattern "Err(InterpreterError::RuntimeError { line_number: 11, .. })"', tests/solution_test.rs:307:9
thread 'solution_test::test_runtime_errors' panicked at 'Expression Err(UnknownVariable { name: "A" }) does not match the pattern "Err(InterpreterError::RuntimeError { line_number: 11, .. })"', tests/solution_test.rs:301:5


failures:
    solution_test::test_full_program
    solution_test::test_runtime_errors

test result: FAILED. 13 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

error: test failed, to rerun pass `--test solution_test`

История (2 версии и 0 коментара)

Станислав качи първо решение на 09.01.2023 14:47 (преди над 2 години)

Станислав качи решение на 09.01.2023 20:36 (преди над 2 години)

use std::io::{self, Write, Read};
use std::io::BufReader;
use std::io::BufRead;
use std::collections::HashMap;
#[derive(Debug)]
pub enum InterpreterError {
IoError(io::Error),
UnknownVariable { name: String },
NotANumber { value: String },
SyntaxError { code: String },
RuntimeError { line_number: u16, message: String },
}
pub struct Line {
number: u16,
tokens: Vec<String>
}
impl Line {
pub fn new(number: u16, tokens: Vec<String>) -> Self {
Line { number: number, tokens: tokens }
}
}
pub struct Interpreter<'a, R: Read, W: Write> {
input: BufReader<R>,
output: &'a mut W,
lines: HashMap<u16, Line>,
curr_line: u16,
variables: HashMap<String, u16>
}
impl<'a, R: Read, W: Write> Interpreter<'a, R, W> {
pub fn new(input: R, output: &'a mut W) -> Self {
Interpreter { input: BufReader::new(input),
output: output,
lines: HashMap::new(),
curr_line: 0,
variables: HashMap::new()
}
}
}
impl<'a, R: Read, W: Write> Interpreter<'a, R, W> {
pub fn add(&mut self, code: &str) -> Result<(), InterpreterError> {
let mut tokenized_str = code.split_whitespace();
let curr_line: u16;
let mut code_tokens: Vec<String> = Vec::new();
// Get the line number
match tokenized_str.next() {
Some(num_str) => {
match num_str.parse::<u16>() {
Ok(num) => { curr_line = num },
Err(_err) => { return Err(InterpreterError::SyntaxError { code: String::from(code) })}
}
},
None => { return Err(InterpreterError::SyntaxError { code: String::from(code) }) }
}
// Get command
match tokenized_str.next() {
Some(command) => {
if command == "IF" || command == "GOTO" || command == "PRINT" || command == "READ" {
code_tokens.push(String::from(command));
} else {
return Err(InterpreterError::SyntaxError { code: String::from(code) })
}
},
None => { return Err(InterpreterError::SyntaxError { code: String::from(code) })}
}
// Push rest of tokens
for token in tokenized_str {
code_tokens.push(String::from(token));
}
// Validations
// Check for too many arguments for PRINT and READ
if code_tokens[0] == "PRINT" || code_tokens[0] == "READ" {
if code_tokens.len() != 2 {
return Err(InterpreterError::SyntaxError { code: String::from(code) })
}
// Check if variable starts with upper case
if code_tokens[0] == "READ" {
if !code_tokens[1].chars().next().unwrap().is_uppercase() {
return Err(InterpreterError::SyntaxError { code: String::from(code) })
}
}
}
// Check for GOTO
if code_tokens[0] == "GOTO" {
if code_tokens.len() != 2 {
return Err(InterpreterError::SyntaxError { code: String::from(code) })
}
// let mut chars = code_tokens[1].chars();
// chars.next_back();
// code_tokens[1] = String::from(chars.as_str());
match code_tokens[1].parse::<u16>() {
Ok(_num) => {},
Err(_err) => { return Err(InterpreterError::SyntaxError { code: String::from(code) })}
}
}
// Check for IF
if code_tokens[0] == "IF" {
if code_tokens.len() != 6 {
println!("len");
return Err(InterpreterError::SyntaxError { code: String::from(code) })
}
if code_tokens[4] != "GOTO" {
println!("goto");
return Err(InterpreterError::SyntaxError { code: String::from(code) })
}
// let mut chars = code_tokens[5].chars();
// chars.next_back();
// code_tokens[5] = String::from(chars.as_str());
match code_tokens[5].parse::<u16>() {
Ok(_num) => {},
Err(_err) => { println!("parse error"); return Err(InterpreterError::SyntaxError { code: String::from(code) })}
}
}
let line = Line {number: curr_line, tokens: code_tokens};
// If first time inserting line with such number, insert a placeholder and update the line after that.
// If line with the same line number already exists, this will return a mutable refence, which we can update.
*self.lines.entry(curr_line).or_insert(Line {number: 0, tokens: Vec::new()}) = line;
Ok(())
}
}
impl<'a, R: Read, W: Write> Interpreter<'a, R, W> {
pub fn eval_value(&self, value: &str) -> Result<u16, InterpreterError> {
if value.chars().next().unwrap().is_uppercase() {
if self.variables.contains_key(value) {
// Safe unwrap, since we check that the key is there
let val = self.variables.get(value).unwrap();
return Ok(*val);
} else {
return Err(InterpreterError::UnknownVariable { name: String::from(value) })
}
} else {
match value.parse::<u16>() {
Ok(num) => { return Ok(num); },
Err(_err) => { return Err(InterpreterError::NotANumber { value: String::from(value) })}
}
}
}
}
impl<'a, R: Read, W: Write> Interpreter<'a, R, W> {
fn check_command(&self, line: &Line) -> Result<String, InterpreterError> {
let code = line.tokens.join(" ");
if line.tokens[0] != "PRINT" && line.tokens[0] != "READ" &&
line.tokens[0] != "GOTO" && line.tokens[0] != "IF" {
return Err(InterpreterError::SyntaxError { code: code })
}
Ok(line.tokens[0].clone())
}
fn command_print(&mut self, line: &Line) -> Result<(), InterpreterError>{
if line.tokens[0] != "PRINT" {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("PRINT was called on the wrong line") })
}
if line.tokens.len() != 2 {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("Malformed line. Incorrect number of arguments") })
}
// Check if variable
if line.tokens[1].chars().next().unwrap().is_uppercase() {
let res = self.eval_value(line.tokens[1].as_str());
match res {
Ok(num) => {
match write!(self.output, "{}\n", num) {
Ok(_) => return Ok(()),
Err(err) => return Err(InterpreterError::IoError(err))
}
},
Err(err) => {
return Err(err);
}
}
} else {
// Check if number
match line.tokens[1].parse::<u16>() {
Ok(num) => {
match write!(self.output, "{}\n", num) {
Ok(_) => return Ok(()),
Err(err) => return Err(InterpreterError::IoError(err))
}
},
Err(_err) => {
// If not number, print as string
match write!(self.output, "{}\n", line.tokens[1]) {
Ok(_) => return Ok(()),
Err(err) => return Err(InterpreterError::IoError(err))
}
}
}
}
}
fn command_read(&mut self, line: &Line) -> Result<(), InterpreterError> {
if line.tokens[0] != "READ" {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("READ was called on the wrong line") })
}
if line.tokens.len() != 2 {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("Malformed line. Incorrect number of arguments") })
}
// Check if variable name starts with capital letter
if line.tokens[1].chars().next().unwrap().is_uppercase() {
let mut str_line = String::new();
let len = self.input.read_line(&mut str_line);
// Remove newline
let mut chars = str_line.chars();
chars.next_back();
str_line = String::from(chars.as_str());
//println!("READ LINE: {}\n", str_line);
match len {
Ok(_) => {
match str_line.parse::<u16>() {
Ok(num) => {
//print!("PARSE READ LINE {}\n", num);
self.variables.insert(line.tokens[1].clone(), num);
return Ok(())
},
Err(_err) => {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("We expect to read a u16 with READ") })
}
}
},
Err(err) => return Err(InterpreterError::IoError(err))
}
} else {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("Variables should start with an uppercase letter") })
}
}
fn command_goto(&mut self, line: &Line) -> Result<u16, InterpreterError> {
if line.tokens[0] != "GOTO" {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("GOTO was called on the wrong line") })
}
if line.tokens.len() != 2 {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("Malformed line. Incorrect number of arguments") })
}
match line.tokens[1].parse::<u16>() {
Ok(num) => {
if self.lines.contains_key(&num) {
return Ok(num);
} else {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("Invalid line passed to GOTO") })
}
},
Err(_err) => {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("The value passed to GOTO should be a valid u16") })
}
}
}
fn command_if(&mut self, line: &Line) -> Result<(), InterpreterError> {
if line.tokens[0] != "IF" {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("IF was called on the wrong line") })
}
if line.tokens.len() != 6 {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("Malformed line. Incorrect number of arguments") })
}
if line.tokens[4] != "GOTO" {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("Malformed line. 4th argument should be GOTO") })
}
if line.tokens[2] != "<" && line.tokens[2] != ">" && line.tokens[2] != "==" {
return Err(InterpreterError::RuntimeError { line_number: line.number, message: String::from("Invalid operator. Possible operators are '>', '<', '=='") })
}
let first_var = self.eval_value(line.tokens[1].as_str())?;
let second_var = self.eval_value(line.tokens[3].as_str())?;
let should_goto: bool;
if line.tokens[2] == "<" {
should_goto = first_var < second_var;
} else if line.tokens[2] == ">" {
should_goto = first_var > second_var;
} else {
should_goto = first_var == second_var;
}
if should_goto {
let mut goto_tokens: Vec<String> = line.tokens.clone().into_iter().rev().take(2).collect();
goto_tokens = goto_tokens.into_iter().rev().collect();
let new_line = Line {number: line.number, tokens: goto_tokens};
let new_current_line = self.command_goto(&new_line)?;
self.curr_line = new_current_line;
}
Ok(())
}
}
impl<'a, R: Read, W: Write> Interpreter<'a, R, W> {
pub fn run(&mut self) -> Result<(), InterpreterError> {
let mut finished: bool = false;
// Get a sorted vector from the lines hashmap
let mut sorted_vector: Vec<(u16, Line)> = Vec::new();
for (key, value) in self.lines.iter() {
sorted_vector.push((*key, Line {number: *key, tokens: value.tokens.clone()}));
}
sorted_vector.sort_by_key(|a| a.0);
let last_line = sorted_vector.iter().next_back().unwrap();
while !finished {
- for (key, value) in sorted_vector.iter() {
+ for (key, value) in sorted_vector.iter().skip(self.curr_line as usize) { //.skip(self.curr_line as usize) {
self.curr_line = *key;
+ println!("{}", self.curr_line);
let str: String = self.check_command(value).unwrap();
if str == "PRINT" {
self.command_print(value)?;
continue;
}
if str == "READ" {
self.command_read(value)?;
continue;
}
if str == "GOTO" {
let line_number = self.command_goto(value)?;
let index = sorted_vector.iter().position(|a| a.0 == line_number).unwrap();
self.curr_line = index as u16;
break;
}
if str == "IF" {
let old_line = self.curr_line;
self.command_if(value)?;
if self.curr_line != old_line {
+ let index = sorted_vector.iter().position(|a| a.0 == self.curr_line).unwrap();
+ self.curr_line = index as u16;
break;
}
}
}
if self.curr_line == last_line.0 {
finished = true;
}
}
Ok(())
}
}