-
Notifications
You must be signed in to change notification settings - Fork 0
/
ScopeTable.cpp
168 lines (150 loc) · 5.02 KB
/
ScopeTable.cpp
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
/*
* File: ScopeTable.cpp
* Author: daniel
*
* Created on October 27, 2013, 11:41 PM
*/
#include "ScopeTable.h"
#include "ASTDeclarationNode.h"
ScopeTable::ScopeTable() : blockLevel(0), accessTable(vector<int>()),
errEnc(vector<EncounteredError>()),
identificationTable(vector<IdentificationTableItem>()), admin(NULL)
{
// Push the null item onto the identification stack
identificationTable.push_back(IdentificationTableItem());
}
ScopeTable::ScopeTable(Admin * adminRef) : blockLevel(0), accessTable(vector<int>()),
errEnc(vector<EncounteredError>()),
identificationTable(vector<IdentificationTableItem>()), admin(adminRef)
{
// Push the null item onto the identification stack
identificationTable.push_back(IdentificationTableItem());
}
ScopeTable::ScopeTable(const ScopeTable& orig) : blockLevel(0),
accessTable(orig.accessTable), errEnc(orig.errEnc),
identificationTable(orig.identificationTable)
{
}
ScopeTable::~ScopeTable() {
accessTable.clear();
errEnc.clear();
identificationTable.clear();
}
/* Prepares the access table to match the size of the Scanner's symbol table
*/
void ScopeTable::initAccessTable(int length) {
for(int i = 0; i < length; i++) {
accessTable.push_back(0);
}
}
/* Returns true if the selected identifier is within the current scope
*/
bool ScopeTable::isInScope(int id) { return accessTable[id] != 0; }
/* Adds a new declaration to the identifier table and updates the access table.
* Also throws semantic errors if the declaration is being redefined a second
* time
*/
void ScopeTable::insertDeclaration(int id, ASTDeclarationNode * decNode) {
// Out of bounds
// Using the assumption that the ids will only ever be inserted in order of
// appearance in program, so only just push back the new one
while(accessTable.size() <= id) {
accessTable.push_back(0);
}
/*else if(accessTable.size() < id) {
for(int i = 0; i < accessTable.size(); i++) {
cout << admin->lookupasdf(identificationTable[accessTable[i]].getDecPtr()->id) << endl;
}
cout << admin->lookupasdf(id) << " is " << id << endl;
throw "Non-sequential insertion of declaration into access table";
}*/
// New declaration
if(accessTable[id] == 0) {
identificationTable.push_back(IdentificationTableItem(blockLevel, 0, id, decNode));
//cout << "new dec " << id << " is " << admin->lookupasdf(id) << endl;
accessTable[id] = identificationTable.size()-1;
//cout << "ident at lex#" << id << " produces " << identificationTable[accessTable[id]].getDecPtr()->id << endl;
}
// Update declaration scope (sub-block)
else if(identificationTable[accessTable[id]].getBlockLevel() != blockLevel) {
identificationTable.push_back(IdentificationTableItem(blockLevel, accessTable[id], id, decNode));
accessTable[id] = identificationTable.size()-1;
}
else if(isInErrEnc(id)) {
// Skip reporting error
}
// Semantic error - double definition
else {
ASTDeclarationNode * decPtr = identificationTable[accessTable[id]].getDecPtr();
admin->semanticError("Identifier redefinition: "
+ decPtr->lookup->getIdentifierName(id),
decNode->lineNumber);
addToErrEnc(id);
}
}
/* Returns the ASTDeclarationNode specified by the id parameter.
* May throw an undeclared identifier if the identifier is not available
* in the current scope
*/
ASTDeclarationNode * ScopeTable::getDeclaration(int id, int lineNumber) {
if(isInErrEnc(id)) {
// Skip reporting error
}
// Semantic error - undeclared identifier
else if(id >= accessTable.size()) {
admin->semanticError("Undeclared identifier: " + admin->getIdentifierName(id),
lineNumber);
addToErrEnc(id);
}
// Pre-declared identifier - return it
else if(accessTable[id] != 0) {
return identificationTable[accessTable[id]].getDecPtr();
}
// Semantic error - undeclared identifier
else {
admin->semanticError("Undeclared identifier: " + admin->getIdentifierName(id),
lineNumber);
addToErrEnc(id);
}
return NULL;
}
/* Increase the block level
*/
void ScopeTable::enterBlock() {
blockLevel++;
}
/* Decrease the block level and remove all identifiers from the scope that is
* being left. Also, update the access table so that identifiers which hid
* external definitions can now access those external definitions
*/
void ScopeTable::exitBlock() {
// Program exception - trying to leave global block
if(blockLevel == 0) {
throw "Trying to exit the global block (block 0)";
}
blockLevel--;
// From top of stack, remove until out of blockLevel
for(int i = identificationTable.size()-1; i >= 0 &&
identificationTable[i].getBlockLevel() > blockLevel; i--) {
accessTable[identificationTable[i].getLexicalIndex()] =
identificationTable[i].getNext();
}
removeBlockFromErrEnc();
}
bool ScopeTable::isInErrEnc(int id) {
for(int i = 0; i < errEnc.size(); i++) {
if(errEnc[i].getId() == id) {
return true;
}
}
return false;
}
void ScopeTable::addToErrEnc(int id) {
errEnc.push_back(EncounteredError(blockLevel, id));
}
void ScopeTable::removeBlockFromErrEnc() {
for(int i = errEnc.size()-1; i >= 0 &&
errEnc[i].getBlockLevel() > blockLevel; i--) {
errEnc.pop_back();
}
}