From d04525788705488f0ec0851da2b22c307f4af905 Mon Sep 17 00:00:00 2001
From: unknown <user@mil8a-202a-05.mmcs.sfedu.ru>
Date: Mon, 7 Nov 2022 10:08:10 +0300
Subject: [PATCH] lab6 done

---
 Module6/ProgramTree.cs |  85 +++++++++++-
 Module6/SimpleLex.cs   | 258 ++++++++++++++++++++--------------
 Module6/SimpleLex.lex  |  38 ++++--
 Module6/SimpleYacc.cs  | 304 +++++++++++++++++++++++++++++------------
 Module6/SimpleYacc.y   |  99 ++++++++++----
 TestASTParser/Tests.cs | 266 ++++++++++++++++++++++--------------
 6 files changed, 711 insertions(+), 339 deletions(-)

diff --git a/Module6/ProgramTree.cs b/Module6/ProgramTree.cs
index ade12f7..6bd3282 100644
--- a/Module6/ProgramTree.cs
+++ b/Module6/ProgramTree.cs
@@ -3,8 +3,9 @@
 namespace ProgramTree
 {
     public enum AssignType { Assign, AssignPlus, AssignMinus, AssignMult, AssignDivide };
+	public enum BinOpType { Plus, Minus, Mult, Division };
 
-    public class Node // базовый класс для всех узлов    
+	public class Node // базовый класс для всех узлов    
     {
     }
 
@@ -65,4 +66,86 @@ namespace ProgramTree
         }
     }
 
+	public class WhileNode : StatementNode
+	{
+		public ExprNode Expr { get; set; }
+		public StatementNode Stat { get; set; }
+		public WhileNode(ExprNode expr, StatementNode stat)
+		{
+			Expr = expr;
+			Stat = stat;
+		}
+	}
+
+	public class RepeatNode : StatementNode
+	{
+		public StatementNode State { get; set; }
+		public ExprNode Expr { get; set; }
+		public RepeatNode(StatementNode state, ExprNode expr)
+		{
+			State = state;
+			Expr = expr;
+		}
+	}
+
+	public class ForNode : StatementNode
+	{
+		public AssignNode Assign { get; set; }
+		public ExprNode Expr { get; set; }
+		public StatementNode State { get; set; }
+		public ForNode(AssignNode assign, ExprNode expr, StatementNode state)
+		{
+			Assign = assign;
+			Expr = expr;
+			State = state;
+		}
+	}
+
+	public class WriteNode : StatementNode
+	{
+		public ExprNode Expr { get; set; }
+		public WriteNode(ExprNode expr)
+		{
+			Expr = expr;
+		}
+	}
+
+	public class IfNode : StatementNode
+	{
+		public ExprNode Expr { get; set; }
+		public StatementNode State { get; set; }
+		public StatementNode ElseStat { get; set; }
+		public IfNode(ExprNode expr, StatementNode state, StatementNode elsestat = null)
+		{
+			Expr = expr;
+			State = state;
+			ElseStat = elsestat;
+		}
+	}
+
+	public class VarDefNode : StatementNode
+	{
+		public List<IdNode> IdList = new List<IdNode>();
+		public VarDefNode(IdNode id)
+		{
+			Add(id);
+		}
+		public void Add(IdNode id)
+		{
+			IdList.Add(id);
+		}
+	}
+
+	public class BinaryNode : ExprNode
+	{
+		public ExprNode Left { get; set; }
+		public ExprNode Right { get; set; }
+		public BinOpType Op { get; set; }
+		public BinaryNode(ExprNode left, ExprNode right, BinOpType op)
+		{
+			Left = left;
+			Right = right;
+			Op = op;
+		}
+	}
 }
\ No newline at end of file
diff --git a/Module6/SimpleLex.cs b/Module6/SimpleLex.cs
index c518c8b..5779184 100644
--- a/Module6/SimpleLex.cs
+++ b/Module6/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:14:30
-//  UserName: someone
-//  GPLEX input file <SimpleLex.lex - 24.09.2018 23:47:03>
+//  Version:  1.1.3.301
+//  Machine:  MIL8A-202A-05
+//  DateTime: 07.11.2022 10:01:58
+//  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 = 7;
-        const int initial = 8;
+        const int maxAccept = 14;
+        const int initial = 15;
         const int eofNum = 0;
         const int goStart = -1;
         const int INITIAL = 0;
@@ -165,24 +161,24 @@ namespace SimpleScanner
         }
     };
 
-    static int[] startState = new int[] {8, 0};
+    static int[] startState = new int[] {15, 0};
 
 #region CompressedCharacterMap
     //
-    // There are 8 equivalence classes
+    // There are 15 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' */ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 0, 7, 7, 
-/*   '\x10' */ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
-/*   '\x20' */ 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 
-/*      '0' */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 6, 7, 5, 7, 7, 
-/*      '@' */ 7, 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, 7, 7, 7, 7, 3, 
-/*      '`' */ 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+/*     '\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, 7, 8, 12, 10, 9, 11, 2, 13, 
+/*      '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, 
 /*      'p' */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };
 
     static sbyte MapC(int code)
@@ -190,22 +186,29 @@ namespace SimpleScanner
       if (code < 123) // '\0' <= code <= 'z'
         return mapC0[code - 0];
       else // '{' <= code <= '\U0010FFFF'
-        return (sbyte)7;
+        return (sbyte)14;
     }
 #endregion
 
