/*
* NOTES
* =====
* - Play does not support multiple tracks. [09/03/2013]
*
*/
#include "rpyparser.h"
// --- Main class
rpyParser::rpyParser(driver *Out)
{
output = Out;
}
int rpyParser::parse(rpyCommand *cmd)
{
// Invisible functions
if (cmd->func == "image") {
// join info
string tag = "";
unsigned int i;
for (i=0; i < cmd->params.size(); i++) {
if (cmd->params[i] == "=") break;
tag += cmd->params[i] + " ";
}
tag = tag.substr(0,tag.find_last_of(" "));
addImage(tag, cmd->params[i+1]);
}
else if (cmd->func == "define") { // Character defines
string color="black";
for (unsigned int x=0; x < cmd->params.size(); x++) {
if (cmd->params[x].substr(0,6) == "color=") {
color = cmd->params[x].substr(6,cmd->params[x].length() - 6);
}
}
addCharacter(cmd->params[3], cmd->params[0], color);
}
else if (cmd->func == "$") { // Variables; TODO: This might also be a generic python-call (not just vars)
// Exec command in python (TODO. This part probably breaks cross platform support)
/*FILE * fp ;
string command;
// Assemble existing vars
for (unsigned int x=0; x < variables.size(); x++) {
command += variables[x].name + " = " + variables[x].value + "\n";
}
command += joinParams(cmd, 0);
command += "\nprint " + cmd->params[0];
command ="echo '" + command + "' | python";
char pOut[PATH_MAX];
string newContent;
fp = popen(command.c_str(), "r");
while ( fgets( pOut, PATH_MAX, fp ) != NULL )
newContent += pOut;
pclose(fp);
if (newContent[newContent.length()-1] == '\n')
newContent.erase(newContent.length()-1,1);*/
setVar(cmd->params[0], pythonExec(cmd->fullParams + "\nprint " + cmd->params[0]));
/*for (unsigned int x=0; x < variables.size(); x++) { // Debugging (displays the vars)
cout << "V" << x << ":" << variables[x].name << "=" << variables[x].value << endl;
}*/
cout << "[I]\tUpdated variable " << cmd->params[0] << endl;
}
// Functions w/ output
else if (cmd->type == RPYTYPE_THOUGHTS) {
output->think(fixSaid(cmd->params[0]));
}
else if (getCharacterFromTag(cmd->func)->name != E404) {
output->say(getCharacterFromTag(cmd->func), fixSaid(cmd->params[0]));
}
else if (cmd->func == "scene") {
//output->scene(getImageFromTag(joinParams(cmd, 0)));
output->scene(getImageFromTag(cmd->fullParams));
}
else if (cmd->func == "show") { // Sprites
output->showPerson(getImageFromTag(cmd->fullParams));
}
else if (cmd->func == "hide") {
output->hidePerson(getImageFromTag(cmd->fullParams));
}
else if (cmd->func == "play") {
if (cmd->params[0] == "music") output->playMusic(cmd->params[1]);
else output->playSound(cmd->params[1]);
}
else if (cmd->func == "stop") {
if (cmd->params[0] == "music") output->stopMusic();
else output->stopSound();
}
else if (cmd->func == "" || cmd->func == "#" || cmd->func == "with" || cmd->func == "pause") {
// These commands are to be ignored. We just include this "else if" to avoid returning an error code.
}
else {
return 1;
}
return 0;
}
string rpyParser::pythonExec(string command)
{
FILE * fp ;
string lCommand = "";
// Assemble existing vars
for (unsigned int x=0; x < variables.size(); x++) {
lCommand += variables[x].name + " = " + variables[x].value + "\n";
}
/* cout << "\n-- Python command:\n" << lCommand + command << "\n----------------\n" << endl; */
lCommand ="echo '" + lCommand + command + "' | python";
char pOut[PATH_MAX];
string newContent;
fp = popen(lCommand.c_str(), "r");
while ( fgets( pOut, PATH_MAX, fp ) != NULL )
newContent += pOut;
pclose(fp);
if (newContent[newContent.length()-1] == '\n')
newContent.erase(newContent.length()-1,1);
return newContent;
}
string rpyParser::joinParams(rpyCommand *cmd, unsigned int start, unsigned int end)
{
string tag = "";
unsigned int i;
for (i=start; i < cmd->params.size() && i <end; i++) {
// if (cmd->params[i] == "=") break; TODO: Why was this here?!
tag += cmd->params[i] + " ";
}
tag = tag.substr(0,tag.find_last_of(" "));
return tag;
}
string rpyParser::fixSaid(string text)
{
string temp;
// Remove styling {...}
bool append=true;
temp = "";
for (unsigned int x=0; x < text.length(); x++) {
if (text[x] == '{') append = false;
else if (text[x] == '}') append = true;
else if (append) temp.push_back(text[x]);
}
text = temp;
// Replace evil characters such as backslashs
for (unsigned int x=0; x < text.length(); x++) {
if (text[x] == '\\') text[x] = '?'; // TODO: Replace with something more sensible later
}
// Replace vars
int st = text.find("%(");
if (st != string::npos) { // TODO: Compiler warning, but changing the datatype causes an error.
temp = text.substr(0, st); // Beginning
text = text.substr(st+2,text.length()-st-2); // Part to replace and ending [+2 to remove %(]
unsigned int x = text.find(")s");
string varname = text.substr(0,x);
x+=2;
text = text.substr(x, text.length()-x);
text = temp + getVariableFromName(varname)->value + text;
}
return text;
}
int rpyParser::addCharacter(string name, string tag, string color)
{
cout << "[I]\tAdding character (" << name << "," << tag << "," << color << ")" << endl; // DEBUG LINE
if (name == "" || tag == "" || color == "") {
cerr << "[E]\tCould not add character (" << name << "," << tag << "," << color << ")" << endl;
return 1;
}
else {
characters.push_back(rpyCharacter(name, tag, color));
return 0;
}
}
rpyCharacter *rpyParser::getCharacterFromTag(string tag)
{
for (unsigned int i=0; i < characters.size(); i++) {
if (tag == characters[i].tag) {
return &characters[i];
}
}
return new rpyCharacter(E404, E404, E404C);
}
int rpyParser::addImage(string tag, string filename)
{
if (filename == "" || tag == "") {
cerr << "[E]\tCould not add image (" << tag << "," << filename << ")" << endl;
return 1;
}
else if (getImageFromTag(tag)->tag != E404) {
cerr << "[W]\tCan't add image (" << tag << "," << filename << "). Tag alreadys exists." << endl;
return 2;
}
else {
cout << "[I]\tAdded image (" << tag << "," << filename << ")" << endl;
images.push_back(rpyImage(tag, filename));
return 0;
}
}
rpyImage *rpyParser::getImageFromTag(string tag)
{
for (unsigned int i=0; i < images.size(); i++) {
if (tag == images[i].tag) {
return &images[i];
}
}
return new rpyImage(E404, E404P);
}
int rpyParser::setVar(string name, string value)
{
rpyVariable *var = getVariableFromName(name);
if (var->name == E404) {
var->name = name;
var->value = value;
variables.push_back(*var);
}
else var->value = value;
return 0;
}
rpyVariable *rpyParser::getVariableFromName(string name)
{
for (unsigned int i=0; i < variables.size(); i++) {
if (name == variables[i].name) {
return &variables[i];
}
}
return new rpyVariable(E404, E404);
}