#include #include #include #include #include #include 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; } string s1; string s2; }; struct V2 { V2(float px, float py) { x = px; y = py; } float x; float y; float rotate = 0; }; void lexicalanalysator(); char caseupper(char c); bool hexletter(char c); bool parser(); void calc(); void syntaxerror(int nr); bool c1(string token); bool c2(string token); bool h6(string token); bool D(string token); vector rows; vector tokens; vector commands; const double pi = 3.1415926535897; string outputColor = "#0000FF"; V2 position = V2(0, 0); vector outputVector; int main() { lexicalanalysator(); if (!parser()) return 0; /*for (int a = 0; a < commands.size(); a++) { cout << commands.at(a).s1 << " " << commands.at(a).s2 << endl; }*/ calc(); } void calc() { bool stateUP = true; for (int a = 0; a < commands.size(); a++) { Command TI = commands.at(a); float 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); position.y += d*sin(pi*position.rotate / 180); 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); position.y -= d*sin(pi*position.rotate / 180); otemp += " " + to_string(position.x) + " " + to_string(position.y); if(!stateUP) cout << otemp << endl; } } } bool parser() { vector citations; vector repactivated; vector repnumbers; vector oldCommandSize; string expected = "none"; int repmult = 1; bool singlerep = false; for (int a = 0; a < tokens.size(); a++) { Token token = tokens.at(a); if (expected == "none") { if (c1(token.s)) { expected = "."; commands.push_back(Command(token.s, "-1")); } else if (c2(token.s)) { expected = "c2nr"; commands.push_back(Command(token.s, "-1")); } else if (token.s == "COLOR") { expected = "colorhex"; commands.push_back(Command(token.s, "-1")); } else if (token.s == "REP") { expected = "repnr"; } else if (token.s == "\"" && repactivated.size() && repactivated.back()) { singlerep = false; expected = "none"; if (citations.back() == "\"") { int commandsSize = commands.size(); for (int b = 0; b < repnumbers.back() - 1; b++) { for (int c = oldCommandSize.back(); c < commandsSize; c++) { commands.push_back(commands.at(c)); } } if (oldCommandSize.back() == commandsSize) { syntaxerror(token.nr); return false; } oldCommandSize.pop_back(); citations.pop_back(); repnumbers.pop_back(); repactivated.pop_back(); } else { citations.back() = "\""; } } else { syntaxerror(token.nr); return false; } } else { if (expected == ".") { expected = "none"; if (singlerep) { Command tempCommand = commands.at(commands.size() - 1); for (int b = 0; b < repnumbers.back() - 1; b++) { commands.push_back(tempCommand); } singlerep = false; oldCommandSize.pop_back(); citations.pop_back(); repnumbers.pop_back(); repactivated.pop_back(); } } else if (expected == "c2nr") { expected = "."; if (D(token.s)) { commands.back().s2 = token.s; } else { syntaxerror(token.nr); return false; } } else if (expected == "colorhex") { expected = "."; if (h6(token.s)) { commands.back().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; } repactivated.push_back(true); repnumbers.push_back(repmult); citations.push_back(""); oldCommandSize.push_back(commands.size()); 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; }