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