-
Notifications
You must be signed in to change notification settings - Fork 5
/
Parser.cpp
143 lines (112 loc) · 4.07 KB
/
Parser.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
/*
* Created by Francois W. Nel on 27 Jun 2016.
*/
#include "Parser.h"
using namespace std;
Parser::Parser(string& fileName) {
fin.open(fileName);
if (fin.fail()) {
cout << fileName << " not found." << endl;
exit(1);
}
// Populate the command map table.
commandTable['@'] = 'A';
commandTable['A'] = 'C';
commandTable['D'] = 'C';
commandTable['M'] = 'C';
commandTable['0'] = 'C';
commandTable['1'] = 'C';
commandTable['-'] = 'C';
commandTable['!'] = 'C';
commandTable['('] = 'L';
}
bool Parser::hasMoreCommands() {
return !fin.eof();
}
void Parser::advance(unsigned long& lineNr) {
string currentLine;
unsigned long commentPos;
bool commandFound;
commandFound = false;
// Read lines until a command is found.
while (!commandFound && getline(fin, currentLine)) {
// Increment the line number corresponding to the source file,
// used for error tracking.
lineNr++;
// Remove whitespace.
currentLine.erase(remove_if(currentLine.begin(), currentLine.end(), ::isspace), currentLine.end());
// Remove comments.
commentPos = currentLine.find("//");
if (commentPos != string::npos) {
currentLine.erase(commentPos, currentLine.length() - commentPos);
}
// If the remaining line is not empty, a command has been found.
commandFound = !currentLine.empty();
}
currentCommand = currentLine;
}
char Parser::commandType(unsigned long& lineNr) {
if (commandTable.find(currentCommand[0]) != commandTable.end()) {
return commandTable[currentCommand[0]];
}
// If an invalid command is found, output an error message and line number.
cout << "Invalid syntax at line: " << lineNr << endl;
exit(1);
}
string Parser::symbol() {
unsigned long openBracketPos, closeBracketPos;
openBracketPos = currentCommand.find('(');
closeBracketPos = currentCommand.find(')');
// A-instruction: return everything after the '@' character.
if (currentCommand[0] == '@') {
return currentCommand.substr(1, currentCommand.length() - 1);
}
// L-instruction: return everything in between the '(' and ')' characters.
else if (openBracketPos != string::npos && closeBracketPos != string::npos) {
return currentCommand.substr(openBracketPos + 1, closeBracketPos - openBracketPos - 1);
}
// If the function was called in error, return a blank string.
return "";
}
string Parser::destM() {
unsigned long equalSignPos;
equalSignPos = currentCommand.find('=');
// Return everything before the '=' character.
if (equalSignPos != string::npos) {
return currentCommand.substr(0, equalSignPos);
}
// If no destination was specified, return a blank string.
return "";
}
string Parser::compM() {
unsigned long equalSignPos, semiColonPos;
equalSignPos = currentCommand.find('=');
semiColonPos = currentCommand.find(';');
// Return the computation mnemonic based on three cases.
if (equalSignPos != string::npos) {
if (semiColonPos != string::npos) {
// Case 1: dest = comp ; jump
return currentCommand.substr(equalSignPos + 1, semiColonPos - equalSignPos - 1);
}
// Case 2: dest = comp
return currentCommand.substr(equalSignPos + 1, currentCommand.length() - equalSignPos - 1);
}
else if (semiColonPos != string::npos) {
// Case 3: comp ; jump
return currentCommand.substr(0, semiColonPos);
}
// If no computation was specified, return a blank string.
// This will result in an error message at the line number.
// The error is handled by CodeTranslator.comp().
return "";
}
string Parser::jumpM() {
unsigned long semiColonPos;
semiColonPos = currentCommand.find(';');
// Return everything after the ';' character.
if (semiColonPos != string::npos) {
return currentCommand.substr(semiColonPos + 1, currentCommand.length() - semiColonPos - 1);
}
// If a jump was not specified, return a blank string.
return "";
}