diff --git a/Module8/Gplex.exe b/Module8/Gplex.exe
new file mode 100644
index 0000000000000000000000000000000000000000..51a522e221f5ca52cc934933e08745f1653a98b5
Binary files /dev/null and b/Module8/Gplex.exe differ
diff --git a/Module8/Gppg.exe b/Module8/Gppg.exe
new file mode 100644
index 0000000000000000000000000000000000000000..edca401986741541f14b7d4bd89adc57802327a2
Binary files /dev/null and b/Module8/Gppg.exe differ
diff --git a/Module8/ParserGenerator.csproj b/Module8/ParserGenerator.csproj
index 089ed8de3f6a6488d4cb80752a66be9bc2120c2d..04a1ba27de72ba30986532878db68afd0b6cbf7e 100644
--- a/Module8/ParserGenerator.csproj
+++ b/Module8/ParserGenerator.csproj
@@ -1,6 +1,6 @@
 п»ї<?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="..\packages\NUnit3TestAdapter.4.2.1\build\net35\NUnit3TestAdapter.props" Condition="Exists('..\packages\NUnit3TestAdapter.4.2.1\build\net35\NUnit3TestAdapter.props')" />
+  <Import Project="..\packages\NUnit3TestAdapter.4.3.1\build\net35\NUnit3TestAdapter.props" Condition="Exists('..\packages\NUnit3TestAdapter.4.3.1\build\net35\NUnit3TestAdapter.props')" />
   <Import Project="..\packages\NUnit.3.13.3\build\NUnit.props" Condition="Exists('..\packages\NUnit.3.13.3\build\NUnit.props')" />
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -101,7 +101,7 @@
       <ErrorText>Данный проект ссылается на пакеты NuGet, отсутствующие на этом компьютере. Используйте восстановление пакетов NuGet, чтобы скачать их.  Дополнительную информацию см. по адресу: http://go.microsoft.com/fwlink/?LinkID=322105. Отсутствует следующий файл: {0}.</ErrorText>
     </PropertyGroup>
     <Error Condition="!Exists('..\packages\NUnit.3.13.3\build\NUnit.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NUnit.3.13.3\build\NUnit.props'))" />
-    <Error Condition="!Exists('..\packages\NUnit3TestAdapter.4.2.1\build\net35\NUnit3TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NUnit3TestAdapter.4.2.1\build\net35\NUnit3TestAdapter.props'))" />
+    <Error Condition="!Exists('..\packages\NUnit3TestAdapter.4.3.1\build\net35\NUnit3TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NUnit3TestAdapter.4.3.1\build\net35\NUnit3TestAdapter.props'))" />
   </Target>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
diff --git a/Module8/ProgramTree.cs b/Module8/ProgramTree.cs
index 500e94046a9d2b86cf850b1525f5933157af86bc..4adb6f182de0a7d54445510f8a445db2d1647fd9 100644
--- a/Module8/ProgramTree.cs
+++ b/Module8/ProgramTree.cs
@@ -146,13 +146,13 @@ namespace ProgramTree
     public class IfNode : StatementNode
     {
         public ExprNode expr;
-        public StatementNode ifTrue, ifFalse;
+        public StatementNode True, False;
 
-        public IfNode(ExprNode expr, StatementNode ifTrue, StatementNode ifFalse = null)
+        public IfNode(ExprNode expr, StatementNode True, StatementNode False = null)
         {
             this.expr = expr;
-            this.ifTrue = ifTrue;
-            this.ifFalse = ifFalse;
+            this.True = True;
+            this.False = False;
         }
 
         public override void Visit(Visitor v)
@@ -160,4 +160,39 @@ namespace ProgramTree
             v.VisitIfNode(this);
         }
     }
+
+	public class WhileNode : StatementNode
+	{
+		public ExprNode Expr { get; set; }
+		public StatementNode Stat { get; set; }
+		public WhileNode(ExprNode expr, StatementNode stat)
+		{
+			this.Expr = expr;
+			this.Stat = stat;
+		}
+		public override void Visit(Visitor v)
+		{
+			v.VisitWhileNode(this);
+		}
+	}
+
+	public class RepeatNode : StatementNode
+	{
+		public List<StatementNode> StList = new List<StatementNode>();
+		public ExprNode Expr { get; set; }
+		public RepeatNode(StatementNode stat, ExprNode expr)
+		{
+			Add(stat);
+			Expr = expr;
+		}
+		public void Add(StatementNode stat)
+		{
+			StList.Add(stat);
+		}
+		public override void Visit(Visitor v)
+		{
+			v.VisitRepeatNode(this);
+		}
+	}
+
 }
\ No newline at end of file
diff --git a/Module8/SimpleLex.cs b/Module8/SimpleLex.cs
index 124489e2d753e8ffee406427501b40410d8779db..ee87c3d102cd19bcb0495759accefc95feafc40c 100644
--- a/Module8/SimpleLex.cs
+++ b/Module8/SimpleLex.cs
@@ -1,14 +1,10 @@
 //
 //  This CSharp output file generated by Gardens Point LEX
-//  Gardens Point LEX (GPLEX) is Copyright (c) John Gough, QUT 2006-2014.
-//  Output produced by GPLEX is the property of the user.
-//  See accompanying file GPLEXcopyright.rtf.
-//
-//  GPLEX Version:  1.2.2
-//  Machine:  MAINHOMEPC2
-//  DateTime: 30.09.2018 18:23:21
-//  UserName: someone
-//  GPLEX input file <SimpleLex.lex - 30.09.2018 18:22:46>
+//  Version:  1.1.3.301
+//  Machine:  MIL8A-202A-05
+//  DateTime: 28.11.2022 13:27:34
+//  UserName: user
+//  GPLEX input file <SimpleLex.lex>
 //  GPLEX frame file <embedded resource>
 //
 //  Option settings: unicode, parser, minimize
@@ -17,8 +13,8 @@
 //
 
 //
-// Revised backup code
-// Version 1.2.1 of 24-June-2013
+// Experimental embedded frame
+// Version 1.1.3 of 18-April-2010
 //
 //
 #define BACKUP
@@ -127,8 +123,8 @@ namespace SimpleScanner
         
         enum Result {accept, noMatch, contextFound};
 
-        const int maxAccept = 17;
-        const int initial = 18;
+        const int maxAccept = 18;
+        const int initial = 19;
         const int eofNum = 0;
         const int goStart = -1;
         const int INITIAL = 0;
@@ -165,24 +161,24 @@ namespace SimpleScanner
         }
     };
 
-    static int[] startState = new int[] {18, 0};
+    static int[] startState = new int[] {19, 0};
 
 #region CompressedCharacterMap
     //
-    // There are 15 equivalence classes
+    // There are 16 equivalence classes
     // There are 2 character sequence regions
     // There are 1 tables, 123 entries
     // There are 1 runs, 0 singletons
     // Decision tree depth is 1
     //
     static sbyte[] mapC0 = new sbyte[123] {
-/*     '\0' */ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 0, 14, 14, 
-/*   '\x10' */ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 
-/*   '\x20' */ 0, 14, 14, 14, 14, 14, 14, 14, 11, 12, 9, 8, 13, 7, 2, 10, 
-/*      '0' */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 6, 14, 5, 14, 14, 
-/*      '@' */ 14, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
-/*      'P' */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 14, 14, 14, 14, 3, 
-/*      '`' */ 14, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+/*     '\0' */ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 
+/*   '\x10' */ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 
+/*   '\x20' */ 0, 15, 15, 15, 15, 14, 15, 15, 11, 12, 9, 8, 13, 7, 2, 10, 
+/*      '0' */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 6, 15, 5, 15, 15, 
+/*      '@' */ 15, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+/*      'P' */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 15, 15, 15, 15, 3, 
+/*      '`' */ 15, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
 /*      'p' */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };
 
     static sbyte MapC(int code)
@@ -190,20 +186,20 @@ namespace SimpleScanner
       if (code < 123) // '\0' <= code <= 'z'
         return mapC0[code - 0];
       else // '{' <= code <= '\U0010FFFF'
-        return (sbyte)14;
+        return (sbyte)15;
     }
 #endregion
 
