00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 #include "vuGuiParser.h"
00005
00006
00007
00008
00009
00010 #define GUI_OPEN " gui %s : %s %n"
00011 #define SECTION_OPEN "%s { %n"
00012 #define CONTROL_DEFINE "%s %s { %n"
00013 #define STRING "%s %n"
00014
00015
00016
00017
00018
00019
00020 vuGuiParser::vuGuiParser() : vuParser()
00021 {
00022 }
00023
00024
00025
00026
00027
00028 vuGuiParser::~vuGuiParser()
00029 {
00030 }
00031
00032
00033
00034
00035
00036 void vuGuiParser::Parse(const char* filename) throw (const char *)
00037 {
00038
00039 readBuffer(filename);
00040 FixBuffer();
00041
00042
00043 ParseGui();
00044 }
00045
00046
00047
00048
00049
00050 void vuGuiParser::ParseGui()
00051 {
00052 int len=0, ret;
00053 char name[64]="";
00054 char base[64]="";
00055
00056
00057 ret = sscanf(&m_Buffer[m_Pos], GUI_OPEN, name, base, &len);
00058 if (ret != 2) throw ("Gui declaration is missing or invalid.");
00059 m_Pos+=len; len = 0;
00060 m_Name = name; m_Base = base;
00061
00062
00063 m_fHeader.open(m_Name + ".h",ios::out);
00064 m_fImpl.open(m_Name + ".cpp",ios::out);
00065 if (!m_fHeader.is_open()||!m_fImpl.is_open())
00066 throw ("Could not open files for output.");
00067
00068
00069 m_fHeader << "#include \"" << m_Base << ".h\"\n\n";
00070 m_fHeader << "class " << m_Name <<": public " << m_Base << "\n{\n";
00071 m_fHeader << "public:\n";
00072
00073
00074 ParseAPIs();
00075
00076
00077 ParseSections();
00078
00079
00080 WriteData();
00081
00082
00083 m_fHeader.close();
00084 m_fImpl.close();
00085 }
00086
00087
00088
00089
00090
00091 void vuGuiParser::ParseAPIs()
00092 {
00093 StringList Apis;
00094
00095
00096 if (readToken('['))
00097 {
00098 Apis = ParseList();
00099 if (!readToken(']'))
00100 throw ("Include header listing not closed properly.");
00101 }
00102
00103
00104 m_fImpl << "#include \"" << m_Name << ".h\"\n";
00105 int num = Apis.getLength();
00106 for (int i=0; i < num; i++)
00107 m_fImpl << "#include \"" << Apis[i] << "\"\n";
00108 m_fImpl << "\n";
00109 };
00110
00111
00112
00113
00114
00115 void vuGuiParser::ParseSections()
00116 {
00117 char name[256] = "";
00118 int len = 0;
00119
00120
00121 if (!readToken('{')) return;
00122
00123
00124 while (!readToken('}') && !finished())
00125 {
00126 if (sscanf(&m_Buffer[m_Pos],SECTION_OPEN,name,&len)!=1)
00127 throw ("Invalid gui section declaration.");
00128 m_Pos += len; len = 0;
00129
00130
00131 if (strcmp(name,"init") == 0)
00132 ParseMethod("init()");
00133 else if (strcmp(name,"close") == 0)
00134 ParseMethod("close()");
00135 else if (strcmp(name,"Top")==0 || strcmp(name,"Bottom")==0 ||
00136 strcmp(name,"Left")==0 || strcmp(name,"Right")==0)
00137 ParseControls(name);
00138 else
00139 throw ("Undefined name for gui section declaration.");
00140 }
00141 }
00142
00143
00144
00145
00146
00147 void vuGuiParser::ParseControls(const char *Location)
00148 {
00149 char name[256],type[256];
00150 int len = 0;
00151 vuString addFunction;
00152
00153 while (!readToken('}') && !finished())
00154 {
00155 if (sscanf(&m_Buffer[m_Pos],CONTROL_DEFINE,type,name,&len)!=2)
00156 throw ("Invalid user interface control declaration.");
00157 m_Pos+=len; len = 0;
00158
00159 if (strcmp(type,"listbox")==0)
00160 addFunction += ParseListBox(name);
00161 else if (strcmp(type,"button")==0)
00162 addFunction += ParseButton(name);
00163 else if (strcmp(type,"slider")==0)
00164 addFunction += ParseSlider(name);
00165 else if (strcmp(type,"checkbox")==0)
00166 addFunction += ParseCheckBox(name);
00167 else if (strcmp(type,"radiobox")==0)
00168 addFunction += ParseRadioBox(name);
00169 addFunction += '\n';
00170 }
00171
00172
00173 m_fHeader << " void add" << Location << "(wxSizer *Sizer);\n";
00174
00175
00176 m_fImpl << "void " << m_Name << "::add" << Location;
00177 m_fImpl << "(wxSizer *Sizer)\n{\n" << addFunction << "};\n\n";
00178 }
00179
00180
00181
00182
00183
00184 StringList vuGuiParser::ParseList()
00185 {
00186 bool read = true;
00187 int len = 0;
00188 char value[256];
00189 StringList slist;
00190
00191 while (read)
00192 {
00193 read = false;
00194 if (readToken(','))
00195 read = true;
00196 else if (readToken(';')) {}
00197 else if (readToken('}',false) || finished()) {}
00198 else if (readToken(']',false)) {}
00199 else if (sscanf(&m_Buffer[m_Pos],STRING,value,&len)==1)
00200 {
00201 m_Pos += len; len = 0;
00202 slist.add(value);
00203 read = true;
00204 }
00205 }
00206 return slist;
00207 }
00208
00209
00210
00211
00212
00213 void vuGuiParser::ParseMethod(const char *Header)
00214 {
00215
00216 m_fHeader << " void " << Header << ";\n";
00217
00218
00219 m_fImpl << "void " << m_Name << "::" << Header << "\n{\n";
00220
00221
00222 while (!readToken('}') && !finished())
00223 m_fImpl << " " << ParseStatement() << ";\n";
00224
00225 m_fImpl << "};\n\n";
00226 }
00227
00228
00229
00230
00231
00232 vuString vuGuiParser::ParseStatement()
00233 {
00234 int len = 0;
00235 char name[256];
00236 vuString statement = "m_Data->";
00237
00238
00239 if (readToken(';')||finished()) return "";
00240
00241
00242 sscanf(&m_Buffer[m_Pos],STRING,name,&len);
00243 m_Pos+=len; len = 0;
00244
00245 statement << name << "(";
00246
00247 if (readToken('('))
00248 {
00249 if (!readToken(')',false))
00250 {
00251 sscanf(&m_Buffer[m_Pos],STRING,name,&len);
00252 m_Pos+=len; len = 0;
00253
00254 if (m_Controls.isMember(vuString("l")+name))
00255 statement << "m_l" << name << "->GetSelection()";
00256 else if (m_Controls.isMember(vuString("s")+name))
00257 statement << "m_s" << name << "->GetValue()";
00258 else if (m_Controls.isMember(vuString("c")+name))
00259 statement << "m_c" << name << "->GetValue()";
00260 else if (m_Controls.isMember(vuString("r")+name))
00261 statement << "m_r" << name << "->GetStringSelection()";
00262 else if (strcmp(name,"glwidth")==0)
00263 statement << "m_glCanvas->getWidth()";
00264 else if (strcmp(name,"glheight")==0)
00265 statement << "m_glCanvas->getHeight()";
00266 else if (m_Controls.isMember(vuString("b")+name))
00267 throw ("Can't pass a button value as a parameter.");
00268 else
00269 throw ("Undefined identifier passed as a parameter.");
00270 }
00271
00272 if (!readToken(')')) throw ("Missing closing paranthesis in code block");
00273 }
00274 statement << ")";
00275
00276 readToken(';');
00277 return statement;
00278 }
00279
00280
00281
00282
00283
00284 void vuGuiParser::WriteData()
00285 {
00286
00287 m_fHeader << "\nprivate:\n";
00288 unsigned int num = m_Controls.getLength();
00289 for (unsigned int i=0; i < num; i++)
00290 {
00291 if (m_Controls[i][(long unsigned int) (0)]=='l')
00292 m_fHeader << " wxListBox* m_" << m_Controls[i].c_str() << ";\n";
00293 else if (m_Controls[i][(long unsigned int) (0)]=='s')
00294 m_fHeader << " wxSlider* m_" << m_Controls[i].c_str() << ";\n";
00295 else if (m_Controls[i][(long unsigned int) (0)]=='b')
00296 m_fHeader << " wxButton* m_" << m_Controls[i].c_str() << ";\n";
00297 else if (m_Controls[i][(long unsigned int) (0)]=='c')
00298 m_fHeader << " wxChoiceBox* m_" << m_Controls[i].c_str() << ";\n";
00299 else if (m_Controls[i][(long unsigned int) (0)]=='r')
00300 m_fHeader << " wxRadioBox* m_" << m_Controls[i].c_str() << ";\n";
00301 }
00302
00303 m_fHeader << "\n DECLARE_EVENT_TABLE()\n";
00304
00305 m_fHeader << "};\n";
00306
00307
00308 m_fImpl << "enum\n{\n";
00309 m_fImpl << " START_VALUE = 100,\n";
00310 for (int i=0; i < int (num-1); i++)
00311 m_fImpl << " id_" << m_Controls[i].c_str() << ",\n";
00312 m_fImpl << " id_" << m_Controls[num-1].c_str() << "\n};\n\n";
00313
00314
00315 m_fImpl << "BEGIN_EVENT_TABLE(" << m_Name << ", " << m_Base << ")\n";
00316 for (unsigned int i=0; i < num; i++)
00317 {
00318 if (m_Controls[i][(long unsigned int) (0)]=='l')
00319 m_fImpl << " EVT_LISTBOX(id_" << m_Controls[i].c_str() << ", "
00320 << m_Name.c_str() << "::On" << m_Controls[i].c_str() << ")\n";
00321 else if (m_Controls[i][(long unsigned int) (0)]=='s')
00322 m_fImpl << " EVT_SLIDER(id_" << m_Controls[i].c_str() << ", "
00323 << m_Name.c_str() << "::On" << m_Controls[i].c_str() << ")\n";
00324 else if (m_Controls[i][(long unsigned int) (0)]=='b')
00325 m_fImpl << " EVT_BUTTON(id_" << m_Controls[i].c_str() << ", "
00326 << m_Name.c_str() << "::On" << m_Controls[i].c_str() << ")\n";
00327 else if (m_Controls[i][(long unsigned int) (0)]=='c')
00328 m_fImpl << " EVT_CHECKBOX(id_" << m_Controls[i].c_str() << ", "
00329 << m_Name.c_str() << "::On" << m_Controls[i].c_str() << ")\n";
00330 else if (m_Controls[i][(long unsigned int) (0)]=='r')
00331 m_fImpl << " EVT_RADIOBOX(id_" << m_Controls[i].c_str() << ", "
00332 << m_Name.c_str() << "::On" << m_Controls[i].c_str() << ")\n";
00333 }
00334 m_fImpl << "END_EVENT_TABLE()\n\n";
00335 m_fImpl.seekp(0,ios::end);
00336 }
00337
00338
00339
00340
00341
00342 vuString vuGuiParser::ParseListBox(const char *cname)
00343 {
00344 vuString name = vuString("l") + cname;
00345 if (m_Controls.isMember(name))
00346 throw ("Defined two controls of the same name.");
00347 m_Controls.add(name);
00348
00349
00350 StringList values = ParseList();
00351 StringList initial = ParseList();
00352 if ((values.getLength()==0)||(initial.getLength()!=1))
00353 throw ("Invalid definition of a listbox control.");
00354
00355
00356 vuString create;
00357 create << " m_" << name << " = new wxListBox(this, ";
00358 create << "id_" << name << ");\n";
00359 int num = values.getLength();
00360 for (int i=0; i < num; i++)
00361 create << " m_" << name << "->Append(\"" << values[i].c_str() << "\");\n";
00362 create << " m_" << name << "->SetStringSelection(\"";
00363 create << initial[0].c_str() << "\");\n";
00364 create << " Sizer->add(m_" << name << ");\n";
00365
00366
00367 ParseMethod("On" + name + "(wxCommandEvent &event)");
00368
00369
00370 return create;
00371 }
00372
00373
00374
00375
00376
00377 vuString vuGuiParser::ParseSlider(const char *cname)
00378 {
00379 vuString name = vuString("s") + cname;
00380 if (m_Controls.isMember(name))
00381 throw ("Defined two controls of the same name.");
00382 m_Controls.add(name);
00383
00384
00385 StringList settings = ParseList();
00386 if (settings.getLength()!=4)
00387 throw ("Invalid definition of a slider control.");
00388
00389
00390 vuString create;
00391 create << " m_" << name << " = new wxSlider(this, ";
00392 create << "id_" << name << "," << settings[2] << "," << settings[0].c_str();
00393 create << "," << settings[1].c_str() << ",wxDefaultPosition,wxDefaultSize,";
00394 if (strcmp(settings[3].c_str(),"vertical")==0)
00395 create << "wxSL_VERTICAL";
00396 else
00397 create << "wxSL_HORIZONTAL";
00398 create << ");\n Sizer->add(m_" << name << ");\n";
00399
00400
00401 ParseMethod("On" + name + "(wxCommandEvent &event)");
00402
00403
00404 return create;
00405 }
00406
00407
00408
00409
00410 vuString vuGuiParser::ParseRadioBox(const char *cname)
00411 {
00412 vuString name = vuString("r") + cname;
00413 if (m_Controls.isMember(name))
00414 throw ("Defined two controls of the same name.");
00415 m_Controls.add(name);
00416
00417
00418 StringList label = ParseList();
00419 StringList choices = ParseList();
00420 StringList initial = ParseList();
00421 if ((label.getLength()==0)||(choices.getLength()==0)
00422 ||(initial.getLength()!=1))
00423 throw ("Invalid definition of a radiobox control.");
00424
00425
00426 vuString create;
00427
00428 create << " vuString label" << name << " = \"";
00429 int num = label.getLength();
00430 for (int i=0; i < num-1; i++)
00431 create << label[i].c_str() << " ";
00432 create << label[num-1].c_str() << "\";\n";
00433 create << " wxString choices[" << choices.getLength() << "];\n";
00434 num = choices.getLength();
00435 for (int i=0; i < num; i++)
00436 create << " choices[" << i << "] = \"" << choices[i].c_str() << "\";\n";
00437 create << " m_" << name << " = new wxRadioBox(this, ";
00438 create << "id_" << name << ",label" << name << ",wxDefaultPosition,";
00439 create << "wxDefaultSize," << num << ",choices);\n";
00440 create << " Sizer->add(m_" << name << ");\n";
00441
00442
00443 ParseMethod("On" + name + "(wxCommandEvent &event)");
00444
00445
00446 return create;
00447 }
00448
00449
00450
00451
00452 vuString vuGuiParser::ParseCheckBox(const char *cname)
00453 {
00454 vuString name = vuString("c") + cname;
00455 if (m_Controls.isMember(name))
00456 throw ("Defined two controls of the same name.");
00457 m_Controls.add(name);
00458
00459
00460 StringList label = ParseList();
00461 StringList initial = ParseList();
00462 if ((label.getLength()==0)||(initial.getLength()==0))
00463 throw ("Invalid definition of a checkbox control.");
00464
00465
00466 vuString create;
00467 create << " wxString label" << name << " = \"";
00468 int num = label.getLength();
00469 for (int i=0; i < num-1; i++)
00470 create << label[i].c_str() << " ";
00471 create << label[num-1].c_str() << "\";\n";
00472 create << " m_" << name << " = new wxCheckBox(this, ";
00473 create << "id_" << name << ",label" << name << ");\n";
00474 create << " m_" << name << "->SetValue(" << initial[0];
00475 create << ");\n Sizer->add(m_" << name << ");\n";
00476
00477
00478 ParseMethod("On" + name + "(wxCommandEvent &event)");
00479
00480
00481 return create;
00482 }
00483
00484
00485
00486
00487 vuString vuGuiParser::ParseButton(const char *cname)
00488 {
00489 vuString name = vuString("b") + cname;
00490 if (m_Controls.isMember(name))
00491 throw ("Defined two controls of the same name.");
00492 m_Controls.add(name);
00493
00494
00495 StringList label = ParseList();
00496 if (label.getLength()==0)
00497 throw ("Invalid definition of a button control.");
00498
00499
00500 vuString create;
00501 create << " wxString label" << name << " = \"";
00502 int num = label.getLength();
00503 for (int i=0; i < num-1; i++)
00504 create << label[i].c_str() << " ";
00505 create << label[num-1].c_str() << "\";\n";
00506 create << " m_" << name << " = new wxButton(this, ";
00507 create << "id_" << name << ",label" << name << ");\n";
00508 create << " Sizer->add(m_" << name << ");\n";
00509
00510
00511 ParseMethod("On" + name + "(wxCommandEvent &event)");
00512
00513
00514 return create;
00515 }