00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "arts.h"
00019 #include <map>
00020 #include "messages.h"
00021 #include "exceptions.h"
00022 #include "file.h"
00023 #include "auto_wsv.h"
00024 #include "methods.h"
00025 #include "parser.h"
00026 #include "wsv_aux.h"
00027
00028 void SourceText::AppendFile(const String& name)
00029 {
00030 mSfLine.push_back(mText.nelem());
00031 mSfName.push_back(name);
00032
00033 read_text_from_file(mText, name);
00034 }
00035
00036 void SourceText::AdvanceChar()
00037 {
00038 if ( mColumn < mText[mLine].nelem()-1 )
00039 {
00040 ++mColumn;
00041 }
00042 else
00043 {
00044 mLineBreak = true;
00045 do
00046 {
00047 if (mLine>=mText.nelem()-1)
00048 {
00049 throw Eot( "",
00050 this->File(),
00051 this->Line(),
00052 this->Column() );
00053 }
00054 else
00055 {
00056 ++mLine;
00057 mColumn = 0;
00058 }
00059 }
00060 while ( 1 > mText[mLine].nelem() );
00061 }
00062 }
00063
00064
00065 void SourceText::AdvanceLine()
00066 {
00067 mLineBreak = true;
00068 mColumn = 0;
00069 do
00070 {
00071 if (mLine>=mText.nelem()-1)
00072 {
00073 throw Eot( "",
00074 this->File(),
00075 this->Line(),
00076 this->Column() );
00077 }
00078 else
00079 {
00080 ++mLine;
00081 }
00082 }
00083 while ( 1 > mText[mLine].nelem() );
00084 }
00085
00086
00087 const String& SourceText::File()
00088 {
00089 Index i = 0;
00090 bool stop = false;
00091
00092 while ( i<mSfLine.nelem()-1 && !stop )
00093 {
00094 if (mLine>=mSfLine[i+1]) ++i;
00095 else stop = true;
00096 }
00097
00098 return mSfName[i];
00099 }
00100
00101
00102 Index SourceText::Line()
00103 {
00104 Index i = 0;
00105 bool stop = false;
00106
00107 while ( i<mSfLine.nelem()-1 && !stop )
00108 {
00109 if (mLine>=mSfLine[i+1]) ++i;
00110 else stop = true;
00111 }
00112
00113 return mLine - mSfLine[i] + 1;
00114 }
00115
00116
00117 void SourceText::Init()
00118 {
00119 mLine = 0;
00120 mColumn = 0;
00121
00122 if ( 1 > mText.nelem() )
00123 {
00124 throw Eot( "Empty text!",
00125 this->File(),
00126 this->Line(),
00127 this->Column() );
00128 }
00129 else
00130 {
00131
00132 while ( 1 > mText[mLine].nelem() )
00133 {
00134 if (mLine>=mText.nelem()-1)
00135 {
00136 throw Eot( "",
00137 this->File(),
00138 this->Line(),
00139 this->Column() );
00140 }
00141 else
00142 {
00143 mLineBreak = true;
00144 ++mLine;
00145 }
00146 }
00147 }
00148 }
00149
00150
00151 ostream& operator << (ostream& os, const SourceText& text)
00152 {
00153 for (Index i=0; i<text.mText.nelem();++i)
00154 cout << i
00155 << "(" << text.mText[i].nelem() << ")"
00156 << ": " << text.mText[i] << '\n';
00157 return(os);
00158 }
00159
00160
00168 bool is_whitespace(const char c)
00169 {
00170 switch (c)
00171 {
00172 case ' ':
00173 case '\r':
00174 case '\t':
00175 case '#':
00176 return true;
00177 break;
00178 default:
00179 return false;
00180 break;
00181 }
00182 }
00183
00193 void eat_whitespace(SourceText& text)
00194 {
00195 char dummy;
00196
00197 while (is_whitespace(dummy=text.Current()))
00198 {
00199 switch (dummy)
00200 {
00201 case ' ':
00202 case '\r':
00203 case '\t':
00204 text.AdvanceChar();
00205 break;
00206 case '#':
00207 text.AdvanceLine();
00208 break;
00209 default:
00210 {
00211 ostringstream os;
00212 os << "Expected whitespace, but got `" << dummy << "'.";
00213 throw UnexpectedChar( os.str(),
00214 text.File(),
00215 text.Line(),
00216 text.Column() );
00217 break;
00218 }
00219 }
00220 }
00221 }
00222
00223
00232 void read_name(String& name, SourceText& text)
00233 {
00234 bool stop = false;
00235 name = "";
00236
00237 while (!stop)
00238 {
00239 char dummy = text.Current();
00240
00241 if ( isalnum(dummy) || '_'==dummy )
00242 {
00243 name += dummy;
00244
00245 text.LineBreak() = false;
00246 text.AdvanceChar();
00247 if ( text.LineBreak() ) stop = true;
00248 }
00249 else
00250 {
00251 stop = true;
00252 }
00253 }
00254
00255
00256 }
00257
00262 void assertain_character(char c, SourceText& text)
00263 {
00264 if ( c != text.Current() )
00265 {
00266 ostringstream os;
00267 os << "Expected `" << c << "', but got `" << text.Current() << "'.";
00268 throw UnexpectedChar( os.str(),
00269 text.File(),
00270 text.Line(),
00271 text.Column() );
00272 }
00273
00274 text.AdvanceChar();
00275 }
00276
00285 void parse_String(String& res, SourceText& text)
00286 {
00287 bool stop = false;
00288 res = "";
00289
00290 text.LineBreak() = false;
00291 assertain_character('"',text);
00292 if ( text.LineBreak() )
00293 throw IllegalLinebreak( "Line break before end of String.",
00294 text.File(),
00295 text.Line(),
00296 text.Column() );
00297
00298 while (!stop)
00299 {
00300 char dummy = text.Current();
00301 if ( dummy != '"' )
00302 {
00303 res += dummy;
00304 text.AdvanceChar();
00305
00306 if ( text.LineBreak() )
00307 throw IllegalLinebreak( "Line break before end of String.",
00308 text.File(),
00309 text.Line(),
00310 text.Column() );
00311 }
00312 else
00313 {
00314 stop = true;
00315 text.AdvanceChar();
00316 }
00317 }
00318 }
00319
00330 void read_integer(String& res, SourceText& text)
00331 {
00332 bool stop = false;
00333 res = "";
00334 char dummy;
00335 text.LineBreak() = false;
00336
00337 dummy = text.Current();
00338 if ( '+' == dummy || '-' == dummy )
00339 {
00340 res += dummy;
00341 text.AdvanceChar();
00342 if ( text.LineBreak() )
00343 throw IllegalLinebreak( "Line break after sign.",
00344 text.File(),
00345 text.Line(),
00346 text.Column() );
00347 }
00348
00349 if (!isdigit(text.Current()))
00350 {
00351 ostringstream os;
00352 os << "Expected digit, but got `" << text.Current() << "'.";
00353 throw UnexpectedChar(os.str(),
00354 text.File(),
00355 text.Line(),
00356 text.Column());
00357 }
00358
00359 while (!stop)
00360 {
00361 char dummy = text.Current();
00362 if ( isdigit(dummy) )
00363 {
00364 res += dummy;
00365 text.AdvanceChar();
00366 if ( text.LineBreak() ) stop = true;
00367 }
00368 else
00369 {
00370 stop = true;
00371 }
00372 }
00373 }
00374
00388 void read_numeric(String& res, SourceText& text)
00389 {
00390 bool stop;
00391 res = "";
00392 char dummy;
00393 text.LineBreak() = false;
00394
00395
00396 bool found_digit = false;
00397
00398
00399 dummy = text.Current();
00400 if ( '+' == dummy || '-' == dummy )
00401 {
00402 res += dummy;
00403 text.AdvanceChar();
00404 if ( text.LineBreak() )
00405 throw IllegalLinebreak( "Linebreak after sign.",
00406 text.File(),
00407 text.Line(),
00408 text.Column() );
00409 }
00410
00411
00412 stop = false;
00413 while (!stop)
00414 {
00415 char dummy = text.Current();
00416 if ( isdigit(dummy) )
00417 {
00418 found_digit = true;
00419 res += dummy;
00420 text.AdvanceChar();
00421 if ( text.LineBreak() ) return;
00422 }
00423 else
00424 {
00425 stop = true;
00426 }
00427 }
00428
00429
00430 if ( '.' == text.Current() )
00431 {
00432 res += ".";
00433 text.AdvanceChar();
00434 if ( text.LineBreak() )
00435 if (found_digit)
00436 {
00437
00438
00439 return;
00440 }
00441 else
00442 {
00443 throw IllegalLinebreak("Expected at least one digit.",
00444 text.File(),
00445 text.Line(),
00446 text.Column());
00447 }
00448
00449
00450 stop = false;
00451 while (!stop)
00452 {
00453 char dummy = text.Current();
00454 if ( isdigit(dummy) )
00455 {
00456 found_digit = true;
00457 res += dummy;
00458 text.AdvanceChar();
00459 if ( text.LineBreak() ) return;
00460 }
00461 else
00462 {
00463 stop = true;
00464 }
00465 }
00466 }
00467
00468
00469 if (!found_digit)
00470 throw ParseError("Expected at least one digit.",
00471 text.File(),
00472 text.Line(),
00473 text.Column());
00474
00475
00476 dummy = text.Current();
00477 if ( 'e' == dummy || 'E' == dummy )
00478 {
00479 res += dummy;
00480 text.AdvanceChar();
00481 if ( text.LineBreak() )
00482 throw IllegalLinebreak( "Linebreak after e/E.",
00483 text.File(),
00484 text.Line(),
00485 text.Column() );
00486
00487
00488 {
00489 String s;
00490 read_integer(s,text);
00491 res += s;
00492 }
00493 }
00494 }
00495
00497 void parse_integer(Index& n, SourceText& text)
00498 {
00499 String res;
00500 read_integer(res, text);
00501 istringstream is(res);
00502 is >> n;
00503 }
00504
00506 void parse_numeric(Numeric& n, SourceText& text)
00507 {
00508 String res;
00509 read_numeric(res, text);
00510 istringstream is(res);
00511 is >> n;
00512 }
00513
00528 void parse_Stringvector(ArrayOfString& res, SourceText& text)
00529 {
00530 bool first = true;
00531 res.resize(0);
00532
00533
00534 assertain_character('[',text);
00535
00536
00537 eat_whitespace(text);
00538
00539
00540
00541 while ( ']' != text.Current() )
00542 {
00543 String dummy;
00544
00545 if (first)
00546 first = false;
00547 else
00548 {
00549 assertain_character(',',text);
00550 eat_whitespace(text);
00551 }
00552
00553 parse_String(dummy, text);
00554 res.push_back(dummy);
00555 eat_whitespace(text);
00556 }
00557
00558 text.AdvanceChar();
00559 }
00560
00572 void parse_intvector(ArrayOfIndex& res, SourceText& text)
00573 {
00574 bool first = true;
00575 res.resize(0);
00576
00577
00578 assertain_character('[',text);
00579
00580
00581 eat_whitespace(text);
00582
00583
00584
00585 while ( ']' != text.Current() )
00586 {
00587 Index dummy;
00588
00589 if (first)
00590 first = false;
00591 else
00592 {
00593 assertain_character(',',text);
00594 eat_whitespace(text);
00595 }
00596
00597 parse_integer(dummy, text);
00598 res.push_back(dummy);
00599 eat_whitespace(text);
00600 }
00601
00602 text.AdvanceChar();
00603 }
00604
00616 void parse_numvector(Vector& res, SourceText& text)
00617 {
00618 bool first = true;
00619
00620
00621
00622
00623 Array<Numeric> tres;
00624
00625
00626 assertain_character('[',text);
00627
00628
00629 eat_whitespace(text);
00630
00631
00632
00633 while ( ']' != text.Current() )
00634 {
00635 Numeric dummy;
00636
00637 if (first)
00638 first = false;
00639 else
00640 {
00641 assertain_character(',',text);
00642 eat_whitespace(text);
00643 }
00644
00645 parse_numeric(dummy, text);
00646 tres.push_back(dummy);
00647 eat_whitespace(text);
00648 }
00649
00650
00651 res.resize(tres.nelem());
00652 res = tres;
00653
00654 text.AdvanceChar();
00655 }
00656
00684 bool parse_method(Index& id,
00685 Array<TokVal>& values,
00686 ArrayOfIndex& output,
00687 ArrayOfIndex& input,
00688 SourceText& text,
00689 const std::map<String, Index> MdMap,
00690 const std::map<String, Index> WsvMap)
00691 {
00692 extern const Array<WsvRecord> wsv_data;
00693 extern const Array<MdRecord> md_data;
00694 extern const ArrayOfString wsv_group_names;
00695
00696 Index wsvid;
00697
00698
00699
00700 id = 0;
00701 values.resize( 0 );
00702 output.resize( 0 );
00703 input.resize( 0 );
00704
00705 {
00706 String methodname;
00707 read_name(methodname, text);
00708
00709 {
00710
00711 const map<String, Index>::const_iterator i = MdMap.find(methodname);
00712 if ( i == MdMap.end() )
00713 throw UnknownMethod(methodname,
00714 text.File(),
00715 text.Line(),
00716 text.Column());
00717
00718 id = i->second;
00719 }
00720
00721
00722 }
00723
00724 eat_whitespace(text);
00725
00726
00727
00728 if ( 0 < md_data[id].GOutput().nelem() + md_data[id].GInput().nelem() )
00729 {
00730
00731 String wsvname;
00732 bool first = true;
00733
00734 assertain_character('(',text);
00735 eat_whitespace(text);
00736
00737
00738 for ( Index j=0 ; j<md_data[id].GOutput().nelem() ; ++j )
00739 {
00740 if (first)
00741 first = false;
00742 else
00743 {
00744 assertain_character(',',text);
00745 eat_whitespace(text);
00746 }
00747
00748 read_name(wsvname, text);
00749
00750 {
00751
00752 const map<String, Index>::const_iterator i = WsvMap.find(wsvname);
00753 if ( i == WsvMap.end() )
00754 throw UnknownWsv( wsvname,
00755 text.File(),
00756 text.Line(),
00757 text.Column() );
00758
00759 wsvid = i->second;
00760 }
00761
00762
00763 if ( wsv_data[wsvid].Group() != md_data[id].GOutput()[j] )
00764 {
00765 throw WrongWsvGroup( wsvname+" is not "+
00766 wsv_group_names[md_data[id].GOutput()[j]]+", it is "+
00767 wsv_group_names[wsv_data[wsvid].Group()],
00768 text.File(),
00769 text.Line(),
00770 text.Column() );
00771 }
00772
00773
00774 output.push_back(wsvid);
00775
00776 eat_whitespace(text);
00777 }
00778
00779
00780 for ( Index j=0 ; j<md_data[id].GInput().nelem() ; ++j )
00781 {
00782 if (first)
00783 first = false;
00784 else
00785 {
00786 assertain_character(',',text);
00787 eat_whitespace(text);
00788 }
00789
00790 read_name(wsvname, text);
00791
00792 {
00793
00794 const map<String, Index>::const_iterator i = WsvMap.find(wsvname);
00795 if ( i == WsvMap.end() )
00796 throw UnknownWsv( wsvname,
00797 text.File(),
00798 text.Line(),
00799 text.Column() );
00800
00801 wsvid = i->second;
00802 }
00803
00804
00805 if ( wsv_data[wsvid].Group() != md_data[id].GInput()[j] )
00806 throw WrongWsvGroup( wsvname+" is not "+
00807 wsv_group_names[md_data[id].GInput()[j]]+", it is "+
00808 wsv_group_names[wsv_data[wsvid].Group()],
00809 text.File(),
00810 text.Line(),
00811 text.Column() );
00812
00813
00814 input.push_back(wsvid);
00815
00816 eat_whitespace(text);
00817 }
00818
00819 assertain_character(')',text);
00820 eat_whitespace(text);
00821 }
00822
00823
00824 assertain_character('{',text);
00825 eat_whitespace(text);
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837 for ( Index i=0 ; i<md_data[id].Keywords().nelem() ; ++i )
00838 {
00839 if (!isalpha(text.Current()) && 1==md_data[id].Keywords().nelem())
00840 {
00841
00842
00843
00844
00845 }
00846 else
00847 {
00848
00849 String keyname;
00850 read_name(keyname,text);
00851
00852
00853 if ( keyname != md_data[id].Keywords()[i] )
00854 {
00855 throw UnexpectedKeyword( keyname,
00856 text.File(),
00857 text.Line(),
00858 text.Column());
00859 }
00860
00861 eat_whitespace(text);
00862
00863
00864 assertain_character('=',text);
00865 eat_whitespace(text);
00866 }
00867
00868
00869
00870
00871 switch (md_data[id].Types()[i])
00872 {
00873 case String_t:
00874 {
00875 String dummy;
00876 parse_String(dummy, text);
00877 values.push_back(dummy);
00878 break;
00879 }
00880 case Index_t:
00881 {
00882 Index n;
00883 parse_integer(n, text);
00884 values.push_back(n);
00885 break;
00886 }
00887 case Numeric_t:
00888 {
00889 Numeric n;
00890 parse_numeric(n, text);
00891 values.push_back(n);
00892 break;
00893 }
00894 case Array_String_t:
00895 {
00896 ArrayOfString dummy;
00897 parse_Stringvector(dummy, text);
00898 values.push_back(dummy);
00899 break;
00900 }
00901 case Array_Index_t:
00902 {
00903 ArrayOfIndex dummy;
00904 parse_intvector(dummy, text);
00905 values.push_back(dummy);
00906 break;
00907 }
00908 case Vector_t:
00909 {
00910 Vector dummy;
00911 parse_numvector(dummy, text);
00912 values.push_back(dummy);
00913 break;
00914 }
00915 default:
00916 throw logic_error("Impossible parameter type.");
00917 break;
00918 }
00919
00920 eat_whitespace(text);
00921
00922
00923
00924 }
00925
00926
00927
00928
00929
00930 try
00931 {
00932 assertain_character('}',text);
00933 }
00934 catch (const Eot x)
00935 {
00936
00937 return true;
00938 }
00939 return false;
00940 }
00941
00955 void parse(Array<MRecord>& tasklist,
00956 SourceText& text,
00957 const std::map<String, Index> MdMap,
00958 const std::map<String, Index> WsvMap)
00959 {
00960 extern const Array<MdRecord> md_data;
00961 bool last = false;
00962
00963 Index id;
00964
00965 Array<TokVal> values;
00966
00967 ArrayOfIndex output;
00968
00969 ArrayOfIndex input;
00970
00971 out3 << "\nParsing:\n";
00972
00973
00974
00975 eat_whitespace(text);
00976
00977 while (!last)
00978 {
00979 last = parse_method(id,values,output,input,text,MdMap,WsvMap);
00980
00981
00982 tasklist.push_back(MRecord(id,values,output,input));
00983
00984 {
00985
00986
00987 extern const Array<WsvRecord> wsv_data;
00988
00989 out3 << "- " << md_data[id].Name() << "\n";
00990
00991 for ( Index j=0 ; j<values.nelem() ; ++j )
00992 {
00993 out3 << " "
00994 << md_data[id].Keywords()[j] << ": "
00995 << values[j] << '\n';
00996 }
00997
00998
00999 if ( 0 < md_data[id].GOutput().nelem() + md_data[id].GInput().nelem() )
01000 {
01001 out3 << " Output: ";
01002 for ( Index j=0 ; j<output.nelem() ; ++j )
01003 {
01004 out3 << wsv_data[output[j]].Name() << " ";
01005 }
01006 out3 << "\n";
01007
01008 out3 << " Input: ";
01009 for ( Index j=0 ; j<input.nelem() ; ++j )
01010 {
01011 out3 << wsv_data[input[j]].Name() << " ";
01012 }
01013 out3 << "\n";
01014 }
01015 }
01016
01017
01018
01019 if (!last)
01020 try
01021 {
01022 eat_whitespace(text);
01023 }
01024 catch (const Eot x)
01025 {
01026 last = true;
01027 }
01028 }
01029 }
01030
01031 void parse_main(Array<MRecord>& tasklist, SourceText& text)
01032 {
01033
01034
01035 extern const std::map<String, Index> MdMap;
01036 extern const std::map<String, Index> WsvMap;
01037
01038 try
01039 {
01040 text.Init();
01041 parse(tasklist,text,MdMap,WsvMap);
01042 }
01043 catch (const Eot x)
01044 {
01045
01046 out0 << "Unexpected end of control script.\n";
01047 out0 << "File: " << x.file() << '\n';
01048 out0 << "Line: " << x.line() << '\n';
01049 exit(true);
01050 }
01051 catch (const UnexpectedChar x)
01052 {
01053
01054 out0 << "Unexpected character:\n";
01055 out0 << x.what() << '\n';
01056 out0 << "File: " << x.file() << '\n';
01057 out0 << "Line: " << x.line() << '\n';
01058 out0 << "Column: " << x.column() << '\n';
01059 exit(true);
01060 }
01061 catch (const IllegalLinebreak x)
01062 {
01063
01064 out0 << "Illegal Line break:\n";
01065 out0 << x.what() << '\n';
01066 out0 << "File: " << x.file() << '\n';
01067 out0 << "Line: " << x.line() << '\n';
01068 exit(true);
01069 }
01070 catch (const UnknownMethod x)
01071 {
01072
01073
01074
01075 out0 << "Unknown Method:\n";
01076 out0 << x.what() << '\n';
01077 out0 << "File: " << x.file() << '\n';
01078 out0 << "Line: " << x.line() << '\n';
01079 out3 << "Column: " << x.column() << '\n';
01080 exit(true);
01081 }
01082 catch (const UnknownWsv x)
01083 {
01084
01085
01086
01087 out0 << "Unknown workspace variable:\n";
01088 out0 << x.what() << '\n';
01089 out0 << "File: " << x.file() << '\n';
01090 out0 << "Line: " << x.line() << '\n';
01091 out3 << "Column: " << x.column() << '\n';
01092 exit(true);
01093 }
01094 catch (const WrongWsvGroup x)
01095 {
01096
01097
01098
01099 out0 << "Workspace variable belongs to the wrong group:\n";
01100 out0 << x.what() << '\n';
01101 out0 << "File: " << x.file() << '\n';
01102 out0 << "Line: " << x.line() << '\n';
01103 out3 << "Column: " << x.column() << '\n';
01104 exit(true);
01105 }
01106 catch (const UnexpectedKeyword x)
01107 {
01108
01109
01110
01111 out0 << "Unknown keyword:\n";
01112 out0 << x.what() << '\n';
01113 out0 << "File: " << x.file() << '\n';
01114 out0 << "Line: " << x.line() << '\n';
01115 out3 << "Column: " << x.column() << '\n';
01116 exit(true);
01117 }
01118 catch (const ParseError x)
01119 {
01120
01121 out0 << "Parse error:\n";
01122 out0 << x.what() << '\n';
01123 out0 << "File: " << x.file() << '\n';
01124 out0 << "Line: " << x.line() << '\n';
01125 out0 << "Column: " << x.column() << '\n';
01126 exit(true);
01127 }
01128 catch (const runtime_error x)
01129 {
01130 cout << "Runtime error: ";
01131 cout << x.what() << '\n';
01132 }
01133 catch (const logic_error x)
01134 {
01135 cout << "Logic error: ";
01136 cout << x.what() << '\n';
01137 }
01138
01139 }