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