-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSymbolTable.cs
More file actions
190 lines (171 loc) · 5.23 KB
/
SymbolTable.cs
File metadata and controls
190 lines (171 loc) · 5.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
using System;
using System.Collections.Generic;
using System.Text;
namespace Compiler
{
enum SymbolType
{
LOCAL_VAR,
FUNCTION,
BUILTIN_FUNCTION,
PARAMETER,
}
class SymbolTable
{
private static int GlobalTableNumber = 0;
private int TableNumber;
public SymbolTable ParentTable { get; set; }
public SymbolTable OuterTable { get; set; }
private Dictionary<string, SymbolTableEntry> _table;
private int _addressCounter = 0;
private int _paramAddressCounter = -4;
// Constructor
// input: none
public SymbolTable()
{
_table = new Dictionary<string, SymbolTableEntry>();
TableNumber = GlobalTableNumber++;
}
// Method rounds type sizes to multiples of four to put in the stack.
// input: original size
// return: size on the stack
private int RoundByFours(int original)
{
return original + Mod(4 - original, 4);
}
// mov implementation which works with negative numbers
// input: a, b
// return: a mod b
private int Mod(int a, int b)
{
return a - b * (int)Math.Floor((double)a / b);
}
// Method adds an entry to the symbol table
// input: declaration object, data (entry), address and size
// return: none
public void AddEntry(string identifier, int line, SymbolTableEntry entry, int address = 0, int size = 4)
{
// check if insertion is possible
if (EntryExists(identifier))
throw new MultipleDefinedNamesError(identifier, line);
if (entry.SymbolType == SymbolType.LOCAL_VAR)
{
_addressCounter += RoundByFours(size);
entry.Address = _addressCounter;
}
else if(entry.SymbolType == SymbolType.PARAMETER)
{
_paramAddressCounter -= RoundByFours(size);
entry.Address = _paramAddressCounter;
}
else
entry.Address = address;
// set address
// insert new entry
_table.Add(identifier, entry);
}
// Method return the entry of a specific symbol from the table
// input: declaration node
// return: symbol's entry
public SymbolTableEntry GetEntry(string identifier, int line)
{
// check if entry exists
if (EntryExists(identifier))
{
SymbolTableEntry entry = _table[identifier].Copy();
if(entry.SymbolType == SymbolType.LOCAL_VAR)
entry.Address += GetOffset();
return entry;
}
// try to find entry in parent
if(ParentTable == null)
throw new UnknownNameError(identifier, line);
return ParentTable.GetEntry(identifier, line);
}
// Method return the entry of a specific symbol from the table
// input: variable reference node
// return: symbol's entry
public SymbolTableEntry GetEntry(Variable variable)
{
return GetEntry(variable.Identifier, variable.Line);
}
// Method checks if a symbol is already defined
// input: symbol name to check
// return: whether it's already in the table or not
public bool EntryExists(string symbol)
{
return _table.ContainsKey(symbol);
}
public bool EntryExistsRecursive(string symbol)
{
return EntryExists(symbol) ||
ParentTable != null && ParentTable.EntryExistsRecursive(symbol);
}
// Method returns the amount of bytes needed for the local variables of this block
// input: none
// return: number of bytes needed to be allocated on the stack
public int VariableBytes()
{
return _addressCounter;
}
// Method returns offset in stack frame
// input: none
// return: offset of variables in stack frame.
public int GetOffset()
{
return GetOffsetTotal() - _addressCounter;
}
// Method returns offset including this table.
private int GetOffsetTotal()
{
if (ParentTable is null)
return _addressCounter;
else
return _addressCounter + ParentTable.GetOffsetTotal();
}
// Method finds closest outer table
// input: none
// return: outer table
public SymbolTable GetOuterTable()
{
if (OuterTable != null)
return OuterTable;
else
return ParentTable?.GetOuterTable();
}
// Method finds entry in this or in outer tables
// input: variable to find
// return: tuple. Entry and Symbol Table it was found in (or null)
public Tuple<SymbolTableEntry, SymbolTable> GetOuterEntry(Variable var)
{
if (EntryExistsRecursive(var.Identifier))
return Tuple.Create(GetEntry(var), this);
else
{
SymbolTable outer = GetOuterTable();
if (outer != null)
return outer.GetOuterEntry(var);
else
return Tuple.Create(GetEntry(var), (SymbolTable)null);
}
}
// To String overload to print content of symbol table
public string ToString(int indent)
{
string indentStr = "";
for (; indent > 0; indent--)
indentStr += '\t';
string result = indentStr + "___SymbolTable" + TableNumber + "___\n" +
indentStr + Helper.StringFormat("Name", 20) + " | " + Helper.StringFormat("Type", 15) + " | " + Helper.StringFormat(
"Value", 12) + " | " + Helper.StringFormat("Address", 12) + "\n";
foreach((string name, SymbolTableEntry entry) in _table)
{
result += indentStr + Helper.StringFormat(name, 20) + " | " + Helper.StringFormat(entry.SymbolType.ToString(), 15) + " | " +
Helper.StringFormat(entry.ValueType.ToString(), 12) + " | " + Helper.StringFormat(entry.Address.ToString(), 12) + "\n";
}
// add relations
result += indentStr + "Parent: " + ParentTable?.TableNumber + ", Outer: " + OuterTable?.TableNumber + "\n";
return result;
}
}
}