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