-    static Table[] NxS = new Table[10] {
+    static Table[] NxS = new Table[17] {
 /* NxS[   0] */ new Table(0, 0, 0, null),
-/* NxS[   1] */ new Table(1, 2, -1, new sbyte[] {1, 9}),
+/* NxS[   1] */ new Table(1, 2, -1, new sbyte[] {1, 16}),
 /* 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[] {6}),
+/* NxS[   4] */ new Table(5, 1, -1, new sbyte[] {13}),
 /* NxS[   5] */ new Table(0, 0, -1, null),
 /* NxS[   6] */ new Table(0, 0, -1, null),
-/* NxS[   7] */ new Table(1, 1, -1, new sbyte[] {7}),
-/* NxS[   8] */ new Table(1, 7, -1, new sbyte[] {1, 2, 3, 4, 2, 5, 
-          2}),
-/* NxS[   9] */ new Table(1, 1, -1, new sbyte[] {7}),
+/* NxS[   7] */ new Table(0, 0, -1, null),
+/* NxS[   8] */ new Table(0, 0, -1, null),
+/* NxS[   9] */ new Table(0, 0, -1, null),
+/* NxS[  10] */ new Table(0, 0, -1, null),
+/* NxS[  11] */ new Table(0, 0, -1, null),
+/* NxS[  12] */ new Table(0, 0, -1, null),
+/* NxS[  13] */ new Table(0, 0, -1, null),
+/* NxS[  14] */ new Table(1, 1, -1, new sbyte[] {14}),
+/* NxS[  15] */ new Table(1, 14, -1, new sbyte[] {1, 2, 3, 4, 2, 5, 
+          6, 7, 8, 9, 10, 11, 12, 2}),
+/* NxS[  16] */ new Table(1, 1, -1, new sbyte[] {14}),
     };
 
 int NextState() {
@@ -215,7 +218,7 @@ int NextState() {
         unchecked {
             int rslt;
             int idx = MapC(code) - NxS[state].min;
-            if (idx < 0) idx += 8;
+            if (idx < 0) idx += 15;
             if ((uint)idx >= (uint)NxS[state].rng) rslt = NxS[state].dflt;
             else rslt = NxS[state].nxt[idx];
             return rslt;
@@ -295,7 +298,8 @@ int NextState() {
 
         public Scanner(Stream file, string codepage) {
             SetSource(file, CodePageHandling.GetCodePage(codepage));
-        }   
+        }
+        
 #endif // !NOFILES
 
      public Scanner() { }
@@ -323,7 +327,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++;
@@ -376,7 +380,9 @@ int NextState() {
             GetCode();
         }
 
+#if !NOFILES        
         // ================ LineBuffer Initialization ===================
+
         /// <summary>
         /// Create and initialize a LineBuff buffer object for this scanner
         /// </summary>
@@ -390,7 +396,6 @@ int NextState() {
             GetCode();
         }
 
-#if !NOFILES        
         // =============== StreamBuffer Initialization ==================
 
         /// <summary>
@@ -492,12 +497,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)
         {
@@ -517,10 +516,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); }
         
@@ -533,23 +528,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;
@@ -558,7 +548,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
@@ -583,56 +573,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:
@@ -646,27 +645,49 @@ yylval.iVal = int.Parse(yytext);
         case 2:
         case 4:
 LexError();
+	return (int)Tokens.EOF;
             break;
         case 3:
 int res = ScannerHelper.GetIDToken(yytext);
   if (res == (int)Tokens.ID)
-	yylval.sVal = yytext;
+    yylval.sVal = yytext;
   return res;
             break;
         case 5:
 return (int)Tokens.SEMICOLON;
             break;
         case 6:
-return (int)Tokens.ASSIGN;
+return (int)Tokens.LEFT_PR;
             break;
         case 7:
+return (int)Tokens.RIGHT_PR;
+            break;
+        case 8:
+return (int)Tokens.COMMA;
+            break;
+        case 9:
+return (int)Tokens.PLUS;
+            break;
+        case 10:
+return (int)Tokens.MINUS;
+            break;
+        case 11:
+return (int)Tokens.MULT;
+            break;
+        case 12:
+return (int)Tokens.DIVISION;
+            break;
+        case 13:
+return (int)Tokens.ASSIGN;
+            break;
+        case 14:
 yylval.dVal = double.Parse(yytext); 
   return (int)Tokens.RNUM;
             break;
         default:
             break;
     }
-#pragma warning restore 162, 1522
+#pragma warning restore 162
 #endregion
                     }
                 }
@@ -679,7 +700,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;
@@ -688,7 +731,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;
@@ -696,7 +740,8 @@ yylloc = new LexLocation(tokLin, tokCol, tokELin, tokECol);
             state = ctx.state;
             code  = ctx.cChr;
         }
-#endif  // BACKUP
+
+#endif // BACKUP
 
         // ============= End of the tokenizer code ================
 
@@ -728,17 +773,17 @@ 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));
+  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 
@@ -751,15 +796,25 @@ class ScannerHelper
     keywords.Add("begin",(int)Tokens.BEGIN);
     keywords.Add("end",(int)Tokens.END);
     keywords.Add("cycle",(int)Tokens.CYCLE);
+	keywords.Add("while",(int)Tokens.WHILE);
+    keywords.Add("do",(int)Tokens.DO);
+    keywords.Add("repeat",(int)Tokens.REPEAT);
+    keywords.Add("until",(int)Tokens.UNTIL);
+    keywords.Add("for",(int)Tokens.FOR);
+    keywords.Add("to",(int)Tokens.TO);
+    keywords.Add("write",(int)Tokens.WRITE);
+    keywords.Add("if",(int)Tokens.IF);
+    keywords.Add("then",(int)Tokens.THEN);
+    keywords.Add("else",(int)Tokens.ELSE);
+    keywords.Add("var",(int)Tokens.VAR);
   }
   public static int GetIDToken(string s)
   {
-	if (keywords.ContainsKey(s.ToLower()))
-	  return keywords[s];
-	else
+    if (keywords.ContainsKey(s.ToLower())) // язык нечувствителен к регистру
+      return keywords[s];
+    else
       return (int)Tokens.ID;
   }
-  
 }
 
 #endregion
@@ -811,7 +866,6 @@ class ScannerHelper
             return new LineBuffer(source);
         }
 
-#if (!NOFILES)
         public static ScanBuff GetBuffer(Stream source)
         {
             return new BuildBuffer(source);
@@ -822,8 +876,7 @@ class ScannerHelper
         {
             return new BuildBuffer(source, fallbackCodePage);
         }
-#endif // !BYTEMODE
-#endif // !NOFILES
+#endif
     }
 
     #region Buffer classes
@@ -946,7 +999,7 @@ class ScannerHelper
             {
                 ix = lstart = 0;
             }
-            while (ix < numLines)
+            for (; ; )
             {
                 int len = line[ix].Length + 1;
                 if (pos < lstart + len) break;
@@ -1004,8 +1057,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;
             }
         }
@@ -1013,7 +1065,7 @@ class ScannerHelper
         public override string ToString() { return "LineBuffer"; }
     }
 
-#if (!NOFILES)
+
     // ==============================================================
     // =====     class BuildBuff : for unicode text files    ========
     // ==============================================================
@@ -1254,13 +1306,12 @@ class ScannerHelper
         }
 #endif // !BYTEMODE
     }
-#endif // !NOFILES
     #endregion Buffer classes
 
     // ==============================================================
     // ============      class CodePageHandling         =============
     // ==============================================================
