diff --git a/Module6/ProgramTree.cs b/Module6/ProgramTree.cs index ade12f7bf2514b8b52857a88840f4f94faa39839..6bd3282920a933ba41110c006feb70ca494d674b 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 c518c8b3443fd6ed15300f8e5f3eea6733bd0974..577918462a8055f382533f87faa7d68be4b518f5 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 20b364f4bf657ae535567648661456eec4a82d52..3be76d677f9683c8343674b81d7ccdd909f3bdf7 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 b13b1e9abfb58162aa20d280d3fec11345fdc298..4608df07996b88872d5191ea4f429eb03fda6c6e 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 b9899b4c1edf1a54720d7dac60d5962c0e8a8c0e..12b2d380cba9dc88248682edd237aa7b4330cddf 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 e5a67a2d471dc7735e0f61864402026de83c9415..12a8241fdf2a067e0639bfbe8f919e18bd214bc1 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"]); + } + } +}