ARTS 2.5.4 (git: 4c0d3b4d)
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 <algorithm>
20#include <iostream>
21#include "arts.h"
22#include "exceptions.h"
23#include "file.h"
24#include "global_data.h"
25#include "methods.h"
26#include "parameters.h"
27#include "workspace_ng.h"
28#include "wsv_aux.h"
29
38 String controlfile,
39 const Verbosity& rverbosity)
40 : mtasklist(tasklist),
41 mcfile(controlfile),
42 mcfile_version(1),
43 verbosity(rverbosity) {
45}
46
52
61void ArtsParser::find_named_arguments(vector<NamedArgument>& named_args) {
62 NamedArgument current_argument;
63
64 named_args.resize(0);
65
66 while (msource.Current() != ')') {
67 read_name(current_argument.name);
69 if (msource.Current() != '=') {
70 ostringstream os;
71 os << "Expected '=', but got '" << msource.Current() << "'.\n"
72 << "Mixing positional and named arguments is not allowed.";
73 throw UnexpectedChar(
74 os.str(), msource.File(), msource.Line(), msource.Column());
75 }
76
79
80 current_argument.line = msource.LineRaw();
81 current_argument.column = msource.ColumnRaw();
82 named_args.push_back(current_argument);
83
85 }
86}
87
93 Index bracket_level = 0;
94 bool inside_quotes = false;
95 char prev_char = 0;
96 Index starting_line = msource.LineRaw();
97 Index starting_col = msource.ColumnRaw();
98
99 while ((bracket_level || inside_quotes) ||
100 (msource.Current() != ',' && msource.Current() != ')')) {
101 try {
102 switch (msource.Current()) {
103 case '[':
104 bracket_level++;
105 break;
106 case ']':
107 bracket_level--;
108 if (bracket_level < 0)
109 throw ParseError("Too many closing brackets",
110 msource.File(),
111 msource.Line(),
112 msource.Column());
113 break;
114 case '"':
115 if (prev_char != '\\') inside_quotes = !inside_quotes;
116 break;
117 }
118
119 prev_char = msource.Current();
120 if (msource.Current() == '#')
122 else
124 } catch (const Eot& x) {
125 msource.SetPosition(starting_line, starting_col);
126 throw ParseError(
127 "Unexpectedly reached end of file.\nProbably a runaway argument.",
128 msource.File(),
129 msource.Line(),
130 msource.Column());
131 }
132 }
133
134 if (msource.Current() == ',') {
135 try {
137 } catch (const Eot& x) {
138 throw ParseError(
139 "blablup", msource.File(), msource.Line(), msource.Column());
140 }
142 }
143}
144
157 if (msource.Current() != ',' && msource.Current() != ')') {
158 ostringstream os;
159 os << "Expected ',' or ')' but found '" << msource.Current() << "' after "
160 << argname;
161 throw UnexpectedChar(
162 os.str(), msource.File(), msource.Line(), msource.Column());
163 }
164}
165
171 NamedArguments& named_args,
172 String name) {
173 for (arg_index = 0; arg_index < (Index)named_args.size(); arg_index++) {
174 if (named_args[(size_t)arg_index].name == name) return;
175 }
176
177 arg_index = -1;
178}
179
188
189 try {
191
192 // For method ids:
193 Index id;
194 // Output workspace variables (for generic methods):
195 ArrayOfIndex output;
196 // Input workspace variables (for generic methods):
197 ArrayOfIndex input;
198 // For include statements, holding the include file's name
199 String include_file;
200
201 ArrayOfIndex auto_vars;
202 Array<TokVal> auto_vars_values;
203
204 out3 << "\nParsing control text:\n";
205
206 msource.Init();
208
209 parse_method(id,
210 output,
211 input,
212 mtasklist,
213 auto_vars,
214 auto_vars_values,
215 include_file,
216 true);
217
218 if ("Arts" != md_data[id].Name() && "Arts2" != md_data[id].Name()) {
219 ostringstream os;
220 os << "The outermost agenda must be Arts2!\n"
221 << "(But it seems to be " << md_data[id].Name() << ".)\n";
222 throw ParseError(
223 os.str(), msource.File(), msource.Line(), msource.Column());
224 }
225
226 try {
228 if (!msource.reachedEot())
229 throw UnexpectedChar(
230 "", msource.File(), msource.Line(), msource.Column());
231 } catch (const Eot&) {
232 // It's ok to reach the end of the file here,
233 // that's actually what we want.
234 } catch (const UnexpectedChar& x) {
235 ostringstream os;
236 os << "Unexpected character(s) at the end of the control file\n";
237 os << "after the main agenda was already closed.\n";
238 os << "File: " << x.file() << '\n';
239 os << "Line: " << x.line() << '\n';
240 os << "Column: " << x.column() << '\n';
241 throw runtime_error(os.str());
242 }
243 } catch (const Eot& x) {
244 // Unexpected end of the source text:
245 ostringstream os;
246 os << "Unexpected end of control script.\n";
247 os << "File: " << x.file() << '\n';
248 os << "Line: " << x.line() << '\n';
249 throw runtime_error(os.str());
250 } catch (const UnexpectedChar& x) {
251 // Unexpected Character:
252 ostringstream os;
253 os << "Unexpected character:\n";
254 os << x.what() << '\n';
255 os << "File: " << x.file() << '\n';
256 os << "Line: " << x.line() << '\n';
257 os << "Column: " << x.column() << '\n';
258 throw runtime_error(os.str());
259 } catch (const IllegalLinebreak& x) {
260 // A line break in an illegal position:
261 ostringstream os;
262 os << "Illegal Line break:\n";
263 os << x.what() << '\n';
264 os << "File: " << x.file() << '\n';
265 os << "Line: " << x.line() << '\n';
266 throw runtime_error(os.str());
267 } catch (const UnknownMethod& x) {
268 // Method unknown:
269 // [**This should give a hint on how to obtain a list of allowed
270 // methods.]
271 ostringstream os;
272 os << "Unknown Method:\n";
273 os << x.what() << '\n';
274 os << "File: " << x.file() << '\n';
275 os << "Line: " << x.line() << '\n';
276 os << "Column: " << x.column() << '\n';
277 throw runtime_error(os.str());
278 } catch (const UnknownWsv& x) {
279 // Workspace variable unknown:
280 // [**This should give a hint on how to obtain a list of allowed
281 // Wsvs.]
282 ostringstream os;
283 os << "Unknown workspace variable:\n";
284 os << x.what() << '\n';
285 os << "File: " << x.file() << '\n';
286 os << "Line: " << x.line() << '\n';
287 os << "Column: " << x.column() << '\n';
288 throw runtime_error(os.str());
289 } catch (const WsvAlreadyExists& x) {
290 // Trying to create the same variable twice:
291 ostringstream os;
292 os << "Attempt to create a workspace variable that already exists:\n";
293 os << x.what() << '\n';
294 os << "File: " << x.file() << '\n';
295 os << "Line: " << x.line() << '\n';
296 os << "Column: " << x.column() << '\n';
297 throw runtime_error(os.str());
298 } catch (const WrongWsvGroup& x) {
299 // Workspace variable unknown:
300 // [**This should give a hint on how to obtain a list of Wsvs in
301 // this group.
302 ostringstream os;
303 os << "Workspace variable belongs to the wrong group:\n";
304 os << x.what() << '\n';
305 os << "File: " << x.file() << '\n';
306 os << "Line: " << x.line() << '\n';
307 os << "Column: " << x.column() << '\n';
308 throw runtime_error(os.str());
309 } catch (const ParseError& x) {
310 // General Parse Error (parent of all the above):
311 ostringstream os;
312 os << "Parse error:\n";
313 os << x.what() << '\n';
314 os << "File: " << x.file() << '\n';
315 os << "Line: " << x.line() << '\n';
316 os << "Column: " << x.column() << '\n';
317 throw runtime_error(os.str());
318 }
319}
320
334void ArtsParser::parse_agenda(Agenda& tasklist, const String& agenda_name) {
337
339
340 // For method ids:
341 Index id;
342 // Output workspace variables:
343 ArrayOfIndex output;
344 // Input workspace variables:
345 ArrayOfIndex input;
346 // For Agenda, if there is any:
347 Agenda tasks;
348 // For include statements, holding the include file's name
349 String include_file;
350
351 ArrayOfIndex auto_vars;
352 Array<TokVal> auto_vars_values;
353
355
356 while ('}' != msource.Current()) {
358 id, output, input, tasks, auto_vars, auto_vars_values, include_file);
359
360 // If parse_method found an include statement it returnes -1 for the
361 // method id
362 if (id == -1) {
363 // Command line parameters which give us the include search path.
364 extern Parameters parameters;
365
366 ArrayOfString current_includepath = parameters.includepath;
367 String includedir;
368 get_dirname(includedir, msource.File());
369 if (includedir.nelem()) {
370 if (current_includepath.nelem() && current_includepath[0] != includedir)
371 current_includepath.insert(current_includepath.begin(), includedir);
372 if (parameters.datapath.nelem() && parameters.datapath[0] != includedir)
373 parameters.datapath.insert(parameters.datapath.begin(), includedir);
374 }
375
376 ArrayOfString matching_files;
377 find_file(matching_files, include_file, current_includepath);
378 find_file(matching_files, include_file + ".arts", current_includepath);
379
380 if (!matching_files.nelem()) {
381 ostringstream os;
382 os << "Cannot find include file " << include_file << ".\n";
383 os << "File: " << msource.File() << '\n';
384 os << "Search path was: " << current_includepath << "\n";
385 throw ParseError(
386 os.str(), msource.File(), msource.Line(), msource.Column());
387 }
388
389 include_file = matching_files[0];
390 out2 << "- Including control file " << include_file << "\n";
391
392 ArtsParser include_parser(tasks, include_file, verbosity);
393 include_parser.parse_tasklist();
394
395 for (Index i = 0; i < tasks.nelem(); i++)
396 tasklist.push_back(tasks.Methods()[i]);
397 } else {
398 if (md_data[id].SetMethod()) {
399 // Append task to task list:
400 tasklist.push_back(
401 MRecord(id, output, input, auto_vars_values[0], tasks));
402 } else {
403 tasklist_insert_set_delete(auto_vars, auto_vars_values, 0, tasklist);
404
405 // Append task to task list:
406 tasklist.push_back(MRecord(id, output, input, TokVal(), tasks));
407
408 tasklist_insert_set_delete(auto_vars, auto_vars_values, 1, tasklist);
409
410 // If Create was called on a variable that already existed,
411 // insert a Delete call to set it back to an uninitialized state
413 const String& mname = md_data[id].Name();
414
415 if (mname.length() > 6 && mname.find("Create") == mname.length() - 6 &&
416 get_wsv_group_id(mname.substr(0, mname.length() - 6)) != -1) {
417 if (agenda_name != "Arts2") {
418 ostringstream os;
419 os << mname << " cannot be called inside an agenda.\n"
420 << "All workspace variables are global and must be created at the top level.";
421 throw ParseError(
422 os.str(), msource.File(), msource.Line(), msource.Column());
423 }
424 using global_data::MdMap;
426 String method_name =
427 "Delete_sg_" +
428 wsv_group_names[Workspace::wsv_data[output[0]].Group()];
429 map<String, Index>::const_iterator mdit;
430 mdit = MdMap.find(method_name);
431 ARTS_ASSERT(mdit != MdMap.end());
432
433 tasklist.push_back(MRecord(
434 mdit->second, ArrayOfIndex(), output, TokVal(), Agenda(), true));
435 }
436 }
437
438 {
439 // Everything in this block is just to generate some
440 // informative output.
441
442 out3 << "- " << md_data[id].Name() << "\n";
443
444 // Output workspace variables for generic methods:
445 if (0 <
446 md_data[id].GOutType().nelem() + md_data[id].GInType().nelem()) {
447 out3 << " Output: ";
448 for (Index j = 0; j < output.nelem(); ++j) {
449 out3 << Workspace::wsv_data[output[j]].Name() << " ";
450 }
451 out3 << "\n";
452
453 out3 << " Input: ";
454 for (Index j = 0; j < input.nelem(); ++j) {
455 out3 << Workspace::wsv_data[input[j]].Name() << " ";
456 }
457 out3 << "\n";
458 }
459 }
460 }
461
463 }
464}
465
498 ArrayOfIndex& output,
499 ArrayOfIndex& input,
500 Agenda& tasks,
501 ArrayOfIndex& auto_vars,
502 Array<TokVal>& auto_vars_values,
503 String& include_file,
504 bool no_eot) {
506
507 String methodname; // We need this out here, since it is
508 // set once and later modified.
509
510 const MdRecord* mdd; // Handle on the method record. Needed here,
511 // because it is modified.
512
513 bool found_curly_brace = false;
514
515 // Clear all output variables:
516 id = 0;
517 output.resize(0);
518 input.resize(0);
519 tasks.resize(0);
520 auto_vars.resize(0);
521 auto_vars_values.resize(0);
522 include_file = "";
523
525 read_name(methodname);
526
527 if (methodname == "INCLUDE") {
529 parse_String(include_file);
530
531 id = -1;
532
533 return;
534 } else {
535 if (methodname == "Arts2") {
536 mcfile_version = 2;
537 } else if (methodname == "Arts") {
538 throw runtime_error(
539 "Arts version 1 controlfiles are no longer supported.");
540 }
541
543
545 mdd, id, methodname, output, input, auto_vars, auto_vars_values);
546
548
549 // Now look for the curly braces:
550 if (msource.Current() == '{') {
553 found_curly_brace = true;
554 }
555
556 // There are two kind of methods, agenda methods, which have other
557 // methods in the body, and normal methods, expecting keywords and
558 // values. Let's take the agenda case first...
559 if (mdd->AgendaMethod()) {
560 out3 << "- " << mdd->Name() << "\n";
561 out3 << "{\n";
562 parse_agenda(tasks, methodname);
563 out3 << "}\n";
564 }
565
566 // Curly braces in non-agenda methods are not valid in v2 controlfiles
567 if (mcfile_version == 2 && !mdd->AgendaMethod() && found_curly_brace) {
568 ostringstream os;
569 os << "Expected method name , but got `" << msource.Current() << "'.";
570 throw UnexpectedChar(
571 os.str(), msource.File(), msource.Line(), msource.Column());
572 os << "" << endl;
573 }
574 }
575
576 // Now look for the closing curly braces. We have to catch Eot,
577 // because after a method description may be a good place to end
578 // the control file.
579 if (found_curly_brace) {
580 try {
582 } catch (const Eot& x) {
583 // Re-throw the error if the no_eot flag is not set:
584 if (!no_eot) throw Eot(x);
585 }
586 }
587}
588
590
605 ArrayOfIndex& auto_vars,
606 Array<TokVal>& auto_vars_values,
607 Index gin_index) {
608 String name;
609
610 if (mdd->GInDefault()[gin_index] != NODEF) {
611 ostringstream os_default_error;
612 os_default_error
613 << "\nParse error in default value for generic input variable.\n"
614 << "This is not a user error but a bug in methods.cc.\n"
615 << "Please contact the ARTS developers.";
616
617 TokVal tv;
618 // Now parse the key value. This can be:
619 // String, Index, Numeric, ArrayOfString, ArrayOfIndex, Vector
620 bool failed = false;
621 if (mdd->GInType()[gin_index] == get_wsv_group_id("String")) {
622 tv = mdd->GInDefault()[gin_index];
623 } else if (mdd->GInType()[gin_index] == get_wsv_group_id("Index")) {
624 Index n;
625 istringstream is(mdd->GInDefault()[gin_index]);
626 is >> n;
627 tv = n;
628 if (is.bad() || is.fail()) failed = true;
629 } else if (mdd->GInType()[gin_index] == get_wsv_group_id("Numeric")) {
630 Numeric n = NAN;
631 istringstream is(mdd->GInDefault()[gin_index]);
632 is >> double_imanip() >> n;
633 tv = n;
634 if (is.bad() || is.fail()) failed = true;
635 } else if (mdd->GInType()[gin_index] == get_wsv_group_id("ArrayOfString")) {
637 String s = mdd->GInDefault()[gin_index];
638 try {
640 failed = true;
641 }
642 } catch (const ParseError& p) {
643 ostringstream os;
644 os << p.what() << os_default_error.str();
645 throw ParseError(os.str(), p.file(), p.line(), p.column());
646 }
647 tv = v;
648 } else if (mdd->GInType()[gin_index] == get_wsv_group_id("Vector")) {
649 Vector v;
650 String s = mdd->GInDefault()[gin_index];
651 try {
653 failed = true;
654 }
655 } catch (const ParseError& p) {
656 ostringstream os;
657 os << p.what() << os_default_error.str();
658 throw ParseError(os.str(), p.file(), p.line(), p.column());
659 }
660 tv = v;
661 } else if (mdd->GInType()[gin_index] == get_wsv_group_id("ArrayOfIndex")) {
663 String s = mdd->GInDefault()[gin_index];
664 try {
666 failed = true;
667 }
668 } catch (const ParseError& p) {
669 ostringstream os;
670 os << p.what() << os_default_error.str();
671 throw ParseError(os.str(), p.file(), p.line(), p.column());
672 }
673 tv = v;
674 } else if (mdd->GInType()[gin_index] == get_wsv_group_id("ArrayOfSpeciesTag")) {
676 String s = mdd->GInDefault()[gin_index];
677 if (s.nelem()) {
678 try {
679 v = ArrayOfSpeciesTag(s);
680 } catch (std::exception& e) {
681 std::ostringstream os;
682 os << e.what() << os_default_error.str();
683 throw ParseError(os.str(), msource.File(), msource.Line(), msource.Column());
684 }
685 }
686 tv = v;
687 } else {
689 ostringstream os;
690 os << "Default values for generic inputs with type "
691 << wsv_group_names[mdd->GInType()[gin_index]]
692 << " are not supported.\n"
693 << "Either remove the default value for generic input '"
694 << mdd->GIn()[gin_index] << "' in workspace method\n"
695 << "*" << mdd->Name() << "* in methods.cc or discuss this "
696 << "issue on the arts-dev mailing list.\n";
697 throw ParseError(
698 os.str(), msource.File(), msource.Line(), msource.Column());
699 }
700
701 Index wsvid;
702
703 {
704 ostringstream os;
705 os << gin_index;
706
707 name = "auto_" + mdd->Name() + "_" + "gin" + os.str() + "_" +
708 mdd->GIn()[gin_index];
709 }
710
711 map<String, Index>::const_iterator wsvit = Workspace::WsvMap.find(name);
712 if (wsvit == Workspace::WsvMap.end()) {
713 wsvid = Workspace::add_wsv(WsvRecord(name.c_str(),
714 "Automatically allocated variable.",
715 mdd->GInType()[gin_index],
716 true));
717 } else {
718 wsvid = wsvit->second;
719 }
720
721 auto_vars.push_back(wsvid);
722 auto_vars_values.push_back(tv);
723
724 if (failed) {
725 ostringstream os;
726 os << "Failed to assign default value for generic '"
727 << mdd->GIn()[gin_index] << "'.\n"
728 << "Check the documentation of workspace method *" << mdd->Name()
729 << "*.\n";
730 throw ParseError(
731 os.str(), msource.File(), msource.Line(), msource.Column());
732 }
733 } else {
734 ostringstream os;
735 os << "Generic input '" << mdd->GIn()[gin_index]
736 << "' omitted but no default value found.\n"
737 << "Check the documentation of workspace method *" << mdd->Name()
738 << "*.\n";
739 throw ParseError(
740 os.str(), msource.File(), msource.Line(), msource.Column());
741 }
742
743 return name;
744}
745
747
761 Index& id,
762 String& methodname,
763 ArrayOfIndex& output,
764 ArrayOfIndex& input,
765 ArrayOfIndex& auto_vars,
766 Array<TokVal>& auto_vars_values) {
769 using global_data::MdMap;
771
772 bool still_supergeneric = true; // Flag that our MdRecord still is
773 // from md_data_raw, not from
774 // md_data.
775
776 // Find method raw id in raw map:
777 const map<String, Index>::const_iterator md_raw_id =
778 MdRawMap.find(methodname);
779 if (md_raw_id == MdRawMap.end())
780 throw UnknownMethod(methodname,
781 msource.File(),
784
785 id = md_raw_id->second;
786
787 // Get a convenient handle on the data record for this method. We
788 // have to use a pointer here, not a reference, because we later
789 // want to change where mdd is pointing!
790 mdd = &md_data_raw[id];
791
792 // Is this a supergeneric method? If not, take the record in
793 // md_data, rather than in md_data_raw:
794 if (!mdd->Supergeneric()) {
795 // Find explicit method id in MdMap:
796 const map<String, Index>::const_iterator i2 = MdMap.find(methodname);
797 ARTS_ASSERT(i2 != MdMap.end());
798 id = i2->second;
799
800 mdd = &md_data[id];
801
802 still_supergeneric = false;
803 }
804
805 if (msource.Current() == '(') {
806 String supergeneric_args;
807 Index supergeneric_index = -1;
808 NamedArguments named_arguments;
809 Index this_method_end_line = -1;
810 Index this_method_end_column = -1;
811 bool call_by_name = false;
812
815
816 // Peak at the first method argument to determine if the method
817 // is called with positional or named arguments
818 if (isalpha(msource.Current())) {
819 Index line = msource.LineRaw();
820 Index column = msource.ColumnRaw();
821 String name = "";
822
823 read_name(name);
825
826 if (msource.Current() == '=') {
829
830 msource.SetPosition(line, column);
831 find_named_arguments(named_arguments);
832
833 call_by_name = true;
834
835 this_method_end_line = msource.LineRaw();
836 this_method_end_column = msource.ColumnRaw();
837 }
838
839 msource.SetPosition(line, column);
840 }
841
842 bool is_first_arg = true;
844 mdd, output, is_first_arg, named_arguments, call_by_name);
845
847 id,
848 methodname,
849 output,
850 is_first_arg,
851 still_supergeneric,
852 supergeneric_args,
853 supergeneric_index,
854 named_arguments,
855 call_by_name);
856
858 input,
859 auto_vars,
860 auto_vars_values,
861 is_first_arg,
862 named_arguments,
863 call_by_name);
864
866 id,
867 methodname,
868 input,
869 auto_vars,
870 auto_vars_values,
871 is_first_arg,
872 still_supergeneric,
873 supergeneric_args,
874 supergeneric_index,
875 named_arguments,
876 call_by_name);
877
878 // Named arguments are not parsed in order. We have to set the cursor
879 // to the end of the method call after all named arguments have been parsed.
880 if (call_by_name)
881 msource.SetPosition(this_method_end_line, this_method_end_column);
882
883 // If we're here and still have named arguments left means that
884 // the user specified too many for this method
885 if (call_by_name && named_arguments.size()) {
886 ostringstream os;
887
888 os << "Error in arguments passed to " << mdd->Name() << ":\n";
889 for (auto& argument_name : named_arguments) {
890 if (std::find(mdd->GIn().begin(),
891 mdd->GIn().end(),
892 argument_name.name) == mdd->GIn().end() &&
893 std::find(mdd->GOut().begin(),
894 mdd->GOut().end(),
895 argument_name.name) == mdd->GOut().end())
896 os << " Unkown argument: ";
897 else
898 os << " Duplicate argument: ";
899 os << argument_name.name << std::endl;
900 }
901 throw ParseError(
902 os.str(), msource.File(), msource.Line(), msource.Column());
903 }
904
905 ARTS_ASSERT(!still_supergeneric);
907 } else {
908 if (mdd->GOut().nelem()) {
909 ostringstream os;
910 os << "This method has generic output. "
911 << "You have to pass a variable!";
912 throw ParseError(os.str(),
913 msource.File(),
916 }
917
918 // If the parenthesis were omitted we still have to add the implicit
919 // outputs and inputs to the methods input and output variable lists
920 ArrayOfIndex vo = mdd->Out();
921 for (ArrayOfIndex::const_iterator outs = vo.begin(); outs < vo.end();
922 ++outs) {
923 output.push_back(*outs);
924 }
925
926 const ArrayOfIndex& vi = mdd->InOnly();
927 for (ArrayOfIndex::const_iterator ins = vi.begin(); ins < vi.end(); ++ins) {
928 input.push_back(*ins);
929 }
930
931 {
932 // Make sure all keywords have default values, otherwise the
933 // user has to specify them in the controlfile.
934 bool all_gin_have_defaults = true;
935 for (Index gin = 0; all_gin_have_defaults && gin < mdd->GIn().nelem();
936 ++gin) {
937 Index wsvid; // Workspace variable id, is used to
938 // access data in wsv_data.
939
940 if (mdd->GInDefault()[gin] == NODEF)
941 all_gin_have_defaults = false;
942 else {
943 String wsvname;
944 wsvname = set_gin_to_default(mdd, auto_vars, auto_vars_values, gin);
945 {
946 // Find Wsv id:
947 const map<String, Index>::const_iterator wsvit =
948 Workspace::WsvMap.find(wsvname);
949 if (wsvit == Workspace::WsvMap.end()) {
950 throw UnknownWsv(wsvname,
951 msource.File(),
954 }
955
956 wsvid = wsvit->second;
957 }
958 input.push_back(wsvid);
959 }
960 }
961
962 if (!all_gin_have_defaults) {
963 ostringstream os;
964 os << "Not all generic inputs of the method *" << methodname
965 << "* have default values, you have to specify them!";
966 throw ParseError(os.str(),
967 msource.File(),
970 }
971 }
972 }
973}
974
992 Index& id,
993 String& methodname,
994 ArrayOfIndex& input,
995 ArrayOfIndex& auto_vars,
996 Array<TokVal>& auto_vars_values,
997 bool& first,
998 bool& still_supergeneric,
999 String& supergeneric_args,
1000 Index& supergeneric_index _U_,
1001 NamedArguments& named_args,
1002 bool call_by_name) {
1003 String wsvname;
1004 Index wsvid;
1006 using global_data::MdMap;
1008
1009 // Then parse all generic input variables
1010 for (Index j = 0; j < mdd->GInType().nelem(); ++j) {
1011 Index this_arg_index = 0;
1012
1013 if (call_by_name) {
1014 get_argument_index_by_name(this_arg_index, named_args, mdd->GIn()[j]);
1015
1016 if (this_arg_index != -1) {
1017 msource.SetPosition(named_args[this_arg_index].line,
1018 named_args[this_arg_index].column);
1019 named_args.erase(named_args.begin() + this_arg_index);
1020 }
1021 } else {
1022 if (first)
1023 first = false;
1024 else {
1025 if (msource.Current() != ')') {
1028 }
1029 }
1030 }
1031
1032 // If no value was specified and we use the default value instead (if there is one)
1033 if ((call_by_name && this_arg_index == -1) || msource.Current() == ',' ||
1034 msource.Current() == ')') {
1035 wsvname = set_gin_to_default(mdd, auto_vars, auto_vars_values, j);
1036 } else {
1037 ostringstream os;
1038 os << j;
1039 if (read_name_or_value(wsvname,
1040 auto_vars,
1041 auto_vars_values,
1042 "generic" + os.str(),
1043 mdd,
1044 mdd->GInType()[j]) == -1 &&
1045 mdd->SetMethod()) {
1046 if (msource.Current() == '=') {
1047 throw UnexpectedChar(
1048 "Unexpected '=' sign encountered.\n"
1049 "Mixing positional and named arguments is not allowed.",
1050 msource.File(),
1051 msource.Line(),
1052 msource.Column());
1053 }
1054 throw ParseError(
1055 "Only constants can be passed to Set methods.\n"
1056 "You might want to use the *Copy* here.",
1057 msource.File(),
1058 msource.Line(),
1059 msource.Column());
1060 }
1061 if (call_by_name) at_end_of_argument("generic input argument");
1062 }
1063
1064 {
1065 // Find Wsv id:
1066 const map<String, Index>::const_iterator wsvit =
1067 Workspace::WsvMap.find(wsvname);
1068 if (wsvit == Workspace::WsvMap.end()) {
1069 throw UnknownWsv(
1070 wsvname, msource.File(), msource.Line(), msource.Column());
1071 }
1072
1073 wsvid = wsvit->second;
1074 }
1075
1076 // Is the method data record still supergeneric? This could
1077 // be the case if there are no output arguments, only input
1078 // arguments. In that case, let's find out the actual group!
1079 if (still_supergeneric) {
1080 ostringstream os;
1081 if (wsv_group_names[mdd->GInType()[j]] == "Any")
1082 supergeneric_args +=
1083 wsv_group_names[Workspace::wsv_data[wsvid].Group()];
1084 os << mdd->Name() << "_sg_" << supergeneric_args;
1085 methodname = os.str();
1086
1087 // Find explicit method id in MdMap:
1088 const map<String, Index>::const_iterator mdit = MdMap.find(methodname);
1089 if (mdit != MdMap.end()) {
1090 id = mdit->second;
1091
1092 mdd = &md_data[id];
1093
1094 still_supergeneric = false;
1095 }
1096 }
1097
1098 // Now we have explicitly the method record for the right
1099 // group. From now on no special treatment of supergeneric
1100 // methods should be necessary.
1101
1102 // Check that this Wsv belongs to the correct group:
1103 if (mdd->GInType()[j] == get_wsv_group_id("Any") &&
1104 mdd->GInSpecType()[j].nelem()) {
1105 if (supergeneric_index == -1) {
1106 bool wrong_group_id = true;
1107 for (Index i = 0; wrong_group_id && i < mdd->GInSpecType()[j].nelem();
1108 i++) {
1109 if (Workspace::wsv_data[wsvid].Group() == mdd->GInSpecType()[j][i]) {
1110 wrong_group_id = false;
1111 supergeneric_index = i;
1112 }
1113 }
1114
1115 if (wrong_group_id) {
1116 ostringstream os;
1117 bool firsttype = true;
1118 for (Index i = 0; i < mdd->GInSpecType()[j].nelem(); i++) {
1119 if (!firsttype)
1120 os << ", ";
1121 else
1122 firsttype = false;
1123 os << wsv_group_names[mdd->GInSpecType()[j][i]];
1124 }
1125
1126 throw WrongWsvGroup(
1127 "*" + mdd->Name() + "* is not defined for " +
1128 wsv_group_names[Workspace::wsv_data[wsvid].Group()] +
1129 " input. Check the online docs.",
1130 msource.File(),
1131 msource.Line(),
1132 msource.Column());
1133 }
1134 } else {
1135 if (Workspace::wsv_data[wsvid].Group() !=
1136 mdd->GInSpecType()[j][supergeneric_index]) {
1137 throw WrongWsvGroup(
1138 wsvname + " is not " +
1139 wsv_group_names[mdd->GInSpecType()[j][supergeneric_index]] +
1140 ", it is " +
1141 wsv_group_names[Workspace::wsv_data[wsvid].Group()],
1142 msource.File(),
1143 msource.Line(),
1144 msource.Column());
1145 }
1146 }
1147 } else if (Workspace::wsv_data[wsvid].Group() != mdd->GInType()[j]) {
1148 throw WrongWsvGroup(
1149 wsvname + " is not " + wsv_group_names[mdd->GInType()[j]] +
1150 ", it is " + wsv_group_names[Workspace::wsv_data[wsvid].Group()],
1151 msource.File(),
1152 msource.Line(),
1153 msource.Column());
1154 }
1155
1156 // Add this one to the list of input variables:
1157 input.push_back(wsvid);
1158
1160 }
1161}
1162
1178 Index& id,
1179 String& methodname,
1180 ArrayOfIndex& output,
1181 bool& first,
1182 bool& still_supergeneric,
1183 String& supergeneric_args,
1184 Index& supergeneric_index,
1185 NamedArguments& named_args,
1186 bool call_by_name) {
1187 String wsvname;
1188 Index wsvid;
1190 using global_data::MdMap;
1192
1193 // Parse all generic output variables
1194 for (Index j = 0; j < mdd->GOut().nelem(); ++j) {
1195 if (call_by_name) {
1196 Index this_arg_index;
1197
1198 get_argument_index_by_name(this_arg_index, named_args, mdd->GOut()[j]);
1199
1200 if (this_arg_index == -1) {
1201 ostringstream os;
1202 os << "This method has generic output. "
1203 << "You have to pass a variable!";
1204 throw ParseError(
1205 os.str(), msource.File(), msource.Line(), msource.Column());
1206 }
1207
1208 msource.SetPosition(named_args[this_arg_index].line,
1209 named_args[this_arg_index].column);
1210 named_args.erase(named_args.begin() + this_arg_index);
1211 } else {
1212 if (first)
1213 first = false;
1214 else {
1217 }
1218 }
1219
1220 read_name(wsvname);
1221 if (call_by_name) at_end_of_argument("generic output argument");
1222
1223 {
1224 wsvid = -1;
1225 // Find Wsv id:
1226 auto wsvit = Workspace::WsvMap.find(wsvname);
1227 if (wsvit == Workspace::WsvMap.end()) {
1228 if (still_supergeneric) {
1229 ostringstream os;
1230 os << "This might be either a typo or you have to create "
1231 << "the variable\nby calling TYPECreate(" << wsvname
1232 << ") first. Replace TYPE with the\n"
1233 << "WSV group your variable should belong to.";
1234
1235 throw UnknownWsv(
1236 os.str(), msource.File(), msource.Line(), msource.Column());
1237 }
1238
1239 if (mdd->Name().length() <= 6 ||
1240 mdd->Name().substr(mdd->Name().length() - 6) != "Create") {
1241 ostringstream os;
1242 os << "This might be either a typo or you have to create "
1243 << "the variable\nby calling "
1244 << wsv_group_names[mdd->GOutType()[j]] << "Create( " << wsvname
1245 << " ) first.\n";
1246
1247 throw UnknownWsv(
1248 os.str(), msource.File(), msource.Line(), msource.Column());
1249 }
1250
1251 wsvid =
1252 Workspace::add_wsv(WsvRecord(wsvname.c_str(),
1253 "Automatically allocated variable.",
1254 mdd->GOutType()[j],
1255 true));
1256 }
1257
1258 if (wsvid == -1) {
1259 if (mdd->Name().length() > 6 &&
1260 mdd->Name().find("Create") == mdd->Name().length() - 6) {
1261 const String& gn =
1262 wsv_group_names[Workspace::wsv_data[wsvit->second].Group()];
1263 if (mdd->Name().find(gn) not_eq 0) {
1264 throw WsvAlreadyExists(
1265 var_string(
1266 wsvname,
1267 " already exists of group ",
1268 gn,
1269 ". A variable cannot be redefined as a different group.\n"),
1270 msource.File(),
1271 msource.Line(),
1272 msource.Column());
1273 }
1274 }
1275 wsvid = wsvit->second;
1276 }
1277 }
1278
1279 // If this is a supergeneric method, now is the time to find
1280 // out the actual group of the argument(s)!
1281 // If the method also has supergeneric input arguments, we'll
1282 // look for a match later again.
1283 if (still_supergeneric) {
1284 ostringstream os;
1285 if (wsv_group_names[mdd->GOutType()[j]] == "Any")
1286 supergeneric_args +=
1287 wsv_group_names[Workspace::wsv_data[wsvid].Group()];
1288 os << mdd->Name() << "_sg_" << supergeneric_args;
1289 methodname = os.str();
1290
1291 // Find explicit method id in MdMap:
1292 const map<String, Index>::const_iterator mdit = MdMap.find(methodname);
1293 if (mdit != MdMap.end()) {
1294 id = mdit->second;
1295
1296 mdd = &md_data[id];
1297
1298 still_supergeneric = false;
1299 }
1300 }
1301
1302 // Now we have explicitly the method record for the right
1303 // group. From now on no special treatment of supergeneric
1304 // methods should be necessary.
1305
1306 // Check that this Wsv belongs to the correct group:
1307 if (mdd->GOutType()[j] == get_wsv_group_id("Any") &&
1308 mdd->GOutSpecType()[j].nelem()) {
1309 if (supergeneric_index == -1) {
1310 bool wrong_group_id = true;
1311 for (Index i = 0; wrong_group_id && i < mdd->GOutSpecType()[j].nelem();
1312 i++) {
1313 if (Workspace::wsv_data[wsvid].Group() == mdd->GOutSpecType()[j][i]) {
1314 wrong_group_id = false;
1315 supergeneric_index = i;
1316 }
1317 }
1318
1319 if (wrong_group_id) {
1320 ostringstream os;
1321 bool firsttype = true;
1322 for (Index i = 0; i < mdd->GOutSpecType()[j].nelem(); i++) {
1323 if (!firsttype)
1324 os << ", ";
1325 else
1326 firsttype = false;
1327 os << wsv_group_names[mdd->GOutSpecType()[j][i]];
1328 }
1329
1330 throw WrongWsvGroup(
1331 "*" + mdd->Name() + "* is not defined for " +
1332 wsv_group_names[Workspace::wsv_data[wsvid].Group()] +
1333 " output. Check the online docs.",
1334 msource.File(),
1335 msource.Line(),
1336 msource.Column());
1337 }
1338 } else {
1339 if (Workspace::wsv_data[wsvid].Group() !=
1340 mdd->GOutSpecType()[j][supergeneric_index]) {
1341 throw WrongWsvGroup(
1342 wsvname + " is not " +
1343 wsv_group_names[mdd->GOutSpecType()[j][supergeneric_index]] +
1344 ", it is " +
1345 wsv_group_names[Workspace::wsv_data[wsvid].Group()],
1346 msource.File(),
1347 msource.Line(),
1348 msource.Column());
1349 }
1350 }
1351 } else if (Workspace::wsv_data[wsvid].Group() != mdd->GOutType()[j]) {
1352 throw WrongWsvGroup(
1353 wsvname + " is not " + wsv_group_names[mdd->GOutType()[j]] +
1354 ", it is " + wsv_group_names[Workspace::wsv_data[wsvid].Group()],
1355 msource.File(),
1356 msource.Line(),
1357 msource.Column());
1358 }
1359
1360 // Add this one to the list of output workspace variables:
1361 output.push_back(wsvid);
1362
1364 }
1365}
1366
1380 ArrayOfIndex& input,
1381 ArrayOfIndex& auto_vars,
1382 Array<TokVal>& auto_vars_values,
1383 bool& first,
1384 NamedArguments& named_args,
1385 bool call_by_name) {
1387
1388 // There are two lists of arguments that we have to read.
1389 ArrayOfIndex vo = mdd->Out(); // Output
1390 const ArrayOfIndex& vi = mdd->InOnly(); // Input
1391
1392 Index wsvid; // Workspace variable id, is used to
1393 // access data in wsv_data.
1394
1395 for (ArrayOfIndex::const_iterator ins = vi.begin(); ins < vi.end(); ++ins) {
1396 String wsvname;
1397
1398 if (call_by_name) {
1399 Index this_arg_index;
1400
1401 wsvname = Workspace::wsv_data[*ins].Name();
1402
1403 get_argument_index_by_name(this_arg_index, named_args, wsvname);
1404
1405 if (this_arg_index != -1) {
1406 msource.SetPosition(named_args[this_arg_index].line,
1407 named_args[this_arg_index].column);
1408 named_args.erase(named_args.begin() + this_arg_index);
1409
1410 read_name_or_value(wsvname,
1411 auto_vars,
1412 auto_vars_values,
1413 Workspace::wsv_data[*ins].Name(),
1414 mdd,
1415 Workspace::wsv_data[*ins].Group());
1416 at_end_of_argument("specific input argument");
1417 }
1418 } else {
1419 if (first)
1420 first = false;
1421 else {
1422 try {
1424 } catch (const UnexpectedChar&) {
1425 ostringstream os;
1426 os << "Expected input WSV *" << Workspace::wsv_data[*ins].Name()
1427 << "*";
1428 }
1430 }
1431
1432 read_name_or_value(wsvname,
1433 auto_vars,
1434 auto_vars_values,
1435 Workspace::wsv_data[*ins].Name(),
1436 mdd,
1437 Workspace::wsv_data[*ins].Group());
1438 }
1439
1440 {
1441 // Find Wsv id:
1442 const map<String, Index>::const_iterator wsvit =
1443 Workspace::WsvMap.find(wsvname);
1444 if (wsvit == Workspace::WsvMap.end())
1445 throw UnknownWsv(
1446 wsvname, msource.File(), msource.Line(), msource.Column());
1447
1448 wsvid = wsvit->second;
1449 }
1450
1451 // Check that this Wsv belongs to the correct group:
1452 if (Workspace::wsv_data[wsvid].Group() !=
1453 Workspace::wsv_data[*ins].Group()) {
1454 throw WrongWsvGroup(
1455 wsvname + " is not " +
1456 wsv_group_names[Workspace::wsv_data[*ins].Group()] + ", it is " +
1458 msource.File(),
1459 msource.Line(),
1460 msource.Column());
1461 }
1462
1463 input.push_back(wsvid);
1464 }
1465
1467}
1468
1480 ArrayOfIndex& output,
1481 bool& first,
1482 NamedArguments& named_args,
1483 bool call_by_name) {
1485
1486 ArrayOfIndex vo = mdd->Out();
1487
1488 Index wsvid; // Workspace variable id, is used to
1489 // access data in wsv_data.
1490
1491 for (ArrayOfIndex::const_iterator outs = vo.begin(); outs < vo.end();
1492 ++outs) {
1493 String wsvname;
1494
1495 if (call_by_name) {
1496 Index this_arg_index = 0;
1497
1498 wsvname = Workspace::wsv_data[*outs].Name();
1499
1500 get_argument_index_by_name(this_arg_index, named_args, wsvname);
1501
1502 if (this_arg_index != -1) {
1503 msource.SetPosition(named_args[this_arg_index].line,
1504 named_args[this_arg_index].column);
1505 named_args.erase(named_args.begin() + this_arg_index);
1506
1507 read_name(wsvname);
1508 at_end_of_argument("specific output argument");
1509 }
1510 } else {
1511 if (first)
1512 first = false;
1513 else {
1514 try {
1516 } catch (const UnexpectedChar&) {
1517 ostringstream os;
1518 os << "Expected output WSV *" << Workspace::wsv_data[*outs].Name()
1519 << "*";
1520 throw ParseError(
1521 os.str(), msource.File(), msource.Line(), msource.Column());
1522 }
1524 }
1525
1526 read_name(wsvname);
1527 }
1528
1529 {
1530 wsvid = -1;
1531 // Find Wsv id:
1532 map<String, Index>::const_iterator wsvit =
1533 Workspace::WsvMap.find(wsvname);
1534 if (wsvit == Workspace::WsvMap.end()) {
1535 if (mdd->Name().length() > 6 &&
1536 mdd->Name().substr(mdd->Name().length() - 6) != "Create") {
1537 ostringstream os;
1538 os << "This might be either a typo or you have to create "
1539 << "the variable\nby calling "
1540 << wsv_group_names[Workspace::wsv_data[*outs].Group()]
1541 << "Create( " << wsvname << " ) first.\n";
1542
1543 throw UnknownWsv(
1544 os.str(), msource.File(), msource.Line(), msource.Column());
1545 } else {
1546 wsvid =
1547 Workspace::add_wsv(WsvRecord(wsvname.c_str(),
1548 "Automatically allocated variable.",
1549 Workspace::wsv_data[*outs].Group(),
1550 true));
1551 }
1552 }
1553
1554 if (wsvid == -1) wsvid = wsvit->second;
1555 }
1556
1557 // Check that this Wsv belongs to the correct group:
1558 if (Workspace::wsv_data[wsvid].Group() !=
1559 Workspace::wsv_data[*outs].Group()) {
1560 throw WrongWsvGroup(
1561 wsvname + " is not " +
1562 wsv_group_names[Workspace::wsv_data[*outs].Group()] + ", it is " +
1564 msource.File(),
1565 msource.Line(),
1566 msource.Column());
1567 }
1568
1569 output.push_back(wsvid);
1570 }
1571
1573}
1574
1589 const ArrayOfIndex& auto_vars,
1590 const Array<TokVal>& auto_vars_values,
1591 const Index method_type,
1592 Agenda& tasklist) {
1593 using global_data::MdMap;
1595
1596 for (Index i = 0; i < auto_vars.nelem(); i++) {
1597 map<String, Index>::const_iterator mdit;
1598 Index init_mdid;
1599 TokVal auto_keyword_value;
1600 ArrayOfIndex auto_output_var;
1601 ArrayOfIndex auto_input_var;
1602 Agenda auto_tasks;
1603
1604 const Index auto_group = Workspace::wsv_data[auto_vars[i]].Group();
1605 if (auto_group != get_wsv_group_id("Index") &&
1606 auto_group != get_wsv_group_id("Numeric") &&
1607 auto_group != get_wsv_group_id("ArrayOfIndex") &&
1608 auto_group != get_wsv_group_id("ArrayOfString") &&
1609 auto_group != get_wsv_group_id("ArrayOfSpeciesTag") &&
1610 auto_group != get_wsv_group_id("String") &&
1611 auto_group != get_wsv_group_id("Vector") &&
1612 auto_group != get_wsv_group_id("Matrix")) {
1613 ostringstream os;
1614 os << "Passing a "
1615 << wsv_group_names[Workspace::wsv_data[auto_vars[i]].Group()]
1616 << " constant to a WSM is not supported!";
1617 throw ParseError(
1618 os.str(), msource.File(), msource.Line(), msource.Column());
1619 }
1620
1621 String method_name;
1622 switch (method_type) {
1623 case 0:
1624 auto_keyword_value = auto_vars_values[i];
1625 auto_output_var.push_back(auto_vars[i]);
1626 method_name =
1627 wsv_group_names[Workspace::wsv_data[auto_vars[i]].Group()] + "Set";
1628 break;
1629 case 1:
1630 auto_input_var.push_back(auto_vars[i]);
1631 method_name =
1632 "Delete_sg_" +
1633 wsv_group_names[Workspace::wsv_data[auto_vars[i]].Group()];
1634 break;
1635 default:
1636 throw ParseError("Invalid method type.",
1637 msource.File(),
1638 msource.Line(),
1639 msource.Column());
1640 }
1641
1642 mdit = MdMap.find(method_name);
1643 ARTS_ASSERT(mdit != MdMap.end());
1644 init_mdid = mdit->second;
1645
1646 tasklist.push_back(MRecord(init_mdid,
1647 auto_output_var,
1648 auto_input_var,
1649 auto_keyword_value,
1650 auto_tasks,
1651 true));
1652 }
1653}
1654
1666 switch (c) {
1667 case ' ':
1668 case '\r':
1669 case '\t':
1670 case '#':
1671 return true;
1672 break;
1673 }
1674
1675 return false;
1676}
1677
1688 char dummy;
1689
1690 while (is_whitespace(dummy = msource.Current())) {
1691 switch (dummy) {
1692 case ' ':
1693 case '\r':
1694 case '\t':
1696 break;
1697 case '#':
1699 break;
1700 default: {
1701 ostringstream os;
1702 os << "Expected whitespace, but got `" << dummy << "'.";
1703 throw UnexpectedChar(
1704 os.str(), msource.File(), msource.Line(), msource.Column());
1705 break;
1706 }
1707 }
1708 }
1709}
1710
1717 while (pos < str.length() && is_whitespace(str[pos])) pos++;
1718}
1719
1732 bool stop = false;
1733 name = "";
1734
1735 if (!isalpha(msource.Current())) {
1736 ostringstream os;
1737 os << "Workspace variable names must start with a letter!";
1738 throw ParseError(
1739 os.str(), msource.File(), msource.Line(), msource.Column());
1740 }
1741
1742 while (!stop) {
1743 char dummy = msource.Current();
1744
1745 if (isalnum(dummy) || '_' == dummy) {
1746 name += dummy;
1747 // AdvanceChar sets LineBreak if a line break occured.
1748 msource.LineBreak() = false;
1750 if (msource.LineBreak()) stop = true;
1751 } else {
1752 stop = true;
1753 }
1754 }
1755}
1756
1777 ArrayOfIndex& auto_vars,
1778 Array<TokVal>& auto_vars_values,
1779 const String& default_name,
1780 const MdRecord* mdd,
1781 const Index group) {
1782 name = "";
1783
1784 if (isalpha(msource.Current())) {
1785 read_name(name);
1786 return -1;
1787 }
1788
1789 if (group == get_wsv_group_id("Any")) {
1790 ostringstream os;
1791 os << "Passing constants as supergeneric arguments is not supported.";
1792 throw ParseError(
1793 os.str(), msource.File(), msource.Line(), msource.Column());
1794 }
1795
1796 // If a value was given instead of a variable name, we create
1797 // a new variable in the workspace and fill it with the given
1798 // value
1799
1800 Index wsvid;
1801
1802 name = "auto_" + mdd->Name() + "_" + default_name;
1803 map<String, Index>::const_iterator wsvit = Workspace::WsvMap.find(name);
1804 if (wsvit == Workspace::WsvMap.end()) {
1806 name.c_str(), "Automatically allocated variable.", group, true));
1807 } else {
1808 wsvid = wsvit->second;
1809 }
1810
1811 auto_vars.push_back(wsvid);
1812
1813 // Now parse the value. This can be:
1814 // String_, Index_, Numeric_, Array_String_, Array_Index_, Vector_, Matrix_
1815 if (group == get_wsv_group_id("String")) {
1816 String dummy;
1817 parse_String(dummy);
1818 auto_vars_values.push_back(dummy);
1819 } else if (group == get_wsv_group_id("Index")) {
1820 Index n;
1821 parse_integer(n);
1822 auto_vars_values.push_back(n);
1823 } else if (group == get_wsv_group_id("Numeric")) {
1824 Numeric n;
1825 parse_numeric(n);
1826 auto_vars_values.push_back(n);
1827 } else if (group == get_wsv_group_id("ArrayOfString")) {
1828 ArrayOfString dummy;
1829 parse_Stringvector(dummy);
1830 auto_vars_values.push_back(dummy);
1831 } else if (group == get_wsv_group_id("ArrayOfIndex")) {
1832 ArrayOfIndex dummy;
1833 parse_intvector(dummy);
1834 auto_vars_values.push_back(dummy);
1835 } else if (group == get_wsv_group_id("ArrayOfSpeciesTag")) {
1836 String dummy;
1837 parse_String(dummy);
1838 ArrayOfSpeciesTag aost;
1839 if (dummy.nelem()) {
1840 aost = ArrayOfSpeciesTag(dummy);
1841 }
1842 auto_vars_values.push_back(aost);
1843 } else if (group == get_wsv_group_id("Vector")) {
1844 Vector dummy;
1845 parse_numvector(dummy);
1846 auto_vars_values.push_back(dummy);
1847 } else if (group == get_wsv_group_id("Matrix")) {
1848 Matrix dummy;
1849 parse_matrix(dummy);
1850 auto_vars_values.push_back(dummy);
1851 } else {
1853 ostringstream os;
1854 os << "Unsupported argument type: " << wsv_group_names[group];
1855 throw ParseError(
1856 os.str(), msource.File(), msource.Line(), msource.Column());
1857 }
1858
1859 return wsvid;
1860}
1861
1869 if (c != msource.Current()) {
1870 ostringstream os;
1871 os << "Expected '" << c << "', but got '" << msource.Current() << "'.";
1872 throw UnexpectedChar(
1873 os.str(), msource.File(), msource.Line(), msource.Column());
1874 }
1875
1877}
1878
1890 bool stop = false;
1891 res = "";
1892
1893 msource.LineBreak() = false;
1895 if (msource.LineBreak())
1896 throw IllegalLinebreak("Line break before end of String.",
1897 msource.File(),
1898 msource.Line(),
1899 msource.Column());
1900
1901 while (!stop) {
1902 char dummy = msource.Current();
1903 if (dummy != '"') {
1904 res += dummy;
1906
1907 if (msource.LineBreak())
1908 throw IllegalLinebreak("Line break before end of String.",
1909 msource.File(),
1910 msource.Line(),
1911 msource.Column());
1912 } else {
1913 stop = true;
1915 }
1916 }
1917}
1918
1932 bool stop = false;
1933 res = "";
1934 char dummy;
1935 msource.LineBreak() = false;
1936
1937 dummy = msource.Current();
1938 if ('+' == dummy || '-' == dummy) {
1939 res += dummy;
1941 if (msource.LineBreak())
1942 throw IllegalLinebreak("Line break after sign.",
1943 msource.File(),
1944 msource.Line(),
1945 msource.Column());
1946 }
1947
1948 if (!isdigit(msource.Current())) {
1949 ostringstream os;
1950 os << "Expected digit or variable name, but got `" << msource.Current()
1951 << "'.";
1952 throw UnexpectedChar(
1953 os.str(), msource.File(), msource.Line(), msource.Column());
1954 }
1955
1956 while (!stop) {
1957 char chtmp = msource.Current();
1958 if (isdigit(chtmp)) {
1959 res += chtmp;
1961 if (msource.LineBreak()) stop = true;
1962 } else {
1963 stop = true;
1964 }
1965 }
1966}
1967
1984 bool stop;
1985 res = "";
1986 char dummy;
1987 msource.LineBreak() = false;
1988
1989 // To make sure that there is at least one digit:
1990 bool found_digit = false;
1991
1992 // Check if there is a sign:
1993 dummy = msource.Current();
1994 if ('+' == dummy || '-' == dummy) {
1995 res += dummy;
1997 if (msource.LineBreak())
1998 throw IllegalLinebreak("Linebreak after sign.",
1999 msource.File(),
2000 msource.Line(),
2001 msource.Column());
2002 }
2003
2004 // There could be some digits here:
2005 stop = false;
2006 while (!stop) {
2007 char chtmp = msource.Current();
2008 if (isdigit(chtmp)) {
2009 found_digit = true;
2010 res += chtmp;
2012 if (msource.LineBreak()) return; // Line break ends scanning immediately.
2013 } else {
2014 stop = true;
2015 }
2016 }
2017
2018 // Next there can be a decimal point
2019 if ('.' == msource.Current()) {
2020 res += ".";
2022 if (msource.LineBreak()) {
2023 if (found_digit) {
2024 // Line break ends scanning immediately, if we have
2025 // already found at least one digit.
2026 return;
2027 } else {
2028 throw IllegalLinebreak("Expected at least one digit.",
2029 msource.File(),
2030 msource.Line(),
2031 msource.Column());
2032 }
2033 }
2034
2035 // ... followed by optional more digits
2036 stop = false;
2037 while (!stop) {
2038 char chtmp = msource.Current();
2039 if (isdigit(chtmp)) {
2040 found_digit = true;
2041 res += chtmp;
2043 if (msource.LineBreak())
2044 return; // Line break ends scanning immediately.
2045 } else {
2046 stop = true;
2047 }
2048 }
2049 }
2050
2051 // At this point, we must have found at least one digit.
2052 if (!found_digit)
2053 throw ParseError("Expected at least one digit.",
2054 msource.File(),
2055 msource.Line(),
2056 msource.Column());
2057
2058 // Now there could be a `e' or `E':
2059 dummy = msource.Current();
2060 if ('e' == dummy || 'E' == dummy) {
2061 res += dummy;
2063 if (msource.LineBreak())
2064 throw IllegalLinebreak("Linebreak after e/E.",
2065 msource.File(),
2066 msource.Line(),
2067 msource.Column());
2068
2069 // Now there must be an integer (with optional sign)
2070 {
2071 String s;
2072 read_integer(s);
2073 res += s;
2074 }
2075 }
2076}
2077
2083 String res;
2084 read_integer(res);
2085 istringstream is(res);
2086 is >> n;
2087}
2088
2094 String res;
2095 read_numeric(res);
2096 istringstream is(res);
2097 is >> double_imanip() >> n;
2098}
2099
2115 bool first = true; // To skip the first comma.
2116 res.resize(0); // Clear the result vector (just in case).
2117
2118 // Make sure that the current character really is `[' and proceed.
2120 // There might have occured a linebreak, which is fine.
2121
2123
2124 // Read the elements of the vector (`]' means that we have
2125 // reached the end):
2126 while (']' != msource.Current()) {
2127 String dummy;
2128
2129 if (first)
2130 first = false;
2131 else {
2134 }
2135
2136 parse_String(dummy);
2137 res.push_back(dummy);
2139 }
2140
2142}
2143
2156 bool first = true; // To skip the first comma.
2157 res.resize(0); // Clear the result vector (just in case).
2158
2159 // Make sure that the current character really is `[' and proceed.
2161 // There might have occured a linebreak, which is fine.
2162
2164
2165 // Read the elements of the vector (`]' means that we have
2166 // reached the end):
2167 while (']' != msource.Current()) {
2168 Index dummy;
2169
2170 if (first)
2171 first = false;
2172 else {
2175 }
2176
2177 parse_integer(dummy);
2178 res.push_back(dummy);
2180 }
2181
2183}
2184
2197 bool first = true; // To skip the first comma.
2198
2199 // We need a temporary Array<Numeric>, so that we can use push_back
2200 // to store the values. FIXME: Need also constructor for Vector from
2201 // Array<Numeric>.
2202 Array<Numeric> tres;
2203
2204 // Make sure that the current character really is `[' and proceed.
2206 // There might have occured a linebreak, which is fine.
2207
2209
2210 // Read the elements of the vector (`]' means that we have
2211 // reached the end):
2212 while (']' != msource.Current()) {
2213 Numeric dummy;
2214
2215 if (first)
2216 first = false;
2217 else {
2220 }
2221
2222 parse_numeric(dummy);
2223 tres.push_back(dummy);
2225 }
2226
2227 // Copy tres to res:
2228 res.resize(tres.nelem());
2229 for (int i = 0; i < tres.nelem(); i++) {
2230 res[i] = tres[i];
2231 }
2232
2234}
2235
2248 bool first = true; // To skip the first comma.
2249
2250 // We need a temporary Array<Numeric>, so that we can use push_back
2251 // to store the values. FIXME: Need also constructor for Vector from
2252 // Array<Numeric>.
2253 Array<Numeric> tres;
2254
2255 // Make sure that the current character really is `[' and proceed.
2257 // There might have occured a linebreak, which is fine.
2258
2260
2261 Index ncols = -1;
2262 Index nrows = 0;
2263 Index cur_ncols = 0;
2264 // Read the elements of the vector (`]' means that we have
2265 // reached the end):
2266 while (']' != msource.Current()) {
2267 Numeric dummy;
2268
2269 if (first) {
2270 first = false;
2271 cur_ncols = 1;
2272 nrows = 1;
2273 } else {
2274 if (',' == msource.Current()) {
2275 cur_ncols++;
2276 if (ncols != -1 && cur_ncols > ncols) {
2277 ostringstream os;
2278 os << "Expected ';', but got '" << msource.Current()
2279 << "'. Check Matrix dimensions.";
2280 throw UnexpectedChar(
2281 os.str(), msource.File(), msource.Line(), msource.Column());
2282 }
2285 } else if (';' == msource.Current()) {
2286 nrows++;
2287 if (ncols == -1) {
2288 ncols = cur_ncols;
2289 } else if (ncols != cur_ncols) {
2290 ostringstream os;
2291 os << "Expected ',', but got '" << msource.Current()
2292 << "'. Check Matrix dimensions.";
2293 throw UnexpectedChar(
2294 os.str(), msource.File(), msource.Line(), msource.Column());
2295 }
2296 cur_ncols = 1;
2299 } else {
2300 char c = ';';
2301 if (ncols > cur_ncols) c = ',';
2302 ostringstream os;
2303 os << "Expected '" << c << "', but got '" << msource.Current()
2304 << "'. Check Matrix dimensions.";
2305 throw UnexpectedChar(
2306 os.str(), msource.File(), msource.Line(), msource.Column());
2307 }
2308 }
2309
2310 parse_numeric(dummy);
2311 tres.push_back(dummy);
2313 }
2314
2315 if (ncols == -1) ncols = cur_ncols;
2316 if (ncols != cur_ncols) {
2317 throw ParseError("Missing element(s) in last row of matrix",
2318 msource.File(),
2319 msource.Line(),
2320 msource.Column());
2321 }
2322
2323 // Copy tres to res:
2324 res.resize(nrows, ncols);
2325 for (Index i = 0; i < nrows; i++)
2326 for (Index j = 0; j < ncols; j++) res(i, j) = tres[i * ncols + j];
2327
2329}
2330
2339 bool first = true; // To skip the first comma.
2340 size_t pos = 0;
2341
2342 // We need a temporary Array<Numeric>, so that we can use push_back
2343 // to store the values.
2344 Array<Index> tres;
2345
2347
2348 // Make sure that the current character really is `[' and proceed.
2349 if (str[pos] != '[') {
2350 throw ParseError("No opening bracket found while parsing ArrayOfIndex.",
2351 msource.File(),
2352 msource.Line(),
2353 msource.Column());
2354 }
2355
2356 pos++;
2357
2359
2360 // Read the elements of the vector (`]' means that we have
2361 // reached the end):
2362 while (pos < str.length() && str[pos] != ']') {
2363 if (first)
2364 first = false;
2365 else {
2366 if (str[pos] != ',') {
2367 return false;
2368 }
2369 pos++;
2371 }
2372
2373 Index dummy;
2374 istringstream is(str.substr(pos));
2375 is >> dummy;
2376 if (is.bad() || is.fail()) return false;
2377 tres.push_back(dummy);
2378 while (pos < str.length() &&
2379 (isdigit(str[pos]) || str[pos] == '-' || str[pos] == 'e'))
2380 pos++;
2382 }
2383
2384 // Copy tres to res:
2385 res.resize(tres.nelem());
2386 for (int i = 0; i < tres.nelem(); i++) {
2387 res[i] = tres[i];
2388 }
2389
2390 return true;
2391}
2392
2401 bool first = true; // To skip the first comma.
2402 size_t pos = 0;
2403
2404 // We need a temporary Array<Numeric>, so that we can use push_back
2405 // to store the values.
2406 Array<Numeric> tres;
2407
2409
2410 // Make sure that the current character really is `[' and proceed.
2411 if (str[pos] != '[') {
2412 throw ParseError("No opening bracket found while parsing Vector.",
2413 msource.File(),
2414 msource.Line(),
2415 msource.Column());
2416 }
2417
2418 pos++;
2419
2421
2422 // Read the elements of the vector (`]' means that we have
2423 // reached the end):
2424 while (pos < str.length() && str[pos] != ']') {
2425 if (first)
2426 first = false;
2427 else {
2428 if (str[pos] != ',') {
2429 return false;
2430 }
2431 pos++;
2433 }
2434
2435 Numeric dummy;
2436 istringstream is(str.substr(pos));
2437 is >> double_imanip() >> dummy;
2438 if (is.bad() || is.fail()) return false;
2439 tres.push_back(dummy);
2440 if (str[pos] == 'N' && str.find("NaN", pos) == pos) {
2441 pos += 3;
2442 } else {
2443 while (pos < str.length() && (isdigit(str[pos]) || str[pos] == '-' ||
2444 str[pos] == '.' || str[pos] == 'e'))
2445 pos++;
2446 }
2448 }
2449
2450 // Copy tres to res:
2451 res.resize(tres.nelem());
2452 for (int i = 0; i < tres.nelem(); i++) {
2453 res[i] = tres[i];
2454 }
2455
2456 return true;
2457}
2458
2468 String& str) {
2469 bool first = true; // To skip the first comma.
2470 size_t pos = 0;
2471
2472 // We need a temporary Array<Numeric>, so that we can use push_back
2473 // to store the values.
2474 ArrayOfString tres;
2475
2477
2478 // Make sure that the current character really is `[' and proceed.
2479 if (str[pos] != '[') {
2480 throw ParseError("No opening bracket found while parsing ArrayOfString.",
2481 msource.File(),
2482 msource.Line(),
2483 msource.Column());
2484 }
2485
2486 pos++;
2487
2489
2490 // Read the elements of the vector (`]' means that we have
2491 // reached the end):
2492 while (pos < str.length() && str[pos] != ']') {
2493 if (first)
2494 first = false;
2495 else {
2496 if (str[pos] != ',') {
2497 return false;
2498 }
2499 pos++;
2501 }
2502
2503 if (str[pos] != '"') {
2504 throw ParseError("Expected quotes while parsing ArrayOfString.",
2505 msource.File(),
2506 msource.Line(),
2507 msource.Column());
2508 }
2509
2510 pos++;
2511
2512 String dummy;
2513 while (pos < str.length() && str[pos] != '"') {
2514 dummy += str[pos];
2515 pos++;
2516 }
2517
2518 if (pos == str.length() || str[pos] != '"') return false;
2519
2520 tres.push_back(dummy);
2521
2523 }
2524
2525 // Copy tres to res:
2526 res.resize(tres.nelem());
2527 for (int i = 0; i < tres.nelem(); i++) {
2528 res[i] = tres[i];
2529 }
2530
2531 return true;
2532}
The global header file for ARTS.
The Agenda class.
Definition: agenda_class.h:51
void push_back(const MRecord &n)
Append a new method to end of list.
Definition: agenda_class.h:265
void resize(Index n)
Resize the method list.
Definition: agenda_class.h:248
const Array< MRecord > & Methods() const
Definition: agenda_class.h:74
Index nelem() const
Return the number of agenda elements.
Definition: agenda_class.h:257
Index nelem() const ARTS_NOEXCEPT
Number of elements.
Definition: array.h:197
bool parse_stringarray_from_string(ArrayOfString &res, String &str)
Read an Array of Strings from a String.
Definition: parser.cc:2467
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:1479
const Verbosity & verbosity
Definition: parser.h:169
void parse_numeric(Numeric &n)
Use a String stream to parse a floating point number.
Definition: parser.cc:2093
void parse_tasklist()
Public interface to the main function of the parser.
Definition: parser.cc:51
void read_name(String &name)
Reads name of method, keyword, or workspace variable.
Definition: parser.cc:1731
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:1588
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:991
Agenda & mtasklist
Definition: parser.h:161
vector< NamedArgument > NamedArguments
Definition: parser.h:39
String mcfile
Definition: parser.h:163
void parse_Stringvector(ArrayOfString &res)
Read a vector of Strings.
Definition: parser.cc:2114
void parse_integer(Index &n)
Use a String stream to parse an integer number.
Definition: parser.cc:2082
void skip_to_next_argument()
Skips forward to the next argument.
Definition: parser.cc:92
void assertain_character(char c)
Make sure that the current character is equal to c and go to the next character.
Definition: parser.cc:1868
SourceText msource
Definition: parser.h:165
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:1379
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:1776
void find_named_arguments(vector< NamedArgument > &named_args)
Find named arguments.
Definition: parser.cc:61
bool parse_intvector_from_string(ArrayOfIndex &res, String &str)
Read an array of integers from a String.
Definition: parser.cc:2338
ArtsParser(Agenda &tasklist, String controlfile, const Verbosity &verbosity)
Constructs a new parser.
Definition: parser.cc:37
bool parse_numvector_from_string(Vector &res, String &str)
Read a vector of Numerics from a String.
Definition: parser.cc:2400
bool is_whitespace(const char c)
Returns true if this character is considered whitespace.
Definition: parser.cc:1665
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:497
void eat_whitespace_from_string(String &str, size_t &pos)
Eats whitespace from a String.
Definition: parser.cc:1716
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:604
void parse_agenda(Agenda &tasklist, const String &agenda_name)
Parse the Contents of text as ARTS control input.
Definition: parser.cc:334
void eat_whitespace()
Eats whitespace.
Definition: parser.cc:1687
void parse_main()
The main function of the parser.
Definition: parser.cc:185
void parse_String(String &res)
Reads a String, complete with quotation marks.
Definition: parser.cc:1889
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:170
void read_numeric(String &res)
Reads a floating point number.
Definition: parser.cc:1983
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:760
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:1177
void parse_numvector(Vector &res)
Read a vector of Numerics.
Definition: parser.cc:2196
void read_integer(String &res)
Reads an integer.
Definition: parser.cc:1931
void parse_intvector(ArrayOfIndex &res)
Read a vector of integers.
Definition: parser.cc:2155
void parse_matrix(Matrix &res)
Read a Matrix.
Definition: parser.cc:2247
void at_end_of_argument(const String &argname)
Check if current position in controlfile is at the end of an argument.
Definition: parser.cc:155
Index mcfile_version
Definition: parser.h:167
Definition: exceptions.h:67
Method runtime data.
Definition: agenda_class.h:121
The Matrix class.
Definition: matpackI.h:1270
void resize(Index r, Index c)
Resize function.
Definition: matpackI.cc:1063
All information for one workspace method.
Definition: methods.h:41
const String & Name() const
Definition: methods.h:88
const ArrayOfIndex & InOnly() const
Definition: methods.h:102
const ArrayOfIndex & GOutType() const
Definition: methods.h:93
const Array< String > & GInDefault() const
Definition: methods.h:100
const ArrayOfArrayOfIndex & GInSpecType() const
Definition: methods.h:99
const ArrayOfString & GOut() const
Definition: methods.h:92
bool AgendaMethod() const
Definition: methods.h:106
bool Supergeneric() const
Definition: methods.h:107
bool SetMethod() const
Definition: methods.h:105
const ArrayOfArrayOfIndex & GOutSpecType() const
Definition: methods.h:94
const ArrayOfIndex & Out() const
Definition: methods.h:91
const ArrayOfIndex & GInType() const
Definition: methods.h:98
const ArrayOfString & GIn() const
Definition: methods.h:97
Structure to hold all command line Parameters.
Definition: parameters.h:42
ArrayOfString includepath
List of paths to search for include files.
Definition: parameters.h:106
ArrayOfString datapath
List of paths to search for data files.
Definition: parameters.h:108
virtual Index line() const
Definition: exceptions.h:55
virtual String file() const
Definition: exceptions.h:54
virtual Index column() const
Definition: exceptions.h:56
Index MarkedLine()
Return the marked line number, but for the file that is associated with the current position.
Definition: sourcetext.h:80
void AdvanceChar()
Advance position pointer by one character.
Definition: sourcetext.cc:29
void AdvanceLine()
Advances position pointer by one line.
Definition: sourcetext.cc:48
Index Line()
Return the line number, but for the file that is associated with the current position.
Definition: sourcetext.h:76
const String & File()
Return the filename associated with the current position.
Definition: sourcetext.cc:60
void SetMark()
Mark current position.
Definition: sourcetext.h:101
void AppendFile(const String &name)
Appends contents of file to the source text.
Definition: sourcetext.cc:22
char Current()
Return the current character.
Definition: sourcetext.h:48
bool & LineBreak()
Read the line break flag.
Definition: sourcetext.h:112
Index MarkedColumn()
Return the current marked column.
Definition: sourcetext.h:92
bool reachedEot()
Check if the current position reached the end.
Definition: sourcetext.h:55
Index Column()
Return the current column.
Definition: sourcetext.h:89
void Init()
This sets the pointer to the first existing character in the text.
Definition: sourcetext.cc:74
Index LineRaw()
Return the line index.
Definition: sourcetext.h:83
Index ColumnRaw()
Return the column index.
Definition: sourcetext.h:86
void SetPosition(Index line, Index column)
Set current position.
Definition: sourcetext.h:95
Definition: tokval.h:27
The Vector class.
Definition: matpackI.h:908
void resize(Index n)
Resize function.
Definition: matpackI.cc:411
static Index add_wsv(const WsvRecord &wsv)
Append a new WSV to the workspace.
Definition: workspace_ng.cc:54
static Array< WsvRecord > wsv_data
Global WSV data.
Definition: workspace_ng.h:58
static map< String, Index > WsvMap
Global map associated with wsv_data.
Definition: workspace_ng.h:61
This class contains all static information for one workspace variable.
Definition: wsv_aux.h:56
Input manipulator class for doubles to enable nan and inf parsing.
Definition: double_imanip.h:64
Index nelem() const
Number of elements.
Definition: mystring.h:253
#define _U_
Definition: config.h:180
#define ARTS_ASSERT(condition,...)
Definition: debug.h:83
std::string var_string(Args &&... args)
Definition: debug.h:36
The declarations of all the exception classes.
void get_dirname(String &dirname, const String &path)
Return the parent directory of a path.
Definition: file.cc:519
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
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:228
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
#define CREATE_OUT3
Definition: messages.h:207
#define CREATE_OUT2
Definition: messages.h:206
#define CREATE_OUT0
Definition: messages.h:204
Declaration of the class MdRecord.
#define NODEF
Definition: methods.h:35
Index nelem(const Lines &l)
Number of lines.
constexpr Rational end(Rational Ju, Rational Jl, Polarization type) noexcept
Gives the largest M for a polarization type of this transition.
Definition: zeemandata.h:113
const Array< MdRecord > md_data_raw
Lookup information for workspace methods.
Definition: methods.cc:39
const Array< MdRecord > md_data
Lookup information for workspace methods.
Definition: methods_aux.cc:48
const map< String, Index > MdMap
The map associated with md_data.
Definition: methods_aux.cc:39
const map< String, Index > MdRawMap
The map associated with md_data_raw.
Definition: methods_aux.cc:41
const ArrayOfString wsv_group_names
The names associated with Wsv groups as Strings.
Definition: global_data.h:90
constexpr int isdigit(int ch) noexcept
Definition: nonstd.h:24
Parameters parameters
Holds the command line parameters.
Definition: parameters.cc:41
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.