From 8b1775974d47a17489786ecaac785d29dfa89688 Mon Sep 17 00:00:00 2001 From: lichx Date: Fri, 27 Dec 2024 01:25:50 +0800 Subject: [PATCH] =?UTF-8?q?[feature]=20=E5=86=8D=E8=A7=81=EF=BC=8C?= =?UTF-8?q?=E7=BC=96=E8=AF=91=E5=8E=9F=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CompilerDesignIflr1.csproj | 3 + CompilerDesignIflr1/LR1Closure.cs | 33 +--- CompilerDesignIflr1/LR1Creator.cs | 10 +- CompilerDesignIflr1/LR1Table.cs | 10 +- CompilerDesignIflr1/LR1Unit.cs | 55 ++++-- CompilerDesignIflr1/LexicalAnalysis.cs | 10 +- CompilerDesignIflr1/Program.cs | 4 +- CompilerDesignIflr1/SemanticAnalysis.cs | 158 ++++++++++++++++-- CompilerDesignIflr1/StateMachine.cs | 23 +-- .../files/{newGrammar => Grammar} | 0 CompilerDesignIflr1/files/GrammarInChinese | 88 ++++++++++ CompilerDesignIflr1/files/code | 14 +- CompilerDesignIflr1/files/if-grammar.grammar | 2 +- CompilerDesignIflr1/files/translateFile | 43 +++++ 14 files changed, 352 insertions(+), 101 deletions(-) rename CompilerDesignIflr1/files/{newGrammar => Grammar} (100%) create mode 100644 CompilerDesignIflr1/files/GrammarInChinese create mode 100644 CompilerDesignIflr1/files/translateFile diff --git a/CompilerDesignIflr1/CompilerDesignIflr1.csproj b/CompilerDesignIflr1/CompilerDesignIflr1.csproj index 0065211..27aeb8d 100644 --- a/CompilerDesignIflr1/CompilerDesignIflr1.csproj +++ b/CompilerDesignIflr1/CompilerDesignIflr1.csproj @@ -14,6 +14,9 @@ Always + + Always + diff --git a/CompilerDesignIflr1/LR1Closure.cs b/CompilerDesignIflr1/LR1Closure.cs index 718692c..f14f4a4 100644 --- a/CompilerDesignIflr1/LR1Closure.cs +++ b/CompilerDesignIflr1/LR1Closure.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Text; namespace CompilerDesignIFlr1 { @@ -32,32 +27,6 @@ namespace CompilerDesignIFlr1 internal void CalculateProspects() { - //Queue queue = []; - //var startUnit = Units.Where(x=>x.Name == LR1Creator.StartSymbol).First(); - //startUnit.Prospect.Add("End"); - - //queue.Enqueue(startUnit); - //while (queue.Count > 0) - //{ - // var unit = queue.Dequeue(); - // var left = unit.Name; - // var units = UnitsHaveDotBefore(left); - // var next = unit.Next(); - // if (next is not null && !LR1Creator.TokenUnit.ContainsKey(next)) - // foreach (var item in Units.Where(x => x.Name == next)) - // queue.Enqueue(item); - // HashSet prospect = units - // .Select(x => GetProspectsOf(x)) - // .Aggregate( - // new HashSet(), - // (set, x) => - // { - // set.UnionWith(x); - // return set; - // } - // ); - // unit.Prospect.UnionWith(prospect); - //} bool haveChange = true; while (haveChange) diff --git a/CompilerDesignIflr1/LR1Creator.cs b/CompilerDesignIflr1/LR1Creator.cs index 1a89247..2847c70 100644 --- a/CompilerDesignIflr1/LR1Creator.cs +++ b/CompilerDesignIflr1/LR1Creator.cs @@ -1,12 +1,4 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Dynamic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace CompilerDesignIFlr1 +namespace CompilerDesignIFlr1 { internal class LR1Creator { diff --git a/CompilerDesignIflr1/LR1Table.cs b/CompilerDesignIflr1/LR1Table.cs index d20d557..be38a3b 100644 --- a/CompilerDesignIflr1/LR1Table.cs +++ b/CompilerDesignIflr1/LR1Table.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Text; namespace CompilerDesignIFlr1 { @@ -68,9 +64,11 @@ namespace CompilerDesignIFlr1 sb.Append("ACTION: \n"); foreach (var (key, value) in ACTION) sb.Append(key).Append(": ").Append(value).Append(", "); - sb.Append("GOTO: \n"); + if(GOTO.Count != 0) + sb.Append("\nGOTO: \n"); foreach (var (key, value) in GOTO) sb.Append(key).Append(": ").Append(value).Append(", "); + sb.Append('\n'); return sb.ToString(); } diff --git a/CompilerDesignIflr1/LR1Unit.cs b/CompilerDesignIflr1/LR1Unit.cs index 56b7c97..726f032 100644 --- a/CompilerDesignIflr1/LR1Unit.cs +++ b/CompilerDesignIflr1/LR1Unit.cs @@ -1,8 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Diagnostics.SymbolStore; using System.Text; -using System.Threading.Tasks; namespace CompilerDesignIFlr1 { @@ -10,6 +7,16 @@ namespace CompilerDesignIFlr1 { internal LR1Unit() { } + internal static string LanguageMode = "English"; + internal static Dictionary EnglishToChinese = []; + internal static void Init(string filePath) + { + string fileContent = File.ReadAllText(filePath); + EnglishToChinese = fileContent + .Split('#') + .Select(x => x.Split(':').Select(x => x.Trim()).ToList()).Where(x=>x.Count == 2).ToList().ToDictionary(x => x[0], x => x[1]); + } + internal LR1Unit(string name, string grammar) { Type = "Token"; @@ -49,7 +56,16 @@ namespace CompilerDesignIFlr1 Grammar = grammar; } - public LR1Unit(int id, string type, string name, int quadrupleIndex, string value, HashSet prospect, int pointPosition, List grammar) + public LR1Unit( + int id, + string type, + string name, + int quadrupleIndex, + string value, + HashSet prospect, + int pointPosition, + List grammar + ) { Id = id; Type = type; @@ -62,7 +78,17 @@ namespace CompilerDesignIFlr1 } internal LR1Unit Clone() => - new LR1Unit(Id, Type, Name, 0, Value,new HashSet(Prospect), PointPosition, [.. Grammar]); + new LR1Unit( + Id, + Type, + Name, + 0, + Value, + new HashSet(Prospect), + PointPosition, + [.. Grammar] + ); + internal int Id { get; set; } = -1; internal string Type { get; set; } = ""; internal string Name { get; set; } = ""; @@ -88,22 +114,29 @@ namespace CompilerDesignIFlr1 public override string ToString() { + string GetName(string s) + { + return LanguageMode switch + { + "Chinese" => EnglishToChinese.TryGetValue(s, out var result) ? result : s, + "English" => s, + _ => throw new Exception("Language mode is not supported.") + }; + } StringBuilder sb = new(); - //if (Grammar.Count == 0) - // return "."; sb.Append($"{Id, 2} "); - sb.Append(Name).Append(" ::= "); + sb.Append(GetName(Name)).Append(" ::= "); for (int i = 0; i < Grammar.Count; i++) { if (PointPosition == i) sb.Append(". "); - sb.Append(Grammar[i] + " "); + sb.Append(GetName(Grammar[i]) + " "); } if (PointPosition == Grammar.Count) sb.Append('.'); foreach (var item in Prospect) { - sb.Append(", " + item); + sb.Append(", " + GetName(item)); } return sb.ToString(); } diff --git a/CompilerDesignIflr1/LexicalAnalysis.cs b/CompilerDesignIflr1/LexicalAnalysis.cs index e16ab21..2123353 100644 --- a/CompilerDesignIflr1/LexicalAnalysis.cs +++ b/CompilerDesignIflr1/LexicalAnalysis.cs @@ -1,12 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using CompilerDesignIFlr1; +using System.Text.RegularExpressions; -namespace CompilerDesignIflr1 +namespace CompilerDesignIFlr1 { internal class LexicalAnalysis { diff --git a/CompilerDesignIflr1/Program.cs b/CompilerDesignIflr1/Program.cs index 7473cc7..bb85641 100644 --- a/CompilerDesignIflr1/Program.cs +++ b/CompilerDesignIflr1/Program.cs @@ -1,8 +1,9 @@ // See https://aka.ms/new-console-template for more information -using CompilerDesignIflr1; using CompilerDesignIFlr1; Console.WriteLine("Hello, World!"); +LR1Unit.Init("./files/translateFile"); +LR1Unit.LanguageMode = "Chinese"; var grammarReader = new GrammarReader("./files/if-grammar.grammar"); var lr1Creator = new LR1Creator(grammarReader); var lr1Table = new LR1Table(lr1Creator); @@ -10,3 +11,4 @@ var lexicalAnalysis = new LexicalAnalysis(lr1Creator, "./files/code"); var semanticAnalysis = new SemanticAnalysis(); var stateMachine = new StateMachine(lr1Table, lexicalAnalysis, lr1Creator, semanticAnalysis); semanticAnalysis.PrintQuadruples(); +semanticAnalysis.OptimizeQuadruples(); diff --git a/CompilerDesignIflr1/SemanticAnalysis.cs b/CompilerDesignIflr1/SemanticAnalysis.cs index facc419..f3f9097 100644 --- a/CompilerDesignIflr1/SemanticAnalysis.cs +++ b/CompilerDesignIflr1/SemanticAnalysis.cs @@ -1,11 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Runtime.InteropServices.Marshalling; -using System.Text; -using System.Threading.Tasks; -using static System.Runtime.InteropServices.JavaScript.JSType; +using System.Text; namespace CompilerDesignIFlr1 { @@ -733,13 +726,155 @@ namespace CompilerDesignIFlr1 internal void PrintQuadruples() { + Console.WriteLine("四元式:"); for (int i = 0; i < Quadruples.Count; i++) { - Console.Write($"{i, 3}"); + //Console.Write($"{i, 3}"); Console.WriteLine(Quadruples[i]); } } + internal void OptimizeQuadruples() + { + HashSet basedOn = []; + bool CanBasedOn(Quadruple quadruple) + { + return quadruple.Operator != "=" || !quadruple.To.Name.StartsWith("@"); + } + Identifier GetFinal(Identifier? identifier, int from) + { + if (identifier == null) + return null!; + if (identifier.Type == IdentifierType.Literal) + { + if (identifier.Value.StartsWith("@")) + { + for (int i = from - 1; i >= 0; i--) + { + if (Quadruples[i].To.Name == identifier.Value) + { + return Identifier.Literal(Quadruples[i].To.Value); + } + } + throw new Exception("Failed to track identifier"); + } + else + return Identifier.Literal(identifier.Value); + } + if (identifier.Name.StartsWith("@")) + { + for (int i = from - 1; i >= 0; i--) + { + if (Quadruples[i].To.Name == identifier.Name) + { + if (Quadruples[i].Operator == "=") + return GetFinal(Quadruples[i].A, i); + else + return identifier; + } + } + throw new Exception("Failed to track identifier"); + } + else + return identifier; + } + for (int i = 0; i < Quadruples.Count; i++) + { + if (CanBasedOn(Quadruples[i])) + { + basedOn.Add(i); + Quadruples[i].A = GetFinal(Quadruples[i].A, i); + Quadruples[i].B = GetFinal(Quadruples[i].B, i); + } + } + List afterList = basedOn.Order().Select(x => Quadruples[x].Clone()).ToList(); + HashSet reAddInAfterList = []; + for (int i = 1; i <= afterList.Count; i++) + { + reAddInAfterList.Add(i); + Quadruple quadruple = afterList[^i]; + if (quadruple.Operator == "=" && quadruple.A.Name.StartsWith('@')) + { + reAddInAfterList.Remove(i); + bool find = false; + for (i++; i <= afterList.Count; i++) + { + reAddInAfterList.Add(i); + if (afterList[^i].To.Name == quadruple.A.Name) + { + afterList[^i].To = quadruple.To; + find = true; + break; + } + } + if(!find) + throw new Exception("Failed to track identifier"); + } + } + afterList = reAddInAfterList.Order().Select(x => afterList[^x]).Reverse().ToList(); + Dictionary tempValueReplace = []; + // >x 时 回填到 y + Stack<(int, int)> addressReset = []; + int tempValueIndex = 0; + string GetNewTempName() + { + return "@T" + tempValueIndex++; + } + for (int i = 0; i < afterList.Count; i++) + { + var quadruple = afterList[i]; + while (addressReset.Count > 0 && addressReset.Peek().Item1 < quadruple.Index) + afterList[addressReset.Pop().Item2].To.Value = i + ""; + quadruple.Index = i; + if (quadruple.A.Name.StartsWith("@")) + { + if (tempValueReplace.TryGetValue(quadruple.A.Name, out string? newName)) + quadruple.A.Name = newName; + else + { + tempValueReplace.Add(quadruple.A.Name, GetNewTempName()); + quadruple.A.Name = tempValueReplace[quadruple.A.Name]; + } + } + if (quadruple.B is not null && quadruple.B.Name.StartsWith("@")) + { + if (tempValueReplace.TryGetValue(quadruple.B.Name, out string? newName)) + quadruple.B.Name = newName; + else + { + tempValueReplace.Add(quadruple.B.Name, GetNewTempName()); + quadruple.B.Name = tempValueReplace[quadruple.B.Name]; + } + } + if ( + quadruple.To.Name.StartsWith("@") + && quadruple.To.Type != IdentifierType.Address + ) + { + if (tempValueReplace.TryGetValue(quadruple.To.Name, out string? newName)) + quadruple.To.Name = newName; + else + { + tempValueReplace.Add(quadruple.To.Name, GetNewTempName()); + quadruple.To.Name = tempValueReplace[quadruple.To.Name]; + } + } + if (quadruple.Operator.StartsWith('j')) + addressReset.Push((int.Parse(quadruple.To.Value), i)); + } + while (addressReset.Count > 0) + afterList[addressReset.Pop().Item2].To.Value = afterList.Count + ""; + Console.WriteLine("After optimize."); + //foreach (int i in basedOn.Order().ToList()) + //{ + // Console.WriteLine(Quadruples[i]); + //} + foreach (var t in afterList) + { + Console.WriteLine(t); + } + } + internal static bool Assert(bool val) => !val ? throw new Exception("Assertion failed.") : false; @@ -892,7 +1027,7 @@ namespace CompilerDesignIFlr1 internal Quadruple(string @operator, int index, Identifier a, Identifier? b, Identifier to) { Operator = @operator; - this.Index = index; + Index = index; A = a; B = b; To = to; @@ -916,7 +1051,8 @@ namespace CompilerDesignIFlr1 return identifier.Name; return identifier.Value; } - sb.Append('(') + sb.Append($"{Index, 3}") + .Append('(') .Append(Operator.PadLeft(4, ' ')) .Append(',') .Append(GetValue(A).PadLeft(4, ' ')) diff --git a/CompilerDesignIflr1/StateMachine.cs b/CompilerDesignIflr1/StateMachine.cs index 7e6b1bd..2773c4f 100644 --- a/CompilerDesignIflr1/StateMachine.cs +++ b/CompilerDesignIflr1/StateMachine.cs @@ -1,11 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using CompilerDesignIflr1; - -namespace CompilerDesignIFlr1 +namespace CompilerDesignIFlr1 { internal class StateMachine { @@ -28,10 +21,18 @@ namespace CompilerDesignIFlr1 internal void Compute() { - while (true) + try { - if (ComputeOnce(Tokens.Pop())) - break; + while (true) + { + if (ComputeOnce(Tokens.Pop())) + break; + } + } + catch (Exception e) + { + Console.WriteLine(e.Message); + Environment.Exit(1); } } diff --git a/CompilerDesignIflr1/files/newGrammar b/CompilerDesignIflr1/files/Grammar similarity index 100% rename from CompilerDesignIflr1/files/newGrammar rename to CompilerDesignIflr1/files/Grammar diff --git a/CompilerDesignIflr1/files/GrammarInChinese b/CompilerDesignIflr1/files/GrammarInChinese new file mode 100644 index 0000000..caeb018 --- /dev/null +++ b/CompilerDesignIflr1/files/GrammarInChinese @@ -0,0 +1,88 @@ +文法: +key: Program + 0 程序 ::= . 语句列表 +key: StatementList + 1 语句列表 ::= . { Statement_0 } +key: IfStatement + 2 判断语句 ::= . If 条件部分 部分判断语句 Else 语句 + 3 判断语句 ::= . If 条件部分 语句 +key: PartIfStatement + 4 部分判断语句 ::= . If 条件部分 部分判断语句 Else 部分判断语句 + 5 部分判断语句 ::= . 无判断语句 +key: ConditionPart + 6 条件部分 ::= . ( 条件 ) +key: Condition + 7 条件 ::= . 条件表达式 LogicalOperator_ConditionalExpression_0 +key: ConditionalExpression + 8 条件表达式 ::= . 表达式 运算符 表达式 + 9 条件表达式 ::= . 表达式 +key: Expression + 10 表达式 ::= . 项 AddLike_Term_0 +key: Statement + 11 语句 ::= . 判断语句 + 12 语句 ::= . 无判断语句 +key: NoIfStatement + 13 无判断语句 ::= . 赋值语句 ; + 14 无判断语句 ::= . 变量定义 ; + 15 无判断语句 ::= . { Statement_1 } + 16 无判断语句 ::= . 常量定义 ; + 17 无判断语句 ::= . ; +key: AssignmentStatement + 18 赋值语句 ::= . 标识符 = 表达式 +key: Term + 19 项 ::= . 因子 MultiplyLike_Factor_0 +key: ConstantDefinition + 20 常量定义 ::= . Const 变量定义 +key: VariableDefinition + 21 变量定义 ::= . 类型 Identifier__AssignmentStatement_0 Comma_Identifier__Comma_AssignmentStatement_0 +key: Type + 22 类型 ::= . Int + 23 类型 ::= . Char +key: Factor + 24 因子 ::= . 标识符 + 25 因子 ::= . 数字 + 26 因子 ::= . 字符 + 27 因子 ::= . ( 表达式 ) +key: AddLike + 28 类加运算符 ::= . + + 29 类加运算符 ::= . - +key: MultiplyLike + 30 类乘运算符 ::= . * + 31 类乘运算符 ::= . / + 32 类乘运算符 ::= . % +key: Number + 33 数字 ::= . 无符号数字 + 34 数字 ::= . - 无符号数字 + 35 数字 ::= . + 无符号数字 +key: Operator + 36 运算符 ::= . EqualTo + 37 运算符 ::= . NotEqualTo + 38 运算符 ::= . LessThan + 39 运算符 ::= . GreaterThan + 40 运算符 ::= . LessThanOrEqual + 41 运算符 ::= . GreaterThanOrEqual +key: LogicalOperator + 42 逻辑运算符 ::= . And + 43 逻辑运算符 ::= . Or +key: Statement_0 + 44 Statement_0 ::= . + 45 Statement_0 ::= . 语句 Statement_0 +key: LogicalOperator_ConditionalExpression_0 + 46 LogicalOperator_ConditionalExpression_0 ::= . + 47 LogicalOperator_ConditionalExpression_0 ::= . 逻辑运算符 条件表达式 LogicalOperator_ConditionalExpression_0 +key: AddLike_Term_0 + 48 AddLike_Term_0 ::= . + 49 AddLike_Term_0 ::= . 类加运算符 项 AddLike_Term_0 +key: Statement_1 + 50 Statement_1 ::= . + 51 Statement_1 ::= . 语句 Statement_1 +key: MultiplyLike_Factor_0 + 52 MultiplyLike_Factor_0 ::= . + 53 MultiplyLike_Factor_0 ::= . 类乘运算符 因子 MultiplyLike_Factor_0 +key: Identifier__AssignmentStatement_0 + 54 Identifier__AssignmentStatement_0 ::= . 标识符 + 55 Identifier__AssignmentStatement_0 ::= . 赋值语句 +key: Comma_Identifier__Comma_AssignmentStatement_0 + 56 Comma_Identifier__Comma_AssignmentStatement_0 ::= . + 57 Comma_Identifier__Comma_AssignmentStatement_0 ::= . 逗号 标识符 Comma_Identifier__Comma_AssignmentStatement_0 + 58 Comma_Identifier__Comma_AssignmentStatement_0 ::= . 逗号 赋值语句 Comma_Identifier__Comma_AssignmentStatement_0 \ No newline at end of file diff --git a/CompilerDesignIflr1/files/code b/CompilerDesignIflr1/files/code index 36d2ca6..d729b7e 100644 --- a/CompilerDesignIflr1/files/code +++ b/CompilerDesignIflr1/files/code @@ -1,12 +1,4 @@ { - int a =1*9+2; - if(a>9){ - a=a+1; - if(9>1){ - a=10; - } - a=2+2; - } - - -} \ No newline at end of file + const int a = 5; + + } \ No newline at end of file diff --git a/CompilerDesignIflr1/files/if-grammar.grammar b/CompilerDesignIflr1/files/if-grammar.grammar index 187a421..dfee99c 100644 --- a/CompilerDesignIflr1/files/if-grammar.grammar +++ b/CompilerDesignIflr1/files/if-grammar.grammar @@ -93,8 +93,8 @@ LogicalOperator { Plus { "+" } Minus { "-" } Multiply { "*" } - Modulo { "%" } Divide { "/" } + Modulo { "%" } LParen { "(" } RParen { ")" } LBrace { "{" } diff --git a/CompilerDesignIflr1/files/translateFile b/CompilerDesignIflr1/files/translateFile new file mode 100644 index 0000000..d616aa6 --- /dev/null +++ b/CompilerDesignIflr1/files/translateFile @@ -0,0 +1,43 @@ +AddLike: 类加运算符 # +AssignmentStatement: 赋值语句 # +Char: Char # +Character: 字符 # +Comma: 逗号 # +Condition: 条件 # +ConditionalExpression: 条件表达式 # +ConditionPart: 条件部分 # +ConstantDefinition: 常量定义 # +Const: Const # +Divide: / # +Else: Else # +Equal: = # +Expression: 表达式 # +Factor: 因子 # +Identifier: 标识符 # +If: If # +IfStatement: 判断语句 # +Int: Int # +LBrace: { # +LParen: ( # +Minus: - # +Modulo: % # +Multiply: * # +MultiplyLike: 类乘运算符 # +NoIfStatement: 无判断语句 # +Number: 数字 # +Operator: 运算符 # +PartIfStatement: 部分判断语句 # +Plus: + # +Program: 程序 # +RBrace: } # +RParen: ) # +Semicolon: ; # +Statement: 语句 # +StatementList: 语句列表 # +String: 字符串 # +Term: 项 # +Type: 类型 # +UnsignedNumber: 无符号数字 # +VariableDefinition: 变量定义 # +Whitespace: 空白字符 # +LogicalOperator: 逻辑运算符 #