-#if (!NOFILES)
+
     public static class CodePageHandling
     {
         public static int GetCodePage(string option)
@@ -1471,7 +1522,6 @@ class ScannerHelper
     
 #endif // !BYTEMODE
 #endregion
-#endif // !NOFILES
 
 // End of code copied from embedded resource
 
diff --git a/Module6/SimpleLex.lex b/Module6/SimpleLex.lex
index 20b364f..3be76d6 100644
--- a/Module6/SimpleLex.lex
+++ b/Module6/SimpleLex.lex
@@ -26,19 +26,27 @@ ID {Alpha}{AlphaDigit}*
 {ID}  { 
   int res = ScannerHelper.GetIDToken(yytext);
   if (res == (int)Tokens.ID)
-	yylval.sVal = yytext;
+    yylval.sVal = yytext;
   return res;
 }
 
 ":=" { return (int)Tokens.ASSIGN; }
-";" { return (int)Tokens.SEMICOLON; }
+";"  { return (int)Tokens.SEMICOLON; }
+"("  { return (int)Tokens.LEFT_PR; }
+")"  { return (int)Tokens.RIGHT_PR; }
+"," { return (int)Tokens.COMMA; }
+"+" { return (int)Tokens.PLUS; }
+"-" { return (int)Tokens.MINUS; }
+"*" { return (int)Tokens.MULT; }
+"/" { return (int)Tokens.DIVISION; }
 
 [^ \r\n] {
 	LexError();
+	return (int)Tokens.EOF; // конец разбора
 }
 
 %{
-  yylloc = new LexLocation(tokLin, tokCol, tokELin, tokECol);
+  yylloc = new LexLocation(tokLin, tokCol, tokELin, tokECol); // позиция символа (терминального или нетерминального), возвращаемая @1 @2 и т.д.
 %}
 
 %%
@@ -52,8 +60,8 @@ public override void yyerror(string format, params object[] args) // 
 
 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 
@@ -66,13 +74,23 @@ class ScannerHelper
     keywords.Add("begin",(int)Tokens.BEGIN);
     keywords.Add("end",(int)Tokens.END);
     keywords.Add("cycle",(int)Tokens.CYCLE);
+	keywords.Add("while",(int)Tokens.WHILE);
+    keywords.Add("do",(int)Tokens.DO);
+    keywords.Add("repeat",(int)Tokens.REPEAT);
+    keywords.Add("until",(int)Tokens.UNTIL);
+    keywords.Add("for",(int)Tokens.FOR);
+    keywords.Add("to",(int)Tokens.TO);
+    keywords.Add("write",(int)Tokens.WRITE);
+    keywords.Add("if",(int)Tokens.IF);
+    keywords.Add("then",(int)Tokens.THEN);
+    keywords.Add("else",(int)Tokens.ELSE);
+    keywords.Add("var",(int)Tokens.VAR);
   }
   public static int GetIDToken(string s)
   {
-	if (keywords.ContainsKey(s.ToLower()))
-	  return keywords[s];
-	else
+    if (keywords.ContainsKey(s.ToLower())) // язык нечувствителен к регистру
+      return keywords[s];
+    else
       return (int)Tokens.ID;
   }
