[feature] 再见,编译原理

This commit is contained in:
lichx 2024-12-27 01:25:50 +08:00
parent e92384f424
commit 8b1775974d
14 changed files with 352 additions and 101 deletions

View File

@ -14,6 +14,9 @@
<None Update="files\if-grammar.grammar"> <None Update="files\if-grammar.grammar">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="files\translateFile">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,9 +1,4 @@
using System; using System.Text;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CompilerDesignIFlr1 namespace CompilerDesignIFlr1
{ {
@ -32,32 +27,6 @@ namespace CompilerDesignIFlr1
internal void CalculateProspects() internal void CalculateProspects()
{ {
//Queue<LR1Unit> 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<string> prospect = units
// .Select(x => GetProspectsOf(x))
// .Aggregate(
// new HashSet<string>(),
// (set, x) =>
// {
// set.UnionWith(x);
// return set;
// }
// );
// unit.Prospect.UnionWith(prospect);
//}
bool haveChange = true; bool haveChange = true;
while (haveChange) while (haveChange)

View File

@ -1,12 +1,4 @@
using System; namespace CompilerDesignIFlr1
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CompilerDesignIFlr1
{ {
internal class LR1Creator internal class LR1Creator
{ {

View File

@ -1,8 +1,4 @@
using System; using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CompilerDesignIFlr1 namespace CompilerDesignIFlr1
{ {
@ -68,9 +64,11 @@ namespace CompilerDesignIFlr1
sb.Append("ACTION: \n"); sb.Append("ACTION: \n");
foreach (var (key, value) in ACTION) foreach (var (key, value) in ACTION)
sb.Append(key).Append(": ").Append(value).Append(", "); 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) foreach (var (key, value) in GOTO)
sb.Append(key).Append(": ").Append(value).Append(", "); sb.Append(key).Append(": ").Append(value).Append(", ");
sb.Append('\n');
return sb.ToString(); return sb.ToString();
} }

View File

@ -1,8 +1,5 @@
using System; using System.Diagnostics.SymbolStore;
using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks;
namespace CompilerDesignIFlr1 namespace CompilerDesignIFlr1
{ {
@ -10,6 +7,16 @@ namespace CompilerDesignIFlr1
{ {
internal LR1Unit() { } internal LR1Unit() { }
internal static string LanguageMode = "English";
internal static Dictionary<string, string> 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) internal LR1Unit(string name, string grammar)
{ {
Type = "Token"; Type = "Token";
@ -49,7 +56,16 @@ namespace CompilerDesignIFlr1
Grammar = grammar; Grammar = grammar;
} }
public LR1Unit(int id, string type, string name, int quadrupleIndex, string value, HashSet<string> prospect, int pointPosition, List<string> grammar) public LR1Unit(
int id,
string type,
string name,
int quadrupleIndex,
string value,
HashSet<string> prospect,
int pointPosition,
List<string> grammar
)
{ {
Id = id; Id = id;
Type = type; Type = type;
@ -62,7 +78,17 @@ namespace CompilerDesignIFlr1
} }
internal LR1Unit Clone() => internal LR1Unit Clone() =>
new LR1Unit(Id, Type, Name, 0, Value,new HashSet<string>(Prospect), PointPosition, [.. Grammar]); new LR1Unit(
Id,
Type,
Name,
0,
Value,
new HashSet<string>(Prospect),
PointPosition,
[.. Grammar]
);
internal int Id { get; set; } = -1; internal int Id { get; set; } = -1;
internal string Type { get; set; } = ""; internal string Type { get; set; } = "";
internal string Name { get; set; } = ""; internal string Name { get; set; } = "";
@ -88,22 +114,29 @@ namespace CompilerDesignIFlr1
public override string ToString() 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(); StringBuilder sb = new();
//if (Grammar.Count == 0)
// return ".";
sb.Append($"{Id, 2} "); sb.Append($"{Id, 2} ");
sb.Append(Name).Append(" ::= "); sb.Append(GetName(Name)).Append(" ::= ");
for (int i = 0; i < Grammar.Count; i++) for (int i = 0; i < Grammar.Count; i++)
{ {
if (PointPosition == i) if (PointPosition == i)
sb.Append(". "); sb.Append(". ");
sb.Append(Grammar[i] + " "); sb.Append(GetName(Grammar[i]) + " ");
} }
if (PointPosition == Grammar.Count) if (PointPosition == Grammar.Count)
sb.Append('.'); sb.Append('.');
foreach (var item in Prospect) foreach (var item in Prospect)
{ {
sb.Append(", " + item); sb.Append(", " + GetName(item));
} }
return sb.ToString(); return sb.ToString();
} }

View File

@ -1,12 +1,6 @@
using System; using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using CompilerDesignIFlr1;
namespace CompilerDesignIflr1 namespace CompilerDesignIFlr1
{ {
internal class LexicalAnalysis internal class LexicalAnalysis
{ {

View File

@ -1,8 +1,9 @@
// See https://aka.ms/new-console-template for more information // See https://aka.ms/new-console-template for more information
using CompilerDesignIflr1;
using CompilerDesignIFlr1; using CompilerDesignIFlr1;
Console.WriteLine("Hello, World!"); Console.WriteLine("Hello, World!");
LR1Unit.Init("./files/translateFile");
LR1Unit.LanguageMode = "Chinese";
var grammarReader = new GrammarReader("./files/if-grammar.grammar"); var grammarReader = new GrammarReader("./files/if-grammar.grammar");
var lr1Creator = new LR1Creator(grammarReader); var lr1Creator = new LR1Creator(grammarReader);
var lr1Table = new LR1Table(lr1Creator); var lr1Table = new LR1Table(lr1Creator);
@ -10,3 +11,4 @@ var lexicalAnalysis = new LexicalAnalysis(lr1Creator, "./files/code");
var semanticAnalysis = new SemanticAnalysis(); var semanticAnalysis = new SemanticAnalysis();
var stateMachine = new StateMachine(lr1Table, lexicalAnalysis, lr1Creator, semanticAnalysis); var stateMachine = new StateMachine(lr1Table, lexicalAnalysis, lr1Creator, semanticAnalysis);
semanticAnalysis.PrintQuadruples(); semanticAnalysis.PrintQuadruples();
semanticAnalysis.OptimizeQuadruples();

View File

@ -1,11 +1,4 @@
using System; using System.Text;
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;
namespace CompilerDesignIFlr1 namespace CompilerDesignIFlr1
{ {
@ -733,13 +726,155 @@ namespace CompilerDesignIFlr1
internal void PrintQuadruples() internal void PrintQuadruples()
{ {
Console.WriteLine("四元式:");
for (int i = 0; i < Quadruples.Count; i++) for (int i = 0; i < Quadruples.Count; i++)
{ {
Console.Write($"{i, 3}"); //Console.Write($"{i, 3}");
Console.WriteLine(Quadruples[i]); Console.WriteLine(Quadruples[i]);
} }
} }
internal void OptimizeQuadruples()
{
HashSet<int> 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<Quadruple> afterList = basedOn.Order().Select(x => Quadruples[x].Clone()).ToList();
HashSet<int> 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<string, string> 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) => internal static bool Assert(bool val) =>
!val ? throw new Exception("Assertion failed.") : false; !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) internal Quadruple(string @operator, int index, Identifier a, Identifier? b, Identifier to)
{ {
Operator = @operator; Operator = @operator;
this.Index = index; Index = index;
A = a; A = a;
B = b; B = b;
To = to; To = to;
@ -916,7 +1051,8 @@ namespace CompilerDesignIFlr1
return identifier.Name; return identifier.Name;
return identifier.Value; return identifier.Value;
} }
sb.Append('(') sb.Append($"{Index, 3}")
.Append('(')
.Append(Operator.PadLeft(4, ' ')) .Append(Operator.PadLeft(4, ' '))
.Append(',') .Append(',')
.Append(GetValue(A).PadLeft(4, ' ')) .Append(GetValue(A).PadLeft(4, ' '))

View File

@ -1,11 +1,4 @@
using System; namespace CompilerDesignIFlr1
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CompilerDesignIflr1;
namespace CompilerDesignIFlr1
{ {
internal class StateMachine internal class StateMachine
{ {
@ -27,6 +20,8 @@ namespace CompilerDesignIFlr1
} }
internal void Compute() internal void Compute()
{
try
{ {
while (true) while (true)
{ {
@ -34,6 +29,12 @@ namespace CompilerDesignIFlr1
break; break;
} }
} }
catch (Exception e)
{
Console.WriteLine(e.Message);
Environment.Exit(1);
}
}
internal bool ComputeOnce(LR1Unit unit) internal bool ComputeOnce(LR1Unit unit)
{ {

View File

@ -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

View File

@ -1,12 +1,4 @@
{ {
int a =1*9+2; const int a = 5;
if(a>9){
a=a+1;
if(9>1){
a=10;
}
a=2+2;
}
}
}

View File

@ -93,8 +93,8 @@ LogicalOperator {
Plus { "+" } Plus { "+" }
Minus { "-" } Minus { "-" }
Multiply { "*" } Multiply { "*" }
Modulo { "%" }
Divide { "/" } Divide { "/" }
Modulo { "%" }
LParen { "(" } LParen { "(" }
RParen { ")" } RParen { ")" }
LBrace { "{" } LBrace { "{" }

View File

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