ARTS  2.3.1285(git:92a29ea9-dirty)
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 "parser.h"
19 #include <iostream>
20 #include "arts.h"
21 #include "exceptions.h"
22 #include "file.h"
23 #include "global_data.h"
24 #include "methods.h"
25 #include "parameters.h"
26 #include "workspace_ng.h"
27 #include "wsv_aux.h"
28 
37  String controlfile,
38  const Verbosity& rverbosity)
39  : mtasklist(tasklist),
40  mcfile(controlfile),
41  mcfile_version(1),
42  verbosity(rverbosity) {
44 }
45 
51 
60 void ArtsParser::find_named_arguments(vector<NamedArgument>& named_args) {
61  NamedArgument current_argument;
62 
63  named_args.resize(0);
64 
65  while (msource.Current() != ')') {
66  read_name(current_argument.name);
68  if (msource.Current() != '=') {
69  ostringstream os;
70  os << "Expected '=', but got '" << msource.Current() << "'.\n"
71  << "Mixing positional and named arguments is not allowed.";
72  throw UnexpectedChar(
73  os.str(), msource.File(), msource.Line(), msource.Column());
74  }
75 
78 
79  current_argument.line = msource.LineRaw();
80  current_argument.column = msource.ColumnRaw();
81  named_args.push_back(current_argument);
82 
84  }
85 }
86 
92  Index bracket_level = 0;
93  bool inside_quotes = false;
94  char prev_char = 0;
95  Index starting_line = msource.LineRaw();
96  Index starting_col = msource.ColumnRaw();
97 
98  while ((bracket_level || inside_quotes) ||
99  (msource.Current() != ',' && msource.Current() != ')')) {
100  try {
101  switch (msource.Current()) {
102  case '[':
103  bracket_level++;
104  break;
105  case ']':
106  bracket_level--;
107  if (bracket_level < 0)
108  throw ParseError("Too many closing brackets",
109  msource.File(),
110  msource.Line(),
111  msource.Column());
112  break;
113  case '"':
114  if (prev_char != '\\') inside_quotes = !inside_quotes;
115  break;
116  }
117 
118  prev_char = msource.Current();
119  if (msource.Current() == '#')
121  else
123  } catch (const Eot& x) {
124  msource.SetPosition(starting_line, starting_col);
125  throw ParseError(
126  "Unexpectedly reached end of file.\nProbably a runaway argument.",
127  msource.File(),
128  msource.Line(),
129  msource.Column());
130  }
131  }
132 
133  if (msource.Current() == ',') {
134  try {
136  } catch (const Eot& x) {
137  throw ParseError(
138  "blablup", msource.File(), msource.Line(), msource.Column());
139  }
140  eat_whitespace();
141  }
142 }
143 
155  eat_whitespace();
156  if (msource.Current() != ',' && msource.Current() != ')') {
157  ostringstream os;
158  os << "Expected ',' or ')' but found '" << msource.Current() << "' after "
159  << argname;
160  throw UnexpectedChar(
161  os.str(), msource.File(), msource.Line(), msource.Column());
162  }
163 }
164 
170  NamedArguments& named_args,
171  String name) {
172  for (arg_index = 0; arg_index < (Index)named_args.size(); arg_index++) {
173  if (named_args[(size_t)arg_index].name == name) return;
174  }
175 
176  arg_index = -1;
177 }
178 
185  CREATE_OUT0;
186  CREATE_OUT3;
187 
188  try {
189  using global_data::md_data;
190 
191  // For method ids:
192  Index id;
193  // Output workspace variables (for generic methods):
194  ArrayOfIndex output;
195  // Input workspace variables (for generic methods):
196  ArrayOfIndex input;
197  // For include statements, holding the include file's name
198  String include_file;
199 
200  ArrayOfIndex auto_vars;
201  Array<TokVal> auto_vars_values;
202 
203  out3 << "\nParsing control text:\n";
204 
205  msource.Init();
206  eat_whitespace();
207 
208  parse_method(id,
209  output,
210  input,
211  mtasklist,
212  auto_vars,
213  auto_vars_values,
214  include_file,
215  true);
216 
217  if ("Arts" != md_data[id].Name() && "Arts2" != md_data[id].Name()) {
218  ostringstream os;
219  os << "The outermost agenda must be Arts2!\n"
220  << "(But it seems to be " << md_data[id].Name() << ".)\n";
221  throw ParseError(
222  os.str(), msource.File(), msource.Line(), msource.Column());
223  }
224 
225  try {
227  if (!msource.reachedEot())
228  throw UnexpectedChar(
229  "", msource.File(), msource.Line(), msource.Column());
230  } catch (const Eot&) {
231  // It's ok to reach the end of the file here,
232  // that's actually what we want.
233  } catch (const UnexpectedChar& x) {
234  ostringstream os;
235  os << "Unexpected character(s) at the end of the control file\n";
236  os << "after the main agenda was already closed.\n";
237  os << "File: " << x.file() << '\n';
238  os << "Line: " << x.line() << '\n';
239  os << "Column: " << x.column() << '\n';
240  throw runtime_error(os.str());
241  }
242  } catch (const Eot& x) {
243  // Unexpected end of the source text:
244  ostringstream os;
245  os << "Unexpected end of control script.\n";
246  os << "File: " << x.file() << '\n';
247  os << "Line: " << x.line() << '\n';
248  throw runtime_error(os.str());
249  } catch (const UnexpectedChar& x) {
250  // Unexpected Character:
251  ostringstream os;
252  os << "Unexpected character:\n";
253  os << x.what() << '\n';
254  os << "File: " << x.file() << '\n';
255  os << "Line: " << x.line() << '\n';
256  os << "Column: " << x.column() << '\n';
257  throw runtime_error(os.str());
258  } catch (const IllegalLinebreak& x) {
259  // A line break in an illegal position:
260  ostringstream os;
261  os << "Illegal Line break:\n";
262  os << x.what() << '\n';
263  os << "File: " << x.file() << '\n';
264  os << "Line: " << x.line() << '\n';
265  throw runtime_error(os.str());
266  } catch (const UnknownMethod& x) {
267  // Method unknown:
268  // [**This should give a hint on how to obtain a list of allowed
269  // methods.]
270  ostringstream os;
271  os << "Unknown Method:\n";
272  os << x.what() << '\n';
273  os << "File: " << x.file() << '\n';
274  os << "Line: " << x.line() << '\n';
275  os << "Column: " << x.column() << '\n';
276  throw runtime_error(os.str());
277  } catch (const UnknownWsv& x) {
278  // Workspace variable unknown:
279  // [**This should give a hint on how to obtain a list of allowed
280  // Wsvs.]
281  ostringstream os;
282  os << "Unknown workspace variable:\n";
283  os << x.what() << '\n';
284  os << "File: " << x.file() << '\n';
285  os << "Line: " << x.line() << '\n';
286  os << "Column: " << x.column() << '\n';
287  throw runtime_error(os.str());
288  } catch (const WsvAlreadyExists& x) {
289  // Trying to create the same variable twice:
290  ostringstream os;
291  os << "Attempt to create a workspace variable that already exists:\n";
292  os << x.what() << '\n';
293  os << "File: " << x.file() << '\n';
294  os << "Line: " << x.line() << '\n';
295  os << "Column: " << x.column() << '\n';
296  throw runtime_error(os.str());
297  } catch (const WrongWsvGroup& x) {
298  // Workspace variable unknown:
299  // [**This should give a hint on how to obtain a list of Wsvs in
300  // this group.
301  ostringstream os;
302  os << "Workspace variable belongs to the wrong group:\n";
303  os << x.what() << '\n';
304  os << "File: " << x.file() << '\n';
305  os << "Line: " << x.line() << '\n';
306  os << "Column: " << x.column() << '\n';
307  throw runtime_error(os.str());
308  } catch (const ParseError& x) {
309  // General Parse Error (parent of all the above):
310  ostringstream os;
311  os << "Parse error:\n";
312  os << x.what() << '\n';
313  os << "File: " << x.file() << '\n';
314  os << "Line: " << x.line() << '\n';
315  os << "Column: " << x.column() << '\n';
316  throw runtime_error(os.str());
317  }
318 }
319 
333 void ArtsParser::parse_agenda(Agenda& tasklist, const String& agenda_name) {
334  CREATE_OUT2;
335  CREATE_OUT3;
336 
337  using global_data::md_data;
338 
339  // For method ids:
340  Index id;
341  // Output workspace variables:
342  ArrayOfIndex output;
343  // Input workspace variables:
344  ArrayOfIndex input;
345  // For Agenda, if there is any:
346  Agenda tasks;
347  // For include statements, holding the include file's name
348  String include_file;
349 
350  ArrayOfIndex auto_vars;
351  Array<TokVal> auto_vars_values;
352 
353  eat_whitespace();
354 
355  while ('}' != msource.Current()) {
356  parse_method(
357  id, output, input, tasks, auto_vars, auto_vars_values, include_file);
358 
359  // If parse_method found an include statement it returnes -1 for the
360  // method id
361  if (id == -1) {
362  // Command line parameters which give us the include search path.
363  extern Parameters parameters;
364 
365  ArrayOfString current_includepath = parameters.includepath;
366  String includedir;
367  get_dirname(includedir, msource.File());
368  if (includedir.nelem()) {
369  if (current_includepath.nelem() && current_includepath[0] != includedir)
370  current_includepath.insert(current_includepath.begin(), includedir);
371  if (parameters.datapath.nelem() && parameters.datapath[0] != includedir)
372  parameters.datapath.insert(parameters.datapath.begin(), includedir);
373  }
374 
375  ArrayOfString matching_files;
376  find_file(matching_files, include_file, current_includepath);
377  find_file(matching_files, include_file + ".arts", current_includepath);
378 
379  if (!matching_files.nelem()) {
380  ostringstream os;
381  os << "Cannot find include file " << include_file << ".\n";
382  os << "File: " << msource.File() << '\n';
383  os << "Search path was: " << current_includepath << "\n";
384  throw ParseError(
385  os.str(), msource.File(), msource.Line(), msource.Column());
386  }
387 
388  include_file = matching_files[0];
389  out2 << "- Including control file " << include_file << "\n";
390 
391  ArtsParser include_parser(tasks, include_file, verbosity);
392  include_parser.parse_tasklist();
393 
394  for (Index i = 0; i < tasks.nelem(); i++)
395  tasklist.push_back(tasks.Methods()[i]);
396  } else {
397  if (md_data[id].SetMethod()) {
398  // Append task to task list:
399  tasklist.push_back(
400  MRecord(id, output, input, auto_vars_values[0], tasks));
401  } else {
402  tasklist_insert_set_delete(auto_vars, auto_vars_values, 0, tasklist);
403 
404  // Append task to task list:
405  tasklist.push_back(MRecord(id, output, input, TokVal(), tasks));
406 
407  tasklist_insert_set_delete(auto_vars, auto_vars_values, 1, tasklist);
408 
409  // If Create was called on a variable that already existed,
410  // insert a Delete call to set it back to an uninitialized state
411  using global_data::md_data;
412  const String& mname = md_data[id].Name();
413 
414  if (mname.length() > 6 && mname.find("Create") == mname.length() - 6 &&
415  get_wsv_group_id(mname.substr(0, mname.length() - 6)) != -1) {
416  if (agenda_name != "Arts2") {
417  ostringstream os;
418  os << mname << " cannot be called inside an agenda.\n"
419  << "All workspace variables are global and must be created at the top level.";
420  throw ParseError(
421  os.str(), msource.File(), msource.Line(), msource.Column());
422  }
423  using global_data::MdMap;
425  String method_name =
426  "Delete_sg_" +
427  wsv_group_names[Workspace::wsv_data[output[0]].Group()];
428  map<String, Index>::const_iterator mdit;
429  mdit = MdMap.find(method_name);
430  assert(mdit != MdMap.end());
431 
432  tasklist.push_back(MRecord(
433  mdit->second, ArrayOfIndex(), output, TokVal(), Agenda(), true));
434  }
435  }
436 
437  {
438  // Everything in this block is just to generate some
439  // informative output.
440 
441  out3 << "- " << md_data[id].Name() << "\n";
442 
443  // Output workspace variables for generic methods:
444  if (0 <
445  md_data[id].GOutType().nelem() + md_data[id].GInType().nelem()) {
446  out3 << " Output: ";
447  for (Index j = 0; j < output.nelem(); ++j) {
448  out3 << Workspace::wsv_data[output[j]].Name() << " ";
449  }
450  out3 << "\n";
451 
452  out3 << " Input: ";
453  for (Index j = 0; j < input.nelem(); ++j) {
454  out3 << Workspace::wsv_data[input[j]].Name() << " ";
455  }
456  out3 << "\n";
457  }
458  }
459  }
460 
461  eat_whitespace();
462  }
463 }
464 
497  ArrayOfIndex& output,
498  ArrayOfIndex& input,
499  Agenda& tasks,
500  ArrayOfIndex& auto_vars,
501  Array<TokVal>& auto_vars_values,
502  String& include_file,
503  bool no_eot) {
504  CREATE_OUT3;
505 
506  String methodname; // We need this out here, since it is
507  // set once and later modified.
508 
509  const MdRecord* mdd; // Handle on the method record. Needed here,
510  // because it is modified.
511 
512  bool found_curly_brace = false;
513 
514  // Clear all output variables:
515  id = 0;
516  output.resize(0);
517  input.resize(0);
518  tasks.resize(0);
519  auto_vars.resize(0);
520  auto_vars_values.resize(0);
521  include_file = "";
522 
523  msource.SetMark();
524  read_name(methodname);
525 
526  if (methodname == "INCLUDE") {
527  eat_whitespace();
528  parse_String(include_file);
529 
530  id = -1;
531 
532  return;
533  } else {
534  if (methodname == "Arts2") {
535  mcfile_version = 2;
536  } else if (methodname == "Arts") {
537  throw runtime_error(
538  "Arts version 1 controlfiles are no longer supported.");
539  }
540 
541  eat_whitespace();
542 
544  mdd, id, methodname, output, input, auto_vars, auto_vars_values);
545 
546  eat_whitespace();
547 
548  // Now look for the curly braces:
549  if (msource.Current() == '{') {
551  eat_whitespace();
552  found_curly_brace = true;
553  }
554 
555  // There are two kind of methods, agenda methods, which have other
556  // methods in the body, and normal methods, expecting keywords and
557  // values. Let's take the agenda case first...
558  if (mdd->AgendaMethod()) {
559  out3 << "- " << mdd->Name() << "\n";
560  out3 << "{\n";
561  parse_agenda(tasks, methodname);
562  out3 << "}\n";
563  }
564 
565  // Curly braces in non-agenda methods are not valid in v2 controlfiles
566  if (mcfile_version == 2 && !mdd->AgendaMethod() && found_curly_brace) {
567  ostringstream os;
568  os << "Expected method name , but got `" << msource.Current() << "'.";
569  throw UnexpectedChar(
570  os.str(), msource.File(), msource.Line(), msource.Column());
571  os << "" << endl;
572  }
573  }
574 
575  // Now look for the closing curly braces. We have to catch Eot,
576  // because after a method description may be a good place to end
577  // the control file.
578  if (found_curly_brace) {
579  try {
580  assertain_character('}');
581  } catch (const Eot& x) {
582  // Re-throw the error if the no_eot flag is not set:
583  if (!no_eot) throw Eot(x);
584  }
585  }
586 }
587 
589 
604  ArrayOfIndex& auto_vars,
605  Array<TokVal>& auto_vars_values,
606  Index gin_index) {
607  String name;
608 
609  if (mdd->GInDefault()[gin_index] != NODEF) {
610  ostringstream os_default_error;
611  os_default_error
612  << "\nParse error in default value for generic input variable.\n"
613  << "This is not a user error but a bug in methods.cc.\n"
614  << "Please contact the ARTS developers.";
615 
616  TokVal tv;
617  // Now parse the key value. This can be:
618  // String, Index, Numeric, ArrayOfString, ArrayOfIndex, Vector
619  bool failed = false;
620  if (mdd->GInType()[gin_index] == get_wsv_group_id("String")) {
621  tv = mdd->GInDefault()[gin_index];
622  } else if (mdd->GInType()[gin_index] == get_wsv_group_id("Index")) {
623  Index n;
624  istringstream is(mdd->GInDefault()[gin_index]);
625  is >> n;
626  tv = n;
627  if (is.bad() || is.fail()) failed = true;
628  } else if (mdd->GInType()[gin_index] == get_wsv_group_id("Numeric")) {
629  Numeric n = NAN;
630  istringstream is(mdd->GInDefault()[gin_index]);
631  is >> double_imanip() >> n;
632  tv = n;
633  if (is.bad() || is.fail()) failed = true;
634  } else if (mdd->GInType()[gin_index] == get_wsv_group_id("ArrayOfString")) {
635  ArrayOfString v;
636  String s = mdd->GInDefault()[gin_index];
637  try {
638  if (!parse_stringarray_from_string(v, s)) {
639  failed = true;
640  }
641  } catch (const ParseError& p) {
642  ostringstream os;
643  os << p.what() << os_default_error.str();
644  throw ParseError(os.str(), p.file(), p.line(), p.column());
645  }
646  tv = v;
647  } else if (mdd->GInType()[gin_index] == get_wsv_group_id("Vector")) {
648  Vector v;
649  String s = mdd->GInDefault()[gin_index];
650  try {
651  if (!parse_numvector_from_string(v, s)) {
652  failed = true;
653  }
654  } catch (const ParseError& p) {
655  ostringstream os;
656  os << p.what() << os_default_error.str();
657  throw ParseError(os.str(), p.file(), p.line(), p.column());
658  }
659  tv = v;
660  } else if (mdd->GInType()[gin_index] == get_wsv_group_id("ArrayOfIndex")) {
661  ArrayOfIndex v;
662  String s = mdd->GInDefault()[gin_index];
663  try {
664  if (!parse_intvector_from_string(v, s)) {
665  failed = true;
666  }
667  } catch (const ParseError& p) {
668  ostringstream os;
669  os << p.what() << os_default_error.str();
670  throw ParseError(os.str(), p.file(), p.line(), p.column());
671  }
672  tv = v;
673  } else {
675  ostringstream os;
676  os << "Default values for generic inputs with type "
677  << wsv_group_names[mdd->GInType()[gin_index]]
678  << " are not supported.\n"
679  << "Either remove the default value for generic input '"
680  << mdd->GIn()[gin_index] << "' in workspace method\n"
681  << "*" << mdd->Name() << "* in methods.cc or discuss this "
682  << "issue on the arts-dev mailing list.\n";
683  throw ParseError(
684  os.str(), msource.File(), msource.Line(), msource.Column());
685  }
686 
687  Index wsvid;
688 
689  {
690  ostringstream os;
691  os << gin_index;
692 
693  name = "auto_" + mdd->Name() + "_" + "gin" + os.str() + "_" +
694  mdd->GIn()[gin_index];
695  }
696 
697  map<String, Index>::const_iterator wsvit = Workspace::WsvMap.find(name);
698  if (wsvit == Workspace::WsvMap.end()) {
699  wsvid = Workspace::add_wsv(WsvRecord(name.c_str(),
700  "Automatically allocated variable.",
701  mdd->GInType()[gin_index],
702  true));
703  } else {
704  wsvid = wsvit->second;
705  }
706 
707  auto_vars.push_back(wsvid);
708  auto_vars_values.push_back(tv);
709 
710  if (failed) {
711  ostringstream os;
712  os << "Failed to assign default value for generic '"
713  << mdd->GIn()[gin_index] << "'.\n"
714  << "Check the documentation of workspace method *" << mdd->Name()
715  << "*.\n";
716  throw ParseError(
717  os.str(), msource.File(), msource.Line(), msource.Column());
718  }
719  } else {
720  ostringstream os;
721  os << "Generic input '" << mdd->GIn()[gin_index]
722  << "' omitted but no default value found.\n"
723  << "Check the documentation of workspace method *" << mdd->Name()
724  << "*.\n";
725  throw ParseError(
726  os.str(), msource.File(), msource.Line(), msource.Column());
727  }
728 
729  return name;
730 }
731 
733 
747  Index& id,
748  String& methodname,
749  ArrayOfIndex& output,
750  ArrayOfIndex& input,
751  ArrayOfIndex& auto_vars,
752  Array<TokVal>& auto_vars_values) {
753  using global_data::md_data;
755  using global_data::MdMap;
756  using global_data::MdRawMap;
757 
758  bool still_supergeneric = true; // Flag that our MdRecord still is
759  // from md_data_raw, not from
760  // md_data.
761 
762  // Find method raw id in raw map:
763  const map<String, Index>::const_iterator md_raw_id =
764  MdRawMap.find(methodname);
765  if (md_raw_id == MdRawMap.end())
766  throw UnknownMethod(methodname,
767  msource.File(),
770 
771  id = md_raw_id->second;
772 
773  // Get a convenient handle on the data record for this method. We
774  // have to use a pointer here, not a reference, because we later
775  // want to change where mdd is pointing!
776  mdd = &md_data_raw[id];
777 
778  // Is this a supergeneric method? If not, take the record in
779  // md_data, rather than in md_data_raw:
780  if (!mdd->Supergeneric()) {
781  // Find explicit method id in MdMap:
782  const map<String, Index>::const_iterator i2 = MdMap.find(methodname);
783  assert(i2 != MdMap.end());
784  id = i2->second;
785 
786  mdd = &md_data[id];
787 
788  still_supergeneric = false;
789  }
790 
791  if (msource.Current() == '(') {
792  String supergeneric_args;
793  Index supergeneric_index = -1;
794  NamedArguments named_arguments;
795  Index this_method_end_line = -1;
796  Index this_method_end_column = -1;
797  bool call_by_name = false;
798 
800  eat_whitespace();
801 
802  // Peak at the first method argument to determine if the method
803  // is called with positional or named arguments
804  if (isalpha(msource.Current())) {
805  Index line = msource.LineRaw();
806  Index column = msource.ColumnRaw();
807  String name = "";
808 
809  read_name(name);
810  eat_whitespace();
811 
812  if (msource.Current() == '=') {
814  eat_whitespace();
815 
816  msource.SetPosition(line, column);
817  find_named_arguments(named_arguments);
818 
819  call_by_name = true;
820 
821  this_method_end_line = msource.LineRaw();
822  this_method_end_column = msource.ColumnRaw();
823  }
824 
825  msource.SetPosition(line, column);
826  }
827 
828  bool is_first_arg = true;
830  mdd, output, is_first_arg, named_arguments, call_by_name);
831 
833  id,
834  methodname,
835  output,
836  is_first_arg,
837  still_supergeneric,
838  supergeneric_args,
839  supergeneric_index,
840  named_arguments,
841  call_by_name);
842 
844  input,
845  auto_vars,
846  auto_vars_values,
847  is_first_arg,
848  named_arguments,
849  call_by_name);
850 
852  id,
853  methodname,
854  input,
855  auto_vars,
856  auto_vars_values,
857  is_first_arg,
858  still_supergeneric,
859  supergeneric_args,
860  supergeneric_index,
861  named_arguments,
862  call_by_name);
863 
864  // Named arguments are not parsed in order. We have to set the cursor
865  // to the end of the method call after all named arguments have been parsed.
866  if (call_by_name)
867  msource.SetPosition(this_method_end_line, this_method_end_column);
868 
869  // If we're here and still have named arguments left means that
870  // the user specified too many for this method
871  if (call_by_name && named_arguments.size()) {
872  ostringstream os;
873 
874  os << "Error in arguments passed to " << mdd->Name() << ":\n";
875  for (auto& argument_name : named_arguments) {
876  if (std::find(mdd->GIn().begin(),
877  mdd->GIn().end(),
878  argument_name.name) == mdd->GIn().end() &&
879  std::find(mdd->GOut().begin(),
880  mdd->GOut().end(),
881  argument_name.name) == mdd->GOut().end())
882  os << " Unkown argument: ";
883  else
884  os << " Duplicate argument: ";
885  os << argument_name.name << std::endl;
886  }
887  throw ParseError(
888  os.str(), msource.File(), msource.Line(), msource.Column());
889  }
890 
891  assert(!still_supergeneric);
892  assertain_character(')');
893  } else {
894  if (mdd->GOut().nelem()) {
895  ostringstream os;
896  os << "This method has generic output. "
897  << "You have to pass a variable!";
898  throw ParseError(os.str(),
899  msource.File(),
902  }
903 
904  // If the parenthesis were omitted we still have to add the implicit
905  // outputs and inputs to the methods input and output variable lists
906  ArrayOfIndex vo = mdd->Out();
907  for (ArrayOfIndex::const_iterator outs = vo.begin(); outs < vo.end();
908  ++outs) {
909  output.push_back(*outs);
910  }
911 
912  const ArrayOfIndex& vi = mdd->InOnly();
913  for (ArrayOfIndex::const_iterator ins = vi.begin(); ins < vi.end(); ++ins) {
914  input.push_back(*ins);
915  }
916 
917  {
918  // Make sure all keywords have default values, otherwise the
919  // user has to specify them in the controlfile.
920  bool all_gin_have_defaults = true;
921  for (Index gin = 0; all_gin_have_defaults && gin < mdd->GIn().nelem();
922  ++gin) {
923  Index wsvid; // Workspace variable id, is used to
924  // access data in wsv_data.
925 
926  if (mdd->GInDefault()[gin] == NODEF)
927  all_gin_have_defaults = false;
928  else {
929  String wsvname;
930  wsvname = set_gin_to_default(mdd, auto_vars, auto_vars_values, gin);
931  {
932  // Find Wsv id:
933  const map<String, Index>::const_iterator wsvit =
934  Workspace::WsvMap.find(wsvname);
935  if (wsvit == Workspace::WsvMap.end()) {
936  throw UnknownWsv(wsvname,
937  msource.File(),
940  }
941 
942  wsvid = wsvit->second;
943  }
944  input.push_back(wsvid);
945  }
946  }
947 
948  if (!all_gin_have_defaults) {
949  ostringstream os;
950  os << "Not all generic inputs of the method *" << methodname
951  << "* have default values, you have to specify them!";
952  throw ParseError(os.str(),
953  msource.File(),
956  }
957  }
958  }
959 }
960 
978  Index& id,
979  String& methodname,
980  ArrayOfIndex& input,
981  ArrayOfIndex& auto_vars,
982  Array<TokVal>& auto_vars_values,
983  bool& first,
984  bool& still_supergeneric,
985  String& supergeneric_args,
986  Index& supergeneric_index _U_,
987  NamedArguments& named_args,
988  bool call_by_name) {
989  String wsvname;
990  Index wsvid;
991  using global_data::md_data;
992  using global_data::MdMap;
994 
995  // Then parse all generic input variables
996  for (Index j = 0; j < mdd->GInType().nelem(); ++j) {
997  Index this_arg_index = 0;
998 
999  if (call_by_name) {
1000  get_argument_index_by_name(this_arg_index, named_args, mdd->GIn()[j]);
1001 
1002  if (this_arg_index != -1) {
1003  msource.SetPosition(named_args[this_arg_index].line,
1004  named_args[this_arg_index].column);
1005  named_args.erase(named_args.begin() + this_arg_index);
1006  }
1007  } else {
1008  if (first)
1009  first = false;
1010  else {
1011  if (msource.Current() != ')') {
1012  assertain_character(',');
1013  eat_whitespace();
1014  }
1015  }
1016  }
1017 
1018  // If no value was specified and we use the default value instead (if there is one)
1019  if ((call_by_name && this_arg_index == -1) || msource.Current() == ',' ||
1020  msource.Current() == ')') {
1021  wsvname = set_gin_to_default(mdd, auto_vars, auto_vars_values, j);
1022  } else {
1023  ostringstream os;
1024  os << j;
1025  if (read_name_or_value(wsvname,
1026  auto_vars,
1027  auto_vars_values,
1028  "generic" + os.str(),
1029  mdd,
1030  mdd->GInType()[j]) == -1 &&
1031  mdd->SetMethod()) {
1032  if (msource.Current() == '=') {
1033  throw UnexpectedChar(
1034  "Unexpected '=' sign encountered.\n"
1035  "Mixing positional and named arguments is not allowed.",
1036  msource.File(),
1037  msource.Line(),
1038  msource.Column());
1039  }
1040  throw ParseError(
1041  "Only constants can be passed to Set methods.\n"
1042  "You might want to use the *Copy* here.",
1043  msource.File(),
1044  msource.Line(),
1045  msource.Column());
1046  }
1047  if (call_by_name) at_end_of_argument("generic input argument");
1048  }
1049 
1050  {
1051  // Find Wsv id:
1052  const map<String, Index>::const_iterator wsvit =
1053  Workspace::WsvMap.find(wsvname);
1054  if (wsvit == Workspace::WsvMap.end()) {
1055  throw UnknownWsv(
1056  wsvname, msource.File(), msource.Line(), msource.Column());
1057  }
1058 
1059  wsvid = wsvit->second;
1060  }
1061 
1062  // Is the method data record still supergeneric? This could
1063  // be the case if there are no output arguments, only input
1064  // arguments. In that case, let's find out the actual group!
1065  if (still_supergeneric) {
1066  ostringstream os;
1067  if (wsv_group_names[mdd->GInType()[j]] == "Any")
1068  supergeneric_args +=
1070  os << mdd->Name() << "_sg_" << supergeneric_args;
1071  methodname = os.str();
1072 
1073  // Find explicit method id in MdMap:
1074  const map<String, Index>::const_iterator mdit = MdMap.find(methodname);
1075  if (mdit != MdMap.end()) {
1076  id = mdit->second;
1077 
1078  mdd = &md_data[id];
1079 
1080  still_supergeneric = false;
1081  }
1082  }
1083 
1084  // Now we have explicitly the method record for the right
1085  // group. From now on no special treatment of supergeneric
1086  // methods should be necessary.
1087 
1088  // Check that this Wsv belongs to the correct group:
1089  if (mdd->GInType()[j] == get_wsv_group_id("Any") &&
1090  mdd->GInSpecType()[j].nelem()) {
1091  if (supergeneric_index == -1) {
1092  bool wrong_group_id = true;
1093  for (Index i = 0; wrong_group_id && i < mdd->GInSpecType()[j].nelem();
1094  i++) {
1095  if (Workspace::wsv_data[wsvid].Group() == mdd->GInSpecType()[j][i]) {
1096  wrong_group_id = false;
1097  supergeneric_index = i;
1098  }
1099  }
1100 
1101  if (wrong_group_id) {
1102  ostringstream os;
1103  bool firsttype = true;
1104  for (Index i = 0; i < mdd->GInSpecType()[j].nelem(); i++) {
1105  if (!firsttype)
1106  os << ", ";
1107  else
1108  firsttype = false;
1109  os << wsv_group_names[mdd->GInSpecType()[j][i]];
1110  }
1111 
1112  throw WrongWsvGroup(
1113  "*" + mdd->Name() + "* is not defined for " +
1114  wsv_group_names[Workspace::wsv_data[wsvid].Group()] +
1115  " input. Check the online docs.",
1116  msource.File(),
1117  msource.Line(),
1118  msource.Column());
1119  }
1120  } else {
1121  if (Workspace::wsv_data[wsvid].Group() !=
1122  mdd->GInSpecType()[j][supergeneric_index]) {
1123  throw WrongWsvGroup(
1124  wsvname + " is not " +
1125  wsv_group_names[mdd->GInSpecType()[j][supergeneric_index]] +
1126  ", it is " +
1127  wsv_group_names[Workspace::wsv_data[wsvid].Group()],
1128  msource.File(),
1129  msource.Line(),
1130  msource.Column());
1131  }
1132  }
1133  } else if (Workspace::wsv_data[wsvid].Group() != mdd->GInType()[j]) {
1134  throw WrongWsvGroup(
1135  wsvname + " is not " + wsv_group_names[mdd->GInType()[j]] +
1136  ", it is " + wsv_group_names[Workspace::wsv_data[wsvid].Group()],
1137  msource.File(),
1138  msource.Line(),
1139  msource.Column());
1140  }
1141 
1142  // Add this one to the list of input variables:
1143  input.push_back(wsvid);
1144 
1145  eat_whitespace();
1146  }
1147 }
1148 
1164  Index& id,
1165  String& methodname,
1166  ArrayOfIndex& output,
1167  bool& first,
1168  bool& still_supergeneric,
1169  String& supergeneric_args,
1170  Index& supergeneric_index,
1171  NamedArguments& named_args,
1172  bool call_by_name) {
1173  String wsvname;
1174  Index wsvid;
1175  using global_data::md_data;
1176  using global_data::MdMap;
1178 
1179  // Parse all generic output variables
1180  for (Index j = 0; j < mdd->GOut().nelem(); ++j) {
1181  if (call_by_name) {
1182  Index this_arg_index;
1183 
1184  get_argument_index_by_name(this_arg_index, named_args, mdd->GOut()[j]);
1185 
1186  if (this_arg_index == -1) {
1187  ostringstream os;
1188  os << "This method has generic output. "
1189  << "You have to pass a variable!";
1190  throw ParseError(
1191  os.str(), msource.File(), msource.Line(), msource.Column());
1192  }
1193 
1194  msource.SetPosition(named_args[this_arg_index].line,
1195  named_args[this_arg_index].column);
1196  named_args.erase(named_args.begin() + this_arg_index);
1197  } else {
1198  if (first)
1199  first = false;
1200  else {
1201  assertain_character(',');
1202  eat_whitespace();
1203  }
1204  }
1205 
1206  read_name(wsvname);
1207  if (call_by_name) at_end_of_argument("generic output argument");
1208 
1209  {
1210  wsvid = -1;
1211  // Find Wsv id:
1212  map<String, Index>::const_iterator wsvit =
1213  Workspace::WsvMap.find(wsvname);
1214  if (wsvit == Workspace::WsvMap.end()) {
1215  if (still_supergeneric) {
1216  ostringstream os;
1217  os << "This might be either a typo or you have to create "
1218  << "the variable\nby calling TYPECreate(" << wsvname
1219  << ") first. Replace TYPE with the\n"
1220  << "WSV group your variable should belong to.";
1221 
1222  throw UnknownWsv(
1223  os.str(), msource.File(), msource.Line(), msource.Column());
1224  } else {
1225  if (mdd->Name().length() <= 6 ||
1226  mdd->Name().substr(mdd->Name().length() - 6) != "Create") {
1227  ostringstream os;
1228  os << "This might be either a typo or you have to create "
1229  << "the variable\nby calling "
1230  << wsv_group_names[mdd->GOutType()[j]] << "Create( " << wsvname
1231  << " ) first.\n";
1232 
1233  throw UnknownWsv(
1234  os.str(), msource.File(), msource.Line(), msource.Column());
1235  } else {
1236  wsvid = Workspace::add_wsv(
1237  WsvRecord(wsvname.c_str(),
1238  "Automatically allocated variable.",
1239  mdd->GOutType()[j],
1240  true));
1241  }
1242  }
1243  }
1244 
1245  if (wsvid == -1) {
1246  if (mdd->Name().length() > 6 &&
1247  mdd->Name().find("Create") == mdd->Name().length() - 6) {
1248  ostringstream os;
1249  os << wsvname
1250  << " already exists. A variable can only be created once.\n";
1251  throw WsvAlreadyExists(
1252  os.str(), msource.File(), msource.Line(), msource.Column());
1253  }
1254  wsvid = wsvit->second;
1255  }
1256  }
1257 
1258  // If this is a supergeneric method, now is the time to find
1259  // out the actual group of the argument(s)!
1260  // If the method also has supergeneric input arguments, we'll
1261  // look for a match later again.
1262  if (still_supergeneric) {
1263  ostringstream os;
1264  if (wsv_group_names[mdd->GOutType()[j]] == "Any")
1265  supergeneric_args +=
1267  os << mdd->Name() << "_sg_" << supergeneric_args;
1268  methodname = os.str();
1269 
1270  // Find explicit method id in MdMap:
1271  const map<String, Index>::const_iterator mdit = MdMap.find(methodname);
1272  if (mdit != MdMap.end()) {
1273  id = mdit->second;
1274 
1275  mdd = &md_data[id];
1276 
1277  still_supergeneric = false;
1278  }
1279  }
1280 
1281  // Now we have explicitly the method record for the right
1282  // group. From now on no special treatment of supergeneric
1283  // methods should be necessary.
1284 
1285  // Check that this Wsv belongs to the correct group:
1286  if (mdd->GOutType()[j] == get_wsv_group_id("Any") &&
1287  mdd->GOutSpecType()[j].nelem()) {
1288  if (supergeneric_index == -1) {
1289  bool wrong_group_id = true;
1290  for (Index i = 0; wrong_group_id && i < mdd->GOutSpecType()[j].nelem();
1291  i++) {
1292  if (Workspace::wsv_data[wsvid].Group() == mdd->GOutSpecType()[j][i]) {
1293  wrong_group_id = false;
1294  supergeneric_index = i;
1295  }
1296  }
1297 
1298  if (wrong_group_id) {
1299  ostringstream os;
1300  bool firsttype = true;
1301  for (Index i = 0; i < mdd->GOutSpecType()[j].nelem(); i++) {
1302  if (!firsttype)
1303  os << ", ";
1304  else
1305  firsttype = false;
1306  os << wsv_group_names[mdd->GOutSpecType()[j][i]];
1307  }
1308 
1309  throw WrongWsvGroup(
1310  "*" + mdd->Name() + "* is not defined for " +
1311  wsv_group_names[Workspace::wsv_data[wsvid].Group()] +
1312  " output. Check the online docs.",
1313  msource.File(),
1314  msource.Line(),
1315  msource.Column());
1316  }
1317  } else {
1318  if (Workspace::wsv_data[wsvid].Group() !=
1319  mdd->GOutSpecType()[j][supergeneric_index]) {
1320  throw WrongWsvGroup(
1321  wsvname + " is not " +
1322  wsv_group_names[mdd->GOutSpecType()[j][supergeneric_index]] +
1323  ", it is " +
1324  wsv_group_names[Workspace::wsv_data[wsvid].Group()],
1325  msource.File(),
1326  msource.Line(),
1327  msource.Column());
1328  }
1329  }
1330  } else if (Workspace::wsv_data[wsvid].Group() != mdd->GOutType()[j]) {
1331  throw WrongWsvGroup(
1332  wsvname + " is not " + wsv_group_names[mdd->GOutType()[j]] +
1333  ", it is " + wsv_group_names[Workspace::wsv_data[wsvid].Group()],
1334  msource.File(),
1335  msource.Line(),
1336  msource.Column());
1337  }
1338 
1339  // Add this one to the list of output workspace variables:
1340  output.push_back(wsvid);
1341 
1342  eat_whitespace();
1343  }
1344 }
1345 
1359  ArrayOfIndex& input,
1360  ArrayOfIndex& auto_vars,
1361  Array<TokVal>& auto_vars_values,
1362  bool& first,
1363  NamedArguments& named_args,
1364  bool call_by_name) {
1366 
1367  // There are two lists of arguments that we have to read.
1368  ArrayOfIndex vo = mdd->Out(); // Output
1369  const ArrayOfIndex& vi = mdd->InOnly(); // Input
1370 
1371  Index wsvid; // Workspace variable id, is used to
1372  // access data in wsv_data.
1373 
1374  for (ArrayOfIndex::const_iterator ins = vi.begin(); ins < vi.end(); ++ins) {
1375  String wsvname;
1376 
1377  if (call_by_name) {
1378  Index this_arg_index;
1379 
1380  wsvname = Workspace::wsv_data[*ins].Name();
1381 
1382  get_argument_index_by_name(this_arg_index, named_args, wsvname);
1383 
1384  if (this_arg_index != -1) {
1385  msource.SetPosition(named_args[this_arg_index].line,
1386  named_args[this_arg_index].column);
1387  named_args.erase(named_args.begin() + this_arg_index);
1388 
1389  read_name_or_value(wsvname,
1390  auto_vars,
1391  auto_vars_values,
1392  Workspace::wsv_data[*ins].Name(),
1393  mdd,
1394  Workspace::wsv_data[*ins].Group());
1395  at_end_of_argument("specific input argument");
1396  }
1397  } else {
1398  if (first)
1399  first = false;
1400  else {
1401  try {
1402  assertain_character(',');
1403  } catch (const UnexpectedChar&) {
1404  ostringstream os;
1405  os << "Expected input WSV *" << Workspace::wsv_data[*ins].Name()
1406  << "*";
1407  }
1408  eat_whitespace();
1409  }
1410 
1411  read_name_or_value(wsvname,
1412  auto_vars,
1413  auto_vars_values,
1414  Workspace::wsv_data[*ins].Name(),
1415  mdd,
1416  Workspace::wsv_data[*ins].Group());
1417  }
1418 
1419  {
1420  // Find Wsv id:
1421  const map<String, Index>::const_iterator wsvit =
1422  Workspace::WsvMap.find(wsvname);
1423  if (wsvit == Workspace::WsvMap.end())
1424  throw UnknownWsv(
1425  wsvname, msource.File(), msource.Line(), msource.Column());
1426 
1427  wsvid = wsvit->second;
1428  }
1429 
1430  // Check that this Wsv belongs to the correct group:
1431  if (Workspace::wsv_data[wsvid].Group() !=
1432  Workspace::wsv_data[*ins].Group()) {
1433  throw WrongWsvGroup(
1434  wsvname + " is not " +
1435  wsv_group_names[Workspace::wsv_data[*ins].Group()] + ", it is " +
1437  msource.File(),
1438  msource.Line(),
1439  msource.Column());
1440  }
1441 
1442  input.push_back(wsvid);
1443  }
1444 
1445  eat_whitespace();
1446 }
1447 
1459  ArrayOfIndex& output,
1460  bool& first,
1461  NamedArguments& named_args,
1462  bool call_by_name) {
1464 
1465  ArrayOfIndex vo = mdd->Out();
1466 
1467  Index wsvid; // Workspace variable id, is used to
1468  // access data in wsv_data.
1469 
1470  for (ArrayOfIndex::const_iterator outs = vo.begin(); outs < vo.end();
1471  ++outs) {
1472  String wsvname;
1473 
1474  if (call_by_name) {
1475  Index this_arg_index = 0;
1476 
1477  wsvname = Workspace::wsv_data[*outs].Name();
1478 
1479  get_argument_index_by_name(this_arg_index, named_args, wsvname);
1480 
1481  if (this_arg_index != -1) {
1482  msource.SetPosition(named_args[this_arg_index].line,
1483  named_args[this_arg_index].column);
1484  named_args.erase(named_args.begin() + this_arg_index);
1485 
1486  read_name(wsvname);
1487  at_end_of_argument("specific output argument");
1488  }
1489  } else {
1490  if (first)
1491  first = false;
1492  else {
1493  try {
1494  assertain_character(',');
1495  } catch (const UnexpectedChar&) {
1496  ostringstream os;
1497  os << "Expected output WSV *" << Workspace::wsv_data[*outs].Name()
1498  << "*";
1499  throw ParseError(
1500  os.str(), msource.File(), msource.Line(), msource.Column());
1501  }
1502  eat_whitespace();
1503  }
1504 
1505  read_name(wsvname);
1506  }
1507 
1508  {
1509  wsvid = -1;
1510  // Find Wsv id:
1511  map<String, Index>::const_iterator wsvit =
1512  Workspace::WsvMap.find(wsvname);
1513  if (wsvit == Workspace::WsvMap.end()) {
1514  if (mdd->Name().length() > 6 &&
1515  mdd->Name().substr(mdd->Name().length() - 6) != "Create") {
1516  ostringstream os;
1517  os << "This might be either a typo or you have to create "
1518  << "the variable\nby calling "
1519  << wsv_group_names[Workspace::wsv_data[*outs].Group()]
1520  << "Create( " << wsvname << " ) first.\n";
1521 
1522  throw UnknownWsv(
1523  os.str(), msource.File(), msource.Line(), msource.Column());
1524  } else {
1525  wsvid =
1526  Workspace::add_wsv(WsvRecord(wsvname.c_str(),
1527  "Automatically allocated variable.",
1528  Workspace::wsv_data[*outs].Group(),
1529  true));
1530  }
1531  }
1532 
1533  if (wsvid == -1) wsvid = wsvit->second;
1534  }
1535 
1536  // Check that this Wsv belongs to the correct group:
1537  if (Workspace::wsv_data[wsvid].Group() !=
1538  Workspace::wsv_data[*outs].Group()) {
1539  throw WrongWsvGroup(
1540  wsvname + " is not " +
1541  wsv_group_names[Workspace::wsv_data[*outs].Group()] + ", it is " +
1543  msource.File(),
1544  msource.Line(),
1545  msource.Column());
1546  }
1547 
1548  output.push_back(wsvid);
1549  }
1550 
1551  eat_whitespace();
1552 }
1553 
1568  const ArrayOfIndex& auto_vars,
1569  const Array<TokVal>& auto_vars_values,
1570  const Index method_type,
1571  Agenda& tasklist) {
1572  using global_data::MdMap;
1574 
1575  for (Index i = 0; i < auto_vars.nelem(); i++) {
1576  map<String, Index>::const_iterator mdit;
1577  Index init_mdid;
1578  TokVal auto_keyword_value;
1579  ArrayOfIndex auto_output_var;
1580  ArrayOfIndex auto_input_var;
1581  Agenda auto_tasks;
1582 
1583  const Index auto_group = Workspace::wsv_data[auto_vars[i]].Group();
1584  if (auto_group != get_wsv_group_id("Index") &&
1585  auto_group != get_wsv_group_id("Numeric") &&
1586  auto_group != get_wsv_group_id("ArrayOfIndex") &&
1587  auto_group != get_wsv_group_id("ArrayOfString") &&
1588  auto_group != get_wsv_group_id("String") &&
1589  auto_group != get_wsv_group_id("Vector") &&
1590  auto_group != get_wsv_group_id("Matrix")) {
1591  ostringstream os;
1592  os << "Passing a "
1593  << wsv_group_names[Workspace::wsv_data[auto_vars[i]].Group()]
1594  << " constant to a WSM is not supported!";
1595  throw ParseError(
1596  os.str(), msource.File(), msource.Line(), msource.Column());
1597  }
1598 
1599  String method_name;
1600  switch (method_type) {
1601  case 0:
1602  auto_keyword_value = auto_vars_values[i];
1603  auto_output_var.push_back(auto_vars[i]);
1604  method_name =
1605  wsv_group_names[Workspace::wsv_data[auto_vars[i]].Group()] + "Set";
1606  break;
1607  case 1:
1608  auto_input_var.push_back(auto_vars[i]);
1609  method_name =
1610  "Delete_sg_" +
1611  wsv_group_names[Workspace::wsv_data[auto_vars[i]].Group()];
1612  break;
1613  default:
1614  throw ParseError("Invalid method type.",
1615  msource.File(),
1616  msource.Line(),
1617  msource.Column());
1618  }
1619 
1620  mdit = MdMap.find(method_name);
1621  assert(mdit != MdMap.end());
1622  init_mdid = mdit->second;
1623 
1624  tasklist.push_back(MRecord(init_mdid,
1625  auto_output_var,
1626  auto_input_var,
1627  auto_keyword_value,
1628  auto_tasks,
1629  true));
1630  }
1631 }
1632 
1643 bool ArtsParser::is_whitespace(const char c) {
1644  switch (c) {
1645  case ' ':
1646  case '\r':
1647  case '\t':
1648  case '#':
1649  return true;
1650  break;
1651  }
1652 
1653  return false;
1654 }
1655 
1666  char dummy;
1667 
1668  while (is_whitespace(dummy = msource.Current())) {
1669  switch (dummy) {
1670  case ' ':
1671  case '\r':
1672  case '\t':
1673  msource.AdvanceChar();
1674  break;
1675  case '#':
1676  msource.AdvanceLine();
1677  break;
1678  default: {
1679  ostringstream os;
1680  os << "Expected whitespace, but got `" << dummy << "'.";
1681  throw UnexpectedChar(
1682  os.str(), msource.File(), msource.Line(), msource.Column());
1683  break;
1684  }
1685  }
1686  }
1687 }
1688 
1695  while (pos < str.length() && is_whitespace(str[pos])) pos++;
1696 }
1697 
1710  bool stop = false;
1711  name = "";
1712 
1713  if (!isalpha(msource.Current())) {
1714  ostringstream os;
1715  os << "Workspace variable names must start with a letter!";
1716  throw ParseError(
1717  os.str(), msource.File(), msource.Line(), msource.Column());
1718  }
1719 
1720  while (!stop) {
1721  char dummy = msource.Current();
1722 
1723  if (isalnum(dummy) || '_' == dummy) {
1724  name += dummy;
1725  // AdvanceChar sets LineBreak if a line break occured.
1726  msource.LineBreak() = false;
1727  msource.AdvanceChar();
1728  if (msource.LineBreak()) stop = true;
1729  } else {
1730  stop = true;
1731  }
1732  }
1733 }
1734 
1755  ArrayOfIndex& auto_vars,
1756  Array<TokVal>& auto_vars_values,
1757  const String& default_name,
1758  const MdRecord* mdd,
1759  const Index group) {
1760  name = "";
1761 
1762  if (isalpha(msource.Current())) {
1763  read_name(name);
1764  return -1;
1765  }
1766 
1767  if (group == get_wsv_group_id("Any")) {
1768  ostringstream os;
1769  os << "Passing constants as supergeneric arguments is not supported.";
1770  throw ParseError(
1771  os.str(), msource.File(), msource.Line(), msource.Column());
1772  }
1773 
1774  // If a value was given instead of a variable name, we create
1775  // a new variable in the workspace and fill it with the given
1776  // value
1777 
1778  Index wsvid;
1779 
1780  name = "auto_" + mdd->Name() + "_" + default_name;
1781  map<String, Index>::const_iterator wsvit = Workspace::WsvMap.find(name);
1782  if (wsvit == Workspace::WsvMap.end()) {
1783  wsvid = Workspace::add_wsv(WsvRecord(
1784  name.c_str(), "Automatically allocated variable.", group, true));
1785  } else {
1786  wsvid = wsvit->second;
1787  }
1788 
1789  auto_vars.push_back(wsvid);
1790 
1791  // Now parse the value. This can be:
1792  // String_, Index_, Numeric_, Array_String_, Array_Index_, Vector_, Matrix_
1793  if (group == get_wsv_group_id("String")) {
1794  String dummy;
1795  parse_String(dummy);
1796  auto_vars_values.push_back(dummy);
1797  } else if (group == get_wsv_group_id("Index")) {
1798  Index n;
1799  parse_integer(n);
1800  auto_vars_values.push_back(n);
1801  } else if (group == get_wsv_group_id("Numeric")) {
1802  Numeric n;
1803  parse_numeric(n);
1804  auto_vars_values.push_back(n);
1805  } else if (group == get_wsv_group_id("ArrayOfString")) {
1806  ArrayOfString dummy;
1807  parse_Stringvector(dummy);
1808  auto_vars_values.push_back(dummy);
1809  } else if (group == get_wsv_group_id("ArrayOfIndex")) {
1810  ArrayOfIndex dummy;
1811  parse_intvector(dummy);
1812  auto_vars_values.push_back(dummy);
1813  } else if (group == get_wsv_group_id("Vector")) {
1814  Vector dummy;
1815  parse_numvector(dummy);
1816  auto_vars_values.push_back(dummy);
1817  } else if (group == get_wsv_group_id("Matrix")) {
1818  Matrix dummy;
1819  parse_matrix(dummy);
1820  auto_vars_values.push_back(dummy);
1821  } else {
1823  ostringstream os;
1824  os << "Unsupported argument type: " << wsv_group_names[group];
1825  throw ParseError(
1826  os.str(), msource.File(), msource.Line(), msource.Column());
1827  }
1828 
1829  return wsvid;
1830 }
1831 
1839  if (c != msource.Current()) {
1840  ostringstream os;
1841  os << "Expected '" << c << "', but got '" << msource.Current() << "'.";
1842  throw UnexpectedChar(
1843  os.str(), msource.File(), msource.Line(), msource.Column());
1844  }
1845 
1846  msource.AdvanceChar();
1847 }
1848 
1860  bool stop = false;
1861  res = "";
1862 
1863  msource.LineBreak() = false;
1864  assertain_character('"');
1865  if (msource.LineBreak())
1866  throw IllegalLinebreak("Line break before end of String.",
1867  msource.File(),
1868  msource.Line(),
1869  msource.Column());
1870 
1871  while (!stop) {
1872  char dummy = msource.Current();
1873  if (dummy != '"') {
1874  res += dummy;
1875  msource.AdvanceChar();
1876 
1877  if (msource.LineBreak())
1878  throw IllegalLinebreak("Line break before end of String.",
1879  msource.File(),
1880  msource.Line(),
1881  msource.Column());
1882  } else {
1883  stop = true;
1884  msource.AdvanceChar();
1885  }
1886  }
1887 }
1888 
1902  bool stop = false;
1903  res = "";
1904  char dummy;
1905  msource.LineBreak() = false;
1906 
1907  dummy = msource.Current();
1908  if ('+' == dummy || '-' == dummy) {
1909  res += dummy;
1910  msource.AdvanceChar();
1911  if (msource.LineBreak())
1912  throw IllegalLinebreak("Line break after sign.",
1913  msource.File(),
1914  msource.Line(),
1915  msource.Column());
1916  }
1917 
1918  if (!isdigit(msource.Current())) {
1919  ostringstream os;
1920  os << "Expected digit or variable name, but got `" << msource.Current()
1921  << "'.";
1922  throw UnexpectedChar(
1923  os.str(), msource.File(), msource.Line(), msource.Column());
1924  }
1925 
1926  while (!stop) {
1927  char chtmp = msource.Current();
1928  if (isdigit(chtmp)) {
1929  res += chtmp;
1930  msource.AdvanceChar();
1931  if (msource.LineBreak()) stop = true;
1932  } else {
1933  stop = true;
1934  }
1935  }
1936 }
1937 
1954  bool stop;
1955  res = "";
1956  char dummy;
1957  msource.LineBreak() = false;
1958 
1959  // To make sure that there is at least one digit:
1960  bool found_digit = false;
1961 
1962  // Check if there is a sign:
1963  dummy = msource.Current();
1964  if ('+' == dummy || '-' == dummy) {
1965  res += dummy;
1966  msource.AdvanceChar();
1967  if (msource.LineBreak())
1968  throw IllegalLinebreak("Linebreak after sign.",
1969  msource.File(),
1970  msource.Line(),
1971  msource.Column());
1972  }
1973 
1974  // There could be some digits here:
1975  stop = false;
1976  while (!stop) {
1977  char chtmp = msource.Current();
1978  if (isdigit(chtmp)) {
1979  found_digit = true;
1980  res += chtmp;
1981  msource.AdvanceChar();
1982  if (msource.LineBreak()) return; // Line break ends scanning immediately.
1983  } else {
1984  stop = true;
1985  }
1986  }
1987 
1988  // Next there can be a decimal point
1989  if ('.' == msource.Current()) {
1990  res += ".";
1991  msource.AdvanceChar();
1992  if (msource.LineBreak()) {
1993  if (found_digit) {
1994  // Line break ends scanning immediately, if we have
1995  // already found at least one digit.
1996  return;
1997  } else {
1998  throw IllegalLinebreak("Expected at least one digit.",
1999  msource.File(),
2000  msource.Line(),
2001  msource.Column());
2002  }
2003  }
2004 
2005  // ... followed by optional more digits
2006  stop = false;
2007  while (!stop) {
2008  char chtmp = msource.Current();
2009  if (isdigit(chtmp)) {
2010  found_digit = true;
2011  res += chtmp;
2012  msource.AdvanceChar();
2013  if (msource.LineBreak())
2014  return; // Line break ends scanning immediately.
2015  } else {
2016  stop = true;
2017  }
2018  }
2019  }
2020 
2021  // At this point, we must have found at least one digit.
2022  if (!found_digit)
2023  throw ParseError("Expected at least one digit.",
2024  msource.File(),
2025  msource.Line(),
2026  msource.Column());
2027 
2028  // Now there could be a `e' or `E':
2029  dummy = msource.Current();
2030  if ('e' == dummy || 'E' == dummy) {
2031  res += dummy;
2032  msource.AdvanceChar();
2033  if (msource.LineBreak())
2034  throw IllegalLinebreak("Linebreak after e/E.",
2035  msource.File(),
2036  msource.Line(),
2037  msource.Column());
2038 
2039  // Now there must be an integer (with optional sign)
2040  {
2041  String s;
2042  read_integer(s);
2043  res += s;
2044  }
2045  }
2046 }
2047 
2053  String res;
2054  read_integer(res);
2055  istringstream is(res);
2056  is >> n;
2057 }
2058 
2064  String res;
2065  read_numeric(res);
2066  istringstream is(res);
2067  is >> double_imanip() >> n;
2068 }
2069 
2085  bool first = true; // To skip the first comma.
2086  res.resize(0); // Clear the result vector (just in case).
2087 
2088  // Make sure that the current character really is `[' and proceed.
2089  assertain_character('[');
2090  // There might have occured a linebreak, which is fine.
2091 
2092  eat_whitespace();
2093 
2094  // Read the elements of the vector (`]' means that we have
2095  // reached the end):
2096  while (']' != msource.Current()) {
2097  String dummy;
2098 
2099  if (first)
2100  first = false;
2101  else {
2102  assertain_character(',');
2103  eat_whitespace();
2104  }
2105 
2106  parse_String(dummy);
2107  res.push_back(dummy);
2108  eat_whitespace();
2109  }
2110 
2111  msource.AdvanceChar();
2112 }
2113 
2126  bool first = true; // To skip the first comma.
2127  res.resize(0); // Clear the result vector (just in case).
2128 
2129  // Make sure that the current character really is `[' and proceed.
2130  assertain_character('[');
2131  // There might have occured a linebreak, which is fine.
2132 
2133  eat_whitespace();
2134 
2135  // Read the elements of the vector (`]' means that we have
2136  // reached the end):
2137  while (']' != msource.Current()) {
2138  Index dummy;
2139 
2140  if (first)
2141  first = false;
2142  else {
2143  assertain_character(',');
2144  eat_whitespace();
2145  }
2146 
2147  parse_integer(dummy);
2148  res.push_back(dummy);
2149  eat_whitespace();
2150  }
2151 
2152  msource.AdvanceChar();
2153 }
2154 
2167  bool first = true; // To skip the first comma.
2168 
2169  // We need a temporary Array<Numeric>, so that we can use push_back
2170  // to store the values. FIXME: Need also constructor for Vector from
2171  // Array<Numeric>.
2172  Array<Numeric> tres;
2173 
2174  // Make sure that the current character really is `[' and proceed.
2175  assertain_character('[');
2176  // There might have occured a linebreak, which is fine.
2177 
2178  eat_whitespace();
2179 
2180  // Read the elements of the vector (`]' means that we have
2181  // reached the end):
2182  while (']' != msource.Current()) {
2183  Numeric dummy;
2184 
2185  if (first)
2186  first = false;
2187  else {
2188  assertain_character(',');
2189  eat_whitespace();
2190  }
2191 
2192  parse_numeric(dummy);
2193  tres.push_back(dummy);
2194  eat_whitespace();
2195  }
2196 
2197  // Copy tres to res:
2198  res.resize(tres.nelem());
2199  for (int i = 0; i < tres.nelem(); i++) {
2200  res[i] = tres[i];
2201  }
2202 
2203  msource.AdvanceChar();
2204 }
2205 
2218  bool first = true; // To skip the first comma.
2219 
2220  // We need a temporary Array<Numeric>, so that we can use push_back
2221  // to store the values. FIXME: Need also constructor for Vector from
2222  // Array<Numeric>.
2223  Array<Numeric> tres;
2224 
2225  // Make sure that the current character really is `[' and proceed.
2226  assertain_character('[');
2227  // There might have occured a linebreak, which is fine.
2228 
2229  eat_whitespace();
2230 
2231  Index ncols = -1;
2232  Index nrows = 0;
2233  Index cur_ncols = 0;
2234  // Read the elements of the vector (`]' means that we have
2235  // reached the end):
2236  while (']' != msource.Current()) {
2237  Numeric dummy;
2238 
2239  if (first) {
2240  first = false;
2241  cur_ncols = 1;
2242  nrows = 1;
2243  } else {
2244  if (',' == msource.Current()) {
2245  cur_ncols++;
2246  if (ncols != -1 && cur_ncols > ncols) {
2247  ostringstream os;
2248  os << "Expected ';', but got '" << msource.Current()
2249  << "'. Check Matrix dimensions.";
2250  throw UnexpectedChar(
2251  os.str(), msource.File(), msource.Line(), msource.Column());
2252  }
2253  msource.AdvanceChar();
2254  eat_whitespace();
2255  } else if (';' == msource.Current()) {
2256  nrows++;
2257  if (ncols == -1) {
2258  ncols = cur_ncols;
2259  } else if (ncols != cur_ncols) {
2260  ostringstream os;
2261  os << "Expected ',', but got '" << msource.Current()
2262  << "'. Check Matrix dimensions.";
2263  throw UnexpectedChar(
2264  os.str(), msource.File(), msource.Line(), msource.Column());
2265  }
2266  cur_ncols = 1;
2267  msource.AdvanceChar();
2268  eat_whitespace();
2269  } else {
2270  char c = ';';
2271  if (ncols > cur_ncols) c = ',';
2272  ostringstream os;
2273  os << "Expected '" << c << "', but got '" << msource.Current()
2274  << "'. Check Matrix dimensions.";
2275  throw UnexpectedChar(
2276  os.str(), msource.File(), msource.Line(), msource.Column());
2277  }
2278  }
2279 
2280  parse_numeric(dummy);
2281  tres.push_back(dummy);
2282  eat_whitespace();
2283  }
2284 
2285  if (ncols == -1) ncols = cur_ncols;
2286  if (ncols != cur_ncols) {
2287  throw ParseError("Missing element(s) in last row of matrix",
2288  msource.File(),
2289  msource.Line(),
2290  msource.Column());
2291  }
2292 
2293  // Copy tres to res:
2294  res.resize(nrows, ncols);
2295  for (Index i = 0; i < nrows; i++)
2296  for (Index j = 0; j < ncols; j++) res(i, j) = tres[i * ncols + j];
2297 
2298  msource.AdvanceChar();
2299 }
2300 
2309  bool first = true; // To skip the first comma.
2310  size_t pos = 0;
2311 
2312  // We need a temporary Array<Numeric>, so that we can use push_back
2313  // to store the values.
2314  Array<Index> tres;
2315 
2316  eat_whitespace_from_string(str, pos);
2317 
2318  // Make sure that the current character really is `[' and proceed.
2319  if (str[pos] != '[') {
2320  throw ParseError("No opening bracket found while parsing ArrayOfIndex.",
2321  msource.File(),
2322  msource.Line(),
2323  msource.Column());
2324  }
2325 
2326  pos++;
2327 
2328  eat_whitespace_from_string(str, pos);
2329 
2330  // Read the elements of the vector (`]' means that we have
2331  // reached the end):
2332  while (pos < str.length() && str[pos] != ']') {
2333  if (first)
2334  first = false;
2335  else {
2336  if (str[pos] != ',') {
2337  return false;
2338  }
2339  pos++;
2340  eat_whitespace_from_string(str, pos);
2341  }
2342 
2343  Index dummy;
2344  istringstream is(str.substr(pos));
2345  is >> dummy;
2346  if (is.bad() || is.fail()) return false;
2347  tres.push_back(dummy);
2348  while (pos < str.length() &&
2349  (isdigit(str[pos]) || str[pos] == '-' || str[pos] == 'e'))
2350  pos++;
2351  eat_whitespace_from_string(str, pos);
2352  }
2353 
2354  // Copy tres to res:
2355  res.resize(tres.nelem());
2356  for (int i = 0; i < tres.nelem(); i++) {
2357  res[i] = tres[i];
2358  }
2359 
2360  return true;
2361 }
2362 
2371  bool first = true; // To skip the first comma.
2372  size_t pos = 0;
2373 
2374  // We need a temporary Array<Numeric>, so that we can use push_back
2375  // to store the values.
2376  Array<Numeric> tres;
2377 
2378  eat_whitespace_from_string(str, pos);
2379 
2380  // Make sure that the current character really is `[' and proceed.
2381  if (str[pos] != '[') {
2382  throw ParseError("No opening bracket found while parsing Vector.",
2383  msource.File(),
2384  msource.Line(),
2385  msource.Column());
2386  }
2387 
2388  pos++;
2389 
2390  eat_whitespace_from_string(str, pos);
2391 
2392  // Read the elements of the vector (`]' means that we have
2393  // reached the end):
2394  while (pos < str.length() && str[pos] != ']') {
2395  if (first)
2396  first = false;
2397  else {
2398  if (str[pos] != ',') {
2399  return false;
2400  }
2401  pos++;
2402  eat_whitespace_from_string(str, pos);
2403  }
2404 
2405  Numeric dummy;
2406  istringstream is(str.substr(pos));
2407  is >> double_imanip() >> dummy;
2408  if (is.bad() || is.fail()) return false;
2409  tres.push_back(dummy);
2410  if (str[pos] == 'N' && str.find("NaN", pos) == pos) {
2411  pos += 3;
2412  } else {
2413  while (pos < str.length() && (isdigit(str[pos]) || str[pos] == '-' ||
2414  str[pos] == '.' || str[pos] == 'e'))
2415  pos++;
2416  }
2417  eat_whitespace_from_string(str, pos);
2418  }
2419 
2420  // Copy tres to res:
2421  res.resize(tres.nelem());
2422  for (int i = 0; i < tres.nelem(); i++) {
2423  res[i] = tres[i];
2424  }
2425 
2426  return true;
2427 }
2428 
2438  String& str) {
2439  bool first = true; // To skip the first comma.
2440  size_t pos = 0;
2441 
2442  // We need a temporary Array<Numeric>, so that we can use push_back
2443  // to store the values.
2444  ArrayOfString tres;
2445 
2446  eat_whitespace_from_string(str, pos);
2447 
2448  // Make sure that the current character really is `[' and proceed.
2449  if (str[pos] != '[') {
2450  throw ParseError("No opening bracket found while parsing ArrayOfString.",
2451  msource.File(),
2452  msource.Line(),
2453  msource.Column());
2454  }
2455 
2456  pos++;
2457 
2458  eat_whitespace_from_string(str, pos);
2459 
2460  // Read the elements of the vector (`]' means that we have
2461  // reached the end):
2462  while (pos < str.length() && str[pos] != ']') {
2463  if (first)
2464  first = false;
2465  else {
2466  if (str[pos] != ',') {
2467  return false;
2468  }
2469  pos++;
2470  eat_whitespace_from_string(str, pos);
2471  }
2472 
2473  if (str[pos] != '"') {
2474  throw ParseError("Expected quotes while parsing ArrayOfString.",
2475  msource.File(),
2476  msource.Line(),
2477  msource.Column());
2478  }
2479 
2480  pos++;
2481 
2482  String dummy;
2483  while (pos < str.length() && str[pos] != '"') {
2484  dummy += str[pos];
2485  pos++;
2486  }
2487 
2488  if (pos == str.length() || str[pos] != '"') return false;
2489 
2490  tres.push_back(dummy);
2491 
2492  eat_whitespace_from_string(str, pos);
2493  }
2494 
2495  // Copy tres to res:
2496  res.resize(tres.nelem());
2497  for (int i = 0; i < tres.nelem(); i++) {
2498  res[i] = tres[i];
2499  }
2500 
2501  return true;
2502 }
const String & File()
Return the filename associated with the current position.
Definition: sourcetext.cc:60
Index get_wsv_group_id(const String &name)
Returns the id of the given group.
Definition: groups.cc:223
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
static Array< WsvRecord > wsv_data
Global WSV data.
Definition: workspace_ng.h:58
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:603
virtual Index line() const
Definition: exceptions.h:55
bool parse_stringarray_from_string(ArrayOfString &res, String &str)
Read an Array of Strings from a String.
Definition: parser.cc:2437
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:353
void at_end_of_argument(const String &argname)
Check if current position in controlfile is at the end of an argument.
Definition: parser.cc:154
Agenda & mtasklist
Definition: parser.h:161
The Agenda class.
Definition: agenda_class.h:44
void find_named_arguments(vector< NamedArgument > &named_args)
Find named arguments.
Definition: parser.cc:60
Index nelem() const
Number of elements.
Definition: array.h:195
virtual String file() const
Definition: exceptions.h:54
bool parse_numvector_from_string(Vector &res, String &str)
Read a vector of Numerics from a String.
Definition: parser.cc:2370
bool AgendaMethod() const
Definition: methods.h:106
The Vector class.
Definition: matpackI.h:860
void parse_tasklist()
Public interface to the main function of the parser.
Definition: parser.cc:50
void SetMark()
Mark current position.
Definition: sourcetext.h:101
Index mcfile_version
Definition: parser.h:167
bool SetMethod() const
Definition: methods.h:105
const ArrayOfIndex & Out() const
Definition: methods.h:91
Index MarkedLine()
Return the marked line number, but for the file that is associated with the current position...
Definition: sourcetext.h:80
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:1754
void resize(Index n)
Resize the method list.
Definition: agenda_class.h:257
void get_dirname(String &dirname, const String &path)
Return the parent directory of a path.
Definition: file.cc:519
ArtsParser(Agenda &tasklist, String controlfile, const Verbosity &verbosity)
Constructs a new parser.
Definition: parser.cc:36
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:41
bool Supergeneric() const
Definition: methods.h:107
void AdvanceChar()
Advance position pointer by one character.
Definition: sourcetext.cc:29
char Current()
Return the current character.
Definition: sourcetext.h:48
const String & Name() const
Definition: methods.h:88
vector< NamedArgument > NamedArguments
Definition: parser.h:39
ArrayOfString includepath
List of paths to search for include files.
Definition: parameters.h:106
void parse_String(String &res)
Reads a String, complete with quotation marks.
Definition: parser.cc:1859
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:2166
void parse_integer(Index &n)
Use a String stream to parse an integer number.
Definition: parser.cc:2052
const ArrayOfString & GOut() const
Definition: methods.h:92
This file contains the Workspace class.
ArrayOfString datapath
List of paths to search for data files.
Definition: parameters.h:108
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:977
const Array< String > & GInDefault() const
Definition: methods.h:100
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:1358
The global header file for ARTS.
#define NODEF
Definition: methods.h:35
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:1567
void parse_numeric(Numeric &n)
Use a String stream to parse a floating point number.
Definition: parser.cc:2063
Parameters parameters
Holds the command line parameters.
Definition: parameters.cc:41
void parse_main()
The main function of the parser.
Definition: parser.cc:184
_CS_string_type str() const
Definition: sstream.h:491
void skip_to_next_argument()
Skips forward to the next argument.
Definition: parser.cc:91
void parse_agenda(Agenda &tasklist, const String &agenda_name)
Parse the Contents of text as ARTS control input.
Definition: parser.cc:333
void AppendFile(const String &name)
Appends contents of file to the source text.
Definition: sourcetext.cc:22
void eat_whitespace_from_string(String &str, size_t &pos)
Eats whitespace from a String.
Definition: parser.cc:1694
The declarations of all the exception classes.
Method runtime data.
Definition: agenda_class.h:121
void eat_whitespace()
Eats whitespace.
Definition: parser.cc:1665
Definition: exceptions.h:67
const ArrayOfArrayOfIndex & GInSpecType() const
Definition: methods.h:99
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
The Matrix class.
Definition: matpackI.h:1193
Index nelem() const
Number of elements.
Definition: mystring.h:246
void read_integer(String &res)
Reads an integer.
Definition: parser.cc:1901
void Init()
This sets the pointer to the first existing character in the text.
Definition: sourcetext.cc:74
void SetPosition(Index line, Index column)
Set current position.
Definition: sourcetext.h:95
String mcfile
Definition: parser.h:163
Index nelem() const
Return the number of agenda elements.
Definition: agenda_class.h:266
bool & LineBreak()
Read the line break flag.
Definition: sourcetext.h:112
void assertain_character(char c)
Make sure that the current character is equal to c and go to the next character.
Definition: parser.cc:1838
Index MarkedColumn()
Return the current marked column.
Definition: sourcetext.h:92
void parse_intvector(ArrayOfIndex &res)
Read a vector of integers.
Definition: parser.cc:2125
const ArrayOfIndex & InOnly() const
Definition: methods.h:102
void read_name(String &name)
Reads name of method, keyword, or workspace variable.
Definition: parser.cc:1709
const ArrayOfIndex & GOutType() const
Definition: methods.h:93
Index ColumnRaw()
Return the column index.
Definition: sourcetext.h:86
const ArrayOfString wsv_group_names
The names associated with Wsv groups as Strings.
Definition: global_data.h:93
SourceText msource
Definition: parser.h:165
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:496
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:1163
static map< String, Index > WsvMap
Global map associated with wsv_data.
Definition: workspace_ng.h:61
void resize(Index n)
Resize function.
Definition: matpackI.cc:404
static Index add_wsv(const WsvRecord &wsv)
Append a new WSV to the workspace.
Definition: workspace_ng.cc:54
const Array< MRecord > & Methods() const
Definition: agenda_class.h:74
bool is_whitespace(const char c)
Returns true if this character is considered whitespace.
Definition: parser.cc:1643
const Verbosity & verbosity
Definition: parser.h:169
void parse_matrix(Matrix &res)
Read a Matrix.
Definition: parser.cc:2217
Index nelem(const Lines &l)
Number of lines.
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:169
virtual Index column() const
Definition: exceptions.h:56
#define _U_
Definition: config.h:183
bool reachedEot()
Check if the current position reached the end.
Definition: sourcetext.h:55
const ArrayOfArrayOfIndex & GOutSpecType() const
Definition: methods.h:94
const Array< MdRecord > md_data
Lookup information for workspace methods.
#define CREATE_OUT0
Definition: messages.h:204
#define CREATE_OUT3
Definition: messages.h:207
const ArrayOfIndex & GInType() const
Definition: methods.h:98
Index LineRaw()
Return the line index.
Definition: sourcetext.h:83
This class contains all static information for one workspace variable.
Definition: wsv_aux.h:56
This file contains header information for the dealing with command line parameters.
constexpr Rational end(Rational Ju, Rational Jl, Polarization type) noexcept
Gives the largest M for a polarization type of this transition.
Definition: zeemandata.h:108
void AdvanceLine()
Advances position pointer by one line.
Definition: sourcetext.cc:48
Index Column()
Return the current column.
Definition: sourcetext.h:89
void parse_Stringvector(ArrayOfString &res)
Read a vector of Strings.
Definition: parser.cc:2084
#define CREATE_OUT2
Definition: messages.h:206
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:746
This stores arbitrary token values and remembers the type.
Definition: token.h:40
Index Line()
Return the line number, but for the file that is associated with the current position.
Definition: sourcetext.h:76
bool parse_intvector_from_string(ArrayOfIndex &res, String &str)
Read an array of integers from a String.
Definition: parser.cc:2308
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:1458
void read_numeric(String &res)
Reads a floating point number.
Definition: parser.cc:1953
Input manipulator class for doubles to enable nan and inf parsing.
Definition: file.h:117
Declaration of the class MdRecord.
const ArrayOfString & GIn() const
Definition: methods.h:97
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:1056
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:274