-  
-}
+}
\ No newline at end of file
diff --git a/Module6/SimpleYacc.cs b/Module6/SimpleYacc.cs
index b13b1e9..4608df0 100644
--- a/Module6/SimpleYacc.cs
+++ b/Module6/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:14:41
-// UserName: someone
-// Input file <SimpleYacc.y - 24.09.2018 23:47:03>
+// GPPG version 1.3.6
+// Machine:  MIL8A-202A-05
+// DateTime: 07.11.2022 10:01:59
+// 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;
@@ -20,95 +19,157 @@ using ProgramTree;
 
 namespace SimpleParser
 {
-public enum Tokens {error=2,EOF=3,BEGIN=4,END=5,CYCLE=6,
-    ASSIGN=7,SEMICOLON=8,INUM=9,RNUM=10,ID=11};
+public enum Tokens {
+    error=1,EOF=2,BEGIN=3,END=4,CYCLE=5,INUM=6,
+    RNUM=7,ID=8,ASSIGN=9,SEMICOLON=10,WHILE=11,DO=12,
+    REPEAT=13,UNTIL=14,FOR=15,TO=16,WRITE=17,LEFT_PR=18,
+    RIGHT_PR=19,IF=20,ELSE=21,THEN=22,VAR=23,COMMA=24,
+    PLUS=25,MINUS=26,MULT=27,DIVISION=28,IFX=29};
 
 public struct ValueType
 { 
-			public double dVal; 
-			public int iVal; 
-			public string sVal; 
-			public Node nVal;
-			public ExprNode eVal;
-			public StatementNode stVal;
-			public BlockNode blVal;
+    public double dVal; 
+    public int iVal; 
+    public string sVal; 
+    public Node nVal;
+    public ExprNode eVal;
+    public StatementNode stVal;
+    public BlockNode blVal;
+	public VarDefNode vdVal;
        }
 // 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 - 24.09.2018 23:47:03
-// Ýòè îáúÿâëåíèÿ äîáàâëÿþòñÿ â êëàññ GPPGParser, ïðåäñòàâëÿþùèé ñîáîé ïàðñåð, ãåíåðèðóåìûé ñèñòåìîé gppg
-    public BlockNode root; // Êîðíåâîé óçåë ñèíòàêñè÷åñêîãî äåðåâà 
+  // Verbatim content from SimpleYacc.y
+	public BlockNode root; // Эти объявления добавляются в класс GPPGParser, представляющий собой парсер, генерируемый системой gppg    
     public Parser(AbstractScanner<ValueType, LexLocation> scanner) : base(scanner) { }
-  // End verbatim content from SimpleYacc.y - 24.09.2018 23:47:03
+  // 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[14];
-  private static State[] states = new State[22];
+  private static Rule[] rules = new Rule[37];
+  private static State[] states = new State[71];
   private static string[] nonTerms = new string[] {
-      "expr", "ident", "assign", "statement", "cycle", "stlist", "block", "progr", 
-      "$accept", };
+      "expr", "ident", "T", "F", "assign", "statement", "cycle", "while", "repeat", 
+      "for", "write", "if", "var", "stlist", "block", "idList", "progr", "$accept", 
+      "Anon@1", };
 
   static Parser() {
-    states[0] = new State(new int[]{4,4},new int[]{-8,1,-7,3});
-    states[1] = new State(new int[]{3,2});
+    states[0] = new State(new int[]{3,4},new int[]{-17,1,-15,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[]{11,14,4,4,6,18},new int[]{-6,5,-4,21,-3,9,-2,10,-7,16,-5,17});
-    states[5] = new State(new int[]{5,6,8,7});
-    states[6] = new State(-12);
-    states[7] = new State(new int[]{11,14,4,4,6,18},new int[]{-4,8,-3,9,-2,10,-7,16,-5,17});
+    states[4] = new State(new int[]{8,18,3,4,5,31,11,35,13,40,15,46,17,53,20,58,23,66},new int[]{-14,5,-6,44,-5,9,-2,10,-15,29,-7,30,-8,34,-9,39,-10,45,-11,52,-12,57,-13,65});
+    states[5] = new State(new int[]{4,6,10,7});
+    states[6] = new State(-16);
+    states[7] = new State(new int[]{8,18,3,4,5,31,11,35,13,40,15,46,17,53,20,58,23,66},new int[]{-6,8,-5,9,-2,10,-15,29,-7,30,-8,34,-9,39,-10,45,-11,52,-12,57,-13,65});
     states[8] = new State(-4);
     states[9] = new State(-5);
-    states[10] = new State(new int[]{7,11});
-    states[11] = new State(new int[]{11,14,9,15},new int[]{-1,12,-2,13});
-    states[12] = new State(-9);
-    states[13] = new State(-10);
-    states[14] = new State(-8);
-    states[15] = new State(-11);
-    states[16] = new State(-6);
-    states[17] = new State(-7);
-    states[18] = new State(new int[]{11,14,9,15},new int[]{-1,19,-2,13});
-    states[19] = new State(new int[]{11,14,4,4,6,18},new int[]{-4,20,-3,9,-2,10,-7,16,-5,17});
-    states[20] = new State(-13);
-    states[21] = new State(-3);
+    states[10] = new State(new int[]{9,11});
+    states[11] = new State(new int[]{8,18,6,19,18,20},new int[]{-1,12,-3,28,-4,27,-2,17});
+    states[12] = new State(new int[]{25,13,26,23,4,-15,10,-15,14,-15,21,-15,16,-15});
+    states[13] = new State(new int[]{8,18,6,19,18,20},new int[]{-3,14,-4,27,-2,17});
+    states[14] = new State(new int[]{27,15,28,25,25,-29,26,-29,4,-29,10,-29,14,-29,21,-29,16,-29,19,-29,8,-29,3,-29,5,-29,11,-29,13,-29,15,-29,17,-29,20,-29,23,-29,12,-29,22,-29});
+    states[15] = new State(new int[]{8,18,6,19,18,20},new int[]{-4,16,-2,17});
+    states[16] = new State(-32);
+    states[17] = new State(-34);
+    states[18] = new State(-14);
+    states[19] = new State(-35);
+    states[20] = new State(new int[]{8,18,6,19,18,20},new int[]{-1,21,-3,28,-4,27,-2,17});
+    states[21] = new State(new int[]{19,22,25,13,26,23});
+    states[22] = new State(-36);
+    states[23] = new State(new int[]{8,18,6,19,18,20},new int[]{-3,24,-4,27,-2,17});
+    states[24] = new State(new int[]{27,15,28,25,25,-30,26,-30,4,-30,10,-30,14,-30,21,-30,16,-30,19,-30,8,-30,3,-30,5,-30,11,-30,13,-30,15,-30,17,-30,20,-30,23,-30,12,-30,22,-30});
+    states[25] = new State(new int[]{8,18,6,19,18,20},new int[]{-4,26,-2,17});
+    states[26] = new State(-33);
+    states[27] = new State(-31);
+    states[28] = new State(new int[]{27,15,28,25,25,-28,26,-28,4,-28,10,-28,14,-28,21,-28,16,-28,19,-28,8,-28,3,-28,5,-28,11,-28,13,-28,15,-28,17,-28,20,-28,23,-28,12,-28,22,-28});
+    states[29] = new State(-6);
+    states[30] = new State(-7);
+    states[31] = new State(new int[]{8,18,6,19,18,20},new int[]{-1,32,-3,28,-4,27,-2,17});
+    states[32] = new State(new int[]{25,13,26,23,8,18,3,4,5,31,11,35,13,40,15,46,17,53,20,58,23,66},new int[]{-6,33,-5,9,-2,10,-15,29,-7,30,-8,34,-9,39,-10,45,-11,52,-12,57,-13,65});
+    states[33] = new State(-17);
+    states[34] = new State(-8);
+    states[35] = new State(new int[]{8,18,6,19,18,20},new int[]{-1,36,-3,28,-4,27,-2,17});
+    states[36] = new State(new int[]{12,37,25,13,26,23});
+    states[37] = new State(new int[]{8,18,3,4,5,31,11,35,13,40,15,46,17,53,20,58,23,66},new int[]{-6,38,-5,9,-2,10,-15,29,-7,30,-8,34,-9,39,-10,45,-11,52,-12,57,-13,65});
+    states[38] = new State(-18);
+    states[39] = new State(-9);
+    states[40] = new State(new int[]{8,18,3,4,5,31,11,35,13,40,15,46,17,53,20,58,23,66},new int[]{-14,41,-6,44,-5,9,-2,10,-15,29,-7,30,-8,34,-9,39,-10,45,-11,52,-12,57,-13,65});
+    states[41] = new State(new int[]{14,42,10,7});
+    states[42] = new State(new int[]{8,18,6,19,18,20},new int[]{-1,43,-3,28,-4,27,-2,17});
+    states[43] = new State(new int[]{25,13,26,23,4,-19,10,-19,14,-19,21,-19});
+    states[44] = new State(-3);
+    states[45] = new State(-10);
+    states[46] = new State(new int[]{8,18},new int[]{-5,47,-2,10});
+    states[47] = new State(new int[]{16,48});
+    states[48] = new State(new int[]{8,18,6,19,18,20},new int[]{-1,49,-3,28,-4,27,-2,17});
+    states[49] = new State(new int[]{12,50,25,13,26,23});
+    states[50] = new State(new int[]{8,18,3,4,5,31,11,35,13,40,15,46,17,53,20,58,23,66},new int[]{-6,51,-5,9,-2,10,-15,29,-7,30,-8,34,-9,39,-10,45,-11,52,-12,57,-13,65});
+    states[51] = new State(-20);
+    states[52] = new State(-11);
+    states[53] = new State(new int[]{18,54});
+    states[54] = new State(new int[]{8,18,6,19,18,20},new int[]{-1,55,-3,28,-4,27,-2,17});
+    states[55] = new State(new int[]{19,56,25,13,26,23});
+    states[56] = new State(-21);
+    states[57] = new State(-12);
+    states[58] = new State(new int[]{8,18,6,19,18,20},new int[]{-1,59,-3,28,-4,27,-2,17});
+    states[59] = new State(new int[]{22,60,25,13,26,23});
+    states[60] = new State(new int[]{8,18,3,4,5,31,11,35,13,40,15,46,17,53,20,58,23,66},new int[]{-6,61,-5,9,-2,10,-15,29,-7,30,-8,34,-9,39,-10,45,-11,52,-12,57,-13,65});
+    states[61] = new State(new int[]{21,63,4,-22,10,-22,14,-22},new int[]{-19,62});
+    states[62] = new State(-23);
+    states[63] = new State(new int[]{8,18,3,4,5,31,11,35,13,40,15,46,17,53,20,58,23,66},new int[]{-6,64,-5,9,-2,10,-15,29,-7,30,-8,34,-9,39,-10,45,-11,52,-12,57,-13,65});
+    states[64] = new State(-24);
+    states[65] = new State(-13);
+    states[66] = new State(new int[]{8,18},new int[]{-16,67,-2,70});
+    states[67] = new State(new int[]{24,68,4,-27,10,-27,14,-27,21,-27});
+    states[68] = new State(new int[]{8,18},new int[]{-2,69});
+    states[69] = new State(-26);
+    states[70] = new State(-25);
 
-    for (int sNo = 0; sNo < states.Length; sNo++) states[sNo].number = sNo;
-
-    rules[1] = new Rule(-9, new int[]{-8,3});
-    rules[2] = new Rule(-8, new int[]{-7});
-    rules[3] = new Rule(-6, new int[]{-4});
-    rules[4] = new Rule(-6, new int[]{-6,8,-4});
-    rules[5] = new Rule(-4, new int[]{-3});
-    rules[6] = new Rule(-4, new int[]{-7});
-    rules[7] = new Rule(-4, new int[]{-5});
-    rules[8] = new Rule(-2, new int[]{11});
-    rules[9] = new Rule(-3, new int[]{-2,7,-1});
-    rules[10] = new Rule(-1, new int[]{-2});
-    rules[11] = new Rule(-1, new int[]{9});
-    rules[12] = new Rule(-7, new int[]{4,-6,5});
-    rules[13] = new Rule(-5, new int[]{6,-1,-4});
+    rules[1] = new Rule(-18, new int[]{-17,2});
+    rules[2] = new Rule(-17, new int[]{-15});
+    rules[3] = new Rule(-14, new int[]{-6});
+    rules[4] = new Rule(-14, new int[]{-14,10,-6});
+    rules[5] = new Rule(-6, new int[]{-5});
+    rules[6] = new Rule(-6, new int[]{-15});
+    rules[7] = new Rule(-6, new int[]{-7});
+    rules[8] = new Rule(-6, new int[]{-8});
+    rules[9] = new Rule(-6, new int[]{-9});
+    rules[10] = new Rule(-6, new int[]{-10});
+    rules[11] = new Rule(-6, new int[]{-11});
+    rules[12] = new Rule(-6, new int[]{-12});
+    rules[13] = new Rule(-6, new int[]{-13});
+    rules[14] = new Rule(-2, new int[]{8});
+    rules[15] = new Rule(-5, new int[]{-2,9,-1});
+    rules[16] = new Rule(-15, new int[]{3,-14,4});
+    rules[17] = new Rule(-7, new int[]{5,-1,-6});
+    rules[18] = new Rule(-8, new int[]{11,-1,12,-6});
+    rules[19] = new Rule(-9, new int[]{13,-14,14,-1});
+    rules[20] = new Rule(-10, new int[]{15,-5,16,-1,12,-6});
+    rules[21] = new Rule(-11, new int[]{17,18,-1,19});
+    rules[22] = new Rule(-19, new int[]{});
+    rules[23] = new Rule(-12, new int[]{20,-1,22,-6,-19});
+    rules[24] = new Rule(-12, new int[]{20,-1,22,-6,21,-6});
+    rules[25] = new Rule(-16, new int[]{-2});
+    rules[26] = new Rule(-16, new int[]{-16,24,-2});
+    rules[27] = new Rule(-13, new int[]{23,-16});
+    rules[28] = new Rule(-1, new int[]{-3});
+    rules[29] = new Rule(-1, new int[]{-1,25,-3});
+    rules[30] = new Rule(-1, new int[]{-1,26,-3});
+    rules[31] = new Rule(-3, new int[]{-4});
+    rules[32] = new Rule(-3, new int[]{-3,27,-4});
+    rules[33] = new Rule(-3, new int[]{-3,28,-4});
+    rules[34] = new Rule(-4, new int[]{-2});
+    rules[35] = new Rule(-4, new int[]{6});
+    rules[36] = new Rule(-4, new int[]{18,-1,19});
   }
 
   protected override void Initialize() {
@@ -120,7 +181,6 @@ public class Parser: ShiftReduceParser<ValueType, LexLocation>
 
   protected override void DoAction(int action)
   {
-#pragma warning disable 162, 1522
     switch (action)
     {
       case 2: // progr -> block
@@ -128,14 +188,14 @@ public class Parser: ShiftReduceParser<ValueType, LexLocation>
         break;
       case 3: // stlist -> statement
 { 
-				CurrentSemanticValue.blVal = new BlockNode(ValueStack[ValueStack.Depth-1].stVal); 
-			}
+			CurrentSemanticValue.blVal = new BlockNode(ValueStack[ValueStack.Depth-1].stVal); 
+		}
         break;
       case 4: // stlist -> stlist, SEMICOLON, statement
 { 
-				ValueStack[ValueStack.Depth-3].blVal.Add(ValueStack[ValueStack.Depth-1].stVal); 
-				CurrentSemanticValue.blVal = ValueStack[ValueStack.Depth-3].blVal; 
-			}
+			ValueStack[ValueStack.Depth-3].blVal.Add(ValueStack[ValueStack.Depth-1].stVal); 
+			CurrentSemanticValue.blVal = ValueStack[ValueStack.Depth-3].blVal; 
+		}
         break;
       case 5: // statement -> assign
 { CurrentSemanticValue.stVal = ValueStack[ValueStack.Depth-1].stVal; }
@@ -146,38 +206,102 @@ public class Parser: ShiftReduceParser<ValueType, LexLocation>
       case 7: // statement -> cycle
 { CurrentSemanticValue.stVal = ValueStack[ValueStack.Depth-1].stVal; }
         break;
-      case 8: // ident -> ID
+      case 8: // statement -> while
+{ CurrentSemanticValue.stVal = ValueStack[ValueStack.Depth-1].stVal; }
+        break;
+      case 9: // statement -> repeat
+{ CurrentSemanticValue.stVal = ValueStack[ValueStack.Depth-1].stVal; }
+        break;
+      case 10: // statement -> for
+{ CurrentSemanticValue.stVal = ValueStack[ValueStack.Depth-1].stVal; }
+        break;
+      case 11: // statement -> write
+{ CurrentSemanticValue.stVal = ValueStack[ValueStack.Depth-1].stVal; }
+        break;
+      case 12: // statement -> if
+{ CurrentSemanticValue.stVal = ValueStack[ValueStack.Depth-1].stVal; }
+        break;
+      case 13: // statement -> var
+{ CurrentSemanticValue.stVal = ValueStack[ValueStack.Depth-1].stVal; }
+        break;
+      case 14: // ident -> ID
 { CurrentSemanticValue.eVal = new IdNode(ValueStack[ValueStack.Depth-1].sVal); }
         break;
-      case 9: // assign -> ident, ASSIGN, expr
+      case 15: // assign -> ident, ASSIGN, expr
 { CurrentSemanticValue.stVal = new AssignNode(ValueStack[ValueStack.Depth-3].eVal as IdNode, ValueStack[ValueStack.Depth-1].eVal); }
         break;
-      case 10: // expr -> ident
+      case 16: // block -> BEGIN, stlist, END
+{ CurrentSemanticValue.blVal = ValueStack[ValueStack.Depth-2].blVal; }
+        break;
+      case 17: // cycle -> CYCLE, expr, statement
+{ CurrentSemanticValue.stVal = new CycleNode(ValueStack[ValueStack.Depth-2].eVal, ValueStack[ValueStack.Depth-1].stVal); }
+        break;
+      case 18: // while -> WHILE, expr, DO, statement
+{ CurrentSemanticValue.stVal = new WhileNode(ValueStack[ValueStack.Depth-3].eVal, ValueStack[ValueStack.Depth-1].stVal); }
+        break;
+      case 19: // repeat -> REPEAT, stlist, UNTIL, expr
+{ CurrentSemanticValue.stVal = new RepeatNode(ValueStack[ValueStack.Depth-3].blVal, ValueStack[ValueStack.Depth-1].eVal); }
+        break;
+      case 20: // for -> FOR, assign, TO, expr, DO, statement
+{ CurrentSemanticValue.stVal = new ForNode(ValueStack[ValueStack.Depth-5].stVal as AssignNode, ValueStack[ValueStack.Depth-3].eVal, ValueStack[ValueStack.Depth-1].stVal); }
+        break;
+      case 21: // write -> WRITE, LEFT_PR, expr, RIGHT_PR
+{ CurrentSemanticValue.stVal = new WriteNode(ValueStack[ValueStack.Depth-2].eVal); }
+        break;
+      case 22: // Anon@1 -> /* empty */
+{ CurrentSemanticValue.stVal = new IfNode(ValueStack[ValueStack.Depth-3].eVal, ValueStack[ValueStack.Depth-1].stVal); }
+        break;
+      case 24: // 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 25: // idList -> ident
+{ CurrentSemanticValue.vdVal = new VarDefNode(ValueStack[ValueStack.Depth-1].eVal as IdNode); }
+        break;
+      case 26: // idList -> idList, COMMA, ident
+{ ValueStack[ValueStack.Depth-3].vdVal.Add(ValueStack[ValueStack.Depth-1].eVal as IdNode); CurrentSemanticValue.vdVal = ValueStack[ValueStack.Depth-3].vdVal; }
+        break;
+      case 27: // var -> VAR, idList
+{ CurrentSemanticValue.stVal = ValueStack[ValueStack.Depth-1].vdVal; }
+        break;
+      case 28: // expr -> T
+{ CurrentSemanticValue.eVal = ValueStack[ValueStack.Depth-1].eVal; }
+        break;
+      case 29: // expr -> expr, PLUS, T
+{ CurrentSemanticValue.eVal = new BinaryNode(ValueStack[ValueStack.Depth-3].eVal, ValueStack[ValueStack.Depth-1].eVal, BinOpType.Plus); }
+        break;
+      case 30: // expr -> expr, MINUS, T
+{ CurrentSemanticValue.eVal = new BinaryNode(ValueStack[ValueStack.Depth-3].eVal, ValueStack[ValueStack.Depth-1].eVal, BinOpType.Minus); }
+        break;
+      case 31: // T -> F
+{ CurrentSemanticValue.eVal = ValueStack[ValueStack.Depth-1].eVal; }
+        break;
+      case 32: // T -> T, MULT, F
+{ CurrentSemanticValue.eVal = new BinaryNode(ValueStack[ValueStack.Depth-3].eVal, ValueStack[ValueStack.Depth-1].eVal, BinOpType.Mult); }
+        break;
+      case 33: // T -> T, DIVISION, F
+{ CurrentSemanticValue.eVal = new BinaryNode(ValueStack[ValueStack.Depth-3].eVal, ValueStack[ValueStack.Depth-1].eVal, BinOpType.Division); }
+        break;
+      case 34: // F -> ident
 { CurrentSemanticValue.eVal = ValueStack[ValueStack.Depth-1].eVal as IdNode; }
         break;
-      case 11: // expr -> INUM
+      case 35: // F -> INUM
 { CurrentSemanticValue.eVal = new IntNumNode(ValueStack[ValueStack.Depth-1].iVal); }
         break;
-      case 12: // block -> BEGIN, stlist, END
-{ CurrentSemanticValue.blVal = ValueStack[ValueStack.Depth-2].blVal; }
-        break;
-      case 13: // cycle -> CYCLE, expr, statement
-{ CurrentSemanticValue.stVal = new CycleNode(ValueStack[ValueStack.Depth-2].eVal, ValueStack[ValueStack.Depth-1].stVal); }
+      case 36: // F -> LEFT_PR, expr, RIGHT_PR
+{ CurrentSemanticValue.eVal = ValueStack[ValueStack.Depth-2].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/Module6/SimpleYacc.y b/Module6/SimpleYacc.y
index b9899b4..12b2d38 100644
--- a/Module6/SimpleYacc.y
+++ b/Module6/SimpleYacc.y
@@ -1,33 +1,35 @@
 %{
-// Эти объявления добавляются в класс GPPGParser, представляющий собой парсер, генерируемый системой gppg
-    public BlockNode root; // Корневой узел синтаксического дерева 
+	public BlockNode root; // Эти объявления добавляются в класс GPPGParser, представляющий собой парсер, генерируемый системой gppg    
     public Parser(AbstractScanner<ValueType, LexLocation> scanner) : base(scanner) { }
 %}
 
 %output = SimpleYacc.cs
 
 %union { 
-			public double dVal; 
-			public int iVal; 
-			public string sVal; 
-			public Node nVal;
-			public ExprNode eVal;
-			public StatementNode stVal;
-			public BlockNode blVal;
+    public double dVal; 
+    public int iVal; 
+    public string sVal; 
+    public Node nVal;
+    public ExprNode eVal;
+    public StatementNode stVal;
+    public BlockNode blVal;
+	public VarDefNode vdVal;
        }
 
 %using ProgramTree;
 
 %namespace SimpleParser
 
-%token BEGIN END CYCLE ASSIGN SEMICOLON
+%token BEGIN END CYCLE INUM RNUM ID ASSIGN SEMICOLON WHILE DO REPEAT UNTIL FOR TO WRITE LEFT_PR RIGHT_PR IF ELSE THEN VAR COMMA INUM PLUS MINUS MULT DIVISION LEFT_PR RIGHT_PR
+
 %token <iVal> INUM 
 %token <dVal> RNUM 
 %token <sVal> ID
 
-%type <eVal> expr ident 
-%type <stVal> assign statement cycle 
+%type <eVal> expr ident T F
+%type <stVal> assign statement cycle while repeat for write if var
 %type <blVal> stlist block
+%type <vdVal> idList
 
 %%
 
@@ -35,36 +37,75 @@ progr   : block { root = $1; }
 		;
 
 stlist	: statement 
-			{ 
-				$$ = new BlockNode($1); 
-			}
+		{ 
+			$$ = new BlockNode($1); 
+		}
 		| stlist SEMICOLON statement 
-			{ 
-				$1.Add($3); 
-				$$ = $1; 
-			}
+		{ 
+			$1.Add($3); 
+			$$ = $1; 
+		}
 		;
 
 statement: assign { $$ = $1; }
-		| block   { $$ = $1; }
-		| cycle   { $$ = $1; }
-	;
+		| block  { $$ = $1; }
+		| cycle  { $$ = $1; }
+		| while { $$ = $1; }
+		| repeat { $$ = $1; }
+		| for { $$ = $1; }
+		| write { $$ = $1; }
+		| if { $$ = $1; }
+		| var { $$ = $1; }
+		;
 
-ident 	: ID { $$ = new IdNode($1); }	
+ident 	: ID { $$ = new IdNode($1); }
 		;
 	
 assign 	: ident ASSIGN expr { $$ = new AssignNode($1 as IdNode, $3); }
 		;
 
-expr	: ident  { $$ = $1 as IdNode; }
-		| INUM { $$ = new IntNumNode($1); }
-		;
-
 block	: BEGIN stlist END { $$ = $2; }
 		;
 
 cycle	: CYCLE expr statement { $$ = new CycleNode($2, $3); }
 		;
-	
-%%
 
+while   : WHILE expr DO statement { $$ = new WhileNode($2, $4); }
+	    ;
+
+repeat  : REPEAT stlist UNTIL expr { $$ = new RepeatNode($2, $4); }
+		;
+
+for     : FOR assign TO expr DO statement { $$ = new ForNode($2 as AssignNode, $4, $6); }
+		;
+
+write   : WRITE LEFT_PR expr RIGHT_PR { $$ = new WriteNode($3); }
+		;
+
+if      : IF expr THEN statement { $$ = new IfNode($2, $4); } %prec IFX
+		| IF expr THEN statement ELSE statement { $$ = new IfNode($2, $4, $6); }
+		;
+
+idList  : ident { $$ = new VarDefNode($1 as IdNode); }
+		| idList COMMA ident { $1.Add($3 as IdNode); $$ = $1; }
+		;
+
+var     : VAR idList { $$ = $2; }
+		;
+
+expr	: T { $$ = $1; }
+		| expr PLUS T { $$ = new BinaryNode($1, $3, BinOpType.Plus); }
+		| expr MINUS T { $$ = new BinaryNode($1, $3, BinOpType.Minus); }
+		;
+
+T		: F { $$ = $1; }
+		| T MULT F { $$ = new BinaryNode($1, $3, BinOpType.Mult); }
+		| T DIVISION F { $$ = new BinaryNode($1, $3, BinOpType.Division); }
+		;
+
+F		: ident { $$ = $1 as IdNode; }
+		| INUM { $$ = new IntNumNode($1); }
+		| LEFT_PR expr RIGHT_PR { $$ = $2; }
+		;
+	
+%%
\ No newline at end of file
diff --git a/TestASTParser/Tests.cs b/TestASTParser/Tests.cs
index e5a67a2..12a8241 100644
--- a/TestASTParser/Tests.cs
+++ b/TestASTParser/Tests.cs
@@ -8,112 +8,168 @@ using Newtonsoft.Json.Linq;
 
 namespace TestASTParser
 {
-    public class ASTParserTests
-    {
-        public static JObject Parse(string text)
-        {
-            Scanner scanner = new Scanner();
-            scanner.SetSource(text, 0);
+	public class ASTParserTests
+	{
+		public static JObject Parse(string text)
+		{
+			Scanner scanner = new Scanner();
+			scanner.SetSource(text, 0);
 
-            Parser parser = new Parser(scanner);
+			Parser parser = new Parser(scanner);
 
-            var b = parser.Parse();
-            if (!b)
-                Assert.Fail("программа не распознана");
-            else
-            {
-                JsonSerializerSettings jsonSettings = new JsonSerializerSettings();
-                jsonSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
-                jsonSettings.TypeNameHandling = TypeNameHandling.All;
-                string output = JsonConvert.SerializeObject(parser.root, jsonSettings);
-                return JObject.Parse(output);
-            }
+			var b = parser.Parse();
+			if (!b)
+				Assert.Fail("программа не распознана");
+			else
+			{
+				JsonSerializerSettings jsonSettings = new JsonSerializerSettings();
+				jsonSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
+				jsonSettings.TypeNameHandling = TypeNameHandling.All;
+				string output = JsonConvert.SerializeObject(parser.root, jsonSettings);
+				return JObject.Parse(output);
+			}
 
-            return null;
+			return null;
 
-        }
-    }
-    
-    [TestFixture]
-    public class WhileTests
-    {
-        
-        [Test]
-        public void TestWhile()
-        {
-            var tree = ASTParserTests.Parse("begin while 2 do a:=2 end");
-            Assert.AreEqual("ProgramTree.WhileNode, SimpleLang", (string)tree["StList"]["$values"][0]["$type"]);   
-            Assert.AreEqual("ProgramTree.IntNumNode, SimpleLang", (string)tree["StList"]["$values"][0]["Expr"]["$type"]);
-            Assert.AreEqual("2", ((string)tree["StList"]["$values"][0]["Expr"]["Num"]).Trim());
-            Assert.AreEqual("ProgramTree.AssignNode, SimpleLang", (string)tree["StList"]["$values"][0]["Stat"]["$type"]);
-        }
-    }
-    
-    [TestFixture]
-    public class RepeatTests
-    {
-        
-        [Test]
-        public void TestRepeat()
-        {
-            var tree = ASTParserTests.Parse("begin repeat a:=2 until 2 end");
-            Assert.AreEqual("ProgramTree.RepeatNode, SimpleLang", (string)tree["StList"]["$values"][0]["$type"]);
-            // TODO: проверить узлы содержимого repeat
-        }
-    }
-    
-    [TestFixture]
-    public class ForTests
-    {
-        
-        [Test]
-        public void TestFor()
-        {
-            var tree = ASTParserTests.Parse("begin for i:=2 to 10 do a:=2 end");
-            Assert.AreEqual("ProgramTree.ForNode, SimpleLang", (string)tree["StList"]["$values"][0]["$type"]);
-            // TODO: проверить узлы содержимого for
-        }
-    }
-    
-    [TestFixture]
-    [Ignore("This test is disabled")]
-    public class WriteTests
-    {
-        
-        [Test]
-        public void TestWrite()
-        {
-            var tree = ASTParserTests.Parse("begin write(2) end");
-            Assert.AreEqual("ProgramTree.WriteNode, SimpleLang", (string)tree["StList"]["$values"][0]["$type"]);
-            // TODO: проверить содержимое write
-        }
-    }
-    
-    [TestFixture]
-    public class ExtraTests
-    {
-        
-        [Test]
-        [Ignore("This test is disabled")]
-        public void TestIf()
-        {
-            Assert.Fail();
-            // TODO: дописать тест
-        }
-        
-        [Test]
-        [Ignore("This test is disabled")]
-        public void TestVarDef()
-        {
-            Assert.Fail();
-            // TODO: дописать тест
-        }
-        
-        [Test]
-        public void TestBinary()
-        {
-            Assert.Fail();
-            // TODO: дописать тест
-        }
-    }
-}
\ No newline at end of file
+		}
+	}
+
+	[TestFixture]
+	public class WhileTests
+	{
+		[Test]
+		// [Ignore("This test is disabled")]
+		public void TestWhile()
+		{
+			var tree = ASTParserTests.Parse("begin while 2 do a:=2 end");
+			Assert.AreEqual("ProgramTree.WhileNode, SimpleLang", (string)tree["StList"]["$values"][0]["$type"]);
+			Assert.AreEqual("ProgramTree.IntNumNode, SimpleLang", (string)tree["StList"]["$values"][0]["Expr"]["$type"]);
+			Assert.AreEqual("2", ((string)tree["StList"]["$values"][0]["Expr"]["Num"]).Trim());
+			Assert.AreEqual("ProgramTree.AssignNode, SimpleLang", (string)tree["StList"]["$values"][0]["Stat"]["$type"]);
+		}
+	}
+
+	[TestFixture]
+	public class RepeatTests
+	{
+		[Test]
+		// [Ignore("This test is disabled")]
+		public void TestRepeat()
+		{
+			var tree = ASTParserTests.Parse("begin repeat a:=2 until 2 end");
+			Assert.AreEqual("ProgramTree.RepeatNode, SimpleLang", (string)tree["StList"]["$values"][0]["$type"]);
+			Assert.AreEqual("a", (string)tree["StList"]["$values"][0]["State"]["StList"]["$values"][0]["Id"]["Name"]);
+			Assert.AreEqual(2, (int)tree["StList"]["$values"][0]["State"]["StList"]["$values"][0]["Expr"]["Num"]);
+			Assert.AreEqual(2, (int)tree["StList"]["$values"][0]["Expr"]["Num"]);
+		}
+	}
+
+	[TestFixture]
+	public class ForTests
+	{
+		[Test]
+		// [Ignore("This test is disabled")]
+		public void TestFor()
+		{
+			var tree = ASTParserTests.Parse("begin for i:=2 to 10 do a:=2 end");
+			Assert.AreEqual("ProgramTree.ForNode, SimpleLang", (string)tree["StList"]["$values"][0]["$type"]);
+			Assert.AreEqual("i", (string)tree["StList"]["$values"][0]["Assign"]["Id"]["Name"]);
+			Assert.AreEqual(2, (int)tree["StList"]["$values"][0]["Assign"]["Expr"]["Num"]);
+			Assert.AreEqual(10, (int)tree["StList"]["$values"][0]["Expr"]["Num"]);
+			Assert.AreEqual("a", (string)tree["StList"]["$values"][0]["State"]["Id"]["Name"]);
+			Assert.AreEqual(2, (int)tree["StList"]["$values"][0]["State"]["Expr"]["Num"]);
+		}
+	}
+
+	[TestFixture]
+	// [Ignore("This test is disabled")]
+	public class WriteTests
+	{
+		[Test]
+		public void TestWrite()
+		{
+			var tree = ASTParserTests.Parse("begin write(2) end");
+			Assert.AreEqual("ProgramTree.WriteNode, SimpleLang", (string)tree["StList"]["$values"][0]["$type"]);
+			Assert.AreEqual(2, (int)tree["StList"]["$values"][0]["Expr"]["Num"]);
+		}
+	}
+
+	[TestFixture]
+	public class ExtraTests
+	{
+		[Test]
+		// [Ignore("This test is disabled")]
+		public void TestIf()
+		{
+			var tree = ASTParserTests.Parse(
+			   @"begin
+                    if 42
+                    then a:=1
+                    else
+                      begin
+                        b:=2;
+                        if 2
+                        then a:=3
+                      end
+                  end");
+
+			Assert.AreEqual("ProgramTree.IfNode, SimpleLang", (string)tree["StList"]["$values"][0]["$type"]);
+			Assert.AreEqual(42, (int)tree["StList"]["$values"][0]["Expr"]["Num"]);
+			Assert.AreEqual("ProgramTree.AssignNode, SimpleLang", (string)tree["StList"]["$values"][0]["State"]["$type"]);
+			Assert.AreEqual("ProgramTree.IdNode, SimpleLang", (string)tree["StList"]["$values"][0]["State"]["Id"]["$type"]);
+			Assert.AreEqual("a", (string)tree["StList"]["$values"][0]["State"]["Id"]["Name"]);
+			Assert.AreEqual(1, (int)tree["StList"]["$values"][0]["State"]["Expr"]["Num"]);
+			Assert.AreEqual("ProgramTree.AssignNode, SimpleLang", (string)tree["StList"]["$values"][0]["ElseStat"]["StList"]["$values"][0]["$type"]);
+			Assert.AreEqual("b", (string)tree["StList"]["$values"][0]["ElseStat"]["StList"]["$values"][0]["Id"]["Name"]);
+			Assert.AreEqual(2, (int)tree["StList"]["$values"][0]["ElseStat"]["StList"]["$values"][0]["Expr"]["Num"]);
+			Assert.AreEqual("ProgramTree.IfNode, SimpleLang", (string)tree["StList"]["$values"][0]["ElseStat"]["StList"]["$values"][1]["$type"]);
+			Assert.AreEqual(2, (int)tree["StList"]["$values"][0]["ElseStat"]["StList"]["$values"][1]["Expr"]["Num"]);
+			Assert.AreEqual("a", (string)tree["StList"]["$values"][0]["ElseStat"]["StList"]["$values"][1]["State"]["Id"]["Name"]);
+			Assert.AreEqual(3, (int)tree["StList"]["$values"][0]["ElseStat"]["StList"]["$values"][1]["State"]["Expr"]["Num"]);
+			Assert.AreEqual(null, (string)tree["StList"]["$values"][0]["ElseStat"]["StList"]["$values"][1]["ElseStat"]);
+		}
+
+		[Test]
+		// [Ignore("This test is disabled")]
+		public void TestVarDef()
+		{
+			var tree = ASTParserTests.Parse(@"begin var a,b,c end");
+			Assert.AreEqual("ProgramTree.VarDefNode, SimpleLang", (string)tree["StList"]["$values"][0]["$type"]);
+			Assert.AreEqual("ProgramTree.IdNode, SimpleLang", (string)tree["StList"]["$values"][0]["IdList"]["$values"][0]["$type"]);
+			Assert.AreEqual("a", (string)tree["StList"]["$values"][0]["IdList"]["$values"][0]["Name"]);
+			Assert.AreEqual("b", (string)tree["StList"]["$values"][0]["IdList"]["$values"][1]["Name"]);
+			Assert.AreEqual("c", (string)tree["StList"]["$values"][0]["IdList"]["$values"][2]["Name"]);
+		}
+
+		[Test]
+		// [Ignore("This test is disabled")]
+		public void TestBinary()
+		{
+			var tree = ASTParserTests.Parse(
+				@"begin
+                    var a,b,c;
+                    a:=1;
+                    b:=2;
+                    c:=a-b;
+                    a:=c+a;
+                    b:=a*2;
+                    c:=(a*b)+(b*c)/2
+                  end");
+
+			Assert.AreEqual("ProgramTree.VarDefNode, SimpleLang", (string)tree["StList"]["$values"][0]["$type"]);
+			for (int i = 1; i <= 6; i++)
+			{
+				Assert.AreEqual("ProgramTree.AssignNode, SimpleLang", (string)tree["StList"]["$values"][i]["$type"]);
+			}
+
+			Assert.AreEqual("ProgramTree.BinaryNode, SimpleLang", (string)tree["StList"]["$values"][3]["Expr"]["$type"]);
+			Assert.AreEqual("a", (string)tree["StList"]["$values"][3]["Expr"]["Left"]["Name"]);
+			Assert.AreEqual("b", (string)tree["StList"]["$values"][3]["Expr"]["Right"]["Name"]);
+			Assert.AreEqual(ProgramTree.BinOpType.Minus, (ProgramTree.BinOpType)(int)tree["StList"]["$values"][3]["Expr"]["Op"]);
+			Assert.AreEqual(ProgramTree.BinOpType.Plus, (ProgramTree.BinOpType)(int)tree["StList"]["$values"][4]["Expr"]["Op"]);
+			Assert.AreEqual(ProgramTree.BinOpType.Mult, (ProgramTree.BinOpType)(int)tree["StList"]["$values"][5]["Expr"]["Op"]);
+			Assert.AreEqual("a", (string)tree["StList"]["$values"][5]["Expr"]["Left"]["Name"]);
+			Assert.AreEqual(2, (int)tree["StList"]["$values"][5]["Expr"]["Right"]["Num"]);
+		}
+	}
+}
-- 
GitLab