diff --git a/info4/kapitel-8/Interpreter/test_goto_interpreter.py b/info4/kapitel-8/Interpreter/test_goto_interpreter.py new file mode 100644 index 0000000000000000000000000000000000000000..3510c713abc69bc12f0aecf3ea2a5b2cf819fd3f --- /dev/null +++ b/info4/kapitel-8/Interpreter/test_goto_interpreter.py @@ -0,0 +1,189 @@ +from gotointerpreter import interpret +from unittest import mock +from unittest import TestCase + + +def input_continue(prompt): + return "" + + +def input_exit(prompt): + return "EXIT" + + +def init_without_tokens(self, regex_to_token, program): + self.regex_to_token = {} + self.program = program + self.current_position = 0 + + +class GOTOInterpreterTest(TestCase): + def test_assignment_default_zero(self): + self.assertEqual(interpret('M1:x0:=x0 + 0;M2:HALT;'), 0) + self.assertEqual(interpret('M1:x0:=x1 + 0;M2:HALT;'), 0) + self.assertEqual(interpret('M1:x0:=x2 + 0;M2:HALT;'), 0) + + def test_assignment_non_negative(self): + self.assertEqual(interpret('M1:x0:=x0-1;M2:HALT;'), 0) + self.assertEqual(interpret('M1:x0:=x1-1;M2:HALT;'), 0) + self.assertEqual(interpret('M1:x0:=x2-6;M2:HALT;'), 0) + + def test_assignment_number(self): + self.assertEqual(interpret('M1:x0:=5;M2:HALT;'), 5) + self.assertEqual(interpret('M1:x0:=2;M2:HALT;'), 2) + self.assertEqual(interpret('M1:x0:=3;M2:HALT;'), 3) + + def test_assignment_variable(self): + self.assertEqual(interpret('M1:x0:=x0+1;M2:HALT;'), 1) + self.assertEqual(interpret('M1:x0:= 5; M2:x0:=x0-1; M3:HALT;'), 4) + self.assertEqual(interpret('M1:x0:=x1-1; M2:x0:=x0+1; M3:HALT;'), 1) + + def test_assignment_wrong_syntax(self): + with self.assertRaises(SyntaxError): + interpret('M1:x1:=x2;M2:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1:x1:=0+x2;M2:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1:x5:=-1+x4;M2:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1:x5:=-x3+x1;M2:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1:x5:=x1-x3;M2:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1:x2:=x1+x4;M2:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1:x2:=x1+2;;M2:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1:x1:=c;M2:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1:xi:=2;M2:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1:x0:=xj+1;M2:HALT;') + + def test_goto_skip_lines(self): + self.assertEqual(interpret('M1:x0:=2;M2:GOTO M4;M3:x0:=0;M4:HALT;'), 2) + self.assertEqual(interpret('M1:x0:=3;M2:GOTO M5;M3:GOTO M1;M4:x0:=5;M5:HALT;'), 3) + self.assertEqual(interpret('M1:GOTO M3;M2:x0:=x2+5;M3:HALT;'), 0) + + def test_if(self): + self.assertEqual(interpret('M1:x2:=10;' + + 'M2:IF x2=0 THEN GOTO M6;' + + 'M3:x0:=x0+1;M4:x2:=x2-1;' + + 'M5:GOTO M2; M6:HALT;'), 10) + self.assertEqual(interpret('M1:IF x0=5 THEN GOTO M4;M2:IF x0=2 THEN GOTO M4;M3:x0:=x0+1;M4:HALT;'), 1) + + def test_syntax_missing_operator(self): + with self.assertRaises(SyntaxError): + interpret('M1:x0:=x1 2;M2:HALT;') + + def test_markers_start_with_one(self): + with self.assertRaises(SyntaxError): + interpret('M0:x0:=2;M1:HALT;') + with self.assertRaises(SyntaxError): + interpret('M2:x0:=2;M3:HALT;') + with self.assertRaises(SyntaxError): + interpret('M10:x0:=2;M11:HALT;') + + def test_markers_increment_by_one(self): + with self.assertRaises(SyntaxError): + interpret('M1:x0:=3;M3:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1:x0:=2;M1:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1: GOTO M3; M3:HALT;') + + def test_linebreaks(self): + self.assertEqual(interpret(''' + M1:x1:=2; + M2: IF x1=2 THEN GOTO M4; + M3:HALT; + M4:GOTO M3;'''), 0) + + @mock.patch('loopinterpreter.input', side_effect=input_continue) + def test_break(self, custom_input): + self.assertEqual(interpret('M1:x0:=2;BREAK M2:HALT;'), 2) + + @mock.patch('loopinterpreter.input', side_effect=input_exit) + def test_break_exit(self, custom_input): + self.assertEqual(interpret('M1:GOTO M1; BREAK'), -1) + + def test_assignment_missing_tokens(self): + with self.assertRaises(SyntaxError): + interpret('M1: x0') + with self.assertRaises(SyntaxError): + interpret('M1: x1 x2+2;') + with self.assertRaises(SyntaxError): + interpret('M1: x1 := x2+2 M2') + with self.assertRaises(SyntaxError): + interpret('M1: GOTO M3; M2:x1 x2+0; M3: HALT;') + with self.assertRaises(SyntaxError): + interpret('M1:GOTO M3; M2:x1:=2 M3: HALT;') + with self.assertRaises(SyntaxError): + interpret('M1:GOTO M3; M2: x1:= M3: HALT;') + with self.assertRaises(SyntaxError): + interpret('M1: GOTO M3; M2: x1 := x2 M3: HALT;') + with self.assertRaises(SyntaxError): + interpret('M1: GOTO M3; M2: x1 := x2 - M3: HALT;') + with self.assertRaises(SyntaxError): + interpret('M1: GOTO M3; M2: x1:= x2 + 1 M3: HALT;') + + def test_goto_missing_tokens(self): + with self.assertRaises(SyntaxError): + interpret('M1:GOTO :HALT;') + with self.assertRaises(SyntaxError): + interpret('M1: GOTO M2' + + 'M2:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1:GOTO M3; M2: GOTO :HALT; M3: HALT;') + with self.assertRaises(SyntaxError): + interpret('M1: GOTO M3;' + + 'M2: GOTO M3' + + 'M3:HALT;') + + def test_goto_jump_not_defined(self): + with self.assertRaises(SyntaxError): + interpret('M1: GOTO M2;') + with self.assertRaises(SyntaxError): + interpret('M1:GOTO M3; M2: GOTO M4; M3:HALT;') + + def test_halt_missing_tokens(self): + with self.assertRaises(SyntaxError): + interpret('M1:HALT M2:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1:GOTO M3; M2: HALT M3:HALT;') + + def test_if_missing_tokens(self): + with self.assertRaises(SyntaxError): + interpret('M1: IF THEN GOTO M2; M2:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1: IF x1 THEN GOTO M2; M2:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1: IF x2 = THEN GOTO M2; M2:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1: IF x0 = 0 GOTO M2; M2:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1: IF x3 = 5 THEN M2; M2:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1:GOTO M3; M2: IF THEN GOTO M3; M3:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1:GOTO M3; M2: IF x1 THEN GOTO M2; M3:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1:GOTO M3; M2: IF x2 = THEN GOTO M2; M3:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1:GOTO M3; M2: IF x0 = 0 GOTO M2; M3:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1:GOTO M3; M2: IF x3 = 5 THEN M2; M3:HALT;') + + def test_line_missing_tokens(self): + with self.assertRaises(SyntaxError): + interpret('M1 GOTO M2; M2: HALT;') + with self.assertRaises(SyntaxError): + interpret('M1: GOTO M3; GOTO M3; M3:HALT;') + with self.assertRaises(SyntaxError): + interpret('M1: GOTO M3; M2 GOTO M3; M3: HALT;') + with self.assertRaises(SyntaxError): + interpret('M1: GOTO M3; M2: M3; M3: HALT;') + + def test_end_without_halt(self): + with self.assertRaises(SyntaxError): + interpret('M1: x0:=2;')