-    static Table[] NxS = new Table[20] {
+    static Table[] NxS = new Table[21] {
 /* NxS[   0] */ new Table(0, 0, 0, null),
-/* NxS[   1] */ new Table(1, 2, -1, new sbyte[] {1, 19}),
+/* NxS[   1] */ new Table(1, 2, -1, new sbyte[] {1, 20}),
 /* NxS[   2] */ new Table(0, 0, -1, null),
 /* NxS[   3] */ new Table(1, 3, -1, new sbyte[] {3, -1, 3}),
-/* NxS[   4] */ new Table(5, 1, -1, new sbyte[] {16}),
+/* NxS[   4] */ new Table(5, 1, -1, new sbyte[] {17}),
 /* NxS[   5] */ new Table(0, 0, -1, null),
-/* NxS[   6] */ new Table(5, 1, -1, new sbyte[] {15}),
-/* NxS[   7] */ new Table(5, 1, -1, new sbyte[] {14}),
-/* NxS[   8] */ new Table(5, 1, -1, new sbyte[] {13}),
+/* NxS[   6] */ new Table(5, 1, -1, new sbyte[] {16}),
+/* NxS[   7] */ new Table(5, 1, -1, new sbyte[] {15}),
+/* NxS[   8] */ new Table(5, 1, -1, new sbyte[] {14}),
 /* NxS[   9] */ new Table(0, 0, -1, null),
 /* NxS[  10] */ new Table(0, 0, -1, null),
 /* NxS[  11] */ new Table(0, 0, -1, null),
@@ -212,10 +208,11 @@ namespace SimpleScanner
 /* NxS[  14] */ new Table(0, 0, -1, null),
 /* NxS[  15] */ new Table(0, 0, -1, null),
 /* NxS[  16] */ new Table(0, 0, -1, null),
-/* NxS[  17] */ new Table(1, 1, -1, new sbyte[] {17}),
-/* NxS[  18] */ new Table(1, 14, -1, new sbyte[] {1, 2, 3, 4, 2, 5, 
-          6, 7, 8, 9, 10, 11, 12, 2}),
-/* NxS[  19] */ new Table(1, 1, -1, new sbyte[] {17}),
+/* NxS[  17] */ new Table(0, 0, -1, null),
+/* NxS[  18] */ new Table(1, 1, -1, new sbyte[] {18}),
+/* NxS[  19] */ new Table(1, 15, -1, new sbyte[] {1, 2, 3, 4, 2, 5, 
+          6, 7, 8, 9, 10, 11, 12, 13, 2}),
+/* NxS[  20] */ new Table(1, 1, -1, new sbyte[] {18}),
     };
 
 int NextState() {
@@ -225,7 +222,7 @@ int NextState() {
         unchecked {
             int rslt;
             int idx = MapC(code) - NxS[state].min;
-            if (idx < 0) idx += 15;
+            if (idx < 0) idx += 16;
             if ((uint)idx >= (uint)NxS[state].rng) rslt = NxS[state].dflt;
             else rslt = NxS[state].nxt[idx];
             return rslt;
@@ -305,7 +302,8 @@ int NextState() {
 
         public Scanner(Stream file, string codepage) {
             SetSource(file, CodePageHandling.GetCodePage(codepage));
-        }   
+        }
+        
 #endif // !NOFILES
 
      public Scanner() { }
@@ -333,7 +331,7 @@ int NextState() {
                     if (next < 0xDC00 || next > 0xDFFF)
                         code = ScanBuff.UnicodeReplacementChar;
                     else
-                        code = (0x10000 + ((code & 0x3FF) << 10) + (next & 0x3FF));
+                        code = (0x10000 + (code & 0x3FF << 10) + (next & 0x3FF));
                 }
 #endif
                 cCol++;
@@ -386,7 +384,9 @@ int NextState() {
             GetCode();
         }
 
+#if !NOFILES        
         // ================ LineBuffer Initialization ===================
+
         /// <summary>
         /// Create and initialize a LineBuff buffer object for this scanner
         /// </summary>
@@ -400,7 +400,6 @@ int NextState() {
             GetCode();
         }
 
-#if !NOFILES        
         // =============== StreamBuffer Initialization ==================
 
         /// <summary>
@@ -502,12 +501,6 @@ int NextState() {
             }
         }
 
-        /// <summary>
-        /// Discards all but the first "n" codepoints in the recognized pattern.
-        /// Resets the buffer position so that only n codepoints have been consumed;
-        /// yytext is also re-evaluated. 
-        /// </summary>
-        /// <param name="n">The number of codepoints to consume</param>
         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
         void yyless(int n)
         {
@@ -527,10 +520,6 @@ int NextState() {
         //  but it does not seem possible to re-establish
         //  the correct column counts except by going forward.
         //
-        /// <summary>
-        /// Removes the last "n" code points from the pattern.
-        /// </summary>
-        /// <param name="n">The number to remove</param>
         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
         void _yytrunc(int n) { yyless(yyleng - n); }
         
@@ -543,23 +532,18 @@ int NextState() {
         // can't use (tokEPos - tokPos) because of the
         // possibility of surrogate pairs in the token.
         //
-        /// <summary>
-        /// The length of the pattern in codepoints (not the same as 
-        /// string-length if the pattern contains any surrogate pairs).
-        /// </summary>
         [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
         [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "yyleng")]
         [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "yyleng")]
         public int yyleng
         {
             get {
+#if BYTEMODE
+                return tokEPos - tokPos;
+#else   
                 if (tokELin == tokLin)
                     return tokECol - tokCol;
-                else
-#if BYTEMODE
-                    return tokEPos - tokPos;
-#else
-                {
+                else {
                     int ch;
                     int count = 0;
                     int save = buffer.Pos;
@@ -568,7 +552,7 @@ int NextState() {
                         ch = buffer.Read();
                         if (!char.IsHighSurrogate((char)ch)) count++;
                     } while (buffer.Pos < tokEPos && ch != ScanBuff.EndOfFile);
-                    buffer.Pos = save;
+                    buffer.Pos = save; 
                     return count;
                 }
 #endif // BYTEMODE
@@ -593,56 +577,65 @@ int NextState() {
 
         // ============== The main tokenizer code =================
 
-        int Scan() {
+        int Scan()
+        {
             try {
-                for (; ; ) {
-                    int next;              // next state to enter
+                for (; ; )
+                {
+                    int next;              // next state to enter                   
+#if BACKUP
+                    Result rslt = Result.noMatch;
+#endif // BACKUP
 #if LEFTANCHORS
-                    for (;;) {
+                    for (;;)
+                    {
                         // Discard characters that do not start any pattern.
                         // Must check the left anchor condition after *every* GetCode!
                         state = ((cCol == 0) ? anchorState[currentScOrd] : currentStart);
-                        if ((next = NextState()) != goStart) break; // LOOP EXIT HERE...
+                        if ((next = NextState()) != goStart) 
+                            break; // LOOP EXIT HERE...
                         GetCode();
                     }
                     
 #else // !LEFTANCHORS
                     state = currentStart;
-                    while ((next = NextState()) == goStart) {
+                    while ((next = NextState()) == goStart)
                         // At this point, the current character has no
                         // transition from the current state.  We discard 
                         // the "no-match" char.   In traditional LEX such 
                         // characters are echoed to the console.
                         GetCode();
-                    }
 #endif // LEFTANCHORS                    
                     // At last, a valid transition ...    
                     MarkToken();
                     state = next;
-                    GetCode();                    
+                    GetCode();
+                    
+                    while ((next = NextState()) > eofNum) // Exit for goStart AND for eofNum
 #if BACKUP
-                    bool contextSaved = false;
-                    while ((next = NextState()) > eofNum) { // Exit for goStart AND for eofNum
-                        if (state <= maxAccept && next > maxAccept) { // need to prepare backup data
-                            // Store data for the *latest* accept state that was found.
-                            SaveStateAndPos( ref ctx );
-                            contextSaved = true;
+                        if (state <= maxAccept && next > maxAccept) // need to prepare backup data
+                        {
+                            // ctx is an object. The fields may be 
+                            // mutated by the call to Recurse2.
+                            // On return the data in ctx is the
+                            // *latest* accept state that was found.
+                            
+                            rslt = Recurse2(ref ctx, next);
+                            if (rslt == Result.noMatch) 
+                                RestoreStateAndPos(ref ctx);
+                            break;
                         }
-                        state = next;
-                        GetCode();
-                    }
-                    if (state > maxAccept && contextSaved)
-                        RestoreStateAndPos( ref ctx );
-#else  // BACKUP
-                    while ((next = NextState()) > eofNum) { // Exit for goStart AND for eofNum
-                         state = next;
-                         GetCode();
-                    }
+                        else
 #endif // BACKUP
-                    if (state <= maxAccept) {
+                        {
+                            state = next;
+                            GetCode();
+                        }
+                    if (state <= maxAccept) 
+                    {
                         MarkEnd();
 #region ActionSwitch
-#pragma warning disable 162, 1522
+#pragma warning disable 162
     switch (state)
     {
         case eofNum:
@@ -651,7 +644,7 @@ int NextState() {
             break;
         case 1:
 yylval.iVal = int.Parse(yytext); 
-  return (int)Tokens.INUM;
+	return (int)Tokens.INUM;
             break;
         case 2:
         case 4:
@@ -659,9 +652,9 @@ LexError();
             break;
         case 3:
 int res = ScannerHelper.GetIDToken(yytext);
-  if (res == (int)Tokens.ID)
-	yylval.sVal = yytext;
-  return res;
+	if (res == (int)Tokens.ID)
+		yylval.sVal = yytext;
+	return res;
             break;
         case 5:
 return (int)Tokens.SEMICOLON;
@@ -688,25 +681,28 @@ return (int)Tokens.RPAREN;
 return (int)Tokens.COLUMN;
             break;
         case 13:
-return (int)Tokens.ASSIGNMULT;
+return (int)Tokens.MOD;
             break;
         case 14:
-return (int)Tokens.ASSIGNPLUS;
+return (int)Tokens.ASSIGNMULT;
             break;
         case 15:
-return (int)Tokens.ASSIGNMINUS;
+return (int)Tokens.ASSIGNPLUS;
             break;
         case 16:
-return (int)Tokens.ASSIGN;
+return (int)Tokens.ASSIGNMINUS;
             break;
         case 17:
+return (int)Tokens.ASSIGN;
+            break;
+        case 18:
 yylval.dVal = double.Parse(yytext); 
-  return (int)Tokens.RNUM;
+	return (int)Tokens.RNUM;
             break;
         default:
             break;
     }
-#pragma warning restore 162, 1522
+#pragma warning restore 162
 #endregion
                     }
                 }
@@ -719,7 +715,29 @@ yylloc = new LexLocation(tokLin, tokCol, tokELin, tokECol);
         }
 
 #if BACKUP
-        void SaveStateAndPos(ref Context ctx) {
+        Result Recurse2(ref Context ctx, int next)
+        {
+            // Assert: at entry "state" is an accept state AND
+            //         NextState(state, code) != goStart AND
+            //         NextState(state, code) is not an accept state.
+            //
+            SaveStateAndPos(ref ctx);
+            state = next;
+            GetCode();
+
+            while ((next = NextState()) > eofNum)
+            {
+                if (state <= maxAccept && next > maxAccept) // need to update backup data
+                    SaveStateAndPos(ref ctx);
+                state = next;
+                if (state == eofNum) return Result.accept;
+                GetCode(); 
+            }
+            return (state <= maxAccept ? Result.accept : Result.noMatch);
+        }
+
+        void SaveStateAndPos(ref Context ctx)
+        {
             ctx.bPos  = buffer.Pos;
             ctx.rPos  = readPos;
             ctx.cCol  = cCol;
@@ -728,7 +746,8 @@ yylloc = new LexLocation(tokLin, tokCol, tokELin, tokECol);
             ctx.cChr  = code;
         }
 
-        void RestoreStateAndPos(ref Context ctx) {
+        void RestoreStateAndPos(ref Context ctx)
+        {
             buffer.Pos = ctx.bPos;
             readPos = ctx.rPos;
             cCol  = ctx.cCol;
@@ -736,7 +755,8 @@ yylloc = new LexLocation(tokLin, tokCol, tokELin, tokECol);
             state = ctx.state;
             code  = ctx.cChr;
         }
-#endif  // BACKUP
+
+#endif // BACKUP
 
         // ============= End of the tokenizer code ================
 
@@ -768,40 +788,46 @@ yylloc = new LexLocation(tokLin, tokCol, tokELin, tokECol);
         
 #region UserCodeSection
 
-public override void yyerror(string format, params object[] args) // îáðàáîòêà ñèíòàêñè÷åñêèõ îøèáîê
+public override void yyerror(string format, params object[] args) // обработка синтаксических ошибок
 {
-  var ww = args.Skip(1).Cast<string>().ToArray();
-  string errorMsg = string.Format("({0},{1}): Âñòðå÷åíî {2}, à îæèäàëîñü {3}", yyline, yycol, args[0], string.Join(" èëè ", ww));
-  throw new SyntaxException(errorMsg);
+	var ww = args.Skip(1).Cast<string>().ToArray();
+	string errorMsg = string.Format("({0},{1}): Встречено {2}, а ожидалось {3}", yyline, yycol, args[0], string.Join(" или ", ww));
+	throw new SyntaxException(errorMsg);
 }
 
 public void LexError()
 {
-  string errorMsg = string.Format("({0},{1}): Íåèçâåñòíûé ñèìâîë {2}", yyline, yycol, yytext);
-  throw new LexException(errorMsg);
+	string errorMsg = string.Format("({0},{1}): Неизвестный символ {2}", yyline, yycol, yytext);
+	throw new LexException(errorMsg);
 }
 
 class ScannerHelper 
 {
-  private static Dictionary<string,int> keywords;
-
-  static ScannerHelper() 
-  {
-    keywords = new Dictionary<string,int>();
-    keywords.Add("begin",(int)Tokens.BEGIN);
-    keywords.Add("end",(int)Tokens.END);
-    keywords.Add("cycle",(int)Tokens.CYCLE);
-    keywords.Add("write",(int)Tokens.WRITE);
-    keywords.Add("var",(int)Tokens.VAR);
-  }
-  public static int GetIDToken(string s)
-  {
-	if (keywords.ContainsKey(s.ToLower()))
-	  return keywords[s];
-	else
-      return (int)Tokens.ID;
-  }
-  
+	private static Dictionary<string,int> keywords;
+
+	static ScannerHelper() 
+	{
+		keywords = new Dictionary<string,int>();
+		keywords.Add("begin",(int)Tokens.BEGIN);
+		keywords.Add("end",(int)Tokens.END);
+		keywords.Add("cycle",(int)Tokens.CYCLE);
+		keywords.Add("write",(int)Tokens.WRITE);
+		keywords.Add("var",(int)Tokens.VAR);
+		keywords.Add("if",(int)Tokens.IF);
+		keywords.Add("then",(int)Tokens.THEN);
+		keywords.Add("else",(int)Tokens.ELSE);
+		keywords.Add("while",(int)Tokens.WHILE);
+		keywords.Add("do",(int)Tokens.DO);
+		keywords.Add("repeat",(int)Tokens.REPEAT);
+		keywords.Add("until",(int)Tokens.UNTIL);
+	}
+	public static int GetIDToken(string s)
+	{
+		if (keywords.ContainsKey(s.ToLower()))
+			return keywords[s];
+		else
+			return (int)Tokens.ID;
+	}
 }
 
 #endregion
@@ -853,7 +879,6 @@ class ScannerHelper
             return new LineBuffer(source);
         }
 
-#if (!NOFILES)
         public static ScanBuff GetBuffer(Stream source)
         {
             return new BuildBuffer(source);
@@ -864,8 +889,7 @@ class ScannerHelper
         {
             return new BuildBuffer(source, fallbackCodePage);
         }
-#endif // !BYTEMODE
-#endif // !NOFILES
+#endif
     }
 
     #region Buffer classes
@@ -988,7 +1012,7 @@ class ScannerHelper
             {
                 ix = lstart = 0;
             }
-            while (ix < numLines)
+            for (; ; )
             {
                 int len = line[ix].Length + 1;
                 if (pos < lstart + len) break;
@@ -1046,8 +1070,7 @@ class ScannerHelper
             {
                 cPos = value;
                 findIndex(cPos, out cLine, out curLineStart);
-                // cLine should be the *next* line after curLine.
-                curLine = (cLine < numLines ? line[cLine++] : "");
+                curLine = line[cLine];
                 curLineEnd = curLineStart + curLine.Length;
             }
         }
@@ -1055,7 +1078,7 @@ class ScannerHelper
         public override string ToString() { return "LineBuffer"; }
     }
 
-#if (!NOFILES)
+
     // ==============================================================
     // =====     class BuildBuff : for unicode text files    ========
     // ==============================================================
@@ -1296,13 +1319,12 @@ class ScannerHelper
         }
 #endif // !BYTEMODE
     }
-#endif // !NOFILES
     #endregion Buffer classes
 
     // ==============================================================
     // ============      class CodePageHandling         =============
     // ==============================================================
-#if (!NOFILES)
+
     public static class CodePageHandling
     {
         public static int GetCodePage(string option)
@@ -1513,7 +1535,6 @@ class ScannerHelper
     
 #endif // !BYTEMODE
 #endregion
-#endif // !NOFILES
 
 // End of code copied from embedded resource
 
diff --git a/Module8/SimpleLex.lex b/Module8/SimpleLex.lex
index 00dfa1249dd0572b3061e40d49d86058b4e1baee..69430d9b5ad9b98239d41a65615ab2753347d5d2 100644
--- a/Module8/SimpleLex.lex
+++ b/Module8/SimpleLex.lex
@@ -14,20 +14,20 @@ ID {Alpha}{AlphaDigit}*
 %%
 
 {INTNUM} { 
-  yylval.iVal = int.Parse(yytext); 
-  return (int)Tokens.INUM; 
+	yylval.iVal = int.Parse(yytext); 
+	return (int)Tokens.INUM; 
 }
 
 {REALNUM} { 
-  yylval.dVal = double.Parse(yytext); 
-  return (int)Tokens.RNUM;
+	yylval.dVal = double.Parse(yytext); 
+	return (int)Tokens.RNUM;
 }
 
 {ID}  { 
-  int res = ScannerHelper.GetIDToken(yytext);
-  if (res == (int)Tokens.ID)
-	yylval.sVal = yytext;
-  return res;
+	int res = ScannerHelper.GetIDToken(yytext);
+	if (res == (int)Tokens.ID)
+		yylval.sVal = yytext;
+	return res;
 }
 
 ":=" { return (int)Tokens.ASSIGN; }
@@ -42,49 +42,56 @@ ID {Alpha}{AlphaDigit}*
 "(" { return (int)Tokens.LPAREN; }
 ")" { return (int)Tokens.RPAREN; }
 "," { return (int)Tokens.COLUMN; }
+"%" { return (int)Tokens.MOD; }
 
 [^ \r\n] {
 	LexError();
 }
 
 %{
-  yylloc = new LexLocation(tokLin, tokCol, tokELin, tokECol);
+	yylloc = new LexLocation(tokLin, tokCol, tokELin, tokECol);
 %}
 
 %%
 
 public override void yyerror(string format, params object[] args) // обработка синтаксических ошибок
 {
-  var ww = args.Skip(1).Cast<string>().ToArray();
-  string errorMsg = string.Format("({0},{1}): Встречено {2}, а ожидалось {3}", yyline, yycol, args[0], string.Join(" или ", ww));
-  throw new SyntaxException(errorMsg);
+	var ww = args.Skip(1).Cast<string>().ToArray();
+	string errorMsg = string.Format("({0},{1}): Встречено {2}, а ожидалось {3}", yyline, yycol, args[0], string.Join(" или ", ww));
+	throw new SyntaxException(errorMsg);
 }
 
 public void LexError()
 {
-  string errorMsg = string.Format("({0},{1}): Неизвестный символ {2}", yyline, yycol, yytext);
-  throw new LexException(errorMsg);
+	string errorMsg = string.Format("({0},{1}): Неизвестный символ {2}", yyline, yycol, yytext);
+	throw new LexException(errorMsg);
 }
 
 class ScannerHelper 
 {
-  private static Dictionary<string,int> keywords;
+	private static Dictionary<string,int> keywords;
 
-  static ScannerHelper() 
-  {
-    keywords = new Dictionary<string,int>();
-    keywords.Add("begin",(int)Tokens.BEGIN);
-    keywords.Add("end",(int)Tokens.END);
-    keywords.Add("cycle",(int)Tokens.CYCLE);
-    keywords.Add("write",(int)Tokens.WRITE);
-    keywords.Add("var",(int)Tokens.VAR);
-  }
-  public static int GetIDToken(string s)
-  {
-	if (keywords.ContainsKey(s.ToLower()))
-	  return keywords[s];
-	else
-      return (int)Tokens.ID;
-  }
-  
-}
+	static ScannerHelper() 
+	{
+		keywords = new Dictionary<string,int>();
+		keywords.Add("begin",(int)Tokens.BEGIN);
+		keywords.Add("end",(int)Tokens.END);
+		keywords.Add("cycle",(int)Tokens.CYCLE);
+		keywords.Add("write",(int)Tokens.WRITE);
+		keywords.Add("var",(int)Tokens.VAR);
+		keywords.Add("if",(int)Tokens.IF);
+		keywords.Add("then",(int)Tokens.THEN);
+		keywords.Add("else",(int)Tokens.ELSE);
+		keywords.Add("while",(int)Tokens.WHILE);
+		keywords.Add("do",(int)Tokens.DO);
+		keywords.Add("repeat",(int)Tokens.REPEAT);
+		keywords.Add("until",(int)Tokens.UNTIL);
+	}
+	public static int GetIDToken(string s)
+	{
+		if (keywords.ContainsKey(s.ToLower()))
+			return keywords[s];
+		else
+			return (int)Tokens.ID;
+	}
+}
\ No newline at end of file
diff --git a/Module8/SimpleYacc.cs b/Module8/SimpleYacc.cs
index 41990d1991abc1e5c84a48ae96c6d9f5381c4264..f2a918b941197796e540adc57fbe71cee9f4e57c 100644
--- a/Module8/SimpleYacc.cs
+++ b/Module8/SimpleYacc.cs
@@ -1,18 +1,17 @@
 // This code was generated by the Gardens Point Parser Generator
-// Copyright (c) Wayne Kelly, John Gough, QUT 2005-2014
+// Copyright (c) Wayne Kelly, QUT 2005-2010
 // (see accompanying GPPGcopyright.rtf)
 
-// GPPG version 1.5.2
-// Machine:  MAINHOMEPC2
-// DateTime: 30.09.2018 18:23:23
-// UserName: someone
-// Input file <SimpleYacc.y - 30.09.2018 18:22:38>
+// GPPG version 1.3.6
+// Machine:  MIL8A-202A-05
+// DateTime: 28.11.2022 13:27:35
+// UserName: user
+// Input file <SimpleYacc.y>
 
 // options: no-lines gplex
 
 using System;
 using System.Collections.Generic;
-using System.CodeDom.Compiler;
 using System.Globalization;
 using System.Text;
 using QUT.Gppg;
@@ -21,10 +20,13 @@ using ProgramTree;
 
 namespace SimpleParser
 {
-public enum Tokens {error=2,EOF=3,BEGIN=4,END=5,CYCLE=6,
-    ASSIGN=7,ASSIGNPLUS=8,ASSIGNMINUS=9,ASSIGNMULT=10,SEMICOLON=11,WRITE=12,
-    VAR=13,PLUS=14,MINUS=15,MULT=16,DIV=17,LPAREN=18,
-    RPAREN=19,COLUMN=20,INUM=21,RNUM=22,ID=23};
+public enum Tokens {
+    error=1,EOF=2,BEGIN=3,END=4,CYCLE=5,ASSIGN=6,
+    ASSIGNPLUS=7,ASSIGNMINUS=8,ASSIGNMULT=9,SEMICOLON=10,WRITE=11,VAR=12,
+    PLUS=13,MINUS=14,MULT=15,DIV=16,MOD=17,LPAREN=18,
+    RPAREN=19,COLUMN=20,WHILE=21,DO=22,REPEAT=23,UNTIL=24,
+    LEFT_PR=25,RIGHT_PR=26,IF=27,THEN=28,ELSE=29,INUM=30,
+    RNUM=31,ID=32,IFX=33};
 
 public struct ValueType
 { 
@@ -37,124 +39,139 @@ public struct ValueType
 			public BlockNode blVal;
        }
 // Abstract base class for GPLEX scanners
-[GeneratedCodeAttribute( "Gardens Point Parser Generator", "1.5.2")]
 public abstract class ScanBase : AbstractScanner<ValueType,LexLocation> {
   private LexLocation __yylloc = new LexLocation();
   public override LexLocation yylloc { get { return __yylloc; } set { __yylloc = value; } }
   protected virtual bool yywrap() { return true; }
 }
 
-// Utility class for encapsulating token information
-[GeneratedCodeAttribute( "Gardens Point Parser Generator", "1.5.2")]
-public class ScanObj {
-  public int token;
-  public ValueType yylval;
-  public LexLocation yylloc;
-  public ScanObj( int t, ValueType val, LexLocation loc ) {
-    this.token = t; this.yylval = val; this.yylloc = loc;
-  }
-}
-
-[GeneratedCodeAttribute( "Gardens Point Parser Generator", "1.5.2")]
 public class Parser: ShiftReduceParser<ValueType, LexLocation>
 {
-  // Verbatim content from SimpleYacc.y - 30.09.2018 18:22:38
-// Ýòè îáúÿâëåíèÿ äîáàâëÿþòñÿ â êëàññ GPPGParser, ïðåäñòàâëÿþùèé ñîáîé ïàðñåð, ãåíåðèðóåìûé ñèñòåìîé gppg
-    public BlockNode root; // Êîðíåâîé óçåë ñèíòàêñè÷åñêîãî äåðåâà 
+  // Verbatim content from SimpleYacc.y
+// Эти объявления добавляются в класс GPPGParser, представляющий собой парсер, генерируемый системой gppg
+    public BlockNode root; // Корневой узел синтаксического дерева 
     public Parser(AbstractScanner<ValueType, LexLocation> scanner) : base(scanner) { }
 	private bool InDefSect = false;
-  // End verbatim content from SimpleYacc.y - 30.09.2018 18:22:38
+  // End verbatim content from SimpleYacc.y
 
 #pragma warning disable 649
-  private static Dictionary<int, string> aliases;
+  private static Dictionary<int, string> aliasses;
 #pragma warning restore 649
-  private static Rule[] rules = new Rule[30];
-  private static State[] states = new State[48];
+  private static Rule[] rules = new Rule[39];
+  private static State[] states = new State[68];
   private static string[] nonTerms = new string[] {
       "progr", "expr", "ident", "T", "F", "statement", "assign", "block", "cycle", 
-      "write", "empty", "var", "varlist", "stlist", "$accept", "Anon@1", };
+      "write", "empty", "var", "varlist", "if", "while", "repeat", "stlist", 
+      "$accept", "Anon@1", "Anon@2", };
 
   static Parser() {
-    states[0] = new State(new int[]{4,4},new int[]{-1,1,-8,3});
-    states[1] = new State(new int[]{3,2});
+    states[0] = new State(new int[]{3,4},new int[]{-1,1,-8,3});
+    states[1] = new State(new int[]{2,2});
     states[2] = new State(-1);
     states[3] = new State(-2);
-    states[4] = new State(new int[]{23,18,4,4,6,31,12,35,13,40,5,-11,11,-11},new int[]{-14,5,-6,47,-7,9,-3,10,-8,29,-9,30,-10,34,-12,39,-11,46});
-    states[5] = new State(new int[]{5,6,11,7});
-    states[6] = new State(-23);
-    states[7] = new State(new int[]{23,18,4,4,6,31,12,35,13,40,5,-11,11,-11},new int[]{-6,8,-7,9,-3,10,-8,29,-9,30,-10,34,-12,39,-11,46});
+    states[4] = new State(new int[]{32,18,3,4,5,33,11,37,12,42,27,50,21,58,23,63,4,-14,10,-14},new int[]{-17,5,-6,67,-7,9,-3,10,-8,31,-9,32,-10,36,-12,41,-11,48,-14,49,-15,57,-16,62});
+    states[5] = new State(new int[]{4,6,10,7});
+    states[6] = new State(-27);
+    states[7] = new State(new int[]{32,18,3,4,5,33,11,37,12,42,27,50,21,58,23,63,4,-14,10,-14,24,-14},new int[]{-6,8,-7,9,-3,10,-8,31,-9,32,-10,36,-12,41,-11,48,-14,49,-15,57,-16,62});
     states[8] = new State(-4);
     states[9] = new State(-5);
-    states[10] = new State(new int[]{7,11});
-    states[11] = new State(new int[]{23,18,21,19,18,20},new int[]{-2,12,-4,28,-5,27,-3,17});
-    states[12] = new State(new int[]{14,13,15,23,5,-13,11,-13});
-    states[13] = new State(new int[]{23,18,21,19,18,20},new int[]{-4,14,-5,27,-3,17});
-    states[14] = new State(new int[]{16,15,17,25,14,-14,15,-14,5,-14,11,-14,19,-14,23,-14,4,-14,6,-14,12,-14,13,-14});
-    states[15] = new State(new int[]{23,18,21,19,18,20},new int[]{-5,16,-3,17});
-    states[16] = new State(-17);
-    states[17] = new State(-20);
-    states[18] = new State(-12);
-    states[19] = new State(-21);
-    states[20] = new State(new int[]{23,18,21,19,18,20},new int[]{-2,21,-4,28,-5,27,-3,17});
-    states[21] = new State(new int[]{19,22,14,13,15,23});
-    states[22] = new State(-22);
-    states[23] = new State(new int[]{23,18,21,19,18,20},new int[]{-4,24,-5,27,-3,17});
-    states[24] = new State(new int[]{16,15,17,25,14,-15,15,-15,5,-15,11,-15,19,-15,23,-15,4,-15,6,-15,12,-15,13,-15});
-    states[25] = new State(new int[]{23,18,21,19,18,20},new int[]{-5,26,-3,17});
-    states[26] = new State(-18);
-    states[27] = new State(-19);
-    states[28] = new State(new int[]{16,15,17,25,14,-16,15,-16,5,-16,11,-16,19,-16,23,-16,4,-16,6,-16,12,-16,13,-16});
-    states[29] = new State(-6);
-    states[30] = new State(-7);
-    states[31] = new State(new int[]{23,18,21,19,18,20},new int[]{-2,32,-4,28,-5,27,-3,17});
-    states[32] = new State(new int[]{14,13,15,23,23,18,4,4,6,31,12,35,13,40,5,-11,11,-11},new int[]{-6,33,-7,9,-3,10,-8,29,-9,30,-10,34,-12,39,-11,46});
-    states[33] = new State(-24);
-    states[34] = new State(-8);
-    states[35] = new State(new int[]{18,36});
-    states[36] = new State(new int[]{23,18,21,19,18,20},new int[]{-2,37,-4,28,-5,27,-3,17});
-    states[37] = new State(new int[]{19,38,14,13,15,23});
-    states[38] = new State(-25);
-    states[39] = new State(-9);
-    states[40] = new State(-26,new int[]{-16,41});
-    states[41] = new State(new int[]{23,18},new int[]{-13,42,-3,45});
-    states[42] = new State(new int[]{20,43,5,-27,11,-27});
-    states[43] = new State(new int[]{23,18},new int[]{-3,44});
-    states[44] = new State(-29);
-    states[45] = new State(-28);
-    states[46] = new State(-10);
-    states[47] = new State(-3);
-
-    for (int sNo = 0; sNo < states.Length; sNo++) states[sNo].number = sNo;
+    states[10] = new State(new int[]{6,11});
+    states[11] = new State(new int[]{32,18,30,19,18,20},new int[]{-2,12,-4,30,-5,29,-3,17});
+    states[12] = new State(new int[]{13,13,14,23,4,-16,10,-16,24,-16,29,-16});
+    states[13] = new State(new int[]{32,18,30,19,18,20},new int[]{-4,14,-5,29,-3,17});
+    states[14] = new State(new int[]{15,15,16,25,17,27,13,-17,14,-17,4,-17,10,-17,24,-17,29,-17,19,-17,32,-17,3,-17,5,-17,11,-17,12,-17,27,-17,21,-17,23,-17,28,-17,22,-17});
+    states[15] = new State(new int[]{32,18,30,19,18,20},new int[]{-5,16,-3,17});
+    states[16] = new State(-20);
+    states[17] = new State(-24);
+    states[18] = new State(-15);
+    states[19] = new State(-25);
+    states[20] = new State(new int[]{32,18,30,19,18,20},new int[]{-2,21,-4,30,-5,29,-3,17});
+    states[21] = new State(new int[]{19,22,13,13,14,23});
+    states[22] = new State(-26);
+    states[23] = new State(new int[]{32,18,30,19,18,20},new int[]{-4,24,-5,29,-3,17});
+    states[24] = new State(new int[]{15,15,16,25,17,27,13,-18,14,-18,4,-18,10,-18,24,-18,29,-18,19,-18,32,-18,3,-18,5,-18,11,-18,12,-18,27,-18,21,-18,23,-18,28,-18,22,-18});
+    states[25] = new State(new int[]{32,18,30,19,18,20},new int[]{-5,26,-3,17});
+    states[26] = new State(-21);
+    states[27] = new State(new int[]{32,18,30,19,18,20},new int[]{-5,28,-3,17});
+    states[28] = new State(-22);
+    states[29] = new State(-23);
+    states[30] = new State(new int[]{15,15,16,25,17,27,13,-19,14,-19,4,-19,10,-19,24,-19,29,-19,19,-19,32,-19,3,-19,5,-19,11,-19,12,-19,27,-19,21,-19,23,-19,28,-19,22,-19});
+    states[31] = new State(-6);
+    states[32] = new State(-7);
+    states[33] = new State(new int[]{32,18,30,19,18,20},new int[]{-2,34,-4,30,-5,29,-3,17});
+    states[34] = new State(new int[]{13,13,14,23,32,18,3,4,5,33,11,37,12,42,27,50,21,58,23,63,4,-14,10,-14,24,-14,29,-14},new int[]{-6,35,-7,9,-3,10,-8,31,-9,32,-10,36,-12,41,-11,48,-14,49,-15,57,-16,62});
+    states[35] = new State(-28);
+    states[36] = new State(-8);
+    states[37] = new State(new int[]{18,38});
+    states[38] = new State(new int[]{32,18,30,19,18,20},new int[]{-2,39,-4,30,-5,29,-3,17});
+    states[39] = new State(new int[]{19,40,13,13,14,23});
+    states[40] = new State(-29);
+    states[41] = new State(-9);
+    states[42] = new State(-30,new int[]{-19,43});
+    states[43] = new State(new int[]{32,18},new int[]{-13,44,-3,47});
+    states[44] = new State(new int[]{20,45,4,-31,10,-31,24,-31,29,-31});
+    states[45] = new State(new int[]{32,18},new int[]{-3,46});
+    states[46] = new State(-33);
+    states[47] = new State(-32);
+    states[48] = new State(-10);
+    states[49] = new State(-11);
+    states[50] = new State(new int[]{32,18,30,19,18,20},new int[]{-2,51,-4,30,-5,29,-3,17});
+    states[51] = new State(new int[]{28,52,13,13,14,23});
+    states[52] = new State(new int[]{32,18,3,4,5,33,11,37,12,42,27,50,21,58,23,63,4,-14,10,-14,24,-14,29,-14},new int[]{-6,53,-7,9,-3,10,-8,31,-9,32,-10,36,-12,41,-11,48,-14,49,-15,57,-16,62});
+    states[53] = new State(new int[]{29,55,4,-34,10,-34,24,-34},new int[]{-20,54});
+    states[54] = new State(-35);
+    states[55] = new State(new int[]{32,18,3,4,5,33,11,37,12,42,27,50,21,58,23,63,4,-14,10,-14,24,-14,29,-14},new int[]{-6,56,-7,9,-3,10,-8,31,-9,32,-10,36,-12,41,-11,48,-14,49,-15,57,-16,62});
+    states[56] = new State(-36);
+    states[57] = new State(-12);
+    states[58] = new State(new int[]{32,18,30,19,18,20},new int[]{-2,59,-4,30,-5,29,-3,17});
+    states[59] = new State(new int[]{22,60,13,13,14,23});
+    states[60] = new State(new int[]{32,18,3,4,5,33,11,37,12,42,27,50,21,58,23,63,4,-14,10,-14,24,-14,29,-14},new int[]{-6,61,-7,9,-3,10,-8,31,-9,32,-10,36,-12,41,-11,48,-14,49,-15,57,-16,62});
+    states[61] = new State(-37);
+    states[62] = new State(-13);
+    states[63] = new State(new int[]{32,18,3,4,5,33,11,37,12,42,27,50,21,58,23,63,24,-14,10,-14},new int[]{-17,64,-6,67,-7,9,-3,10,-8,31,-9,32,-10,36,-12,41,-11,48,-14,49,-15,57,-16,62});
+    states[64] = new State(new int[]{24,65,10,7});
+    states[65] = new State(new int[]{32,18,30,19,18,20},new int[]{-2,66,-4,30,-5,29,-3,17});
+    states[66] = new State(new int[]{13,13,14,23,4,-38,10,-38,24,-38,29,-38});
+    states[67] = new State(-3);
 
-    rules[1] = new Rule(-15, new int[]{-1,3});
+    rules[1] = new Rule(-18, new int[]{-1,2});
     rules[2] = new Rule(-1, new int[]{-8});
-    rules[3] = new Rule(-14, new int[]{-6});
-    rules[4] = new Rule(-14, new int[]{-14,11,-6});
+    rules[3] = new Rule(-17, new int[]{-6});
+    rules[4] = new Rule(-17, new int[]{-17,10,-6});
     rules[5] = new Rule(-6, new int[]{-7});
     rules[6] = new Rule(-6, new int[]{-8});
     rules[7] = new Rule(-6, new int[]{-9});
     rules[8] = new Rule(-6, new int[]{-10});
     rules[9] = new Rule(-6, new int[]{-12});
     rules[10] = new Rule(-6, new int[]{-11});
-    rules[11] = new Rule(-11, new int[]{});
-    rules[12] = new Rule(-3, new int[]{23});
-    rules[13] = new Rule(-7, new int[]{-3,7,-2});
-    rules[14] = new Rule(-2, new int[]{-2,14,-4});
-    rules[15] = new Rule(-2, new int[]{-2,15,-4});
-    rules[16] = new Rule(-2, new int[]{-4});
-    rules[17] = new Rule(-4, new int[]{-4,16,-5});
-    rules[18] = new Rule(-4, new int[]{-4,17,-5});
-    rules[19] = new Rule(-4, new int[]{-5});
-    rules[20] = new Rule(-5, new int[]{-3});
-    rules[21] = new Rule(-5, new int[]{21});
-    rules[22] = new Rule(-5, new int[]{18,-2,19});
-    rules[23] = new Rule(-8, new int[]{4,-14,5});
-    rules[24] = new Rule(-9, new int[]{6,-2,-6});
-    rules[25] = new Rule(-10, new int[]{12,18,-2,19});
-    rules[26] = new Rule(-16, new int[]{});
-    rules[27] = new Rule(-12, new int[]{13,-16,-13});
-    rules[28] = new Rule(-13, new int[]{-3});
-    rules[29] = new Rule(-13, new int[]{-13,20,-3});
+    rules[11] = new Rule(-6, new int[]{-14});
+    rules[12] = new Rule(-6, new int[]{-15});
+    rules[13] = new Rule(-6, new int[]{-16});
+    rules[14] = new Rule(-11, new int[]{});
+    rules[15] = new Rule(-3, new int[]{32});
+    rules[16] = new Rule(-7, new int[]{-3,6,-2});
+    rules[17] = new Rule(-2, new int[]{-2,13,-4});
+    rules[18] = new Rule(-2, new int[]{-2,14,-4});
+    rules[19] = new Rule(-2, new int[]{-4});
+    rules[20] = new Rule(-4, new int[]{-4,15,-5});
+    rules[21] = new Rule(-4, new int[]{-4,16,-5});
+    rules[22] = new Rule(-4, new int[]{-4,17,-5});
+    rules[23] = new Rule(-4, new int[]{-5});
+    rules[24] = new Rule(-5, new int[]{-3});
+    rules[25] = new Rule(-5, new int[]{30});
+    rules[26] = new Rule(-5, new int[]{18,-2,19});
+    rules[27] = new Rule(-8, new int[]{3,-17,4});
+    rules[28] = new Rule(-9, new int[]{5,-2,-6});
+    rules[29] = new Rule(-10, new int[]{11,18,-2,19});
+    rules[30] = new Rule(-19, new int[]{});
+    rules[31] = new Rule(-12, new int[]{12,-19,-13});
+    rules[32] = new Rule(-13, new int[]{-3});
+    rules[33] = new Rule(-13, new int[]{-13,20,-3});
+    rules[34] = new Rule(-20, new int[]{});
+    rules[35] = new Rule(-14, new int[]{27,-2,28,-6,-20});
+    rules[36] = new Rule(-14, new int[]{27,-2,28,-6,29,-6});
+    rules[37] = new Rule(-15, new int[]{21,-2,22,-6});
+    rules[38] = new Rule(-16, new int[]{23,-17,24,-2});
   }
 
   protected override void Initialize() {
@@ -166,7 +183,6 @@ public class Parser: ShiftReduceParser<ValueType, LexLocation>
 
   protected override void DoAction(int action)
   {
-#pragma warning disable 162, 1522
     switch (action)
     {
       case 2: // progr -> block
@@ -201,90 +217,114 @@ public class Parser: ShiftReduceParser<ValueType, LexLocation>
       case 10: // statement -> empty
 { CurrentSemanticValue.stVal = ValueStack[ValueStack.Depth-1].stVal; }
         break;
-      case 11: // empty -> /* empty */
+      case 11: // statement -> if
+{ CurrentSemanticValue.stVal = ValueStack[ValueStack.Depth-1].stVal; }
+        break;
+      case 12: // statement -> while
+{ CurrentSemanticValue.stVal = ValueStack[ValueStack.Depth-1].stVal; }
+        break;
+      case 13: // statement -> repeat
+{ CurrentSemanticValue.stVal = ValueStack[ValueStack.Depth-1].stVal; }
+        break;
+      case 14: // empty -> /* empty */
 { CurrentSemanticValue.stVal = new EmptyNode(); }
         break;
-      case 12: // ident -> ID
+      case 15: // ident -> ID
 {
 			if (!InDefSect)
 				if (!SymbolTable.vars.ContainsKey(ValueStack[ValueStack.Depth-1].sVal))
-					throw new Exception("("+LocationStack[LocationStack.Depth-1].StartLine+","+LocationStack[LocationStack.Depth-1].StartColumn+"): Ïåðåìåííàÿ "+ValueStack[ValueStack.Depth-1].sVal+" íå îïèñàíà");
+					throw new Exception("("+LocationStack[LocationStack.Depth-1].StartLine+","+LocationStack[LocationStack.Depth-1].StartColumn+"): Переменная "+ValueStack[ValueStack.Depth-1].sVal+" не описана");
 			CurrentSemanticValue.eVal = new IdNode(ValueStack[ValueStack.Depth-1].sVal); 
 		}
         break;
-      case 13: // assign -> ident, ASSIGN, expr
+      case 16: // assign -> ident, ASSIGN, expr
 { CurrentSemanticValue.stVal = new AssignNode(ValueStack[ValueStack.Depth-3].eVal as IdNode, ValueStack[ValueStack.Depth-1].eVal); }
         break;
-      case 14: // expr -> expr, PLUS, T
+      case 17: // expr -> expr, PLUS, T
 { CurrentSemanticValue.eVal = new BinOpNode(ValueStack[ValueStack.Depth-3].eVal,ValueStack[ValueStack.Depth-1].eVal,'+'); }
         break;
-      case 15: // expr -> expr, MINUS, T
+      case 18: // expr -> expr, MINUS, T
 { CurrentSemanticValue.eVal = new BinOpNode(ValueStack[ValueStack.Depth-3].eVal,ValueStack[ValueStack.Depth-1].eVal,'-'); }
         break;
-      case 16: // expr -> T
+      case 19: // expr -> T
 { CurrentSemanticValue.eVal = ValueStack[ValueStack.Depth-1].eVal; }
         break;
-      case 17: // T -> T, MULT, F
+      case 20: // T -> T, MULT, F
 { CurrentSemanticValue.eVal = new BinOpNode(ValueStack[ValueStack.Depth-3].eVal,ValueStack[ValueStack.Depth-1].eVal,'*'); }
         break;
-      case 18: // T -> T, DIV, F
+      case 21: // T -> T, DIV, F
 { CurrentSemanticValue.eVal = new BinOpNode(ValueStack[ValueStack.Depth-3].eVal,ValueStack[ValueStack.Depth-1].eVal,'/'); }
         break;
-      case 19: // T -> F
+      case 22: // T -> T, MOD, F
+{ CurrentSemanticValue.eVal = new BinOpNode(ValueStack[ValueStack.Depth-3].eVal,ValueStack[ValueStack.Depth-1].eVal,'%'); }
+        break;
+      case 23: // T -> F
 { CurrentSemanticValue.eVal = ValueStack[ValueStack.Depth-1].eVal; }
         break;
-      case 20: // F -> ident
+      case 24: // F -> ident
 { CurrentSemanticValue.eVal = ValueStack[ValueStack.Depth-1].eVal as IdNode; }
         break;
-      case 21: // F -> INUM
+      case 25: // F -> INUM
 { CurrentSemanticValue.eVal = new IntNumNode(ValueStack[ValueStack.Depth-1].iVal); }
         break;
-      case 22: // F -> LPAREN, expr, RPAREN
+      case 26: // F -> LPAREN, expr, RPAREN
 { CurrentSemanticValue.eVal = ValueStack[ValueStack.Depth-2].eVal; }
         break;
-      case 23: // block -> BEGIN, stlist, END
+      case 27: // block -> BEGIN, stlist, END
 { CurrentSemanticValue.blVal = ValueStack[ValueStack.Depth-2].blVal; }
         break;
-      case 24: // cycle -> CYCLE, expr, statement
+      case 28: // cycle -> CYCLE, expr, statement
 { CurrentSemanticValue.stVal = new CycleNode(ValueStack[ValueStack.Depth-2].eVal,ValueStack[ValueStack.Depth-1].stVal); }
         break;
-      case 25: // write -> WRITE, LPAREN, expr, RPAREN
+      case 29: // write -> WRITE, LPAREN, expr, RPAREN
 { CurrentSemanticValue.stVal = new WriteNode(ValueStack[ValueStack.Depth-2].eVal); }
         break;
-      case 26: // Anon@1 -> /* empty */
+      case 30: // Anon@1 -> /* empty */
 { InDefSect = true; }
         break;
-      case 27: // var -> VAR, Anon@1, varlist
+      case 31: // var -> VAR, Anon@1, varlist
 { 
 			foreach (var v in (ValueStack[ValueStack.Depth-1].stVal as VarDefNode).vars)
 				SymbolTable.NewVarDef(v.Name, type.tint);
 			InDefSect = false;	
 		}
         break;
-      case 28: // varlist -> ident
+      case 32: // varlist -> ident
 { 
 			CurrentSemanticValue.stVal = new VarDefNode(ValueStack[ValueStack.Depth-1].eVal as IdNode); 
 		}
         break;
-      case 29: // varlist -> varlist, COLUMN, ident
+      case 33: // varlist -> varlist, COLUMN, ident
 { 
 			(ValueStack[ValueStack.Depth-3].stVal as VarDefNode).Add(ValueStack[ValueStack.Depth-1].eVal as IdNode);
 			CurrentSemanticValue.stVal = ValueStack[ValueStack.Depth-3].stVal;
 		}
         break;
+      case 34: // Anon@2 -> /* empty */
+{ CurrentSemanticValue.stVal = new IfNode(ValueStack[ValueStack.Depth-3].eVal, ValueStack[ValueStack.Depth-1].stVal); }
+        break;
+      case 36: // if -> IF, expr, THEN, statement, ELSE, statement
+{ CurrentSemanticValue.stVal = new IfNode(ValueStack[ValueStack.Depth-5].eVal, ValueStack[ValueStack.Depth-3].stVal, ValueStack[ValueStack.Depth-1].stVal); }
+        break;
+      case 37: // while -> WHILE, expr, DO, statement
+{ CurrentSemanticValue.stVal = new WhileNode(ValueStack[ValueStack.Depth-3].eVal, ValueStack[ValueStack.Depth-1].stVal); }
+        break;
+      case 38: // repeat -> REPEAT, stlist, UNTIL, expr
+{ CurrentSemanticValue.stVal = new RepeatNode(ValueStack[ValueStack.Depth-3].blVal, ValueStack[ValueStack.Depth-1].eVal); }
+        break;
     }
-#pragma warning restore 162, 1522
   }
 
   protected override string TerminalToString(int terminal)
   {
-    if (aliases != null && aliases.ContainsKey(terminal))
-        return aliases[terminal];
+    if (aliasses != null && aliasses.ContainsKey(terminal))
+        return aliasses[terminal];
     else if (((Tokens)terminal).ToString() != terminal.ToString(CultureInfo.InvariantCulture))
         return ((Tokens)terminal).ToString();
     else
         return CharToString((char)terminal);
   }
 
+
 }
 }
diff --git a/Module8/SimpleYacc.y b/Module8/SimpleYacc.y
index 20087e00b11254a052c1bfcd87f137d81203b253..868eb38b3d9be9400fc3525dbbaca632c711f114 100644
--- a/Module8/SimpleYacc.y
+++ b/Module8/SimpleYacc.y
@@ -24,13 +24,13 @@
 
 %start progr
 
-%token BEGIN END CYCLE ASSIGN ASSIGNPLUS ASSIGNMINUS ASSIGNMULT SEMICOLON WRITE VAR PLUS MINUS MULT DIV LPAREN RPAREN COLUMN
+%token BEGIN END CYCLE ASSIGN ASSIGNPLUS ASSIGNMINUS ASSIGNMULT SEMICOLON WRITE VAR PLUS MINUS MULT DIV MOD LPAREN RPAREN COLUMN WHILE DO REPEAT UNTIL LEFT_PR RIGHT_PR IF THEN ELSE
 %token <iVal> INUM 
 %token <dVal> RNUM 
 %token <sVal> ID
 
 %type <eVal> expr ident T F 
-%type <stVal> statement assign block cycle write empty var varlist 
+%type <stVal> statement assign block cycle write empty var varlist if while repeat 
 %type <blVal> stlist block
 
 %%
@@ -55,6 +55,9 @@ statement: assign { $$ = $1; }
 		| write   { $$ = $1; }
 		| var     { $$ = $1; }
 		| empty   { $$ = $1; }
+		| if      { $$ = $1; }
+		| while   { $$ = $1; }
+		| repeat  { $$ = $1; }
 		;
 
 empty	: { $$ = new EmptyNode(); }
@@ -79,6 +82,7 @@ expr	: expr PLUS T { $$ = new BinOpNode($1,$3,'+'); }
 		
 T 		: T MULT F { $$ = new BinOpNode($1,$3,'*'); }
 		| T DIV F { $$ = new BinOpNode($1,$3,'/'); }
+		| T MOD F { $$ = new BinOpNode($1,$3,'%'); }
 		| F { $$ = $1; }
 		;
 		
@@ -114,6 +118,16 @@ varlist	: ident
 			$$ = $1;
 		}
 		;
+
+if 		: IF expr THEN statement { $$ = new IfNode($2, $4); } %prec IFX
+		| IF expr THEN statement ELSE statement { $$ = new IfNode($2, $4, $6); }
+		;
+
+while   : WHILE expr DO statement { $$ = new WhileNode($2, $4); }
+		;
+
+repeat : REPEAT stlist UNTIL expr { $$ = new RepeatNode($2, $4); }
+		;
 	
 %%
 
diff --git a/Module8/Visitors/AutoVisitor.cs b/Module8/Visitors/AutoVisitor.cs
index 5d508770fc5449f20e1d15859b78725d4e64af48..28b94226db5eb3775c477c0bb130e4a395880f90 100644
--- a/Module8/Visitors/AutoVisitor.cs
+++ b/Module8/Visitors/AutoVisitor.cs
@@ -44,11 +44,23 @@ namespace SimpleLang.Visitors
         public override void VisitIfNode(IfNode cond)
         {
             cond.expr.Visit(this);
-            cond.ifTrue.Visit(this);
-            if (cond.ifFalse != null)
+            cond.True.Visit(this);
+            if (cond.False != null)
             {
-                cond.ifFalse.Visit(this);
+                cond.False.Visit(this);
             }
         }
-    }
+		public override void VisitWhileNode(WhileNode wh)
+		{
+			wh.Expr.Visit(this);
+			wh.Stat.Visit(this);
+		}
+
+		public override void VisitRepeatNode(RepeatNode rp)
+		{
+			foreach (var st in rp.StList)
+				st.Visit(this);
+			rp.Expr.Visit(this);
+		}
+	}
 }
diff --git a/Module8/Visitors/GenCodeVisitors/GenCodeVisitor.cs b/Module8/Visitors/GenCodeVisitors/GenCodeVisitor.cs
index 88891ad31e66280ab20cdf988e42cb6e1390af22..74efe970082036abebc33ea0eb81243d7b416b8f 100644
--- a/Module8/Visitors/GenCodeVisitors/GenCodeVisitor.cs
+++ b/Module8/Visitors/GenCodeVisitors/GenCodeVisitor.cs
@@ -44,8 +44,12 @@ namespace SimpleLang.Visitors
                 case '/':
                     genc.Emit(OpCodes.Div);
                     break;
-            }
-        }
+				case '%':
+					genc.Emit(OpCodes.Rem);
+					break;
+
+			}
+		}
         public override void VisitAssignNode(AssignNode a) 
         {
             a.Expr.Visit(this);
@@ -94,7 +98,51 @@ namespace SimpleLang.Visitors
                 vars[v.Name] = genc.DeclareLocal(typeof(int));
         }
 
-        public void EndProgram()
+		public override void VisitIfNode(IfNode i)
+		{
+			i.expr.Visit(this);
+			Label elseLabel = genc.DefineLabel();
+			Label endIfLabel = genc.DefineLabel();
+			genc.Emit(OpCodes.Brfalse, elseLabel);
+			i.True.Visit(this);
+			genc.Emit(OpCodes.Br, endIfLabel);
+			genc.MarkLabel(elseLabel);
+			if (i.False != null)
+				i.False.Visit(this);
+			genc.MarkLabel(endIfLabel);
+		}
+
+		public override void VisitWhileNode(WhileNode whileNode)
+		{
+			var loopLabel = genc.DefineLabel();
+			var endLabel = genc.DefineLabel();
+
+			genc.MarkLabel(loopLabel);
+			whileNode.Expr.Visit(this);
+			genc.Emit(OpCodes.Ldc_I4_0);
+			genc.Emit(OpCodes.Beq, endLabel);
+			whileNode.Stat.Visit(this);
+			genc.Emit(OpCodes.Br, loopLabel);
+			genc.MarkLabel(endLabel);
+		}
+
+		public override void VisitRepeatNode(RepeatNode repeatNode)
+		{
+			var loopLabel = genc.DefineLabel();
+			var endLabel = genc.DefineLabel();
+
+			genc.MarkLabel(loopLabel);
+			foreach (var st in repeatNode.StList)
+				st.Visit(this);
+			repeatNode.Expr.Visit(this);
+			genc.Emit(OpCodes.Ldc_I4_0);
+			genc.Emit(OpCodes.Beq, endLabel);
+			genc.Emit(OpCodes.Br, loopLabel);
+			genc.MarkLabel(endLabel);
+		}
+
+
+		public void EndProgram()
         {
             genc.EndProgram();
         }
diff --git a/Module8/Visitors/PrettyPrintVisitor.cs b/Module8/Visitors/PrettyPrintVisitor.cs
index 3d15de39959c545a460a796bde688a34245d45b0..1a49154e45ee2a1d6c9a882394cac1e17324af61 100644
--- a/Module8/Visitors/PrettyPrintVisitor.cs
+++ b/Module8/Visitors/PrettyPrintVisitor.cs
@@ -91,15 +91,15 @@ namespace SimpleLang.Visitors
             Text += " then ";
             Text += Environment.NewLine;
             IndentPlus();
-            cond.ifTrue.Visit(this);
+            cond.True.Visit(this);
             IndentMinus();
-            if (null != cond.ifFalse)
+            if (null != cond.False)
             {
                 Text += Environment.NewLine;
                 Text += IndentStr() + "else ";
                 Text += Environment.NewLine;
                 IndentPlus();
-                cond.ifFalse.Visit(this);
+                cond.False.Visit(this);
                 IndentMinus();
             }
         }
diff --git a/Module8/Visitors/Visitor.cs b/Module8/Visitors/Visitor.cs
index 5fc65fcae1f33553c60fe2590eba8e3f086a85ca..faf85a576b8238404c011b86f2f283968f960f28 100644
--- a/Module8/Visitors/Visitor.cs
+++ b/Module8/Visitors/Visitor.cs
@@ -18,5 +18,8 @@ namespace SimpleLang.Visitors
         public virtual void VisitVarDefNode(VarDefNode w) { }
         public virtual void VisitEmptyNode(EmptyNode w) { }
         public virtual void VisitIfNode(IfNode cond) { }
-    }
+		public virtual void VisitWhileNode(WhileNode cond) { }
+		public virtual void VisitRepeatNode(RepeatNode cond) { }
+
+	}
 }
diff --git a/Module8/packages.config b/Module8/packages.config
index 14b53d1ecb2e718f6d9c15e6fcb20c081a72bdd1..d0fb986492e0124959ef4ef01a8aaaa3e862c76b 100644
--- a/Module8/packages.config
+++ b/Module8/packages.config
@@ -1,6 +1,6 @@
 п»ї<?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="NUnit" version="3.13.3" targetFramework="net40" />
-  <package id="NUnit.ConsoleRunner" version="3.15.2" targetFramework="net40" />
-  <package id="NUnit3TestAdapter" version="4.2.1" targetFramework="net40" />
+  <package id="NUnit.ConsoleRunner" version="3.16.0" targetFramework="net40" />
+  <package id="NUnit3TestAdapter" version="4.3.1" targetFramework="net40" />
 </packages>
\ No newline at end of file