00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <iostream>
00019 #include "parser.h"
00020 #include "arts.h"
00021 #include "exceptions.h"
00022 #include "file.h"
00023 #include "methods.h"
00024 #include "parameters.h"
00025 #include "wsv_aux.h"
00026 #include "workspace_ng.h"
00027
00028
00036 ArtsParser::ArtsParser(Agenda& tasklist, String controlfile)
00037 : mtasklist (tasklist), mcfile (controlfile), mcfile_version (1)
00038 {
00039 msource.AppendFile (mcfile);
00040 }
00041
00042
00047 void ArtsParser::parse_tasklist ()
00048 {
00049 parse_main ();
00050 }
00051
00052
00058 void ArtsParser::parse_main()
00059 {
00060 try
00061 {
00062 extern const Array<MdRecord> md_data;
00063
00064
00065 Index id;
00066
00067 ArrayOfIndex output;
00068
00069 ArrayOfIndex input;
00070
00071 String include_file;
00072
00073 ArrayOfIndex auto_vars;
00074 Array<TokVal> auto_vars_values;
00075
00076 out3 << "\nParsing control text:\n";
00077
00078 msource.Init();
00079 eat_whitespace();
00080
00081 parse_method(id,output,input,mtasklist,auto_vars,auto_vars_values,
00082 include_file,true);
00083
00084 if ( "Arts" != md_data[id].Name() && "Arts2" != md_data[id].Name() )
00085 {
00086 out0 << "The outermost agenda must be Arts2!\n"
00087 << "(But it seems to be " << md_data[id].Name() << ".)\n";
00088 arts_exit ();
00089 }
00090 }
00091 catch (const Eot x)
00092 {
00093
00094 out0 << "Unexpected end of control script.\n";
00095 out0 << "File: " << x.file() << '\n';
00096 out0 << "Line: " << x.line() << '\n';
00097 arts_exit ();
00098 }
00099 catch (const UnexpectedChar x)
00100 {
00101
00102 out0 << "Unexpected character:\n";
00103 out0 << x.what() << '\n';
00104 out0 << "File: " << x.file() << '\n';
00105 out0 << "Line: " << x.line() << '\n';
00106 out0 << "Column: " << x.column() << '\n';
00107 arts_exit ();
00108 }
00109 catch (const IllegalLinebreak x)
00110 {
00111
00112 out0 << "Illegal Line break:\n";
00113 out0 << x.what() << '\n';
00114 out0 << "File: " << x.file() << '\n';
00115 out0 << "Line: " << x.line() << '\n';
00116 arts_exit ();
00117 }
00118 catch (const UnknownMethod x)
00119 {
00120
00121
00122
00123 out0 << "Unknown Method:\n";
00124 out0 << x.what() << '\n';
00125 out0 << "File: " << x.file() << '\n';
00126 out0 << "Line: " << x.line() << '\n';
00127 out0 << "Column: " << x.column() << '\n';
00128 arts_exit ();
00129 }
00130 catch (const UnknownWsv x)
00131 {
00132
00133
00134
00135 out0 << "Unknown workspace variable:\n";
00136 out0 << x.what() << '\n';
00137 out0 << "File: " << x.file() << '\n';
00138 out0 << "Line: " << x.line() << '\n';
00139 out0 << "Column: " << x.column() << '\n';
00140 arts_exit ();
00141 }
00142 catch (const WrongWsvGroup x)
00143 {
00144
00145
00146
00147 out0 << "Workspace variable belongs to the wrong group:\n";
00148 out0 << x.what() << '\n';
00149 out0 << "File: " << x.file() << '\n';
00150 out0 << "Line: " << x.line() << '\n';
00151 out0 << "Column: " << x.column() << '\n';
00152 arts_exit ();
00153 }
00154 catch (const ParseError x)
00155 {
00156
00157 out0 << "Parse error:\n";
00158 out0 << x.what() << '\n';
00159 out0 << "File: " << x.file() << '\n';
00160 out0 << "Line: " << x.line() << '\n';
00161 out0 << "Column: " << x.column() << '\n';
00162 arts_exit ();
00163 }
00164 }
00165
00166
00180 void ArtsParser::parse_agenda( Agenda& tasklist )
00181 {
00182 extern const Array<MdRecord> md_data;
00183
00184
00185 Index id;
00186
00187 ArrayOfIndex output;
00188
00189 ArrayOfIndex input;
00190
00191 Agenda tasks;
00192
00193 String include_file;
00194
00195 ArrayOfIndex auto_vars;
00196 Array<TokVal> auto_vars_values;
00197
00198 eat_whitespace();
00199
00200 while ( '}' != msource.Current() )
00201 {
00202 parse_method(id,output,input,tasks,
00203 auto_vars,auto_vars_values,include_file);
00204
00205
00206
00207 if (id == -1)
00208 {
00209
00210 extern const Parameters parameters;
00211
00212 if (!find_file (include_file, ".arts"))
00213 {
00214 ostringstream os;
00215 os << "Cannot find include file " << include_file
00216 << ".\n";
00217 os << "File: " << msource.File() << '\n';
00218 os << "Search path was: . " << parameters.includepath
00219 << "\n";
00220 throw runtime_error (os.str());
00221 }
00222
00223 out3 << "- Including control file " << include_file << "\n";
00224
00225 ArtsParser include_parser (tasks, include_file);
00226 include_parser.parse_tasklist();
00227
00228 for (Index i = 0; i < tasks.nelem(); i++)
00229 tasklist.push_back (tasks.Methods()[i]);
00230 }
00231 else
00232 {
00233 if (md_data[id].SetMethod())
00234 {
00235
00236 tasklist.push_back(MRecord(id,output,input,
00237 auto_vars_values[0],tasks));
00238 }
00239 else
00240 {
00241 tasklist_insert_set_delete(auto_vars, auto_vars_values,
00242 0, tasklist);
00243
00244
00245 tasklist.push_back(MRecord(id,output,input,TokVal(),tasks));
00246
00247 tasklist_insert_set_delete(auto_vars, auto_vars_values,
00248 1, tasklist);
00249 }
00250
00251 {
00252
00253
00254
00255 out3 << "- " << md_data[id].Name() << "\n";
00256
00257
00258 if ( 0 < md_data[id].GOutType().nelem()
00259 + md_data[id].GInType().nelem() )
00260 {
00261 out3 << " Output: ";
00262 for ( Index j=0 ; j<output.nelem() ; ++j )
00263 {
00264 out3 << Workspace::wsv_data[output[j]].Name() << " ";
00265 }
00266 out3 << "\n";
00267
00268 out3 << " Input: ";
00269 for ( Index j=0 ; j<input.nelem() ; ++j )
00270 {
00271 out3 << Workspace::wsv_data[input[j]].Name() << " ";
00272 }
00273 out3 << "\n";
00274 }
00275 }
00276 }
00277
00278 eat_whitespace();
00279 msource.Current();
00280 }
00281 }
00282
00283
00314 void ArtsParser::parse_method(Index& id,
00315 ArrayOfIndex& output,
00316 ArrayOfIndex& input,
00317 Agenda& tasks,
00318 ArrayOfIndex& auto_vars,
00319 Array<TokVal>& auto_vars_values,
00320 String& include_file,
00321 bool no_eot)
00322 {
00323 String methodname;
00324
00325
00326 const MdRecord* mdd;
00327
00328
00329 bool found_curly_brace = false;
00330
00331
00332 id = 0;
00333 output.resize( 0 );
00334 input.resize( 0 );
00335 tasks.resize( 0 );
00336 auto_vars.resize( 0 );
00337 auto_vars_values.resize( 0 );
00338 include_file = "";
00339
00340 read_name(methodname);
00341
00342 if (methodname == "INCLUDE")
00343 {
00344 String s;
00345 eat_whitespace ();
00346 parse_String (include_file);
00347
00348 id = -1;
00349
00350 return;
00351 }
00352 else
00353 {
00354 if (methodname == "Arts2")
00355 {
00356 mcfile_version = 2;
00357 methodname = "Arts";
00358 }
00359 else if (methodname == "Arts")
00360 {
00361 throw runtime_error("Arts version 1 controlfiles are no longer supported.");
00362 }
00363
00364 eat_whitespace();
00365
00366 parse_method_args(mdd, id, methodname, output, input,
00367 auto_vars, auto_vars_values);
00368
00369 eat_whitespace();
00370
00371
00372 if (msource.Current() == '{')
00373 {
00374 msource.AdvanceChar();
00375 eat_whitespace();
00376 found_curly_brace = true;
00377 }
00378
00379
00380
00381
00382 if ( mdd->AgendaMethod() )
00383 {
00384 out3 << "- " << mdd->Name() << "\n";
00385 out3 << "{\n";
00386 parse_agenda(tasks);
00387 out3 << "}\n";
00388 }
00389
00390
00391 if (mcfile_version == 2 && !mdd->AgendaMethod() && found_curly_brace)
00392 {
00393 ostringstream os;
00394 os << "Expected method name , but got `" << msource.Current() << "'.";
00395 throw UnexpectedChar( os.str(),
00396 msource.File(),
00397 msource.Line(),
00398 msource.Column() );os << "" << endl;
00399 }
00400 }
00401
00402
00403
00404
00405 if (found_curly_brace)
00406 {
00407 try
00408 {
00409 assertain_character('}');
00410 }
00411 catch (const Eot x)
00412 {
00413
00414 if (!no_eot) throw Eot(x);
00415 }
00416 }
00417 }
00418
00419
00421
00435 String ArtsParser::set_gin_to_default(const MdRecord* mdd,
00436 ArrayOfIndex& auto_vars,
00437 Array<TokVal>& auto_vars_values,
00438 Index gin_index)
00439 {
00440 String name;
00441
00442 if (mdd->GInDefault()[gin_index] != NODEF)
00443 {
00444 TokVal tv;
00445
00446
00447 bool failed = false;
00448 if (mdd->GInType()[gin_index] == get_wsv_group_id ("String"))
00449 {
00450 tv = mdd->GInDefault()[gin_index];
00451 }
00452 else if (mdd->GInType()[gin_index] == get_wsv_group_id ("Index"))
00453 {
00454 Index n;
00455 istringstream is(mdd->GInDefault()[gin_index]);
00456 is >> n;
00457 tv = n;
00458 if (is.bad () || is.fail ())
00459 failed = true;
00460 }
00461 else if (mdd->GInType()[gin_index] == get_wsv_group_id ("Numeric"))
00462 {
00463 Numeric n;
00464 istringstream is(mdd->GInDefault()[gin_index]);
00465 is >> n;
00466 tv = n;
00467 if (is.bad () || is.fail ())
00468 failed = true;
00469 }
00470 else if (mdd->GInType()[gin_index] == get_wsv_group_id ("ArrayOfString"))
00471 {
00472 ArrayOfString v;
00473 String s = mdd->GInDefault()[gin_index];
00474 if (!parse_stringarray_from_string(v, s))
00475 {
00476 failed = true;
00477 }
00478 tv = v;
00479 }
00480 else if (mdd->GInType()[gin_index] == get_wsv_group_id ("ArrayOfIndex"))
00481 {
00482 ostringstream os;
00483 os << "Default values for generic inputs with type "
00484 << "ArrayOfIndex are not supported.\n"
00485 << "Either remove the default value for generic input '"
00486 << mdd->GIn()[gin_index] << "' in workspace method *"
00487 << mdd->Name() << "* in methods.cc or discuss this "
00488 << "issue on the arts-dev mailing list.\n";
00489 throw ParseError (os.str(),
00490 msource.File(),
00491 msource.Line(),
00492 msource.Column());
00493 }
00494 else if (mdd->GInType()[gin_index] == get_wsv_group_id ("Vector"))
00495 {
00496 Vector v;
00497 String s = mdd->GInDefault()[gin_index];
00498 if (!parse_numvector_from_string(v, s))
00499 {
00500 failed = true;
00501 }
00502 tv = v;
00503 }
00504 else
00505 {
00506 failed = true;
00507 }
00508
00509 Index wsvid;
00510
00511 {
00512 ostringstream os;
00513 os << gin_index;
00514
00515 name = "auto_" + mdd->Name() + "_" + "gin" + os.str() + "_"
00516 + mdd->GIn()[gin_index];
00517 }
00518
00519 map<String, Index>::const_iterator wsvit =
00520 Workspace::WsvMap.find(name);
00521 if (wsvit == Workspace::WsvMap.end())
00522 {
00523 wsvid = Workspace::add_wsv(
00524 WsvRecord(name.c_str(),
00525 "Automatically allocated variable.",
00526 mdd->GInType()[gin_index],
00527 true));
00528 }
00529 else
00530 {
00531 wsvid = wsvit->second;
00532 }
00533
00534 auto_vars.push_back(wsvid);
00535 auto_vars_values.push_back(tv);
00536
00537 if (failed)
00538 {
00539 ostringstream os;
00540 os << "Failed to assign default value for generic '"
00541 << mdd->GIn()[gin_index] << "'.\n"
00542 << "Check the documentation of workspace method *"
00543 << mdd->Name() << "*.\n";
00544 throw ParseError (os.str(),
00545 msource.File(),
00546 msource.Line(),
00547 msource.Column());
00548 }
00549 }
00550 else
00551 {
00552 ostringstream os;
00553 os << "Generic input '" << mdd->GIn()[gin_index]
00554 << "' omitted but no default value found.\n"
00555 << "Check the documentation of workspace method *"
00556 << mdd->Name() << "*.\n";
00557 throw ParseError (os.str(),
00558 msource.File(),
00559 msource.Line(),
00560 msource.Column());
00561 }
00562
00563 return name;
00564 }
00565
00566
00568
00581 void ArtsParser::parse_method_args(const MdRecord*& mdd,
00582 Index& id,
00583 String& methodname,
00584 ArrayOfIndex& output,
00585 ArrayOfIndex& input,
00586 ArrayOfIndex& auto_vars,
00587 Array<TokVal>& auto_vars_values)
00588 {
00589 extern const map<String, Index> MdRawMap;
00590 extern const Array<MdRecord> md_data;
00591 extern const Array<MdRecord> md_data_raw;
00592 extern const map<String, Index> MdMap;
00593
00594 Index wsvid;
00595
00596
00597 bool still_supergeneric=true;
00598
00599
00600
00601
00602 const map<String, Index>::const_iterator i = MdRawMap.find(methodname);
00603 if ( i == MdRawMap.end() )
00604 throw UnknownMethod(methodname,
00605 msource.File(),
00606 msource.Line(),
00607 msource.Column());
00608
00609 id = i->second;
00610
00611
00612
00613
00614 mdd = &md_data_raw[id];
00615
00616
00617
00618 if ( !mdd->Supergeneric() )
00619 {
00620
00621 const map<String, Index>::const_iterator i2 = MdMap.find(methodname);
00622 assert ( i2 != MdMap.end() );
00623 id = i2->second;
00624
00625 mdd = &md_data[id];
00626
00627 still_supergeneric = false;
00628 }
00629
00630 if (msource.Current() == '(')
00631 {
00632 String wsvname;
00633 bool first = true;
00634 String supergeneric_args;
00635 Index supergeneric_index = -1;
00636
00637 msource.AdvanceChar();
00638 eat_whitespace();
00639
00640 parse_specific_output(mdd, output, first);
00641
00642 parse_generic_output(mdd, id, methodname, output,
00643 first, still_supergeneric, supergeneric_args,
00644 supergeneric_index);
00645
00646 parse_specific_input(mdd, input, auto_vars, auto_vars_values, first);
00647
00648 parse_generic_input(mdd, id, methodname, input,
00649 auto_vars, auto_vars_values,
00650 first, still_supergeneric, supergeneric_args,
00651 supergeneric_index);
00652
00653 assert(!still_supergeneric);
00654 assertain_character(')');
00655 }
00656 else
00657 {
00658
00659
00660 ArrayOfIndex vo=mdd->Out();
00661 for (ArrayOfIndex::const_iterator outs=vo.begin();
00662 outs<vo.end(); ++outs)
00663 {
00664 output.push_back (*outs);
00665 }
00666
00667 const ArrayOfIndex &vi = mdd->InOnly();
00668 for (ArrayOfIndex::const_iterator ins=vi.begin(); ins<vi.end(); ++ins)
00669 {
00670 input.push_back (*ins);
00671 }
00672
00673 {
00674
00675
00676 bool all_gin_have_defaults = true;
00677 for (Index gin = 0;
00678 all_gin_have_defaults && gin < mdd->GIn().nelem();
00679 ++gin)
00680 {
00681 if (mdd->GInDefault()[gin] == NODEF)
00682 all_gin_have_defaults = false;
00683 else
00684 {
00685 String wsvname;
00686 wsvname = set_gin_to_default(mdd, auto_vars,
00687 auto_vars_values, gin);
00688 {
00689
00690 const map<String, Index>::const_iterator wsvit =
00691 Workspace::WsvMap.find(wsvname);
00692 if ( wsvit == Workspace::WsvMap.end() )
00693 {
00694 throw UnknownWsv( wsvname,
00695 msource.File(),
00696 msource.Line(),
00697 msource.Column() );
00698 }
00699
00700 wsvid = wsvit->second;
00701 }
00702 input.push_back(wsvid);
00703 }
00704 }
00705
00706 if (!all_gin_have_defaults)
00707 {
00708 ostringstream os;
00709 os << "Not all generic inputs of this method have default "
00710 << "values, you have to specify them!";
00711 throw UnexpectedChar( os.str(),
00712 msource.File(),
00713 msource.Line(),
00714 msource.Column() );
00715 }
00716 }
00717 }
00718 }
00719
00720
00737 void ArtsParser::parse_generic_input(const MdRecord*& mdd,
00738 Index& id,
00739 String& methodname,
00740 ArrayOfIndex& input,
00741 ArrayOfIndex& auto_vars,
00742 Array<TokVal>& auto_vars_values,
00743 bool& first,
00744 bool& still_supergeneric,
00745 String& supergeneric_args,
00746 Index& supergeneric_index _U_)
00747 {
00748 String wsvname;
00749 Index wsvid;
00750 extern const ArrayOfString wsv_group_names;
00751 extern const Array<MdRecord> md_data;
00752 extern const map<String, Index> MdMap;
00753
00754
00755 for ( Index j=0 ; j<mdd->GInType().nelem() ; ++j )
00756 {
00757 if (first)
00758 first = false;
00759 else
00760 {
00761 if (msource.Current() != ')')
00762 {
00763 assertain_character(',');
00764 eat_whitespace();
00765 }
00766 }
00767
00768
00769
00770 if (msource.Current() == ',' || msource.Current() == ')')
00771 {
00772 wsvname = set_gin_to_default(mdd, auto_vars, auto_vars_values, j);
00773 }
00774 else
00775 {
00776 ostringstream os;
00777 os << j;
00778 if (read_name_or_value(wsvname, auto_vars, auto_vars_values,
00779 "generic" + os.str(),
00780 mdd, mdd->GInType()[j]) == -1
00781 && mdd->SetMethod())
00782 {
00783 throw ParseError("Only constants can be passed to Set methods.\n"
00784 "You might want to use the *Copy* here.",
00785 msource.File(),
00786 msource.Line(),
00787 msource.Column() );
00788 }
00789 }
00790
00791 {
00792
00793 const map<String, Index>::const_iterator wsvit =
00794 Workspace::WsvMap.find(wsvname);
00795 if ( wsvit == Workspace::WsvMap.end() )
00796 {
00797 throw UnknownWsv( wsvname,
00798 msource.File(),
00799 msource.Line(),
00800 msource.Column() );
00801 }
00802
00803 wsvid = wsvit->second;
00804 }
00805
00806
00807
00808
00809 if ( still_supergeneric )
00810 {
00811 ostringstream os;
00812 if (wsv_group_names[mdd->GInType()[j]] == "Any")
00813 supergeneric_args +=
00814 wsv_group_names[Workspace::wsv_data[wsvid].Group()];
00815 os << mdd->Name() << "_sg_" << supergeneric_args;
00816 methodname = os.str();
00817
00818
00819 const map<String, Index>::const_iterator mdit =
00820 MdMap.find(methodname);
00821 if (mdit != MdMap.end())
00822 {
00823 id = mdit->second;
00824
00825 mdd = &md_data[id];
00826
00827 still_supergeneric = false;
00828 }
00829 }
00830
00831
00832
00833
00834
00835
00836 if (mdd->GInType()[j] == get_wsv_group_id ("Any")
00837 && mdd->GInSpecType()[j].nelem() )
00838 {
00839 if (supergeneric_index == -1)
00840 {
00841 bool wrong_group_id = true;
00842 for (Index i = 0; wrong_group_id && i < mdd->GInSpecType()[j].nelem(); i++)
00843 {
00844 if (Workspace::wsv_data[wsvid].Group()
00845 == mdd->GInSpecType()[j][i])
00846 {
00847 wrong_group_id = false;
00848 supergeneric_index = i;
00849 }
00850 }
00851
00852 if (wrong_group_id)
00853 {
00854 ostringstream os;
00855 bool firsttype = true;
00856 for (Index i = 0; i < mdd->GInSpecType()[j].nelem(); i++)
00857 {
00858 if (!firsttype) os << ", "; else firsttype = false;
00859 os << wsv_group_names[mdd->GInSpecType()[j][i]];
00860 }
00861
00862 throw WrongWsvGroup( "*" + mdd->Name()+"* is not defined for "
00863 +wsv_group_names[Workspace::wsv_data[wsvid].Group()]
00864 +" input. Check the online docs.",
00865 msource.File(),
00866 msource.Line(),
00867 msource.Column() );
00868 }
00869 }
00870 else
00871 {
00872 if (Workspace::wsv_data[wsvid].Group()
00873 != mdd->GInSpecType()[j][supergeneric_index])
00874 {
00875 throw WrongWsvGroup( wsvname+" is not "+
00876 wsv_group_names[mdd->GInSpecType()[j][supergeneric_index]]
00877 +", it is "+
00878 wsv_group_names[Workspace::wsv_data[wsvid].Group()],
00879 msource.File(),
00880 msource.Line(),
00881 msource.Column());
00882 }
00883 }
00884 }
00885 else if (Workspace::wsv_data[wsvid].Group() != mdd->GInType()[j])
00886 {
00887 throw WrongWsvGroup( wsvname+" is not "+
00888 wsv_group_names[mdd->GInType()[j]]+", it is "+
00889 wsv_group_names[Workspace::wsv_data[wsvid].Group()],
00890 msource.File(),
00891 msource.Line(),
00892 msource.Column() );
00893 }
00894
00895
00896 input.push_back(wsvid);
00897
00898 eat_whitespace();
00899 }
00900
00901 }
00902
00903
00918 void ArtsParser::parse_generic_output(const MdRecord*& mdd,
00919 Index& id,
00920 String& methodname,
00921 ArrayOfIndex& output,
00922 bool& first,
00923 bool& still_supergeneric,
00924 String& supergeneric_args,
00925 Index& supergeneric_index)
00926 {
00927 String wsvname;
00928 Index wsvid;
00929 extern const ArrayOfString wsv_group_names;
00930 extern const Array<MdRecord> md_data;
00931 extern const map<String, Index> MdMap;
00932
00933
00934 for ( Index j=0 ; j<mdd->GOut().nelem() ; ++j )
00935 {
00936 if (first)
00937 first = false;
00938 else
00939 {
00940 assertain_character(',');
00941 eat_whitespace();
00942 }
00943
00944 read_name(wsvname);
00945
00946 {
00947 wsvid = -1;
00948
00949 map<String, Index>::const_iterator wsvit =
00950 Workspace::WsvMap.find(wsvname);
00951 if ( wsvit == Workspace::WsvMap.end() )
00952 {
00953 if (still_supergeneric)
00954 {
00955 ostringstream os;
00956 os << "This might be either a typo or you have to create "
00957 << "the variable\nby calling TYPECreate(" << wsvname
00958 << ") first. Replace TYPE with the\n"
00959 << "WSV group your variable should belong to.";
00960
00961 throw UnknownWsv( os.str(),
00962 msource.File(),
00963 msource.Line(),
00964 msource.Column() );
00965 }
00966 else
00967 {
00968 if (mdd->Name().length() > 6
00969 && mdd->Name().substr (mdd->Name().length() - 6)
00970 != "Create")
00971 {
00972 ostringstream os;
00973 os << "This might be either a typo or you have to create "
00974 << "the variable\nby calling "
00975 << wsv_group_names[mdd->GOutType()[j]]
00976 << "Create( " << wsvname
00977 << " ) first.\n";
00978
00979 throw UnknownWsv( os.str(),
00980 msource.File(),
00981 msource.Line(),
00982 msource.Column() );
00983 }
00984 else
00985 {
00986 wsvid = Workspace::add_wsv(
00987 WsvRecord(wsvname.c_str(),
00988 "Automatically allocated variable.",
00989 mdd->GOutType()[j],
00990 true));
00991 }
00992 }
00993 }
00994
00995 if (wsvid == -1)
00996 wsvid = wsvit->second;
00997 }
00998
00999
01000
01001
01002
01003 if ( still_supergeneric )
01004 {
01005 ostringstream os;
01006 if (wsv_group_names[mdd->GOutType()[j]] == "Any")
01007 supergeneric_args +=
01008 wsv_group_names[Workspace::wsv_data[wsvid].Group()];
01009 os << mdd->Name() << "_sg_" << supergeneric_args;
01010 methodname = os.str();
01011
01012
01013 const map<String, Index>::const_iterator mdit = MdMap.find(methodname);
01014 if (mdit != MdMap.end() )
01015 {
01016 id = mdit->second;
01017
01018 mdd = &md_data[id];
01019
01020 still_supergeneric = false;
01021 }
01022 }
01023
01024
01025
01026
01027
01028
01029 if (mdd->GOutType()[j] == get_wsv_group_id ("Any")
01030 && mdd->GOutSpecType()[j].nelem() )
01031 {
01032 if (supergeneric_index == -1)
01033 {
01034 bool wrong_group_id = true;
01035 for (Index i = 0; wrong_group_id && i < mdd->GOutSpecType()[j].nelem(); i++)
01036 {
01037 if (Workspace::wsv_data[wsvid].Group()
01038 == mdd->GOutSpecType()[j][i])
01039 {
01040 wrong_group_id = false;
01041 supergeneric_index = i;
01042 }
01043 }
01044
01045 if (wrong_group_id)
01046 {
01047 ostringstream os;
01048 bool firsttype = true;
01049 for (Index i = 0; i < mdd->GOutSpecType()[j].nelem(); i++)
01050 {
01051 if (!firsttype) os << ", "; else firsttype = false;
01052 os << wsv_group_names[mdd->GOutSpecType()[j][i]];
01053 }
01054
01055 throw WrongWsvGroup( "*" + mdd->Name() + "* is not defined for "
01056 +wsv_group_names[Workspace::wsv_data[wsvid].Group()]
01057 +" output. Check the online docs.",
01058 msource.File(),
01059 msource.Line(),
01060 msource.Column() );
01061 }
01062 }
01063 else
01064 {
01065 if (Workspace::wsv_data[wsvid].Group()
01066 != mdd->GOutSpecType()[j][supergeneric_index])
01067 {
01068 throw WrongWsvGroup( wsvname+" is not "+
01069 wsv_group_names[mdd->GOutSpecType()[j][supergeneric_index]]
01070 +", it is "+
01071 wsv_group_names[Workspace::wsv_data[wsvid].Group()],
01072 msource.File(),
01073 msource.Line(),
01074 msource.Column());
01075 }
01076 }
01077 }
01078 else if ( Workspace::wsv_data[wsvid].Group() != mdd->GOutType()[j] )
01079 {
01080 throw WrongWsvGroup( wsvname+" is not "+
01081 wsv_group_names[mdd->GOutType()[j]]+", it is "+
01082 wsv_group_names[Workspace::wsv_data[wsvid].Group()],
01083 msource.File(),
01084 msource.Line(),
01085 msource.Column() );
01086 }
01087
01088
01089 output.push_back(wsvid);
01090
01091 eat_whitespace();
01092 }
01093 }
01094
01095
01108 void ArtsParser::parse_specific_input(const MdRecord* mdd,
01109 ArrayOfIndex& input,
01110 ArrayOfIndex& auto_vars,
01111 Array<TokVal>& auto_vars_values,
01112 bool& first)
01113 {
01114 extern const ArrayOfString wsv_group_names;
01115
01116
01117 ArrayOfIndex vo=mdd->Out();
01118 const ArrayOfIndex &vi = mdd->InOnly();
01119
01120 Index wsvid;
01121
01122
01123 for (ArrayOfIndex::const_iterator ins=vi.begin(); ins<vi.end(); ++ins)
01124 {
01125 String wsvname;
01126
01127 if (first)
01128 first = false;
01129 else
01130 {
01131 try
01132 {
01133 assertain_character(',');
01134 }
01135 catch (UnexpectedChar)
01136 {
01137 ostringstream os;
01138 os << "Expected input WSV *" << Workspace::wsv_data[*ins].Name() << "*";
01139 }
01140 eat_whitespace();
01141 }
01142
01143 read_name_or_value(wsvname, auto_vars, auto_vars_values,
01144 Workspace::wsv_data[*ins].Name(),
01145 mdd, Workspace::wsv_data[*ins].Group());
01146
01147 {
01148
01149 const map<String, Index>::const_iterator wsvit =
01150 Workspace::WsvMap.find(wsvname);
01151 if ( wsvit == Workspace::WsvMap.end() )
01152 throw UnknownWsv( wsvname,
01153 msource.File(),
01154 msource.Line(),
01155 msource.Column() );
01156
01157 wsvid = wsvit->second;
01158 }
01159
01160
01161 if ( Workspace::wsv_data[wsvid].Group() != Workspace::wsv_data[*ins].Group() )
01162 {
01163 throw WrongWsvGroup( wsvname+" is not "+
01164 wsv_group_names[Workspace::wsv_data[*ins].Group()]+", it is "+
01165 wsv_group_names[Workspace::wsv_data[wsvid].Group()],
01166 msource.File(),
01167 msource.Line(),
01168 msource.Column() );
01169 }
01170
01171 input.push_back(wsvid);
01172 }
01173
01174 eat_whitespace();
01175 }
01176
01177
01188 void ArtsParser::parse_specific_output(const MdRecord* mdd,
01189 ArrayOfIndex& output,
01190 bool& first)
01191 {
01192 extern const ArrayOfString wsv_group_names;
01193
01194 ArrayOfIndex vo=mdd->Out();
01195
01196 Index wsvid;
01197
01198
01199 for (ArrayOfIndex::const_iterator outs=vo.begin(); outs<vo.end(); ++outs)
01200 {
01201 String wsvname;
01202
01203 if (first)
01204 first = false;
01205 else
01206 {
01207 try
01208 {
01209 assertain_character(',');
01210 }
01211 catch (UnexpectedChar)
01212 {
01213 ostringstream os;
01214 os << "Expected output WSV *" << Workspace::wsv_data[*outs].Name() << "*";
01215 throw ParseError( os.str(),
01216 msource.File(),
01217 msource.Line(),
01218 msource.Column() );
01219 }
01220 eat_whitespace();
01221 }
01222
01223 read_name(wsvname);
01224
01225 {
01226 wsvid = -1;
01227
01228 map<String, Index>::const_iterator wsvit =
01229 Workspace::WsvMap.find(wsvname);
01230 if ( wsvit == Workspace::WsvMap.end() )
01231 {
01232 if (mdd->Name().length() > 6
01233 && mdd->Name().substr (mdd->Name().length() - 6)
01234 != "Create")
01235 {
01236 ostringstream os;
01237 os << "This might be either a typo or you have to create "
01238 << "the variable\nby calling "
01239 << wsv_group_names[Workspace::wsv_data[*outs].Group()]
01240 << "Create( " << wsvname
01241 << " ) first.\n";
01242
01243 throw UnknownWsv( os.str(),
01244 msource.File(),
01245 msource.Line(),
01246 msource.Column() );
01247 }
01248 else
01249 {
01250 wsvid = Workspace::add_wsv(
01251 WsvRecord(wsvname.c_str(),
01252 "Automatically allocated variable.",
01253 Workspace::wsv_data[*outs].Group(),
01254 true));
01255 }
01256 }
01257
01258 if (wsvid == -1)
01259 wsvid = wsvit->second;
01260 }
01261
01262
01263 if ( Workspace::wsv_data[wsvid].Group() != Workspace::wsv_data[*outs].Group() )
01264 {
01265 throw WrongWsvGroup( wsvname+" is not "+
01266 wsv_group_names[Workspace::wsv_data[*outs].Group()]+", it is "+
01267 wsv_group_names[Workspace::wsv_data[wsvid].Group()],
01268 msource.File(),
01269 msource.Line(),
01270 msource.Column() );
01271 }
01272
01273 output.push_back(wsvid);
01274 }
01275
01276 eat_whitespace();
01277 }
01278
01279
01293 void ArtsParser::tasklist_insert_set_delete(const ArrayOfIndex& auto_vars,
01294 const Array<TokVal>& auto_vars_values,
01295 const Index method_type,
01296 Agenda& tasklist)
01297 {
01298 extern const map<String, Index> MdMap;
01299 extern const ArrayOfString wsv_group_names;
01300
01301 for (Index i=0; i<auto_vars.nelem(); i++)
01302 {
01303 map<String, Index>::const_iterator mdit;
01304 Index init_mdid;
01305 TokVal auto_keyword_value;
01306 ArrayOfIndex auto_output_var;
01307 ArrayOfIndex auto_input_var;
01308 Agenda auto_tasks;
01309
01310 const Index auto_group = Workspace::wsv_data[auto_vars[i]].Group();
01311 if (auto_group != get_wsv_group_id("Index")
01312 && auto_group != get_wsv_group_id("Numeric")
01313 && auto_group != get_wsv_group_id("ArrayOfIndex")
01314 && auto_group != get_wsv_group_id("ArrayOfString")
01315 && auto_group != get_wsv_group_id("String")
01316 && auto_group != get_wsv_group_id("Vector"))
01317 {
01318 ostringstream os;
01319 os << "Passing a "
01320 << wsv_group_names[Workspace::wsv_data[auto_vars[i]].Group()]
01321 << " constant to a WSM is not supported!";
01322 throw ParseError (os.str(),
01323 msource.File(),
01324 msource.Line(),
01325 msource.Column());
01326 }
01327
01328 String method_name;
01329 switch (method_type)
01330 {
01331 case 0:
01332 auto_keyword_value = auto_vars_values[i];
01333 auto_output_var.push_back(auto_vars[i]);
01334 method_name = wsv_group_names[
01335 Workspace::wsv_data[auto_vars[i]].Group()] + "Set";
01336 break;
01337 case 1:
01338 auto_input_var.push_back(auto_vars[i]);
01339 method_name = "Delete_sg_" + wsv_group_names[Workspace::wsv_data[auto_vars[i]].Group()];
01340 break;
01341 default:
01342 throw runtime_error("Invalid method_type");
01343 }
01344
01345 mdit = MdMap.find(method_name);
01346 assert ( mdit != MdMap.end() );
01347 init_mdid = mdit->second;
01348
01349 tasklist.push_back(MRecord(init_mdid,
01350 auto_output_var, auto_input_var,
01351 auto_keyword_value,
01352 auto_tasks));
01353 }
01354 }
01355
01356
01367 bool ArtsParser::is_whitespace(const char c)
01368 {
01369 switch (c)
01370 {
01371 case ' ':
01372 case '\r':
01373 case '\t':
01374 case '#':
01375 return true;
01376 break;
01377 }
01378
01379 return false;
01380 }
01381
01382
01392 void ArtsParser::eat_whitespace()
01393 {
01394 char dummy;
01395
01396 while (is_whitespace(dummy=msource.Current()))
01397 {
01398 switch (dummy)
01399 {
01400 case ' ':
01401 case '\r':
01402 case '\t':
01403 msource.AdvanceChar();
01404 break;
01405 case '#':
01406 msource.AdvanceLine();
01407 break;
01408 default:
01409 {
01410 ostringstream os;
01411 os << "Expected whitespace, but got `" << dummy << "'.";
01412 throw UnexpectedChar( os.str(),
01413 msource.File(),
01414 msource.Line(),
01415 msource.Column() );
01416 break;
01417 }
01418 }
01419 }
01420 }
01421
01422
01428 void ArtsParser::eat_whitespace_from_string(String& str, size_t& pos)
01429 {
01430 while (pos < str.length() && is_whitespace(str[pos]))
01431 pos++;
01432 }
01433
01434
01446 void ArtsParser::read_name(String& name)
01447 {
01448 bool stop = false;
01449 name = "";
01450
01451 if (!isalpha(msource.Current()))
01452 {
01453 ostringstream os;
01454 os << "Workspace variable names must start with a letter!";
01455 throw ParseError( os.str(),
01456 msource.File(),
01457 msource.Line(),
01458 msource.Column() );
01459 }
01460
01461 while (!stop)
01462 {
01463 char dummy = msource.Current();
01464
01465 if ( isalnum(dummy) || '_'==dummy )
01466 {
01467 name += dummy;
01468
01469 msource.LineBreak() = false;
01470 msource.AdvanceChar();
01471 if ( msource.LineBreak() ) stop = true;
01472 }
01473 else
01474 {
01475 stop = true;
01476 }
01477 }
01478 }
01479
01480
01500 Index ArtsParser::read_name_or_value( String& name,
01501 ArrayOfIndex& auto_vars,
01502 Array<TokVal>& auto_vars_values,
01503 const String& default_name,
01504 const MdRecord* mdd,
01505 const Index group)
01506 {
01507 name = "";
01508
01509 if (isalpha(msource.Current()))
01510 {
01511 read_name(name);
01512 return -1;
01513 }
01514
01515 if (group == get_wsv_group_id ("Any"))
01516 {
01517 ostringstream os;
01518 os << "Passing constants as supergeneric parameters is not supported.";
01519 throw ParseError (os.str (),
01520 msource.File(),
01521 msource.Line(),
01522 msource.Column());
01523 }
01524
01525
01526
01527
01528
01529 Index wsvid;
01530
01531 name = "auto_" + mdd->Name() + "_" + default_name;
01532 map<String, Index>::const_iterator wsvit = Workspace::WsvMap.find(name);
01533 if (wsvit == Workspace::WsvMap.end())
01534 {
01535 wsvid = Workspace::add_wsv(WsvRecord(name.c_str(),
01536 "Automatically allocated variable.",
01537 group,
01538 true));
01539 }
01540 else
01541 {
01542 wsvid = wsvit->second;
01543 }
01544
01545 auto_vars.push_back(wsvid);
01546
01547
01548
01549 if (group == get_wsv_group_id("String"))
01550 {
01551 String dummy;
01552 parse_String(dummy);
01553 auto_vars_values.push_back(dummy);
01554 }
01555 else if (group == get_wsv_group_id("Index"))
01556 {
01557 Index n;
01558 parse_integer(n);
01559 auto_vars_values.push_back(n);
01560 }
01561 else if (group == get_wsv_group_id("Numeric"))
01562 {
01563 Numeric n;
01564 parse_numeric(n);
01565 auto_vars_values.push_back(n);
01566 }
01567 else if (group == get_wsv_group_id("ArrayOfString"))
01568 {
01569 ArrayOfString dummy;
01570 parse_Stringvector(dummy);
01571 auto_vars_values.push_back(dummy);
01572 }
01573 else if (group == get_wsv_group_id("ArrayOfIndex"))
01574 {
01575 ArrayOfIndex dummy;
01576 parse_intvector(dummy);
01577 auto_vars_values.push_back(dummy);
01578 }
01579 else if (group == get_wsv_group_id("Vector"))
01580 {
01581 Vector dummy;
01582 parse_numvector(dummy);
01583 auto_vars_values.push_back(dummy);
01584 }
01585 else
01586 {
01587 extern const ArrayOfString wsv_group_names;
01588 ostringstream os;
01589 os << "Unsupported parameter type: " << wsv_group_names[group];
01590 throw runtime_error (os.str());
01591 }
01592
01593 return wsvid;
01594 }
01595
01596
01603 void ArtsParser::assertain_character(char c)
01604 {
01605 if ( c != msource.Current() )
01606 {
01607 ostringstream os;
01608 os << "Expected '" << c << "', but got '" << msource.Current() << "'.";
01609 throw UnexpectedChar( os.str(),
01610 msource.File(),
01611 msource.Line(),
01612 msource.Column() );
01613 }
01614
01615 msource.AdvanceChar();
01616 }
01617
01618
01629 void ArtsParser::parse_String(String& res)
01630 {
01631 bool stop = false;
01632 res = "";
01633
01634 msource.LineBreak() = false;
01635 assertain_character('"');
01636 if ( msource.LineBreak() )
01637 throw IllegalLinebreak( "Line break before end of String.",
01638 msource.File(),
01639 msource.Line(),
01640 msource.Column() );
01641
01642 while (!stop)
01643 {
01644 char dummy = msource.Current();
01645 if ( dummy != '"' )
01646 {
01647 res += dummy;
01648 msource.AdvanceChar();
01649
01650 if ( msource.LineBreak() )
01651 throw IllegalLinebreak( "Line break before end of String.",
01652 msource.File(),
01653 msource.Line(),
01654 msource.Column() );
01655 }
01656 else
01657 {
01658 stop = true;
01659 msource.AdvanceChar();
01660 }
01661 }
01662 }
01663
01664
01677 void ArtsParser::read_integer(String& res)
01678 {
01679 bool stop = false;
01680 res = "";
01681 char dummy;
01682 msource.LineBreak() = false;
01683
01684 dummy = msource.Current();
01685 if ( '+' == dummy || '-' == dummy )
01686 {
01687 res += dummy;
01688 msource.AdvanceChar();
01689 if ( msource.LineBreak() )
01690 throw IllegalLinebreak( "Line break after sign.",
01691 msource.File(),
01692 msource.Line(),
01693 msource.Column() );
01694 }
01695
01696 if (!isdigit(msource.Current()))
01697 {
01698 ostringstream os;
01699 os << "Expected digit or variable name, but got `" << msource.Current()
01700 << "'.";
01701 throw UnexpectedChar(os.str(),
01702 msource.File(),
01703 msource.Line(),
01704 msource.Column());
01705 }
01706
01707 while (!stop)
01708 {
01709 char chtmp = msource.Current();
01710 if ( isdigit(chtmp) )
01711 {
01712 res += chtmp;
01713 msource.AdvanceChar();
01714 if ( msource.LineBreak() ) stop = true;
01715 }
01716 else
01717 {
01718 stop = true;
01719 }
01720 }
01721 }
01722
01723
01739 void ArtsParser::read_numeric(String& res)
01740 {
01741 bool stop;
01742 res = "";
01743 char dummy;
01744 msource.LineBreak() = false;
01745
01746
01747 bool found_digit = false;
01748
01749
01750 dummy = msource.Current();
01751 if ( '+' == dummy || '-' == dummy )
01752 {
01753 res += dummy;
01754 msource.AdvanceChar();
01755 if ( msource.LineBreak() )
01756 throw IllegalLinebreak( "Linebreak after sign.",
01757 msource.File(),
01758 msource.Line(),
01759 msource.Column() );
01760 }
01761
01762
01763 stop = false;
01764 while (!stop)
01765 {
01766 char chtmp = msource.Current();
01767 if ( isdigit(chtmp) )
01768 {
01769 found_digit = true;
01770 res += chtmp;
01771 msource.AdvanceChar();
01772 if ( msource.LineBreak() ) return;
01773 }
01774 else
01775 {
01776 stop = true;
01777 }
01778 }
01779
01780
01781 if ( '.' == msource.Current() )
01782 {
01783 res += ".";
01784 msource.AdvanceChar();
01785 if ( msource.LineBreak() )
01786 {
01787 if (found_digit)
01788 {
01789
01790
01791 return;
01792 }
01793 else
01794 {
01795 throw IllegalLinebreak("Expected at least one digit.",
01796 msource.File(),
01797 msource.Line(),
01798 msource.Column());
01799 }
01800 }
01801
01802
01803 stop = false;
01804 while (!stop)
01805 {
01806 char chtmp = msource.Current();
01807 if ( isdigit(chtmp) )
01808 {
01809 found_digit = true;
01810 res += chtmp;
01811 msource.AdvanceChar();
01812 if ( msource.LineBreak() ) return;
01813 }
01814 else
01815 {
01816 stop = true;
01817 }
01818 }
01819 }
01820
01821
01822 if (!found_digit)
01823 throw ParseError("Expected at least one digit.",
01824 msource.File(),
01825 msource.Line(),
01826 msource.Column());
01827
01828
01829 dummy = msource.Current();
01830 if ( 'e' == dummy || 'E' == dummy )
01831 {
01832 res += dummy;
01833 msource.AdvanceChar();
01834 if ( msource.LineBreak() )
01835 throw IllegalLinebreak( "Linebreak after e/E.",
01836 msource.File(),
01837 msource.Line(),
01838 msource.Column() );
01839
01840
01841 {
01842 String s;
01843 read_integer(s);
01844 res += s;
01845 }
01846 }
01847 }
01848
01849
01854 void ArtsParser::parse_integer(Index& n)
01855 {
01856 String res;
01857 read_integer(res);
01858 istringstream is(res);
01859 is >> n;
01860 }
01861
01862
01867 void ArtsParser::parse_numeric(Numeric& n)
01868 {
01869 String res;
01870 read_numeric(res);
01871 istringstream is(res);
01872 is >> n;
01873 }
01874
01875
01890 void ArtsParser::parse_Stringvector(ArrayOfString& res)
01891 {
01892 bool first = true;
01893 res.resize(0);
01894
01895
01896 assertain_character('[');
01897
01898
01899 eat_whitespace();
01900
01901
01902
01903 while ( ']' != msource.Current() )
01904 {
01905 String dummy;
01906
01907 if (first)
01908 first = false;
01909 else
01910 {
01911 assertain_character(',');
01912 eat_whitespace();
01913 }
01914
01915 parse_String(dummy);
01916 res.push_back(dummy);
01917 eat_whitespace();
01918 }
01919
01920 msource.AdvanceChar();
01921 }
01922
01923
01935 void ArtsParser::parse_intvector(ArrayOfIndex& res)
01936 {
01937 bool first = true;
01938 res.resize(0);
01939
01940
01941 assertain_character('[');
01942
01943
01944 eat_whitespace();
01945
01946
01947
01948 while ( ']' != msource.Current() )
01949 {
01950 Index dummy;
01951
01952 if (first)
01953 first = false;
01954 else
01955 {
01956 assertain_character(',');
01957 eat_whitespace();
01958 }
01959
01960 parse_integer(dummy);
01961 res.push_back(dummy);
01962 eat_whitespace();
01963 }
01964
01965 msource.AdvanceChar();
01966 }
01967
01968
01980 void ArtsParser::parse_numvector(Vector& res)
01981 {
01982 bool first = true;
01983
01984
01985
01986
01987 Array<Numeric> tres;
01988
01989
01990 assertain_character('[');
01991
01992
01993 eat_whitespace();
01994
01995
01996
01997 while ( ']' != msource.Current() )
01998 {
01999 Numeric dummy;
02000
02001 if (first)
02002 first = false;
02003 else
02004 {
02005 assertain_character(',');
02006 eat_whitespace();
02007 }
02008
02009 parse_numeric(dummy);
02010 tres.push_back(dummy);
02011 eat_whitespace();
02012 }
02013
02014
02015 res.resize(tres.nelem());
02016 for (int i = 0; i < tres.nelem (); i++)
02017 {
02018 res[i] = tres[i];
02019 }
02020
02021 msource.AdvanceChar();
02022 }
02023
02024
02032 bool ArtsParser::parse_numvector_from_string (Vector& res, String& str)
02033 {
02034 bool first = true;
02035 size_t pos = 0;
02036
02037
02038
02039 Array<Numeric> tres;
02040
02041 eat_whitespace_from_string (str, pos);
02042
02043
02044 if (str[pos] != '[')
02045 {
02046 throw runtime_error ("No opening bracket\n");
02047 }
02048
02049 pos++;
02050
02051 eat_whitespace_from_string (str, pos);
02052
02053
02054
02055 while ( pos < str.length() && str[pos] != ']' )
02056 {
02057 if (first)
02058 first = false;
02059 else
02060 {
02061 if (str[pos] != ',')
02062 {
02063 return false;
02064 }
02065 pos++;
02066 eat_whitespace_from_string (str, pos);
02067 }
02068
02069 Numeric dummy;
02070 istringstream is (str.substr(pos));
02071 is >> dummy;
02072 if (is.bad () || is.fail ())
02073 return false;
02074 tres.push_back(dummy);
02075 while (pos < str.length()
02076 && (isdigit(str[pos]) || str[pos] == '-' || str[pos] == '.'
02077 || str[pos] == 'e'))
02078 pos++;
02079 eat_whitespace_from_string (str, pos);
02080 }
02081
02082
02083 res.resize(tres.nelem());
02084 for (int i = 0; i < tres.nelem (); i++)
02085 {
02086 res[i] = tres[i];
02087 }
02088
02089 return true;
02090 }
02091
02092
02101 bool ArtsParser::parse_stringarray_from_string (ArrayOfString& res, String& str)
02102 {
02103 bool first = true;
02104 size_t pos = 0;
02105
02106
02107
02108 ArrayOfString tres;
02109
02110 eat_whitespace_from_string (str, pos);
02111
02112
02113 if (str[pos] != '[')
02114 {
02115 throw runtime_error ("No opening bracket\n");
02116 }
02117
02118 pos++;
02119
02120 eat_whitespace_from_string (str, pos);
02121
02122
02123
02124 while ( pos < str.length() && str[pos] != ']' )
02125 {
02126 if (first)
02127 first = false;
02128 else
02129 {
02130 if (str[pos] != ',')
02131 {
02132 return false;
02133 }
02134 pos++;
02135 eat_whitespace_from_string (str, pos);
02136 }
02137
02138 if (str[pos] != '"')
02139 {
02140 throw runtime_error ("Expected quotes\n");
02141 }
02142
02143 pos++;
02144
02145 String dummy;
02146 while ( pos < str.length() && str[pos] != '"' )
02147 {
02148 dummy += str[pos];
02149 pos++;
02150 }
02151
02152 if (pos == str.length() || str[pos] != '"')
02153 return false;
02154
02155 tres.push_back(dummy);
02156
02157 eat_whitespace_from_string (str, pos);
02158 }
02159
02160
02161 res.resize(tres.nelem());
02162 for (int i = 0; i < tres.nelem (); i++)
02163 {
02164 res[i] = tres[i];
02165 }
02166
02167 return true;
02168 }
02169