/*
Av :
Dawood Rehman 960109-4114
Ramtin Javanmardi 950922-5075
*/
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <regex>
#include <algorithm>
using namespace std;
struct Token
{
Token(int n, string c)
{
s = c;
nr = n;
}
string s;
int nr;
};
struct Command
{
Command(string p1, string p2)
{
s1 = p1;
s2 = p2;
next = NULL;
branch = NULL;
}
string s1;
string s2;
Command *next;
Command *branch;
};
struct V2
{
V2(double px, double py)
{
x = px;
y = py;
}
double x;
double y;
int rotate = 0;
};
// lexicalanalysator is used for tokenizing
void lexicalanalysator();
// caseupper is used for turning all letters to uppercase
char caseupper(char c);
// hexletter checks wheter a given character is a hexadecimal number
bool hexletter(char c);
// parser is used for parsing and checking the grammar
bool parser();
// calc is used for calculating the line segments and printing them out
void calc(Command *ptr);
// syntaxerror prints syntaxerror on the given row
void syntaxerror(int nr);
// c1, c2, h6 and D are used for checking whether a token is valid or not.
// For en example, c1 checks if a token is "UP" or "DOWN".
bool c1(string token);
bool c2(string token);
bool h6(string token);
bool D(string token);
vector<string> rows;
vector<Token> tokens;
vector<Command*> branchJumpBack;
Command *commandTree = new Command("-1", "-1");
Command *commandTreePtr = commandTree;
const double pi = 3.1415926535897;
string outputColor = "#0000FF";
V2 position = V2(0, 0);
vector<string> outputVector;
int main()
{
lexicalanalysator();
if (!parser()) return 0;
calc(commandTreePtr);
}
void calc(Command *ptr)
{
static bool stateUP = true;
if (ptr == NULL)
return;
else if (ptr->s1 == "-1")
return;
Command TI = *ptr;
double d = atoi(TI.s2.c_str());
if (TI.s1 == "DOWN") stateUP = false;
else if (TI.s1 == "UP") stateUP = true;
else if (TI.s1 == "COLOR") outputColor = TI.s2;
else if (TI.s1 == "LEFT") position.rotate += d;
else if (TI.s1 == "RIGHT") position.rotate -= d;
else if (TI.s1 == "FORW")
{
string otemp = "";
otemp += outputColor + " " + to_string(position.x) + " " + to_string(position.y);
position.x += d*cos(pi*position.rotate / 180.0);
position.y += d*sin(pi*position.rotate / 180.0);
otemp += " " + to_string(position.x) + " " + to_string(position.y);
if (!stateUP) cout << otemp << endl;
}
else if (TI.s1 == "BACK")
{
string otemp = "";
otemp += outputColor + " " + to_string(position.x) + " " + to_string(position.y);
position.x -= d*cos(pi*position.rotate / 180.0);
position.y -= d*sin(pi*position.rotate / 180.0);
otemp += " " + to_string(position.x) + " " + to_string(position.y);
if (!stateUP) cout << otemp << endl;
}
if (ptr->s1 == "REP")
{
for (int a = 0; a < atoi((ptr->s2).c_str()); a++)
{
calc(ptr->branch);
}
}
calc(ptr->next);
}
bool parser()
{
vector<string> citations;
vector<bool> repactivated;
string expected = "none";
bool singlerep = false;
bool branch = false;
bool done = false;
bool noCommand = false;
int repmult = 1;
for (int a = 0; a < tokens.size(); a++)
{
if (done)
{
done = false;
if (branch)
{
branch = false;
commandTree->branch = new Command("-1", "-1");
commandTree = commandTree->branch;
}
else
{
commandTree->next = new Command("-1", "-1");
commandTree = commandTree->next;
}
}
Token token = tokens.at(a);
if (expected == "none")
{
if (c1(token.s))
{
expected = ".";
commandTree->s1 = token.s;
}
else if (c2(token.s))
{
expected = "c2nr";
commandTree->s1 = token.s;
}
else if (token.s == "COLOR")
{
expected = "colorhex";
commandTree->s1 = token.s;
}
else if (token.s == "REP")
{
expected = "repnr";
commandTree->s1 = token.s;
}
else if (token.s == "\"" && repactivated.size() && repactivated.back())
{
expected = "none";
singlerep = false;
if (citations.back() == "\"")
{
if (noCommand)
{
syntaxerror(token.nr);
return false;
}
citations.pop_back();
repactivated.pop_back();
commandTree = branchJumpBack.back();
branchJumpBack.pop_back();
done = true;
}
else
{
citations.back() = "\"";
}
}
else
{
syntaxerror(token.nr);
return false;
}
}
else
{
if (expected == ".")
{
done = true;
noCommand = false;
expected = "none";
if (singlerep)
{
singlerep = false;
citations.pop_back();
repactivated.pop_back();
commandTree = branchJumpBack.back();
branchJumpBack.pop_back();
}
}
else if (expected == "c2nr")
{
expected = ".";
if (D(token.s))
{
commandTree->s2 = token.s;
}
else
{
syntaxerror(token.nr);
return false;
}
}
else if (expected == "colorhex")
{
expected = ".";
if (h6(token.s))
{
commandTree->s2 = token.s;
}
else
{
syntaxerror(token.nr);
return false;
}
}
else if (expected == "repnr")
{
expected = "none";
if (D(token.s))
{
repmult *= atoi(token.s.c_str());
if (tokens.at(a + 1).s == "REP")
{
continue;
}
branch = true;
done = true;
noCommand = true;
commandTree->s2 = to_string(repmult);
branchJumpBack.push_back(commandTree);
repactivated.push_back(true);
citations.push_back("");
singlerep = true;
repmult = 1;
}
else
{
syntaxerror(token.nr);
return false;
}
}
}
}
if (repactivated.size())
{
syntaxerror(tokens.at(tokens.size() - 1).nr);
return false;
}
if (expected != "none")
{
syntaxerror(tokens.at(tokens.size() - 1).nr);
return false;
}
return true;
}
bool c1(string token)
{
if (token == "UP" || token == "DOWN")
return true;
return false;
}
bool c2(string token)
{
if (token == "FORW" || token == "BACK" || token == "LEFT" || token == "RIGHT")
return true;
return false;
}
bool h6(string token)
{
if (token.length() == 7 && token[0] == '#' && hexletter(token[1]) && hexletter(token[2]) && hexletter(token[3]) && hexletter(token[4]) && hexletter(token[5]) && hexletter(token[6]))
return true;
return false;
}
bool D(string token)
{
if (!(token[0] > 48 && token[0] < 58))
return false;
for (int a = 0; a < token.length(); a++)
{
if (!(token[a] > 47 && token[a] < 58))
return false;
}
return true;
}
bool hexletter(char c)
{
if ((c > 47 && c < 58) || (c > 64 && c < 71))
return true;
return false;
}
void lexicalanalysator()
{
string row;
string word;
ios_base::sync_with_stdio(false);
while (getline(cin, row)) rows.push_back(row);
for (int a = 0; a < rows.size(); a++)
{
bool bc = false;
row = rows.at(a);
word = "";
for (int b = 0; b < row.length(); b++)
{
char c = row.at(b);
if (c == '%')
{
if (bc)
{
bc = false;
tokens.push_back(Token(a + 1, word));
}
break;
}
else if (c == ' ' || c == '\t')
{
if (bc)
{
bc = false;
tokens.push_back(Token(a + 1, word));
}
word = "";
continue;
}
else if (c == '.')
{
if (word != "")
tokens.push_back(Token(a + 1, word));
tokens.push_back(Token(a + 1, "."));
word = "";
bc = false;
continue;
}
else if (word == "\"")
{
if (bc)
{
bc = false;
tokens.push_back(Token(a + 1, word));
}
word = "";
}
bc = true;
word += caseupper(row.at(b));
if (b == row.length() - 1) tokens.push_back(Token(a + 1, word));
}
}
//for (int a = 0; a < tokens.size(); a++)
//cout << tokens.at(a).nr << " " << tokens.at(a).s << endl;
}
char caseupper(char c)
{
if (c > 96 && c < 123)
return char(c - 32);
return c;
}
void syntaxerror(int nr)
{
cout << "syntaxfel på rad " << nr << endl;
}
Comments