ARTS  2.2.66
parser.cc
Go to the documentation of this file.
1 /* Copyright (C) 2012 Oliver Lemke <olemke@core-dump.info>
2 
3  This program is free software; you can redistribute it and/or modify it
4  under the terms of the GNU General Public License as published by the
5  Free Software Foundation; either version 2, or (at your option) any
6  later version.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16  USA. */
17 
18 #include <iostream>
19 #include "parser.h"
20 #include "arts.h"
21 #include "exceptions.h"
22 #include "file.h"
23 #include "methods.h"
24 #include "parameters.h"
25 #include "wsv_aux.h"
26 #include "workspace_ng.h"
27 #include "global_data.h"
28 
29 
37 ArtsParser::ArtsParser(Agenda& tasklist, String controlfile, const Verbosity& rverbosity)
38 : mtasklist (tasklist), mcfile (controlfile), mcfile_version (1), verbosity (rverbosity)
39 {
41 }
42 
43 
49 {
50  parse_main ();
51 }
52 
53 
62 void ArtsParser::find_named_arguments(vector<NamedArgument>& named_args)
63 {
64  NamedArgument current_argument;
65 
66  named_args.resize(0);
67 
68  while (msource.Current() != ')')
69  {
70  read_name(current_argument.name);
72  if (msource.Current() != '=')
73  {
74  ostringstream os;
75  os << "Expected '=', but got '" << msource.Current() << "'.\n"
76  << "Mixing positional and named arguments is not allowed.";
77  throw UnexpectedChar( os.str(),
78  msource.File(),
79  msource.Line(),
80  msource.Column() );
81  }
82 
85 
86  current_argument.line = msource.LineRaw();
87  current_argument.column = msource.ColumnRaw();
88  named_args.push_back(current_argument);
89 
91  }
92 }
93 
94 
100 {
101  Index bracket_level = 0;
102  bool inside_quotes = false;
103  char prev_char = 0;
104  Index starting_line = msource.LineRaw();
105  Index starting_col = msource.ColumnRaw();
106 
107  while ((bracket_level || inside_quotes)
108  || (msource.Current() != ',' && msource.Current() != ')'))
109  {
110  try {
111  switch (msource.Current())
112  {
113  case '[': bracket_level++; break;
114  case ']':
115  bracket_level--;
116  if (bracket_level < 0)
117  throw ParseError("Too many closing brackets",
118  msource.File(),
119  msource.Line(),
120  msource.Column() );
121  break;
122  case '"':
123  if (prev_char != '\\')
124  inside_quotes = !inside_quotes;
125  break;
126  }
127 
128  prev_char = msource.Current();
130  }
131  catch (const Eot& x)
132  {
133  msource.SetPosition(starting_line, starting_col);
134  throw ParseError("Unexpectedly reached end of file.\nProbably a runaway argument.",
135  msource.File(),
136  msource.Line(),
137  msource.Column() );
138  }
139  }
140 
141  if (msource.Current() == ',')
142  {
143  try {
145  }
146  catch (const Eot& x)
147  {
148 
149  throw ParseError( "blablup",
150  msource.File(),
151  msource.Line(),
152  msource.Column() );
153  }
154  eat_whitespace();
155  }
156 }
157 
158 
170 {
171  eat_whitespace();
172  if (msource.Current() != ',' && msource.Current() != ')')
173  {
174  ostringstream os;
175  os << "Expected ',' or ')' but found '" << msource.Current() << "' after " << argname;
176  throw UnexpectedChar(os.str(),
177  msource.File(),
178  msource.Line(),
179  msource.Column());
180  }
181 }
182 
183 
189  NamedArguments& named_args,
190  String name)
191 {
192  for (arg_index = 0; arg_index < (Index)named_args.size(); arg_index++)
193  {
194  if (named_args[(size_t)arg_index].name == name)
195  return;
196  }
197 
198  arg_index = -1;
199 }
200 
201 
208 {
209  CREATE_OUT0;
210  CREATE_OUT3;
211 
212  try
213  {
214  using global_data::md_data;
215 
216  // For method ids:
217  Index id;
218  // Output workspace variables (for generic methods):
219  ArrayOfIndex output;
220  // Input workspace variables (for generic methods):
221  ArrayOfIndex input;
222  // For include statements, holding the include file's name
223  String include_file;
224 
225  ArrayOfIndex auto_vars;
226  Array<TokVal> auto_vars_values;
227 
228  out3 << "\nParsing control text:\n";
229 
230  msource.Init();
231  eat_whitespace();
232 
233  parse_method(id,output,input,mtasklist,auto_vars,auto_vars_values,
234  include_file,true);
235 
236  if ( "Arts" != md_data[id].Name() && "Arts2" != md_data[id].Name() )
237  {
238  ostringstream os;
239  os << "The outermost agenda must be Arts2!\n"
240  << "(But it seems to be " << md_data[id].Name() << ".)\n";
241  throw runtime_error(os.str());
242  }
243 
244  try {
246  if (!msource.reachedEot()) throw UnexpectedChar("",
247  msource.File(),
248  msource.Line(),
249  msource.Column() );
250  }
251  catch (const Eot&)
252  {
253  // It's ok to reach the end of the file here,
254  // that's actually what we want.
255  }
256  catch (const UnexpectedChar& x)
257  {
258  ostringstream os;
259  os << "Unexpected character(s) at the end of the control file\n";
260  os << "after the main agenda was already closed.\n";
261  os << "File: " << x.file() << '\n';
262  os << "Line: " << x.line() << '\n';
263  os << "Column: " << x.column() << '\n';
264  throw runtime_error(os.str());
265  }
266  }
267  catch (const Eot& x)
268  {
269  // Unexpected end of the source text:
270  ostringstream os;
271  os << "Unexpected end of control script.\n";
272  os << "File: " << x.file() << '\n';
273  os << "Line: " << x.line() << '\n';
274  throw runtime_error(os.str());
275  }
276  catch (const UnexpectedChar& x)
277  {
278  // Unexpected Character:
279  ostringstream os;
280  os << "Unexpected character:\n";
281  os << x.what() << '\n';
282  os << "File: " << x.file() << '\n';
283  os << "Line: " << x.line() << '\n';
284  os << "Column: " << x.column() << '\n';
285  throw runtime_error(os.str());
286  }
287  catch (const IllegalLinebreak& x)
288  {
289  // A line break in an illegal position:
290  ostringstream os;
291  os << "Illegal Line break:\n";
292  os << x.what() << '\n';
293  os << "File: " << x.file() << '\n';
294  os << "Line: " << x.line() << '\n';
295  throw runtime_error(os.str());
296  }
297  catch (const UnknownMethod& x)
298  {
299  // Method unknown:
300  // [**This should give a hint on how to obtain a list of allowed
301  // methods.]
302  ostringstream os;
303  os << "Unknown Method:\n";
304  os << x.what() << '\n';
305  os << "File: " << x.file() << '\n';
306  os << "Line: " << x.line() << '\n';
307  os << "Column: " << x.column() << '\n';
308  throw runtime_error(os.str());
309  }
310  catch (const UnknownWsv& x)
311  {
312  // Workspace variable unknown:
313  // [**This should give a hint on how to obtain a list of allowed
314  // Wsvs.]
315  ostringstream os;
316  os << "Unknown workspace variable:\n";
317  os << x.what() << '\n';
318  os << "File: " << x.file() << '\n';
319  os << "Line: " << x.line() << '\n';
320  os << "Column: " << x.column() << '\n';
321  throw runtime_error(os.str());
322  }
323  catch (const WsvAlreadyExists& x)
324  {
325  // Trying to create the same variable twice:
326  ostringstream os;
327  os << "Attempt to create a workspace variable that already exists:\n";
328  os << x.what() << '\n';
329  os << "File: " << x.file() << '\n';
330  os << "Line: " << x.line() << '\n';
331  os << "Column: " << x.column() << '\n';
332  throw runtime_error(os.str());
333  }
334  catch (const WrongWsvGroup& x)
335  {
336  // Workspace variable unknown:
337  // [**This should give a hint on how to obtain a list of Wsvs in
338  // this group.
339  ostringstream os;
340  os << "Workspace variable belongs to the wrong group:\n";
341  os << x.what() << '\n';
342  os << "File: " << x.file() << '\n';
343  os << "Line: " << x.line() << '\n';
344  os << "Column: " << x.column() << '\n';
345  throw runtime_error(os.str());
346  }
347  catch (const ParseError& x)
348  {
349  // General Parse Error (parent of all the above):
350  ostringstream os;
351  os << "Parse error:\n";
352  os << x.what() << '\n';
353  os << "File: " << x.file() << '\n';
354  os << "Line: " << x.line() << '\n';
355  os << "Column: " << x.column() << '\n';
356  throw runtime_error(os.str());
357  }
358 }
359 
360 
375 {
376  CREATE_OUT2;
377  CREATE_OUT3;
378 
379  using global_data::md_data;
380 
381  // For method ids:
382  Index id;
383  // Output workspace variables:
384  ArrayOfIndex output;
385  // Input workspace variables:
386  ArrayOfIndex input;
387  // For Agenda, if there is any:
388  Agenda tasks;
389  // For include statements, holding the include file's name
390  String include_file;
391 
392  ArrayOfIndex auto_vars;
393  Array<TokVal> auto_vars_values;
394 
395  eat_whitespace();
396 
397  while ( '}' != msource.Current() )
398  {
399  parse_method(id,output,input,tasks,
400  auto_vars,auto_vars_values,include_file);
401 
402  // If parse_method found an include statement it returnes -1 for the
403  // method id
404  if (id == -1)
405  {
406  // Command line parameters which give us the include search path.
407  extern Parameters parameters;
408 
409  ArrayOfString current_includepath = parameters.includepath;
410  String includedir;
411  get_dirname(includedir, msource.File());
412  if (includedir.nelem())
413  {
414  if (current_includepath.nelem() && current_includepath[0] != includedir)
415  current_includepath.insert(current_includepath.begin(), includedir);
416  if (parameters.datapath.nelem() && parameters.datapath[0] != includedir)
417  parameters.datapath.insert(parameters.datapath.begin(), includedir);
418  }
419 
420  ArrayOfString matching_files;
421  find_file (matching_files, include_file, current_includepath);
422  find_file (matching_files, include_file + ".arts", current_includepath);
423 
424  if (!matching_files.nelem())
425  {
426  ostringstream os;
427  os << "Cannot find include file " << include_file
428  << ".\n";
429  os << "File: " << msource.File() << '\n';
430  os << "Search path was: " << current_includepath
431  << "\n";
432  throw runtime_error (os.str());
433  }
434 
435  include_file = matching_files[0];
436  out2 << "- Including control file " << include_file << "\n";
437 
438  ArtsParser include_parser (tasks, include_file, verbosity);
439  include_parser.parse_tasklist();
440 
441  for (Index i = 0; i < tasks.nelem(); i++)
442  tasklist.push_back (tasks.Methods()[i]);
443  }
444  else
445  {
446  if (md_data[id].SetMethod())
447  {
448  // Append task to task list:
449  tasklist.push_back(MRecord(id,output,input,
450  auto_vars_values[0],tasks));
451  }
452  else
453  {
454  tasklist_insert_set_delete(auto_vars, auto_vars_values,
455  0, tasklist);
456 
457  // Append task to task list:
458  tasklist.push_back(MRecord(id,output,input,TokVal(),tasks));
459 
460  tasklist_insert_set_delete(auto_vars, auto_vars_values,
461  1, tasklist);
462 
463  // If Create was called on a variable that already existed,
464  // insert a Delete call to set it back to an uninitialized state
465  using global_data::md_data;
466  const String& mname = md_data[id].Name();
467 
468  if (mname.length() > 6 &&
469  mname.find ("Create") == mname.length() - 6 &&
470  get_wsv_group_id(mname.substr(0, mname.length() - 6)) != -1)
471  {
472  using global_data::MdMap;
474  String method_name = "Delete_sg_" + wsv_group_names[Workspace::wsv_data[output[0]].Group()];
475  map<String, Index>::const_iterator mdit;
476  mdit = MdMap.find(method_name);
477  assert ( mdit != MdMap.end() );
478 
479  tasklist.push_back(MRecord(mdit->second,ArrayOfIndex(),output,TokVal(),Agenda(),true));
480  }
481  }
482 
483  {
484  // Everything in this block is just to generate some
485  // informative output.
486 
487  out3 << "- " << md_data[id].Name() << "\n";
488 
489  // Output workspace variables for generic methods:
490  if ( 0 < md_data[id].GOutType().nelem()
491  + md_data[id].GInType().nelem() )
492  {
493  out3 << " Output: ";
494  for ( Index j=0 ; j<output.nelem() ; ++j )
495  {
496  out3 << Workspace::wsv_data[output[j]].Name() << " ";
497  }
498  out3 << "\n";
499 
500  out3 << " Input: ";
501  for ( Index j=0 ; j<input.nelem() ; ++j )
502  {
503  out3 << Workspace::wsv_data[input[j]].Name() << " ";
504  }
505  out3 << "\n";
506  }
507  }
508  }
509 
510  eat_whitespace();
511  }
512 }
513 
514 
547  ArrayOfIndex& output,
548  ArrayOfIndex& input,
549  Agenda& tasks,
550  ArrayOfIndex& auto_vars,
551  Array<TokVal>& auto_vars_values,
552  String& include_file,
553  bool no_eot)
554 {
555  CREATE_OUT3;
556 
557  String methodname; // We need this out here, since it is
558  // set once and later modified.
559 
560  const MdRecord* mdd; // Handle on the method record. Needed here,
561  // because it is modified.
562 
563  bool found_curly_brace = false;
564 
565  // Clear all output variables:
566  id = 0;
567  output.resize( 0 );
568  input.resize( 0 );
569  tasks.resize( 0 );
570  auto_vars.resize( 0 );
571  auto_vars_values.resize( 0 );
572  include_file = "";
573 
574  read_name(methodname);
575 
576  if (methodname == "INCLUDE")
577  {
578  eat_whitespace ();
579  parse_String (include_file);
580 
581  id = -1;
582 
583  return;
584  }
585  else
586  {
587  if (methodname == "Arts2")
588  {
589  mcfile_version = 2;
590  }
591  else if (methodname == "Arts")
592  {
593  throw runtime_error("Arts version 1 controlfiles are no longer supported.");
594  }
595 
596  eat_whitespace();
597 
598  parse_method_args(mdd, id, methodname, output, input,
599  auto_vars, auto_vars_values);
600 
601  eat_whitespace();
602 
603  // Now look for the curly braces:
604  if (msource.Current() == '{')
605  {
607  eat_whitespace();
608  found_curly_brace = true;
609  }
610 
611  // There are two kind of methods, agenda methods, which have other
612  // methods in the body, and normal methods, expecting keywords and
613  // values. Let's take the agenda case first...
614  if ( mdd->AgendaMethod() )
615  {
616  out3 << "- " << mdd->Name() << "\n";
617  out3 << "{\n";
618  parse_agenda(tasks);
619  out3 << "}\n";
620  }
621 
622  // Curly braces in non-agenda methods are not valid in v2 controlfiles
623  if (mcfile_version == 2 && !mdd->AgendaMethod() && found_curly_brace)
624  {
625  ostringstream os;
626  os << "Expected method name , but got `" << msource.Current() << "'.";
627  throw UnexpectedChar( os.str(),
628  msource.File(),
629  msource.Line(),
630  msource.Column() );os << "" << endl;
631  }
632  }
633 
634  // Now look for the closing curly braces. We have to catch Eot,
635  // because after a method description may be a good place to end
636  // the control file.
637  if (found_curly_brace)
638  {
639  try
640  {
641  assertain_character('}');
642  }
643  catch (const Eot x)
644  {
645  // Re-throw the error if the no_eot flag is not set:
646  if (!no_eot) throw Eot(x);
647  }
648  }
649 }
650 
651 
653 
668  ArrayOfIndex& auto_vars,
669  Array<TokVal>& auto_vars_values,
670  Index gin_index)
671 {
672  String name;
673 
674  if (mdd->GInDefault()[gin_index] != NODEF)
675  {
676  TokVal tv;
677  // Now parse the key value. This can be:
678  // String, Index, Numeric, ArrayOfString, ArrayOfIndex, Vector
679  bool failed = false;
680  if (mdd->GInType()[gin_index] == get_wsv_group_id ("String"))
681  {
682  tv = mdd->GInDefault()[gin_index];
683  }
684  else if (mdd->GInType()[gin_index] == get_wsv_group_id ("Index"))
685  {
686  Index n;
687  istringstream is(mdd->GInDefault()[gin_index]);
688  is >> n;
689  tv = n;
690  if (is.bad () || is.fail ())
691  failed = true;
692  }
693  else if (mdd->GInType()[gin_index] == get_wsv_group_id ("Numeric"))
694  {
695  Numeric n;
696  istringstream is(mdd->GInDefault()[gin_index]);
697  is >> n;
698  tv = n;
699  if (is.bad () || is.fail ())
700  failed = true;
701  }
702  else if (mdd->GInType()[gin_index] == get_wsv_group_id ("ArrayOfString"))
703  {
704  ArrayOfString v;
705  String s = mdd->GInDefault()[gin_index];
707  {
708  failed = true;
709  }
710  tv = v;
711  }
712  else if (mdd->GInType()[gin_index] == get_wsv_group_id ("Vector"))
713  {
714  Vector v;
715  String s = mdd->GInDefault()[gin_index];
716  if (!parse_numvector_from_string(v, s))
717  {
718  failed = true;
719  }
720  tv = v;
721  }
722  else
723  {
725  ostringstream os;
726  os
727  << "Default values for generic inputs with type "
728  << wsv_group_names[mdd->GInType()[gin_index]] << " are not supported.\n"
729  << "Either remove the default value for generic input '"
730  << mdd->GIn()[gin_index] << "' in workspace method\n"
731  << "*" << mdd->Name() << "* in methods.cc or discuss this "
732  << "issue on the arts-dev mailing list.\n";
733  throw ParseError (os.str(),
734  msource.File(),
735  msource.Line(),
736  msource.Column());
737  }
738 
739  Index wsvid;
740 
741  {
742  ostringstream os;
743  os << gin_index;
744 
745  name = "auto_" + mdd->Name() + "_" + "gin" + os.str() + "_"
746  + mdd->GIn()[gin_index];
747  }
748 
749  map<String, Index>::const_iterator wsvit =
750  Workspace::WsvMap.find(name);
751  if (wsvit == Workspace::WsvMap.end())
752  {
753  wsvid = Workspace::add_wsv(WsvRecord(name.c_str(),
754  "Automatically allocated variable.",
755  mdd->GInType()[gin_index],
756  true));
757  }
758  else
759  {
760  wsvid = wsvit->second;
761  }
762 
763  auto_vars.push_back(wsvid);
764  auto_vars_values.push_back(tv);
765 
766  if (failed)
767  {
768  ostringstream os;
769  os << "Failed to assign default value for generic '"
770  << mdd->GIn()[gin_index] << "'.\n"
771  << "Check the documentation of workspace method *"
772  << mdd->Name() << "*.\n";
773  throw ParseError (os.str(),
774  msource.File(),
775  msource.Line(),
776  msource.Column());
777  }
778  }
779  else
780  {
781  ostringstream os;
782  os << "Generic input '" << mdd->GIn()[gin_index]
783  << "' omitted but no default value found.\n"
784  << "Check the documentation of workspace method *"
785  << mdd->Name() << "*.\n";
786  throw ParseError (os.str(),
787  msource.File(),
788  msource.Line(),
789  msource.Column());
790  }
791 
792  return name;
793 }
794 
795 
797 
811  Index& id,
812  String& methodname,
813  ArrayOfIndex& output,
814  ArrayOfIndex& input,
815  ArrayOfIndex& auto_vars,
816  Array<TokVal>& auto_vars_values)
817 {
818  using global_data::MdRawMap;
819  using global_data::md_data;
821  using global_data::MdMap;
822 
823  bool still_supergeneric=true; // Flag that our MdRecord still is
824  // from md_data_raw, not from
825  // md_data.
826 
827  // Find method raw id in raw map:
828  const map<String, Index>::const_iterator md_raw_id = MdRawMap.find(methodname);
829  if ( md_raw_id == MdRawMap.end() )
830  throw UnknownMethod(methodname,
831  msource.File(),
832  msource.Line(),
833  msource.Column());
834 
835  id = md_raw_id->second;
836 
837  // Get a convenient handle on the data record for this method. We
838  // have to use a pointer here, not a reference, because we later
839  // want to change where mdd is pointing!
840  mdd = &md_data_raw[id];
841 
842  // Is this a supergeneric method? If not, take the record in
843  // md_data, rather than in md_data_raw:
844  if ( !mdd->Supergeneric() )
845  {
846  // Find explicit method id in MdMap:
847  const map<String, Index>::const_iterator i2 = MdMap.find(methodname);
848  assert ( i2 != MdMap.end() );
849  id = i2->second;
850 
851  mdd = &md_data[id];
852 
853  still_supergeneric = false;
854  }
855 
856  if (msource.Current() == '(')
857  {
858  String supergeneric_args;
859  Index supergeneric_index = -1;
860  NamedArguments named_arguments;
861  Index this_method_end_line = -1;
862  Index this_method_end_column = -1;
863  bool call_by_name = false;
864 
866  eat_whitespace();
867 
868  // Peak at the first method argument to determine if the method
869  // is called with positional or named arguments
870  if (isalpha(msource.Current()))
871  {
872  Index line = msource.LineRaw();
873  Index column = msource.ColumnRaw();
874  String name = "";
875 
876  read_name(name);
877  eat_whitespace();
878 
879  if (msource.Current() == '=')
880  {
882  eat_whitespace();
883 
884  msource.SetPosition(line, column);
885  find_named_arguments(named_arguments);
886 
887  call_by_name = true;
888 
889  this_method_end_line = msource.LineRaw();
890  this_method_end_column = msource.ColumnRaw();
891  }
892 
893  msource.SetPosition(line, column);
894  }
895 
896  bool is_first_arg = true;
897  parse_specific_output(mdd, output, is_first_arg, named_arguments, call_by_name);
898 
899  parse_generic_output(mdd, id, methodname, output,
900  is_first_arg, still_supergeneric, supergeneric_args,
901  supergeneric_index, named_arguments, call_by_name);
902 
903  parse_specific_input(mdd, input, auto_vars, auto_vars_values, is_first_arg,
904  named_arguments, call_by_name);
905 
906  parse_generic_input(mdd, id, methodname, input,
907  auto_vars, auto_vars_values,
908  is_first_arg, still_supergeneric, supergeneric_args,
909  supergeneric_index, named_arguments, call_by_name);
910 
911  // Named arguments are not parsed in order. We have to set the cursor
912  // to the end of the method call after all named arguments have been parsed.
913  if (call_by_name)
914  msource.SetPosition(this_method_end_line, this_method_end_column);
915 
916  // If we're here and still have named arguments left means that
917  // the user specified too many for this method
918  if (call_by_name && named_arguments.size())
919  {
920  ostringstream os;
921 
922  os << "Too many arguments passed to " << mdd->Name() << ": ";
923  bool first = true;
924  for (size_t i = 0; i < named_arguments.size(); i++)
925  {
926  if (!first) os << ", ";
927  else first = false;
928  os << named_arguments[i].name;
929  }
930  throw ParseError(os.str(),
931  msource.File(),
932  msource.Line(),
933  msource.Column());
934  }
935 
936  assert(!still_supergeneric);
937  assertain_character(')');
938  }
939  else
940  {
941  if (mdd->GOut().nelem())
942  {
943  ostringstream os;
944  os << "This method has generic output. "
945  << "You have to pass a variable!";
946  throw ParseError(os.str(),
947  msource.File(),
948  msource.Line(),
949  msource.Column());
950  }
951 
952  // If the parenthesis were omitted we still have to add the implicit
953  // outputs and inputs to the methods input and output variable lists
954  ArrayOfIndex vo=mdd->Out();
955  for (ArrayOfIndex::const_iterator outs=vo.begin();
956  outs<vo.end(); ++outs)
957  {
958  output.push_back (*outs);
959  }
960 
961  const ArrayOfIndex &vi = mdd->InOnly();
962  for (ArrayOfIndex::const_iterator ins=vi.begin(); ins<vi.end(); ++ins)
963  {
964  input.push_back (*ins);
965  }
966 
967  {
968  // Make sure all keywords have default values, otherwise the
969  // user has to specify them in the controlfile.
970  bool all_gin_have_defaults = true;
971  for (Index gin = 0;
972  all_gin_have_defaults && gin < mdd->GIn().nelem();
973  ++gin)
974  {
975  Index wsvid; // Workspace variable id, is used to
976  // access data in wsv_data.
977 
978  if (mdd->GInDefault()[gin] == NODEF)
979  all_gin_have_defaults = false;
980  else
981  {
982  String wsvname;
983  wsvname = set_gin_to_default(mdd, auto_vars,
984  auto_vars_values, gin);
985  {
986  // Find Wsv id:
987  const map<String, Index>::const_iterator wsvit =
988  Workspace::WsvMap.find(wsvname);
989  if ( wsvit == Workspace::WsvMap.end() )
990  {
991  throw UnknownWsv( wsvname,
992  msource.File(),
993  msource.Line(),
994  msource.Column() );
995  }
996 
997  wsvid = wsvit->second;
998  }
999  input.push_back(wsvid);
1000  }
1001  }
1002 
1003  if (!all_gin_have_defaults)
1004  {
1005  ostringstream os;
1006  os << "Not all generic inputs of this method have default "
1007  << "values, you have to specify them!";
1008  throw ParseError( os.str(),
1009  msource.File(),
1010  msource.Line(),
1011  msource.Column() );
1012  }
1013  }
1014  }
1015 }
1016 
1017 
1035  Index& id,
1036  String& methodname,
1037  ArrayOfIndex& input,
1038  ArrayOfIndex& auto_vars,
1039  Array<TokVal>& auto_vars_values,
1040  bool& first,
1041  bool& still_supergeneric,
1042  String& supergeneric_args,
1043  Index& supergeneric_index _U_,
1044  NamedArguments& named_args,
1045  bool call_by_name)
1046 {
1047  String wsvname;
1048  Index wsvid;
1050  using global_data::md_data;
1051  using global_data::MdMap;
1052 
1053  // Then parse all generic input variables
1054  for ( Index j=0 ; j<mdd->GInType().nelem() ; ++j )
1055  {
1056  Index this_arg_index = 0;
1057 
1058  if (call_by_name)
1059  {
1060  get_argument_index_by_name(this_arg_index, named_args, mdd->GIn()[j]);
1061 
1062  if (this_arg_index != -1)
1063  {
1064  msource.SetPosition(named_args[this_arg_index].line,
1065  named_args[this_arg_index].column);
1066  named_args.erase(named_args.begin()+this_arg_index);
1067  }
1068  }
1069  else
1070  {
1071  if (first)
1072  first = false;
1073  else
1074  {
1075  if (msource.Current() != ')')
1076  {
1077  assertain_character(',');
1078  eat_whitespace();
1079  }
1080  }
1081  }
1082 
1083  // If no value was specified and we use the default value instead (if there is one)
1084  if ((call_by_name && this_arg_index == -1)
1085  || msource.Current() == ',' || msource.Current() == ')')
1086  {
1087  wsvname = set_gin_to_default(mdd, auto_vars, auto_vars_values, j);
1088  }
1089  else
1090  {
1091  ostringstream os;
1092  os << j;
1093  if (read_name_or_value(wsvname, auto_vars, auto_vars_values,
1094  "generic" + os.str(),
1095  mdd, mdd->GInType()[j]) == -1
1096  && mdd->SetMethod())
1097  {
1098  if (msource.Current() == '=')
1099  {
1100  throw UnexpectedChar("Unexpected '=' sign encountered.\n"
1101  "Mixing positional and named arguments is not allowed.",
1102  msource.File(),
1103  msource.Line(),
1104  msource.Column() );
1105  }
1106  throw ParseError("Only constants can be passed to Set methods.\n"
1107  "You might want to use the *Copy* here.",
1108  msource.File(),
1109  msource.Line(),
1110  msource.Column() );
1111  }
1112  if (call_by_name) at_end_of_argument("generic input argument");
1113  }
1114 
1115  {
1116  // Find Wsv id:
1117  const map<String, Index>::const_iterator wsvit =
1118  Workspace::WsvMap.find(wsvname);
1119  if ( wsvit == Workspace::WsvMap.end() )
1120  {
1121  throw UnknownWsv( wsvname,
1122  msource.File(),
1123  msource.Line(),
1124  msource.Column() );
1125  }
1126 
1127  wsvid = wsvit->second;
1128  }
1129 
1130  // Is the method data record still supergeneric? This could
1131  // be the case if there are no output arguments, only input
1132  // arguments. In that case, let's find out the actual group!
1133  if ( still_supergeneric )
1134  {
1135  ostringstream os;
1136  if (wsv_group_names[mdd->GInType()[j]] == "Any")
1137  supergeneric_args +=
1138  wsv_group_names[Workspace::wsv_data[wsvid].Group()];
1139  os << mdd->Name() << "_sg_" << supergeneric_args;
1140  methodname = os.str();
1141 
1142  // Find explicit method id in MdMap:
1143  const map<String, Index>::const_iterator mdit =
1144  MdMap.find(methodname);
1145  if (mdit != MdMap.end())
1146  {
1147  id = mdit->second;
1148 
1149  mdd = &md_data[id];
1150 
1151  still_supergeneric = false;
1152  }
1153  }
1154 
1155  // Now we have explicitly the method record for the right
1156  // group. From now on no special treatment of supergeneric
1157  // methods should be necessary.
1158 
1159  // Check that this Wsv belongs to the correct group:
1160  if (mdd->GInType()[j] == get_wsv_group_id ("Any")
1161  && mdd->GInSpecType()[j].nelem() )
1162  {
1163  if (supergeneric_index == -1)
1164  {
1165  bool wrong_group_id = true;
1166  for (Index i = 0; wrong_group_id && i < mdd->GInSpecType()[j].nelem(); i++)
1167  {
1168  if (Workspace::wsv_data[wsvid].Group()
1169  == mdd->GInSpecType()[j][i])
1170  {
1171  wrong_group_id = false;
1172  supergeneric_index = i;
1173  }
1174  }
1175 
1176  if (wrong_group_id)
1177  {
1178  ostringstream os;
1179  bool firsttype = true;
1180  for (Index i = 0; i < mdd->GInSpecType()[j].nelem(); i++)
1181  {
1182  if (!firsttype) os << ", "; else firsttype = false;
1183  os << wsv_group_names[mdd->GInSpecType()[j][i]];
1184  }
1185 
1186  throw WrongWsvGroup( "*" + mdd->Name()+"* is not defined for "
1187  +wsv_group_names[Workspace::wsv_data[wsvid].Group()]
1188  +" input. Check the online docs.",
1189  msource.File(),
1190  msource.Line(),
1191  msource.Column() );
1192  }
1193  }
1194  else
1195  {
1196  if (Workspace::wsv_data[wsvid].Group()
1197  != mdd->GInSpecType()[j][supergeneric_index])
1198  {
1199  throw WrongWsvGroup( wsvname+" is not "+
1200  wsv_group_names[mdd->GInSpecType()[j][supergeneric_index]]
1201  +", it is "+
1202  wsv_group_names[Workspace::wsv_data[wsvid].Group()],
1203  msource.File(),
1204  msource.Line(),
1205  msource.Column());
1206  }
1207  }
1208  }
1209  else if (Workspace::wsv_data[wsvid].Group() != mdd->GInType()[j])
1210  {
1211  throw WrongWsvGroup( wsvname+" is not "+
1212  wsv_group_names[mdd->GInType()[j]]+", it is "+
1213  wsv_group_names[Workspace::wsv_data[wsvid].Group()],
1214  msource.File(),
1215  msource.Line(),
1216  msource.Column() );
1217  }
1218 
1219  // Add this one to the list of input variables:
1220  input.push_back(wsvid);
1221 
1222  eat_whitespace();
1223  }
1224 
1225 }
1226 
1227 
1243  Index& id,
1244  String& methodname,
1245  ArrayOfIndex& output,
1246  bool& first,
1247  bool& still_supergeneric,
1248  String& supergeneric_args,
1249  Index& supergeneric_index,
1250  NamedArguments& named_args,
1251  bool call_by_name)
1252 {
1253  String wsvname;
1254  Index wsvid;
1256  using global_data::md_data;
1257  using global_data::MdMap;
1258 
1259  // Parse all generic output variables
1260  for ( Index j=0 ; j<mdd->GOut().nelem() ; ++j )
1261  {
1262  if (call_by_name)
1263  {
1264  Index this_arg_index;
1265 
1266  get_argument_index_by_name(this_arg_index, named_args, mdd->GOut()[j]);
1267 
1268  if (this_arg_index == -1)
1269  {
1270  ostringstream os;
1271  os << "This method has generic output. "
1272  << "You have to pass a variable!";
1273  throw ParseError(os.str(),
1274  msource.File(),
1275  msource.Line(),
1276  msource.Column() );
1277  }
1278 
1279  msource.SetPosition(named_args[this_arg_index].line,
1280  named_args[this_arg_index].column);
1281  named_args.erase(named_args.begin()+this_arg_index);
1282  }
1283  else
1284  {
1285  if (first)
1286  first = false;
1287  else
1288  {
1289  assertain_character(',');
1290  eat_whitespace();
1291  }
1292  }
1293 
1294  read_name(wsvname);
1295  if (call_by_name) at_end_of_argument("generic output argument");
1296 
1297  {
1298  wsvid = -1;
1299  // Find Wsv id:
1300  map<String, Index>::const_iterator wsvit =
1301  Workspace::WsvMap.find(wsvname);
1302  if ( wsvit == Workspace::WsvMap.end() )
1303  {
1304  if (still_supergeneric)
1305  {
1306  ostringstream os;
1307  os << "This might be either a typo or you have to create "
1308  << "the variable\nby calling TYPECreate(" << wsvname
1309  << ") first. Replace TYPE with the\n"
1310  << "WSV group your variable should belong to.";
1311 
1312  throw UnknownWsv(os.str(),
1313  msource.File(),
1314  msource.Line(),
1315  msource.Column());
1316  }
1317  else
1318  {
1319  if (mdd->Name().length() <= 6
1320  || mdd->Name().substr(mdd->Name().length() - 6) != "Create")
1321  {
1322  ostringstream os;
1323  os << "This might be either a typo or you have to create "
1324  << "the variable\nby calling "
1325  << wsv_group_names[mdd->GOutType()[j]]
1326  << "Create( " << wsvname
1327  << " ) first.\n";
1328 
1329  throw UnknownWsv(os.str(),
1330  msource.File(),
1331  msource.Line(),
1332  msource.Column());
1333  }
1334  else
1335  {
1336  wsvid = Workspace::add_wsv(WsvRecord(wsvname.c_str(),
1337  "Automatically allocated variable.",
1338  mdd->GOutType()[j],
1339  true));
1340  }
1341  }
1342  }
1343 
1344  if (wsvid == -1)
1345  {
1346  if (mdd->Name().length() > 6 &&
1347  mdd->Name().find ("Create") == mdd->Name().length() - 6)
1348  {
1349  ostringstream os;
1350  os << wsvname << " already exists. A variable can only be created once.\n";
1351  throw WsvAlreadyExists(os.str(),
1352  msource.File(),
1353  msource.Line(),
1354  msource.Column());
1355  }
1356  wsvid = wsvit->second;
1357  }
1358  }
1359 
1360  // If this is a supergeneric method, now is the time to find
1361  // out the actual group of the argument(s)!
1362  // If the method also has supergeneric input arguments, we'll
1363  // look for a match later again.
1364  if ( still_supergeneric )
1365  {
1366  ostringstream os;
1367  if (wsv_group_names[mdd->GOutType()[j]] == "Any")
1368  supergeneric_args +=
1369  wsv_group_names[Workspace::wsv_data[wsvid].Group()];
1370  os << mdd->Name() << "_sg_" << supergeneric_args;
1371  methodname = os.str();
1372 
1373  // Find explicit method id in MdMap:
1374  const map<String, Index>::const_iterator mdit = MdMap.find(methodname);
1375  if (mdit != MdMap.end() )
1376  {
1377  id = mdit->second;
1378 
1379  mdd = &md_data[id];
1380 
1381  still_supergeneric = false;
1382  }
1383  }
1384 
1385  // Now we have explicitly the method record for the right
1386  // group. From now on no special treatment of supergeneric
1387  // methods should be necessary.
1388 
1389  // Check that this Wsv belongs to the correct group:
1390  if (mdd->GOutType()[j] == get_wsv_group_id ("Any")
1391  && mdd->GOutSpecType()[j].nelem() )
1392  {
1393  if (supergeneric_index == -1)
1394  {
1395  bool wrong_group_id = true;
1396  for (Index i = 0; wrong_group_id && i < mdd->GOutSpecType()[j].nelem(); i++)
1397  {
1398  if (Workspace::wsv_data[wsvid].Group()
1399  == mdd->GOutSpecType()[j][i])
1400  {
1401  wrong_group_id = false;
1402  supergeneric_index = i;
1403  }
1404  }
1405 
1406  if (wrong_group_id)
1407  {
1408  ostringstream os;
1409  bool firsttype = true;
1410  for (Index i = 0; i < mdd->GOutSpecType()[j].nelem(); i++)
1411  {
1412  if (!firsttype) os << ", "; else firsttype = false;
1413  os << wsv_group_names[mdd->GOutSpecType()[j][i]];
1414  }
1415 
1416  throw WrongWsvGroup("*" + mdd->Name() + "* is not defined for "
1417  +wsv_group_names[Workspace::wsv_data[wsvid].Group()]
1418  +" output. Check the online docs.",
1419  msource.File(),
1420  msource.Line(),
1421  msource.Column());
1422  }
1423  }
1424  else
1425  {
1426  if (Workspace::wsv_data[wsvid].Group()
1427  != mdd->GOutSpecType()[j][supergeneric_index])
1428  {
1429  throw WrongWsvGroup(wsvname + " is not "
1430  + wsv_group_names[mdd->GOutSpecType()[j][supergeneric_index]]
1431  + ", it is "
1432  + wsv_group_names[Workspace::wsv_data[wsvid].Group()],
1433  msource.File(),
1434  msource.Line(),
1435  msource.Column());
1436  }
1437  }
1438  }
1439  else if ( Workspace::wsv_data[wsvid].Group() != mdd->GOutType()[j] )
1440  {
1441  throw WrongWsvGroup(wsvname + " is not "
1442  + wsv_group_names[mdd->GOutType()[j]]
1443  + ", it is "
1444  + wsv_group_names[Workspace::wsv_data[wsvid].Group()],
1445  msource.File(),
1446  msource.Line(),
1447  msource.Column());
1448  }
1449 
1450  // Add this one to the list of output workspace variables:
1451  output.push_back(wsvid);
1452 
1453  eat_whitespace();
1454  }
1455 }
1456 
1457 
1471  ArrayOfIndex& input,
1472  ArrayOfIndex& auto_vars,
1473  Array<TokVal>& auto_vars_values,
1474  bool& first,
1475  NamedArguments& named_args,
1476  bool call_by_name)
1477 {
1479 
1480  // There are two lists of arguments that we have to read.
1481  ArrayOfIndex vo=mdd->Out(); // Output
1482  const ArrayOfIndex &vi = mdd->InOnly(); // Input
1483 
1484  Index wsvid; // Workspace variable id, is used to
1485  // access data in wsv_data.
1486 
1487  for (ArrayOfIndex::const_iterator ins=vi.begin(); ins<vi.end(); ++ins)
1488  {
1489  String wsvname;
1490 
1491  if (call_by_name)
1492  {
1493  Index this_arg_index;
1494 
1495  wsvname = Workspace::wsv_data[*ins].Name();
1496 
1497  get_argument_index_by_name(this_arg_index, named_args, wsvname);
1498 
1499  if (this_arg_index != -1)
1500  {
1501  msource.SetPosition(named_args[this_arg_index].line,
1502  named_args[this_arg_index].column);
1503  named_args.erase(named_args.begin()+this_arg_index);
1504 
1505  read_name_or_value(wsvname, auto_vars, auto_vars_values,
1506  Workspace::wsv_data[*ins].Name(),
1507  mdd, Workspace::wsv_data[*ins].Group());
1508  at_end_of_argument("specific input argument");
1509  }
1510  }
1511  else
1512  {
1513  if (first)
1514  first = false;
1515  else
1516  {
1517  try
1518  {
1519  assertain_character(',');
1520  }
1521  catch (UnexpectedChar)
1522  {
1523  ostringstream os;
1524  os << "Expected input WSV *" << Workspace::wsv_data[*ins].Name() << "*";
1525  }
1526  eat_whitespace();
1527  }
1528 
1529  read_name_or_value(wsvname, auto_vars, auto_vars_values,
1530  Workspace::wsv_data[*ins].Name(),
1531  mdd, Workspace::wsv_data[*ins].Group());
1532 
1533  }
1534 
1535  {
1536  // Find Wsv id:
1537  const map<String, Index>::const_iterator wsvit =
1538  Workspace::WsvMap.find(wsvname);
1539  if ( wsvit == Workspace::WsvMap.end() )
1540  throw UnknownWsv(wsvname,
1541  msource.File(),
1542  msource.Line(),
1543  msource.Column());
1544 
1545  wsvid = wsvit->second;
1546  }
1547 
1548  // Check that this Wsv belongs to the correct group:
1549  if ( Workspace::wsv_data[wsvid].Group() != Workspace::wsv_data[*ins].Group() )
1550  {
1551  throw WrongWsvGroup(wsvname+" is not "+
1552  wsv_group_names[Workspace::wsv_data[*ins].Group()]+", it is "+
1553  wsv_group_names[Workspace::wsv_data[wsvid].Group()],
1554  msource.File(),
1555  msource.Line(),
1556  msource.Column());
1557  }
1558 
1559  input.push_back(wsvid);
1560  }
1561 
1562  eat_whitespace();
1563 }
1564 
1565 
1577  ArrayOfIndex& output,
1578  bool& first,
1579  NamedArguments& named_args,
1580  bool call_by_name)
1581 {
1583 
1584  ArrayOfIndex vo=mdd->Out();
1585 
1586  Index wsvid; // Workspace variable id, is used to
1587  // access data in wsv_data.
1588 
1589  for (ArrayOfIndex::const_iterator outs=vo.begin(); outs<vo.end(); ++outs)
1590  {
1591  String wsvname;
1592 
1593  if (call_by_name)
1594  {
1595  Index this_arg_index=0;
1596 
1597  wsvname = Workspace::wsv_data[*outs].Name();
1598 
1599  get_argument_index_by_name(this_arg_index, named_args,
1600  wsvname);
1601 
1602  if (this_arg_index != -1)
1603  {
1604  msource.SetPosition(named_args[this_arg_index].line,
1605  named_args[this_arg_index].column);
1606  named_args.erase(named_args.begin()+this_arg_index);
1607 
1608  read_name(wsvname);
1609  at_end_of_argument("specific output argument");
1610  }
1611  }
1612  else
1613  {
1614  if (first)
1615  first = false;
1616  else
1617  {
1618  try
1619  {
1620  assertain_character(',');
1621  }
1622  catch (UnexpectedChar)
1623  {
1624  ostringstream os;
1625  os << "Expected output WSV *" << Workspace::wsv_data[*outs].Name() << "*";
1626  throw ParseError(os.str(),
1627  msource.File(),
1628  msource.Line(),
1629  msource.Column());
1630  }
1631  eat_whitespace();
1632  }
1633 
1634  read_name(wsvname);
1635  }
1636 
1637  {
1638  wsvid = -1;
1639  // Find Wsv id:
1640  map<String, Index>::const_iterator wsvit =
1641  Workspace::WsvMap.find(wsvname);
1642  if ( wsvit == Workspace::WsvMap.end() )
1643  {
1644  if (mdd->Name().length() > 6
1645  && mdd->Name().substr (mdd->Name().length() - 6)
1646  != "Create")
1647  {
1648  ostringstream os;
1649  os << "This might be either a typo or you have to create "
1650  << "the variable\nby calling "
1651  << wsv_group_names[Workspace::wsv_data[*outs].Group()]
1652  << "Create( " << wsvname
1653  << " ) first.\n";
1654 
1655  throw UnknownWsv(os.str(),
1656  msource.File(),
1657  msource.Line(),
1658  msource.Column());
1659  }
1660  else
1661  {
1662  wsvid = Workspace::add_wsv(WsvRecord(wsvname.c_str(),
1663  "Automatically allocated variable.",
1664  Workspace::wsv_data[*outs].Group(),
1665  true));
1666  }
1667  }
1668 
1669  if (wsvid == -1)
1670  wsvid = wsvit->second;
1671  }
1672 
1673  // Check that this Wsv belongs to the correct group:
1674  if ( Workspace::wsv_data[wsvid].Group() != Workspace::wsv_data[*outs].Group() )
1675  {
1676  throw WrongWsvGroup(wsvname+" is not "
1677  + wsv_group_names[Workspace::wsv_data[*outs].Group()]
1678  + ", it is "
1679  + wsv_group_names[Workspace::wsv_data[wsvid].Group()],
1680  msource.File(),
1681  msource.Line(),
1682  msource.Column());
1683  }
1684 
1685  output.push_back(wsvid);
1686  }
1687 
1688  eat_whitespace();
1689 }
1690 
1691 
1706  const Array<TokVal>& auto_vars_values,
1707  const Index method_type,
1708  Agenda& tasklist)
1709 {
1710  using global_data::MdMap;
1712 
1713  for (Index i=0; i<auto_vars.nelem(); i++)
1714  {
1715  map<String, Index>::const_iterator mdit;
1716  Index init_mdid;
1717  TokVal auto_keyword_value;
1718  ArrayOfIndex auto_output_var;
1719  ArrayOfIndex auto_input_var;
1720  Agenda auto_tasks;
1721 
1722  const Index auto_group = Workspace::wsv_data[auto_vars[i]].Group();
1723  if (auto_group != get_wsv_group_id("Index")
1724  && auto_group != get_wsv_group_id("Numeric")
1725  && auto_group != get_wsv_group_id("ArrayOfIndex")
1726  && auto_group != get_wsv_group_id("ArrayOfString")
1727  && auto_group != get_wsv_group_id("String")
1728  && auto_group != get_wsv_group_id("Vector")
1729  && auto_group != get_wsv_group_id("Matrix"))
1730  {
1731  ostringstream os;
1732  os << "Passing a "
1733  << wsv_group_names[Workspace::wsv_data[auto_vars[i]].Group()]
1734  << " constant to a WSM is not supported!";
1735  throw ParseError (os.str(),
1736  msource.File(),
1737  msource.Line(),
1738  msource.Column());
1739  }
1740 
1741  String method_name;
1742  switch (method_type)
1743  {
1744  case 0:
1745  auto_keyword_value = auto_vars_values[i];
1746  auto_output_var.push_back(auto_vars[i]);
1747  method_name = wsv_group_names[Workspace::wsv_data[auto_vars[i]].Group()] + "Set";
1748  break;
1749  case 1:
1750  auto_input_var.push_back(auto_vars[i]);
1751  method_name = "Delete_sg_" + wsv_group_names[Workspace::wsv_data[auto_vars[i]].Group()];
1752  break;
1753  default:
1754  throw runtime_error("Invalid method_type");
1755  }
1756 
1757  mdit = MdMap.find(method_name);
1758  assert ( mdit != MdMap.end() );
1759  init_mdid = mdit->second;
1760 
1761  tasklist.push_back(MRecord(init_mdid,
1762  auto_output_var, auto_input_var,
1763  auto_keyword_value,
1764  auto_tasks, true));
1765  }
1766 }
1767 
1768 
1779 bool ArtsParser::is_whitespace(const char c)
1780 {
1781  switch (c)
1782  {
1783  case ' ':
1784  case '\r':
1785  case '\t':
1786  case '#':
1787  return true;
1788  break;
1789  }
1790 
1791  return false;
1792 }
1793 
1794 
1805 {
1806  char dummy;
1807 
1808  while (is_whitespace(dummy=msource.Current()))
1809  {
1810  switch (dummy)
1811  {
1812  case ' ':
1813  case '\r':
1814  case '\t':
1815  msource.AdvanceChar();
1816  break;
1817  case '#':
1818  msource.AdvanceLine();
1819  break;
1820  default:
1821  {
1822  ostringstream os;
1823  os << "Expected whitespace, but got `" << dummy << "'.";
1824  throw UnexpectedChar(os.str(),
1825  msource.File(),
1826  msource.Line(),
1827  msource.Column());
1828  break;
1829  }
1830  }
1831  }
1832 }
1833 
1834 
1841 {
1842  while (pos < str.length() && is_whitespace(str[pos]))
1843  pos++;
1844 }
1845 
1846 
1859 {
1860  bool stop = false;
1861  name = "";
1862 
1863  if (!isalpha(msource.Current()))
1864  {
1865  ostringstream os;
1866  os << "Workspace variable names must start with a letter!";
1867  throw ParseError(os.str(),
1868  msource.File(),
1869  msource.Line(),
1870  msource.Column());
1871  }
1872 
1873  while (!stop)
1874  {
1875  char dummy = msource.Current();
1876 
1877  if ( isalnum(dummy) || '_'==dummy )
1878  {
1879  name += dummy;
1880  // AdvanceChar sets LineBreak if a line break occured.
1881  msource.LineBreak() = false;
1882  msource.AdvanceChar();
1883  if ( msource.LineBreak() ) stop = true;
1884  }
1885  else
1886  {
1887  stop = true;
1888  }
1889  }
1890 }
1891 
1892 
1913  ArrayOfIndex& auto_vars,
1914  Array<TokVal>& auto_vars_values,
1915  const String& default_name,
1916  const MdRecord* mdd,
1917  const Index group)
1918 {
1919  name = "";
1920 
1921  if (isalpha(msource.Current()))
1922  {
1923  read_name(name);
1924  return -1;
1925  }
1926 
1927  if (group == get_wsv_group_id ("Any"))
1928  {
1929  ostringstream os;
1930  os << "Passing constants as supergeneric arguments is not supported.";
1931  throw ParseError (os.str (),
1932  msource.File(),
1933  msource.Line(),
1934  msource.Column());
1935  }
1936 
1937  // If a value was given instead of a variable name, we create
1938  // a new variable in the workspace and fill it with the given
1939  // value
1940 
1941  Index wsvid;
1942 
1943  name = "auto_" + mdd->Name() + "_" + default_name;
1944  map<String, Index>::const_iterator wsvit = Workspace::WsvMap.find(name);
1945  if (wsvit == Workspace::WsvMap.end())
1946  {
1947  wsvid = Workspace::add_wsv(WsvRecord(name.c_str(),
1948  "Automatically allocated variable.",
1949  group,
1950  true));
1951  }
1952  else
1953  {
1954  wsvid = wsvit->second;
1955  }
1956 
1957  auto_vars.push_back(wsvid);
1958 
1959  // Now parse the value. This can be:
1960  // String_, Index_, Numeric_, Array_String_, Array_Index_, Vector_, Matrix_
1961  if (group == get_wsv_group_id("String"))
1962  {
1963  String dummy;
1964  parse_String(dummy);
1965  auto_vars_values.push_back(dummy);
1966  }
1967  else if (group == get_wsv_group_id("Index"))
1968  {
1969  Index n;
1970  parse_integer(n);
1971  auto_vars_values.push_back(n);
1972  }
1973  else if (group == get_wsv_group_id("Numeric"))
1974  {
1975  Numeric n;
1976  parse_numeric(n);
1977  auto_vars_values.push_back(n);
1978  }
1979  else if (group == get_wsv_group_id("ArrayOfString"))
1980  {
1981  ArrayOfString dummy;
1982  parse_Stringvector(dummy);
1983  auto_vars_values.push_back(dummy);
1984  }
1985  else if (group == get_wsv_group_id("ArrayOfIndex"))
1986  {
1987  ArrayOfIndex dummy;
1988  parse_intvector(dummy);
1989  auto_vars_values.push_back(dummy);
1990  }
1991  else if (group == get_wsv_group_id("Vector"))
1992  {
1993  Vector dummy;
1994  parse_numvector(dummy);
1995  auto_vars_values.push_back(dummy);
1996  }
1997  else if (group == get_wsv_group_id("Matrix"))
1998  {
1999  Matrix dummy;
2000  parse_matrix(dummy);
2001  auto_vars_values.push_back(dummy);
2002  }
2003  else
2004  {
2006  ostringstream os;
2007  os << "Unsupported argument type: " << wsv_group_names[group];
2008  throw ParseError (os.str(),
2009  msource.File(),
2010  msource.Line(),
2011  msource.Column());
2012  }
2013 
2014  return wsvid;
2015 }
2016 
2017 
2025 {
2026  if ( c != msource.Current() )
2027  {
2028  ostringstream os;
2029  os << "Expected '" << c << "', but got '" << msource.Current() << "'.";
2030  throw UnexpectedChar( os.str(),
2031  msource.File(),
2032  msource.Line(),
2033  msource.Column() );
2034  }
2035 
2036  msource.AdvanceChar();
2037 }
2038 
2039 
2051 {
2052  bool stop = false;
2053  res = "";
2054 
2055  msource.LineBreak() = false;
2056  assertain_character('"');
2057  if ( msource.LineBreak() )
2058  throw IllegalLinebreak("Line break before end of String.",
2059  msource.File(),
2060  msource.Line(),
2061  msource.Column());
2062 
2063  while (!stop)
2064  {
2065  char dummy = msource.Current();
2066  if ( dummy != '"' )
2067  {
2068  res += dummy;
2069  msource.AdvanceChar();
2070 
2071  if ( msource.LineBreak() )
2072  throw IllegalLinebreak("Line break before end of String.",
2073  msource.File(),
2074  msource.Line(),
2075  msource.Column());
2076  }
2077  else
2078  {
2079  stop = true;
2080  msource.AdvanceChar();
2081  }
2082  }
2083 }
2084 
2085 
2099 {
2100  bool stop = false;
2101  res = "";
2102  char dummy;
2103  msource.LineBreak() = false;
2104 
2105  dummy = msource.Current();
2106  if ( '+' == dummy || '-' == dummy )
2107  {
2108  res += dummy;
2109  msource.AdvanceChar();
2110  if ( msource.LineBreak() )
2111  throw IllegalLinebreak( "Line break after sign.",
2112  msource.File(),
2113  msource.Line(),
2114  msource.Column() );
2115  }
2116 
2117  if (!isdigit(msource.Current()))
2118  {
2119  ostringstream os;
2120  os << "Expected digit or variable name, but got `" << msource.Current()
2121  << "'.";
2122  throw UnexpectedChar(os.str(),
2123  msource.File(),
2124  msource.Line(),
2125  msource.Column());
2126  }
2127 
2128  while (!stop)
2129  {
2130  char chtmp = msource.Current();
2131  if ( isdigit(chtmp) )
2132  {
2133  res += chtmp;
2134  msource.AdvanceChar();
2135  if ( msource.LineBreak() ) stop = true;
2136  }
2137  else
2138  {
2139  stop = true;
2140  }
2141  }
2142 }
2143 
2144 
2161 {
2162  bool stop;
2163  res = "";
2164  char dummy;
2165  msource.LineBreak() = false;
2166 
2167  // To make sure that there is at least one digit:
2168  bool found_digit = false;
2169 
2170  // Check if there is a sign:
2171  dummy = msource.Current();
2172  if ( '+' == dummy || '-' == dummy )
2173  {
2174  res += dummy;
2175  msource.AdvanceChar();
2176  if ( msource.LineBreak() )
2177  throw IllegalLinebreak("Linebreak after sign.",
2178  msource.File(),
2179  msource.Line(),
2180  msource.Column());
2181  }
2182 
2183  // There could be some digits here:
2184  stop = false;
2185  while (!stop)
2186  {
2187  char chtmp = msource.Current();
2188  if ( isdigit(chtmp) )
2189  {
2190  found_digit = true;
2191  res += chtmp;
2192  msource.AdvanceChar();
2193  if ( msource.LineBreak() ) return; // Line break ends scanning immediately.
2194  }
2195  else
2196  {
2197  stop = true;
2198  }
2199  }
2200 
2201  // Next there can be a decimal point
2202  if ( '.' == msource.Current() )
2203  {
2204  res += ".";
2205  msource.AdvanceChar();
2206  if ( msource.LineBreak() )
2207  {
2208  if (found_digit)
2209  {
2210  // Line break ends scanning immediately, if we have
2211  // already found at least one digit.
2212  return;
2213  }
2214  else
2215  {
2216  throw IllegalLinebreak("Expected at least one digit.",
2217  msource.File(),
2218  msource.Line(),
2219  msource.Column());
2220  }
2221  }
2222 
2223  // ... followed by optional more digits
2224  stop = false;
2225  while (!stop)
2226  {
2227  char chtmp = msource.Current();
2228  if ( isdigit(chtmp) )
2229  {
2230  found_digit = true;
2231  res += chtmp;
2232  msource.AdvanceChar();
2233  if ( msource.LineBreak() ) return; // Line break ends scanning immediately.
2234  }
2235  else
2236  {
2237  stop = true;
2238  }
2239  }
2240  }
2241 
2242  // At this point, we must have found at least one digit.
2243  if (!found_digit)
2244  throw ParseError("Expected at least one digit.",
2245  msource.File(),
2246  msource.Line(),
2247  msource.Column());
2248 
2249  // Now there could be a `e' or `E':
2250  dummy = msource.Current();
2251  if ( 'e' == dummy || 'E' == dummy )
2252  {
2253  res += dummy;
2254  msource.AdvanceChar();
2255  if ( msource.LineBreak() )
2256  throw IllegalLinebreak( "Linebreak after e/E.",
2257  msource.File(),
2258  msource.Line(),
2259  msource.Column() );
2260 
2261  // Now there must be an integer (with optional sign)
2262  {
2263  String s;
2264  read_integer(s);
2265  res += s;
2266  }
2267  }
2268 }
2269 
2270 
2276 {
2277  String res;
2278  read_integer(res);
2279  istringstream is(res);
2280  is >> n;
2281 }
2282 
2283 
2289 {
2290  String res;
2291  read_numeric(res);
2292  istringstream is(res);
2293  is >> n;
2294 }
2295 
2296 
2312 {
2313  bool first = true; // To skip the first comma.
2314  res.resize(0); // Clear the result vector (just in case).
2315 
2316  // Make sure that the current character really is `[' and proceed.
2317  assertain_character('[');
2318  // There might have occured a linebreak, which is fine.
2319 
2320  eat_whitespace();
2321 
2322  // Read the elements of the vector (`]' means that we have
2323  // reached the end):
2324  while ( ']' != msource.Current() )
2325  {
2326  String dummy;
2327 
2328  if (first)
2329  first = false;
2330  else
2331  {
2332  assertain_character(',');
2333  eat_whitespace();
2334  }
2335 
2336  parse_String(dummy);
2337  res.push_back(dummy);
2338  eat_whitespace();
2339  }
2340 
2341  msource.AdvanceChar();
2342 }
2343 
2344 
2357 {
2358  bool first = true; // To skip the first comma.
2359  res.resize(0); // Clear the result vector (just in case).
2360 
2361  // Make sure that the current character really is `[' and proceed.
2362  assertain_character('[');
2363  // There might have occured a linebreak, which is fine.
2364 
2365  eat_whitespace();
2366 
2367  // Read the elements of the vector (`]' means that we have
2368  // reached the end):
2369  while ( ']' != msource.Current() )
2370  {
2371  Index dummy;
2372 
2373  if (first)
2374  first = false;
2375  else
2376  {
2377  assertain_character(',');
2378  eat_whitespace();
2379  }
2380 
2381  parse_integer(dummy);
2382  res.push_back(dummy);
2383  eat_whitespace();
2384  }
2385 
2386  msource.AdvanceChar();
2387 }
2388 
2389 
2402 {
2403  bool first = true; // To skip the first comma.
2404 
2405  // We need a temporary Array<Numeric>, so that we can use push_back
2406  // to store the values. FIXME: Need also constructor for Vector from
2407  // Array<Numeric>.
2408  Array<Numeric> tres;
2409 
2410  // Make sure that the current character really is `[' and proceed.
2411  assertain_character('[');
2412  // There might have occured a linebreak, which is fine.
2413 
2414  eat_whitespace();
2415 
2416  // Read the elements of the vector (`]' means that we have
2417  // reached the end):
2418  while ( ']' != msource.Current() )
2419  {
2420  Numeric dummy;
2421 
2422  if (first)
2423  first = false;
2424  else
2425  {
2426  assertain_character(',');
2427  eat_whitespace();
2428  }
2429 
2430  parse_numeric(dummy);
2431  tres.push_back(dummy);
2432  eat_whitespace();
2433  }
2434 
2435  // Copy tres to res:
2436  res.resize(tres.nelem());
2437  for (int i = 0; i < tres.nelem (); i++)
2438  {
2439  res[i] = tres[i];
2440  }
2441 
2442  msource.AdvanceChar();
2443 }
2444 
2445 
2458 {
2459  bool first = true; // To skip the first comma.
2460 
2461  // We need a temporary Array<Numeric>, so that we can use push_back
2462  // to store the values. FIXME: Need also constructor for Vector from
2463  // Array<Numeric>.
2464  Array<Numeric> tres;
2465 
2466  // Make sure that the current character really is `[' and proceed.
2467  assertain_character('[');
2468  // There might have occured a linebreak, which is fine.
2469 
2470  eat_whitespace();
2471 
2472  Index ncols = -1;
2473  Index cur_ncols = 1;
2474  // Read the elements of the vector (`]' means that we have
2475  // reached the end):
2476  while ( ']' != msource.Current() )
2477  {
2478  Numeric dummy;
2479 
2480  if (first)
2481  first = false;
2482  else
2483  {
2484  if (',' == msource.Current())
2485  {
2486  cur_ncols++;
2487  if (ncols != -1 && cur_ncols > ncols)
2488  {
2489  ostringstream os;
2490  os << "Expected ';', but got '" << msource.Current() << "'. Check Matrix dimensions.";
2491  throw UnexpectedChar(os.str(),
2492  msource.File(),
2493  msource.Line(),
2494  msource.Column());
2495  }
2496  msource.AdvanceChar();
2497  eat_whitespace();
2498  }
2499  else if (';' == msource.Current())
2500  {
2501  if (ncols == -1)
2502  {
2503  ncols = cur_ncols;
2504  }
2505  else if (ncols != cur_ncols)
2506  {
2507  ostringstream os;
2508  os << "Expected ',', but got '" << msource.Current() << "'. Check Matrix dimensions.";
2509  throw UnexpectedChar(os.str(),
2510  msource.File(),
2511  msource.Line(),
2512  msource.Column());
2513  }
2514  cur_ncols = 1;
2515  msource.AdvanceChar();
2516  eat_whitespace();
2517  }
2518  else
2519  {
2520  char c = ';';
2521  if (ncols > cur_ncols)
2522  c = ',';
2523  ostringstream os;
2524  os << "Expected '" << c << "', but got '" << msource.Current() << "'. Check Matrix dimensions.";
2525  throw UnexpectedChar(os.str(),
2526  msource.File(),
2527  msource.Line(),
2528  msource.Column());
2529  }
2530  }
2531 
2532  parse_numeric(dummy);
2533  tres.push_back(dummy);
2534  eat_whitespace();
2535  }
2536 
2537  if (ncols == -1) ncols = cur_ncols;
2538  if (ncols != cur_ncols)
2539  {
2540  throw ParseError("Missing element(s) in last row of matrix",
2541  msource.File(),
2542  msource.Line(),
2543  msource.Column());
2544  }
2545 
2546 
2547  // Copy tres to res:
2548  Index nrows = tres.nelem() / ncols;
2549  res.resize(nrows, ncols);
2550  for (Index i = 0; i < nrows; i++)
2551  for (Index j = 0; j < ncols; j++)
2552  res(i, j) = tres[i*ncols+j];
2553 
2554  msource.AdvanceChar();
2555 }
2556 
2557 
2566 {
2567  bool first = true; // To skip the first comma.
2568  size_t pos = 0;
2569 
2570  // We need a temporary Array<Numeric>, so that we can use push_back
2571  // to store the values.
2572  Array<Numeric> tres;
2573 
2574  eat_whitespace_from_string (str, pos);
2575 
2576  // Make sure that the current character really is `[' and proceed.
2577  if (str[pos] != '[')
2578  {
2579  throw runtime_error ("No opening bracket\n");
2580  }
2581 
2582  pos++;
2583 
2584  eat_whitespace_from_string (str, pos);
2585 
2586  // Read the elements of the vector (`]' means that we have
2587  // reached the end):
2588  while ( pos < str.length() && str[pos] != ']' )
2589  {
2590  if (first)
2591  first = false;
2592  else
2593  {
2594  if (str[pos] != ',')
2595  {
2596  return false;
2597  }
2598  pos++;
2599  eat_whitespace_from_string (str, pos);
2600  }
2601 
2602  Numeric dummy;
2603  istringstream is (str.substr(pos));
2604  is >> dummy;
2605  if (is.bad () || is.fail ())
2606  return false;
2607  tres.push_back(dummy);
2608  while (pos < str.length()
2609  && (isdigit(str[pos]) || str[pos] == '-' || str[pos] == '.'
2610  || str[pos] == 'e'))
2611  pos++;
2612  eat_whitespace_from_string (str, pos);
2613  }
2614 
2615  // Copy tres to res:
2616  res.resize(tres.nelem());
2617  for (int i = 0; i < tres.nelem (); i++)
2618  {
2619  res[i] = tres[i];
2620  }
2621 
2622  return true;
2623 }
2624 
2625 
2635 {
2636  bool first = true; // To skip the first comma.
2637  size_t pos = 0;
2638 
2639  // We need a temporary Array<Numeric>, so that we can use push_back
2640  // to store the values.
2641  ArrayOfString tres;
2642 
2643  eat_whitespace_from_string (str, pos);
2644 
2645  // Make sure that the current character really is `[' and proceed.
2646  if (str[pos] != '[')
2647  {
2648  throw runtime_error ("No opening bracket\n");
2649  }
2650 
2651  pos++;
2652 
2653  eat_whitespace_from_string (str, pos);
2654 
2655  // Read the elements of the vector (`]' means that we have
2656  // reached the end):
2657  while ( pos < str.length() && str[pos] != ']' )
2658  {
2659  if (first)
2660  first = false;
2661  else
2662  {
2663  if (str[pos] != ',')
2664  {
2665  return false;
2666  }
2667  pos++;
2668  eat_whitespace_from_string (str, pos);
2669  }
2670 
2671  if (str[pos] != '"')
2672  {
2673  throw runtime_error ("Expected quotes\n");
2674  }
2675 
2676  pos++;
2677 
2678  String dummy;
2679  while ( pos < str.length() && str[pos] != '"' )
2680  {
2681  dummy += str[pos];
2682  pos++;
2683  }
2684 
2685  if (pos == str.length() || str[pos] != '"')
2686  return false;
2687 
2688  tres.push_back(dummy);
2689 
2690  eat_whitespace_from_string (str, pos);
2691  }
2692 
2693  // Copy tres to res:
2694  res.resize(tres.nelem());
2695  for (int i = 0; i < tres.nelem (); i++)
2696  {
2697  res[i] = tres[i];
2698  }
2699 
2700  return true;
2701 }
2702 
const String & File()
Return the filename associated with the current position.
Definition: sourcetext.cc:88
Index get_wsv_group_id(const String &name)
Returns the id of the given group.
Definition: groups.cc:205
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:35
static Array< WsvRecord > wsv_data
Definition: workspace_ng.h:64
String set_gin_to_default(const MdRecord *mdd, ArrayOfIndex &auto_vars, Array< TokVal > &auto_vars_values, Index keyword_index)
Set generic input to default value.
Definition: parser.cc:667
virtual Index line() const
Definition: exceptions.h:54
bool parse_stringarray_from_string(ArrayOfString &res, String &str)
Read an Array of Strings from a String.
Definition: parser.cc:2634
Parameters parameters
Holds the command line parameters.
Definition: parameters.cc:41
bool find_file(ArrayOfString &matches, const String &filename, const ArrayOfString &paths, const ArrayOfString &extensions)
Searches through paths for a file with a matching name.
Definition: file.cc:402
void at_end_of_argument(const String &argname)
Check if current position in controlfile is at the end of an argument.
Definition: parser.cc:169
Agenda & mtasklist
Definition: parser.h:165
The Agenda class.
Definition: agenda_class.h:44
void find_named_arguments(vector< NamedArgument > &named_args)
Find named arguments.
Definition: parser.cc:62
Index nelem() const
Number of elements.
Definition: array.h:176
virtual String file() const
Definition: exceptions.h:53
bool parse_numvector_from_string(Vector &res, String &str)
Read a vector of Numerics from a String.
Definition: parser.cc:2565
void parse_agenda(Agenda &tasklist)
Parse the Contents of text as ARTS control input.
Definition: parser.cc:374
bool AgendaMethod() const
Definition: methods.h:107
The Vector class.
Definition: matpackI.h:556
void parse_tasklist()
Public interface to the main function of the parser.
Definition: parser.cc:48
Index mcfile_version
Definition: parser.h:171
bool SetMethod() const
Definition: methods.h:106
const ArrayOfIndex & Out() const
Definition: methods.h:92
Index read_name_or_value(String &name, ArrayOfIndex &auto_vars, Array< TokVal > &auto_vars_values, const String &default_name, const MdRecord *mdd, const Index group)
Reads name of a workspace variable or a value.
Definition: parser.cc:1912
void resize(Index n)
Resize the method list.
Definition: agenda_class.h:248
void get_dirname(String &dirname, const String &path)
Return the parent directory of a path.
Definition: file.cc:553
ArtsParser(Agenda &tasklist, String controlfile, const Verbosity &verbosity)
Constructs a new parser.
Definition: parser.cc:37
const map< String, Index > MdRawMap
The map associated with md_data_raw.
Definition: methods_aux.cc:41
This file contains basic functions to handle ASCII files.
Structure to hold all command line Parameters.
Definition: parameters.h:42
All information for one workspace method.
Definition: methods.h:42
bool Supergeneric() const
Definition: methods.h:108
void AdvanceChar()
Advance position pointer by one character.
Definition: sourcetext.cc:32
char Current()
Return the current character.
Definition: sourcetext.h:49
const String & Name() const
Definition: methods.h:89
vector< NamedArgument > NamedArguments
Definition: parser.h:40
ArrayOfString includepath
List of paths to search for include files.
Definition: parameters.h:105
void parse_String(String &res)
Reads a String, complete with quotation marks.
Definition: parser.cc:2050
const map< String, Index > MdMap
The map associated with md_data.
Definition: methods_aux.cc:39
void parse_numvector(Vector &res)
Read a vector of Numerics.
Definition: parser.cc:2401
void parse_integer(Index &n)
Use a String stream to parse an integer number.
Definition: parser.cc:2275
const ArrayOfString & GOut() const
Definition: methods.h:93
This file contains the declaration and partly the implementation of the workspace class...
ArrayOfString datapath
List of paths to search for data files.
Definition: parameters.h:107
void parse_generic_input(const MdRecord *&mdd, Index &id, String &methodname, ArrayOfIndex &input, ArrayOfIndex &auto_vars, Array< TokVal > &auto_vars_values, bool &first, bool &still_supergeneric, String &supergeneric_args, Index &supergeneric_index, NamedArguments &named_args, bool call_by_name)
Parse the generic input WSVs for current method from the controlfile.
Definition: parser.cc:1034
const Array< String > & GInDefault() const
Definition: methods.h:101
void parse_specific_input(const MdRecord *mdd, ArrayOfIndex &input, ArrayOfIndex &auto_vars, Array< TokVal > &auto_vars_values, bool &first, NamedArguments &named_args, bool call_by_name)
Parse the specific input WSVs for current method from the controlfile.
Definition: parser.cc:1470
The global header file for ARTS.
#define NODEF
Definition: methods.h:36
void tasklist_insert_set_delete(const ArrayOfIndex &auto_vars, const Array< TokVal > &auto_vars_values, const Index method_type, Agenda &tasklist)
Insert Set and Delete methods for automatically allocated output WSVs.
Definition: parser.cc:1705
void parse_numeric(Numeric &n)
Use a String stream to parse a floating point number.
Definition: parser.cc:2288
void parse_main()
The main function of the parser.
Definition: parser.cc:207
void skip_to_next_argument()
Skips forward to the next argument.
Definition: parser.cc:99
void AppendFile(const String &name)
Appends contents of file to the source text.
Definition: sourcetext.cc:23
void eat_whitespace_from_string(String &str, size_t &pos)
Eats whitespace from a String.
Definition: parser.cc:1840
The declarations of all the exception classes.
Method runtime data.
Definition: agenda_class.h:113
void eat_whitespace()
Eats whitespace.
Definition: parser.cc:1804
Definition: exceptions.h:67
const ArrayOfArrayOfIndex & GInSpecType() const
Definition: methods.h:100
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:29
The Matrix class.
Definition: matpackI.h:788
Index nelem() const
Number of elements.
Definition: mystring.h:278
void read_integer(String &res)
Reads an integer.
Definition: parser.cc:2098
void Init()
This sets the pointer to the first existing character in the text.
Definition: sourcetext.cc:118
void SetPosition(Index line, Index column)
Set current position.
Definition: sourcetext.h:90
String mcfile
Definition: parser.h:167
Index nelem() const
Return the number of agenda elements.
Definition: agenda_class.h:260
bool & LineBreak()
Read the line break flag.
Definition: sourcetext.h:102
void assertain_character(char c)
Make sure that the current character is equal to c and go to the next character.
Definition: parser.cc:2024
void parse_intvector(ArrayOfIndex &res)
Read a vector of integers.
Definition: parser.cc:2356
const ArrayOfIndex & InOnly() const
Definition: methods.h:103
void read_name(String &name)
Reads name of method, keyword, or workspace variable.
Definition: parser.cc:1858
const ArrayOfIndex & GOutType() const
Definition: methods.h:94
Index ColumnRaw()
Return the column index.
Definition: sourcetext.h:84
const ArrayOfString wsv_group_names
The names associated with Wsv groups as Strings.
Definition: global_data.h:94
SourceText msource
Definition: parser.h:169
void parse_method(Index &id, ArrayOfIndex &output, ArrayOfIndex &input, Agenda &tasks, ArrayOfIndex &auto_vars, Array< TokVal > &auto_vars_values, String &include_file, bool no_eot=false)
Parse the Contents of text as ARTS control input.
Definition: parser.cc:546
void parse_generic_output(const MdRecord *&mdd, Index &id, String &methodname, ArrayOfIndex &output, bool &first, bool &still_supergeneric, String &supergeneric_args, Index &supergeneric_index, NamedArguments &named_args, bool call_by_name)
Parse the generic output WSVs for current method from the controlfile.
Definition: parser.cc:1242
static map< String, Index > WsvMap
Definition: workspace_ng.h:67
void resize(Index n)
Assignment operator from VectorView.
Definition: matpackI.cc:798
static Index add_wsv(const WsvRecord &wsv)
Definition: workspace_ng.cc:62
const Array< MRecord > & Methods() const
Definition: agenda_class.h:70
bool is_whitespace(const char c)
Returns true if this character is considered whitespace.
Definition: parser.cc:1779
const Verbosity & verbosity
Definition: parser.h:173
void parse_matrix(Matrix &res)
Read a Matrix.
Definition: parser.cc:2457
void get_argument_index_by_name(Index &arg_index, NamedArguments &named_args, String name)
Return the index of the argument with the given name.
Definition: parser.cc:188
virtual Index column() const
Definition: exceptions.h:55
#define _U_
Definition: config.h:167
bool reachedEot()
Check if the current position reached the end.
Definition: sourcetext.h:57
const ArrayOfArrayOfIndex & GOutSpecType() const
Definition: methods.h:95
const Array< MdRecord > md_data
Lookup information for workspace methods.
Definition: methods_aux.cc:48
#define CREATE_OUT0
Definition: messages.h:211
#define CREATE_OUT3
Definition: messages.h:214
const ArrayOfIndex & GInType() const
Definition: methods.h:99
Index LineRaw()
Return the line index.
Definition: sourcetext.h:81
This class contains all static information for one workspace variable.
Definition: wsv_aux.h:54
This file contains header information for the dealing with command line parameters.
void AdvanceLine()
Advances position pointer by one line.
Definition: sourcetext.cc:66
Index Column()
Return the current column.
Definition: sourcetext.h:87
void parse_Stringvector(ArrayOfString &res)
Read a vector of Strings.
Definition: parser.cc:2311
#define CREATE_OUT2
Definition: messages.h:213
void parse_method_args(const MdRecord *&mdd, Index &id, String &methodname, ArrayOfIndex &output, ArrayOfIndex &input, ArrayOfIndex &auto_vars, Array< TokVal > &auto_vars_values)
Parse method&#39;s argument list.
Definition: parser.cc:810
This stores arbitrary token values and remembers the type.
Definition: token.h:33
Index Line()
Return the line number, but for the file that is associated with the current position.
Definition: sourcetext.cc:103
void parse_specific_output(const MdRecord *mdd, ArrayOfIndex &output, bool &first, NamedArguments &named_args, bool call_by_name)
Parse the output WSVs for current method from the controlfile.
Definition: parser.cc:1576
void read_numeric(String &res)
Reads a floating point number.
Definition: parser.cc:2160
Declaration of the class MdRecord.
const ArrayOfString & GIn() const
Definition: methods.h:98
const Array< MdRecord > md_data_raw
Lookup information for workspace methods.
Definition: methods.cc:39
void resize(Index r, Index c)
Resize function.
Definition: matpackI.cc:1580
Auxiliary header stuff related to workspace variable groups.
void push_back(const MRecord &n)
Append a new method to end of list.
Definition: agenda_class.h:272