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: 逻辑运算符 #