ARTS 2.5.0 (git: 9ee3ac6c)
parser.cc
Go to the documentation of this file.
1/* Copyright (C) 2012 Oliver Lemke <olemke@core-dump.info>
2
3 This program is free software; you can redistribute it and/or modify it
4 under the terms of the GNU General Public License as published by the
5 Free Software Foundation; either version 2, or (at your option) any
6 later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 USA. */
17
18#include "parser.h"
19#include <iostream>
20#include "arts.h"
21#include "exceptions.h"
22#include "file.h"
23#include "global_data.h"
24#include "methods.h"
25#include "parameters.h"
26#include "workspace_ng.h"
27#include "wsv_aux.h"
28
37 String controlfile,
38 const Verbosity& rverbosity)
39 : mtasklist(tasklist),
40 mcfile(controlfile),
41 mcfile_version(1),
42 verbosity(rverbosity) {
44}
45
51
60void ArtsParser::find_named_arguments(vector<NamedArgument>& named_args) {
61 NamedArgument current_argument;
62
63 named_args.resize(0);
64
65 while (msource.Current() != ')') {
66 read_name(current_argument.name);
68 if (msource.Current() != '=') {
69 ostringstream os;
70 os << "Expected '=', but got '" << msource.Current() << "'.\n"
71 << "Mixing positional and named arguments is not allowed.";
72 throw UnexpectedChar(
73 os.str(), msource.File(), msource.Line(), msource.Column());
74 }
75
78
79 current_argument.line = msource.LineRaw();
80 current_argument.column = msource.ColumnRaw();
81 named_args.push_back(current_argument);
82
84 }
85}
86
92 Index bracket_level = 0;
93 bool inside_quotes = false;
94 char prev_char = 0;
95 Index starting_line = msource.LineRaw();
96 Index starting_col = msource.ColumnRaw();
97
98 while ((bracket_level || inside_quotes) ||
99 (msource.Current() != ',' && msource.Current() != ')')) {
100 try {
101 switch (msource.Current()) {
102 case '[':
103 bracket_level++;
104 break;
105 case ']':
106 bracket_level--;
107 if (bracket_level < 0)
108 throw ParseError("Too many closing brackets",
109 msource.File(),
110 msource.Line(),
111 msource.Column());
112 break;
113 case '"':
114 if (prev_char != '\\') inside_quotes = !inside_quotes;
115 break;
116 }
117
118 prev_char = msource.Current();
119 if (msource.Current() == '#')
121 else
123 } catch (const Eot& x) {
124 msource.SetPosition(starting_line, starting_col);
125 throw ParseError(
126 "Unexpectedly reached end of file.\nProbably a runaway argument.",
127 msource.File(),
128 msource.Line(),
129 msource.Column());
130 }
131 }
132
133 if (msource.Current() == ',') {
134 try {
136 } catch (const Eot& x) {
137 throw ParseError(
138 "blablup", msource.File(), msource.Line(), msource.Column());
139 }
141 }
142}
143
156 if (msource.Current() != ',' && msource.Current() != ')') {
157 ostringstream os;
158 os << "Expected ',' or ')' but found '" << msource.Current() << "' after "
159 << argname;
160 throw UnexpectedChar(
161 os.str(), msource.File(), msource.Line(), msource.Column());
162 }
163}
164
170 NamedArguments& named_args,
171 String name) {
172 for (arg_index = 0; arg_index < (Index)named_args.size(); arg_index++) {
173 if (named_args[(size_t)arg_index].name == name) return;
174 }
175
176 arg_index = -1;
177}
178
187
188 try {
190
191 // For method ids:
192 Index id;
193 // Output workspace variables (for generic methods):
194 ArrayOfIndex output;
195 // Input workspace variables (for generic methods):
196 ArrayOfIndex input;
197 // For include statements, holding the include file's name
198 String include_file;
199
200 ArrayOfIndex auto_vars;
201 Array<TokVal> auto_vars_values;
202
203 out3 << "\nParsing control text:\n";
204
205 msource.Init();
207
208 parse_method(id,
209 output,
210 input,
211 mtasklist,
212 auto_vars,
213 auto_vars_values,
214 include_file,
215 true);
216
217 if ("Arts" != md_data[id].Name() && "Arts2" != md_data[id].Name()) {
218 ostringstream os;
219 os << "The outermost agenda must be Arts2!\n"
220 << "(But it seems to be " << md_data[id].Name() << ".)\n";
221 throw ParseError(
222 os.str(), msource.File(), msource.Line(), msource.Column());
223 }
224
225 try {
227 if (!msource.reachedEot())
228 throw UnexpectedChar(
229 "", msource.File(), msource.Line(), msource.Column());
230 } catch (const Eot&) {
231 // It's ok to reach the end of the file here,
232 // that's actually what we want.
233 } catch (const UnexpectedChar& x) {
234 ostringstream os;
235 os << "Unexpected character(s) at the end of the control file\n";
236 os << "after the main agenda was already closed.\n";
237 os << "File: " << x.file() << '\n';
238 os << "Line: " << x.line() << '\n';
239 os << "Column: " << x.column() << '\n';
240 throw runtime_error(os.str());
241 }
242 } catch (const Eot& x) {
243 // Unexpected end of the source text:
244 ostringstream os;
245 os << "Unexpected end of control script.\n";
246 os << "File: " << x.file() << '\n';
247 os << "Line: " << x.line() << '\n';
248 throw runtime_error(os.str());
249 } catch (const UnexpectedChar& x) {
250 // Unexpected Character:
251 ostringstream os;
252 os << "Unexpected character:\n";
253 os << x.what() << '\n';
254 os << "File: " << x.file() << '\n';
255 os << "Line: " << x.line() << '\n';
256 os << "Column: " << x.column() << '\n';
257 throw runtime_error(os.str());
258 } catch (const IllegalLinebreak& x) {
259 // A line break in an illegal position:
260 ostringstream os;
261 os << "Illegal Line break:\n";
262 os << x.what() << '\n';
263 os << "File: " << x.file() << '\n';
264 os << "Line: " << x.line() << '\n';
265 throw runtime_error(os.str());
266 } catch (const UnknownMethod& x) {
267 // Method unknown:
268 // [**This should give a hint on how to obtain a list of allowed
269 // methods.]
270 ostringstream os;
271 os << "Unknown Method:\n";
272 os << x.what() << '\n';
273 os << "File: " << x.file() << '\n';
274 os << "Line: " << x.line() << '\n';
275 os << "Column: " << x.column() << '\n';
276 throw runtime_error(os.str());
277 } catch (const UnknownWsv& x) {
278 // Workspace variable unknown:
279 // [**This should give a hint on how to obtain a list of allowed
280 // Wsvs.]
281 ostringstream os;
282 os << "Unknown workspace variable:\n";
283 os << x.what() << '\n';
284 os << "File: " << x.file() << '\n';
285 os << "Line: " << x.line() << '\n';
286 os << "Column: " << x.column() << '\n';
287 throw runtime_error(os.str());
288 } catch (const WsvAlreadyExists& x) {
289 // Trying to create the same variable twice:
290 ostringstream os;
291 os << "Attempt to create a workspace variable that already exists:\n";
292 os << x.what() << '\n';
293 os << "File: " << x.file() << '\n';
294 os << "Line: " << x.line() << '\n';
295 os << "Column: " << x.column() << '\n';
296 throw runtime_error(os.str());
297 } catch (const WrongWsvGroup& x) {
298 // Workspace variable unknown:
299 // [**This should give a hint on how to obtain a list of Wsvs in
300 // this group.
301 ostringstream os;
302 os << "Workspace variable belongs to the wrong group:\n";
303 os << x.what() << '\n';
304 os << "File: " << x.file() << '\n';
305 os << "Line: " << x.line() << '\n';
306 os << "Column: " << x.column() << '\n';
307 throw runtime_error(os.str());
308 } catch (const ParseError& x) {
309 // General Parse Error (parent of all the above):
310 ostringstream os;
311 os << "Parse error:\n";
312 os << x.what() << '\n';
313 os << "File: " << x.file() << '\n';
314 os << "Line: " << x.line() << '\n';
315 os << "Column: " << x.column() << '\n';
316 throw runtime_error(os.str());
317 }
318}
319
333void ArtsParser::parse_agenda(Agenda& tasklist, const String& agenda_name) {
336
338
339 // For method ids:
340 Index id;
341 // Output workspace variables:
342 ArrayOfIndex output;
343 // Input workspace variables:
344 ArrayOfIndex input;
345 // For Agenda, if there is any:
346 Agenda tasks;
347 // For include statements, holding the include file's name
348 String include_file;
349
350 ArrayOfIndex auto_vars;
351 Array<TokVal> auto_vars_values;
352
354
355 while ('}' != msource.Current()) {
357 id, output, input, tasks, auto_vars, auto_vars_values, include_file);
358
359 // If parse_method found an include statement it returnes -1 for the
360 // method id
361 if (id == -1) {
362 // Command line parameters which give us the include search path.
363 extern Parameters parameters;
364
365 ArrayOfString current_includepath = parameters.includepath;
366 String includedir;
367 get_dirname(includedir, msource.File());
368 if (includedir.nelem()) {
369 if (current_includepath.nelem() && current_includepath[0] != includedir)
370 current_includepath.insert(current_includepath.begin(), includedir);
371 if (parameters.datapath.nelem() && parameters.datapath[0] != includedir)
372 parameters.datapath.insert(parameters.datapath.begin(), includedir);
373 }
374
375 ArrayOfString matching_files;
376 find_file(matching_files, include_file, current_includepath);
377 find_file(matching_files, include_file + ".arts", current_includepath);
378
379 if (!matching_files.nelem()) {
380 ostringstream os;
381 os << "Cannot find include file " << include_file << ".\n";
382 os << "File: " << msource.File() << '\n';
383 os << "Search path was: " << current_includepath << "\n";
384 throw ParseError(
385 os.str(), msource.File(), msource.Line(), msource.Column());
386 }
387
388 include_file = matching_files[0];
389 out2 << "- Including control file " << include_file << "\n";
390
391 ArtsParser include_parser(tasks, include_file, verbosity);
392 include_parser.parse_tasklist();
393
394 for (Index i = 0; i < tasks.nelem(); i++)
395 tasklist.push_back(tasks.Methods()[i]);
396 } else {
397 if (md_data[id].SetMethod()) {
398 // Append task to task list:
399 tasklist.push_back(
400 MRecord(id, output, input, auto_vars_values[0], tasks));
401 } else {
402 tasklist_insert_set_delete(auto_vars, auto_vars_values, 0, tasklist);
403
404 // Append task to task list:
405 tasklist.push_back(MRecord(id, output, input, TokVal(), tasks));
406
407 tasklist_insert_set_delete(auto_vars, auto_vars_values, 1, tasklist);
408
409 // If Create was called on a variable that already existed,
410 // insert a Delete call to set it back to an uninitialized state
412 const String& mname = md_data[id].Name();
413
414 if (mname.length() > 6 && mname.find("Create") == mname.length() - 6 &&
415 get_wsv_group_id(mname.substr(0, mname.length() - 6)) != -1) {
416 if (agenda_name != "Arts2") {
417 ostringstream os;
418 os << mname << " cannot be called inside an agenda.\n"
419 << "All workspace variables are global and must be created at the top level.";
420 throw ParseError(
421 os.str(), msource.File(), msource.Line(), msource.Column());
422 }
423 using global_data::MdMap;
425 String method_name =
426 "Delete_sg_" +
427 wsv_group_names[Workspace::wsv_data[output[0]].Group()];
428 map<String, Index>::const_iterator mdit;
429 mdit = MdMap.find(method_name);
430 ARTS_ASSERT(mdit != MdMap.end());
431
432 tasklist.push_back(MRecord(
433 mdit->second, ArrayOfIndex(), output, TokVal(), Agenda(), true));
434 }
435 }
436
437 {
438 // Everything in this block is just to generate some
439 // informative output.
440
441 out3 << "- " << md_data[id].Name() << "\n";
442
443 // Output workspace variables for generic methods:
444 if (0 <
445 md_data[id].GOutType().nelem() + md_data[id].GInType().nelem()) {
446 out3 << " Output: ";
447 for (Index j = 0; j < output.nelem(); ++j) {
448 out3 << Workspace::wsv_data[output[j]].Name() << " ";
449 }
450 out3 << "\n";
451
452 out3 << " Input: ";
453 for (Index j = 0; j < input.nelem(); ++j) {
454 out3 << Workspace::wsv_data[input[j]].Name() << " ";
455 }
456 out3 << "\n";
457 }
458 }
459 }
460
462 }
463}
464
497 ArrayOfIndex& output,
498 ArrayOfIndex& input,
499 Agenda& tasks,
500 ArrayOfIndex& auto_vars,
501 Array<TokVal>& auto_vars_values,
502 String& include_file,
503 bool no_eot) {
505
506 String methodname; // We need this out here, since it is
507 // set once and later modified.
508
509 const MdRecord* mdd; // Handle on the method record. Needed here,
510 // because it is modified.
511
512 bool found_curly_brace = false;
513
514 // Clear all output variables:
515 id = 0;
516 output.resize(0);
517 input.resize(0);
518 tasks.resize(0);
519 auto_vars.resize(0);
520 auto_vars_values.resize(0);
521 include_file = "";
522
524 read_name(methodname);
525
526 if (methodname == "INCLUDE") {
528 parse_String(include_file);
529
530 id = -1;
531
532 return;
533 } else {
534 if (methodname == "Arts2") {
535 mcfile_version = 2;
536 } else if (methodname == "Arts") {
537 throw runtime_error(
538 "Arts version 1 controlfiles are no longer supported.");
539 }
540
542
544 mdd, id, methodname, output, input, auto_vars, auto_vars_values);
545
547
548 // Now look for the curly braces:
549 if (msource.Current() == '{') {
552 found_curly_brace = true;
553 }
554
555 // There are two kind of methods, agenda methods, which have other
556 // methods in the body, and normal methods, expecting keywords and
557 // values. Let's take the agenda case first...
558 if (mdd->AgendaMethod()) {
559 out3 << "- " << mdd->Name() << "\n";
560 out3 << "{\n";
561 parse_agenda(tasks, methodname);
562 out3 << "}\n";
563 }
564
565 // Curly braces in non-agenda methods are not valid in v2 controlfiles
566 if (mcfile_version == 2 && !mdd->AgendaMethod() && found_curly_brace) {
567 ostringstream os;
568 os << "Expected method name , but got `" << msource.Current() << "'.";
569 throw UnexpectedChar(
570 os.str(), msource.File(), msource.Line(), msource.Column());
571 os << "" << endl;
572 }
573 }
574
575 // Now look for the closing curly braces. We have to catch Eot,
576 // because after a method description may be a good place to end
577 // the control file.
578 if (found_curly_brace) {
579 try {
581 } catch (const Eot& x) {
582 // Re-throw the error if the no_eot flag is not set:
583 if (!no_eot) throw Eot(x);
584 }
585 }
586}
587
589
604 ArrayOfIndex& auto_vars,
605 Array<TokVal>& auto_vars_values,
606 Index gin_index) {
607 String name;
608
609 if (mdd->GInDefault()[gin_index] != NODEF) {
610 ostringstream os_default_error;
611 os_default_error
612 << "\nParse error in default value for generic input variable.\n"
613 << "This is not a user error but a bug in methods.cc.\n"
614 << "Please contact the ARTS developers.";
615
616 TokVal tv;
617 // Now parse the key value. This can be:
618 // String, Index, Numeric, ArrayOfString, ArrayOfIndex, Vector
619 bool failed = false;
620 if (mdd->GInType()[gin_index] == get_wsv_group_id("String")) {
621 tv = mdd->GInDefault()[gin_index];
622 } else if (mdd->GInType()[gin_index] == get_wsv_group_id("Index")) {
623 Index n;
624 istringstream is(mdd->GInDefault()[gin_index]);
625 is >> n;
626 tv = n;
627 if (is.bad() || is.fail()) failed = true;
628 } else if (mdd->GInType()[gin_index] == get_wsv_group_id("Numeric")) {
629 Numeric n = NAN;
630 istringstream is(mdd->GInDefault()[gin_index]);
631 is >> double_imanip() >> n;
632 tv = n;
633 if (is.bad() || is.fail()) failed = true;
634 } else if (mdd->GInType()[gin_index] == get_wsv_group_id("ArrayOfString")) {
636 String s = mdd->GInDefault()[gin_index];
637 try {
639 failed = true;
640 }
641 } catch (const ParseError& p) {
642 ostringstream os;
643 os << p.what() << os_default_error.str();
644 throw ParseError(os.str(), p.file(), p.line(), p.column());
645 }
646 tv = v;
647 } else if (mdd->GInType()[gin_index] == get_wsv_group_id("Vector")) {
648 Vector v;
649 String s = mdd->GInDefault()[gin_index];
650 try {
652 failed = true;
653 }
654 } catch (const ParseError& p) {
655 ostringstream os;
656 os << p.what() << os_default_error.str();
657 throw ParseError(os.str(), p.file(), p.line(), p.column());
658 }
659 tv = v;
660 } else if (mdd->GInType()[gin_index] == get_wsv_group_id("ArrayOfIndex")) {
662 String s = mdd->GInDefault()[gin_index];
663 try {
665 failed = true;
666 }
667 } catch (const ParseError& p) {
668 ostringstream os;
669 os << p.what() << os_default_error.str();
670 throw ParseError(os.str(), p.file(), p.line(), p.column());
671 }
672 tv = v;
673 } else if (mdd->GInType()[gin_index] == get_wsv_group_id("ArrayOfSpeciesTag")) {
675 String s = mdd->GInDefault()[gin_index];
676 if (s.nelem()) {
677 try {
678 v = ArrayOfSpeciesTag(s);
679 } catch (std::exception& e) {
680 std::ostringstream os;
681 os << e.what() << os_default_error.str();
682 throw ParseError(os.str(), msource.File(), msource.Line(), msource.Column());
683 }
684 }
685 tv = v;
686 } else {
688 ostringstream os;
689 os << "Default values for generic inputs with type "
690 << wsv_group_names[mdd->GInType()[gin_index]]
691 << " are not supported.\n"
692 << "Either remove the default value for generic input '"
693 << mdd->GIn()[gin_index] << "' in workspace method\n"
694 << "*" << mdd->Name() << "* in methods.cc or discuss this "
695 << "issue on the arts-dev mailing list.\n";
696 throw ParseError(
697 os.str(), msource.File(), msource.Line(), msource.Column());
698 }
699
700 Index wsvid;
701
702 {
703 ostringstream os;
704 os << gin_index;
705
706 name = "auto_" + mdd->Name() + "_" + "gin" + os.str() + "_" +
707 mdd->GIn()[gin_index];
708 }
709
710 map<String, Index>::const_iterator wsvit = Workspace::WsvMap.find(name);
711 if (wsvit == Workspace::WsvMap.end()) {
712 wsvid = Workspace::add_wsv(WsvRecord(name.c_str(),
713 "Automatically allocated variable.",
714 mdd->GInType()[gin_index],
715 true));
716 } else {
717 wsvid = wsvit->second;
718 }
719
720 auto_vars.push_back(wsvid);
721 auto_vars_values.push_back(tv);
722
723 if (failed) {
724 ostringstream os;
725 os << "Failed to assign default value for generic '"
726 << mdd->GIn()[gin_index] << "'.\n"
727 << "Check the documentation of workspace method *" << mdd->Name()
728 << "*.\n";
729 throw ParseError(
730 os.str(), msource.File(), msource.Line(), msource.Column());
731 }
732 } else {
733 ostringstream os;
734 os << "Generic input '" << mdd->GIn()[gin_index]
735 << "' omitted but no default value found.\n"
736 << "Check the documentation of workspace method *" << mdd->Name()
737 << "*.\n";
738 throw ParseError(
739 os.str(), msource.File(), msource.Line(), msource.Column());
740 }
741
742 return name;
743}
744
746
760 Index& id,
761 String& methodname,
762 ArrayOfIndex& output,
763 ArrayOfIndex& input,
764 ArrayOfIndex& auto_vars,
765 Array<TokVal>& auto_vars_values) {
768 using global_data::MdMap;
770
771 bool still_supergeneric = true; // Flag that our MdRecord still is
772 // from md_data_raw, not from
773 // md_data.
774
775 // Find method raw id in raw map:
776 const map<String, Index>::const_iterator md_raw_id =
777 MdRawMap.find(methodname);
778 if (md_raw_id == MdRawMap.end())
779 throw UnknownMethod(methodname,
780 msource.File(),
783
784 id = md_raw_id->second;
785
786 // Get a convenient handle on the data record for this method. We
787 // have to use a pointer here, not a reference, because we later
788 // want to change where mdd is pointing!
789 mdd = &md_data_raw[id];
790
791 // Is this a supergeneric method? If not, take the record in
792 // md_data, rather than in md_data_raw:
793 if (!mdd->Supergeneric()) {
794 // Find explicit method id in MdMap:
795 const map<String, Index>::const_iterator i2 = MdMap.find(methodname);
796 ARTS_ASSERT(i2 != MdMap.end());
797 id = i2->second;
798
799 mdd = &md_data[id];
800
801 still_supergeneric = false;
802 }
803
804 if (msource.Current() == '(') {
805 String supergeneric_args;
806 Index supergeneric_index = -1;
807 NamedArguments named_arguments;
808 Index this_method_end_line = -1;
809 Index this_method_end_column = -1;
810 bool call_by_name = false;
811
814
815 // Peak at the first method argument to determine if the method
816 // is called with positional or named arguments
817 if (isalpha(msource.Current())) {
818 Index line = msource.LineRaw();
819 Index column = msource.ColumnRaw();
820 String name = "";
821
822 read_name(name);
824
825 if (msource.Current() == '=') {
828
829 msource.SetPosition(line, column);
830 find_named_arguments(named_arguments);
831
832 call_by_name = true;
833
834 this_method_end_line = msource.LineRaw();
835 this_method_end_column = msource.ColumnRaw();
836 }
837
838 msource.SetPosition(line, column);
839 }
840
841 bool is_first_arg = true;
843 mdd, output, is_first_arg, named_arguments, call_by_name);
844
846 id,
847 methodname,
848 output,
849 is_first_arg,
850 still_supergeneric,
851 supergeneric_args,
852 supergeneric_index,
853 named_arguments,
854 call_by_name);
855
857 input,
858 auto_vars,
859 auto_vars_values,
860 is_first_arg,
861 named_arguments,
862 call_by_name);
863
865 id,
866 methodname,
867 input,
868 auto_vars,
869 auto_vars_values,
870 is_first_arg,
871 still_supergeneric,
872 supergeneric_args,
873 supergeneric_index,
874 named_arguments,
875 call_by_name);
876
877 // Named arguments are not parsed in order. We have to set the cursor
878 // to the end of the method call after all named arguments have been parsed.
879 if (call_by_name)
880 msource.SetPosition(this_method_end_line, this_method_end_column);
881
882 // If we're here and still have named arguments left means that
883 // the user specified too many for this method
884 if (call_by_name && named_arguments.size()) {
885 ostringstream os;
886
887 os << "Error in arguments passed to " << mdd->Name() << ":\n";
888 for (auto& argument_name : named_arguments) {
889 if (std::find(mdd->GIn().begin(),
890 mdd->GIn().end(),
891 argument_name.name) == mdd->GIn().end() &&
892 std::find(mdd->GOut().begin(),
893 mdd->GOut().end(),
894 argument_name.name) == mdd->GOut().end())
895 os << " Unkown argument: ";
896 else
897 os << " Duplicate argument: ";
898 os << argument_name.name << std::endl;
899 }
900 throw ParseError(
901 os.str(), msource.File(), msource.Line(), msource.Column());
902 }
903
904 ARTS_ASSERT(!still_supergeneric);
906 } else {
907 if (mdd->GOut().nelem()) {
908 ostringstream os;
909 os << "This method has generic output. "
910 << "You have to pass a variable!";
911 throw ParseError(os.str(),
912 msource.File(),
915 }
916
917 // If the parenthesis were omitted we still have to add the implicit
918 // outputs and inputs to the methods input and output variable lists
919 ArrayOfIndex vo = mdd->Out();
920 for (ArrayOfIndex::const_iterator outs = vo.begin(); outs < vo.end();
921 ++outs) {
922 output.push_back(*outs);
923 }
924
925 const ArrayOfIndex& vi = mdd->InOnly();
926 for (ArrayOfIndex::const_iterator ins = vi.begin(); ins < vi.end(); ++ins) {
927 input.push_back(*ins);
928 }
929
930 {
931 // Make sure all keywords have default values, otherwise the
932 // user has to specify them in the controlfile.
933 bool all_gin_have_defaults = true;
934 for (Index gin = 0; all_gin_have_defaults && gin < mdd->GIn().nelem();
935 ++gin) {
936 Index wsvid; // Workspace variable id, is used to
937 // access data in wsv_data.
938
939 if (mdd->GInDefault()[gin] == NODEF)
940 all_gin_have_defaults = false;
941 else {
942 String wsvname;
943 wsvname = set_gin_to_default(mdd, auto_vars, auto_vars_values, gin);
944 {
945 // Find Wsv id:
946 const map<String, Index>::const_iterator wsvit =
947 Workspace::WsvMap.find(wsvname);
948 if (wsvit == Workspace::WsvMap.end()) {
949 throw UnknownWsv(wsvname,
950 msource.File(),
953 }
954
955 wsvid = wsvit->second;
956 }
957 input.push_back(wsvid);
958 }
959 }
960
961 if (!all_gin_have_defaults) {
962 ostringstream os;
963 os << "Not all generic inputs of the method *" << methodname
964 << "* have default values, you have to specify them!";
965 throw ParseError(os.str(),
966 msource.File(),
969 }
970 }
971 }
972}
973
991 Index& id,
992 String& methodname,
993 ArrayOfIndex& input,
994 ArrayOfIndex& auto_vars,
995 Array<TokVal>& auto_vars_values,
996 bool& first,
997 bool& still_supergeneric,
998 String& supergeneric_args,
999 Index& supergeneric_index _U_,
1000 NamedArguments& named_args,
1001 bool call_by_name) {
1002 String wsvname;
1003 Index wsvid;
1005 using global_data::MdMap;
1007
1008 // Then parse all generic input variables
1009 for (Index j = 0; j < mdd->GInType().nelem(); ++j) {
1010 Index this_arg_index = 0;
1011
1012 if (call_by_name) {
1013 get_argument_index_by_name(this_arg_index, named_args, mdd->GIn()[j]);
1014
1015 if (this_arg_index != -1) {
1016 msource.SetPosition(named_args[this_arg_index].line,
1017 named_args[this_arg_index].column);
1018 named_args.erase(named_args.begin() + this_arg_index);
1019 }
1020 } else {
1021 if (first)
1022 first = false;
1023 else {
1024 if (msource.Current() != ')') {
1027 }
1028 }
1029 }
1030
1031 // If no value was specified and we use the default value instead (if there is one)
1032 if ((call_by_name && this_arg_index == -1) || msource.Current() == ',' ||
1033 msource.Current() == ')') {
1034 wsvname = set_gin_to_default(mdd, auto_vars, auto_vars_values, j);
1035 } else {
1036 ostringstream os;
1037 os << j;
1038 if (read_name_or_value(wsvname,
1039 auto_vars,
1040 auto_vars_values,
1041 "generic" + os.str(),
1042 mdd,
1043 mdd->GInType()[j]) == -1 &&
1044 mdd->SetMethod()) {
1045 if (msource.Current() == '=') {
1046 throw UnexpectedChar(
1047 "Unexpected '=' sign encountered.\n"
1048 "Mixing positional and named arguments is not allowed.",
1049 msource.File(),
1050 msource.Line(),
1051 msource.Column());
1052 }
1053 throw ParseError(
1054 "Only constants can be passed to Set methods.\n"
1055 "You might want to use the *Copy* here.",
1056 msource.File(),
1057 msource.Line(),
1058 msource.Column());
1059 }
1060 if (call_by_name) at_end_of_argument("generic input argument");
1061 }
1062
1063 {
1064 // Find Wsv id:
1065 const map<String, Index>::const_iterator wsvit =
1066 Workspace::WsvMap.find(wsvname);
1067 if (wsvit == Workspace::WsvMap.end()) {
1068 throw UnknownWsv(
1069 wsvname, msource.File(), msource.Line(), msource.Column());
1070 }
1071
1072 wsvid = wsvit->second;
1073 }
1074
1075 // Is the method data record still supergeneric? This could
1076 // be the case if there are no output arguments, only input
1077 // arguments. In that case, let's find out the actual group!
1078 if (still_supergeneric) {
1079 ostringstream os;
1080 if (wsv_group_names[mdd->GInType()[j]] == "Any")
1081 supergeneric_args +=
1082 wsv_group_names[Workspace::wsv_data[wsvid].Group()];
1083 os << mdd->Name() << "_sg_" << supergeneric_args;
1084 methodname = os.str();
1085
1086 // Find explicit method id in MdMap:
1087 const map<String, Index>::const_iterator mdit = MdMap.find(methodname);
1088 if (mdit != MdMap.end()) {
1089 id = mdit->second;
1090
1091 mdd = &md_data[id];
1092
1093 still_supergeneric = false;
1094 }
1095 }
1096
1097 // Now we have explicitly the method record for the right
1098 // group. From now on no special treatment of supergeneric
1099 // methods should be necessary.
1100
1101 // Check that this Wsv belongs to the correct group:
1102 if (mdd->GInType()[j] == get_wsv_group_id("Any") &&
1103 mdd->GInSpecType()[j].nelem()) {
1104 if (supergeneric_index == -1) {
1105 bool wrong_group_id = true;
1106 for (Index i = 0; wrong_group_id && i < mdd->GInSpecType()[j].nelem();
1107 i++) {
1108 if (Workspace::wsv_data[wsvid].Group() == mdd->GInSpecType()[j][i]) {
1109 wrong_group_id = false;
1110 supergeneric_index = i;
1111 }
1112 }
1113
1114 if (wrong_group_id) {
1115 ostringstream os;
1116 bool firsttype = true;
1117 for (Index i = 0; i < mdd->GInSpecType()[j].nelem(); i++) {
1118 if (!firsttype)
1119 os << ", ";
1120 else
1121 firsttype = false;
1122 os << wsv_group_names[mdd->GInSpecType()[j][i]];
1123 }
1124
1125 throw WrongWsvGroup(
1126 "*" + mdd->Name() + "* is not defined for " +
1127 wsv_group_names[Workspace::wsv_data[wsvid].Group()] +
1128 " input. Check the online docs.",
1129 msource.File(),
1130 msource.Line(),
1131 msource.Column());
1132 }
1133 } else {
1134 if (Workspace::wsv_data[wsvid].Group() !=
1135 mdd->GInSpecType()[j][supergeneric_index]) {
1136 throw WrongWsvGroup(
1137 wsvname + " is not " +
1138 wsv_group_names[mdd->GInSpecType()[j][supergeneric_index]] +
1139 ", it is " +
1140 wsv_group_names[Workspace::wsv_data[wsvid].Group()],
1141 msource.File(),
1142 msource.Line(),
1143 msource.Column());
1144 }
1145 }
1146 } else if (Workspace::wsv_data[wsvid].Group() != mdd->GInType()[j]) {
1147 throw WrongWsvGroup(
1148 wsvname + " is not " + wsv_group_names[mdd->GInType()[j]] +
1149 ", it is " + wsv_group_names[Workspace::wsv_data[wsvid].Group()],
1150 msource.File(),
1151 msource.Line(),
1152 msource.Column());
1153 }
1154
1155 // Add this one to the list of input variables:
1156 input.push_back(wsvid);
1157
1159 }
1160}
1161
1177 Index& id,
1178 String& methodname,
1179 ArrayOfIndex& output,
1180 bool& first,
1181 bool& still_supergeneric,
1182 String& supergeneric_args,
1183 Index& supergeneric_index,
1184 NamedArguments& named_args,
1185 bool call_by_name) {
1186 String wsvname;
1187 Index wsvid;
1189 using global_data::MdMap;
1191
1192 // Parse all generic output variables
1193 for (Index j = 0; j < mdd->GOut().nelem(); ++j) {
1194 if (call_by_name) {
1195 Index this_arg_index;
1196
1197 get_argument_index_by_name(this_arg_index, named_args, mdd->GOut()[j]);
1198
1199 if (this_arg_index == -1) {
1200 ostringstream os;
1201 os << "This method has generic output. "
1202 << "You have to pass a variable!";
1203 throw ParseError(
1204 os.str(), msource.File(), msource.Line(), msource.Column());
1205 }
1206
1207 msource.SetPosition(named_args[this_arg_index].line,
1208 named_args[this_arg_index].column);
1209 named_args.erase(named_args.begin() + this_arg_index);
1210 } else {
1211 if (first)
1212 first = false;
1213 else {
1216 }
1217 }
1218
1219 read_name(wsvname);
1220 if (call_by_name) at_end_of_argument("generic output argument");
1221
1222 {
1223 wsvid = -1;
1224 // Find Wsv id:
1225 map<String, Index>::const_iterator wsvit =
1226 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 } else {
1238 if (mdd->Name().length() <= 6 ||
1239 mdd->Name().substr(mdd->Name().length() - 6) != "Create") {
1240 ostringstream os;
1241 os << "This might be either a typo or you have to create "
1242 << "the variable\nby calling "
1243 << wsv_group_names[mdd->GOutType()[j]] << "Create( " << wsvname
1244 << " ) first.\n";
1245
1246 throw UnknownWsv(
1247 os.str(), msource.File(), msource.Line(), msource.Column());
1248 } else {
1249 wsvid = Workspace::add_wsv(
1250 WsvRecord(wsvname.c_str(),
1251 "Automatically allocated variable.",
1252 mdd->GOutType()[j],
1253 true));
1254 }
1255 }
1256 }
1257
1258 if (wsvid == -1) {
1259 if (mdd->Name().length() > 6 &&
1260 mdd->Name().find("Create") == mdd->Name().length() - 6) {
1261 ostringstream os;
1262 os << wsvname
1263 << " already exists. A variable can only be created once.\n";
1264 throw WsvAlreadyExists(
1265 os.str(), msource.File(), msource.Line(), msource.Column());
1266 }
1267 wsvid = wsvit->second;
1268 }
1269 }
1270
1271 // If this is a supergeneric method, now is the time to find
1272 // out the actual group of the argument(s)!
1273 // If the method also has supergeneric input arguments, we'll
1274 // look for a match later again.
1275 if (still_supergeneric) {
1276 ostringstream os;
1277 if (wsv_group_names[mdd->GOutType()[j]] == "Any")
1278 supergeneric_args +=
1279 wsv_group_names[Workspace::wsv_data[wsvid].Group()];
1280 os << mdd->Name() << "_sg_" << supergeneric_args;
1281 methodname = os.str();
1282
1283 // Find explicit method id in MdMap:
1284 const map<String, Index>::const_iterator mdit = MdMap.find(methodname);
1285 if (mdit != MdMap.end()) {
1286 id = mdit->second;
1287
1288 mdd = &md_data[id];
1289
1290 still_supergeneric = false;
1291 }
1292 }
1293
1294 // Now we have explicitly the method record for the right
1295 // group. From now on no special treatment of supergeneric
1296 // methods should be necessary.
1297
1298 // Check that this Wsv belongs to the correct group:
1299 if (mdd->GOutType()[j] == get_wsv_group_id("Any") &&
1300 mdd->GOutSpecType()[j].nelem()) {
1301 if (supergeneric_index == -1) {
1302 bool wrong_group_id = true;
1303 for (Index i = 0; wrong_group_id && i < mdd->GOutSpecType()[j].nelem();
1304 i++) {
1305 if (Workspace::wsv_data[wsvid].Group() == mdd->GOutSpecType()[j][i]) {
1306 wrong_group_id = false;
1307 supergeneric_index = i;
1308 }
1309 }
1310
1311 if (wrong_group_id) {
1312 ostringstream os;
1313 bool firsttype = true;
1314 for (Index i = 0; i < mdd->GOutSpecType()[j].nelem(); i++) {
1315 if (!firsttype)
1316 os << ", ";
1317 else
1318 firsttype = false;
1319 os << wsv_group_names[mdd->GOutSpecType()[j][i]];
1320 }
1321
1322 throw WrongWsvGroup(
1323 "*" + mdd->Name() + "* is not defined for " +
1324 wsv_group_names[Workspace::wsv_data[wsvid].Group()] +
1325 " output. Check the online docs.",
1326 msource.File(),
1327 msource.Line(),
1328 msource.Column());
1329 }
1330 } else {
1331 if (Workspace::wsv_data[wsvid].Group() !=
1332 mdd->GOutSpecType()[j][supergeneric_index]) {
1333 throw WrongWsvGroup(
1334 wsvname + " is not " +
1335 wsv_group_names[mdd->GOutSpecType()[j][supergeneric_index]] +
1336 ", it is " +
1337 wsv_group_names[Workspace::wsv_data[wsvid].Group()],
1338 msource.File(),
1339 msource.Line(),
1340 msource.Column());
1341 }
1342 }
1343 } else if (Workspace::wsv_data[wsvid].Group() != mdd->GOutType()[j]) {
1344 throw WrongWsvGroup(
1345 wsvname + " is not " + wsv_group_names[mdd->GOutType()[j]] +
1346 ", it is " + wsv_group_names[Workspace::wsv_data[wsvid].Group()],
1347 msource.File(),
1348 msource.Line(),
1349 msource.Column());
1350 }
1351
1352 // Add this one to the list of output workspace variables:
1353 output.push_back(wsvid);
1354
1356 }
1357}
1358
1372 ArrayOfIndex& input,
1373 ArrayOfIndex& auto_vars,
1374 Array<TokVal>& auto_vars_values,
1375 bool& first,
1376 NamedArguments& named_args,
1377 bool call_by_name) {
1379
1380 // There are two lists of arguments that we have to read.
1381 ArrayOfIndex vo = mdd->Out(); // Output
1382 const ArrayOfIndex& vi = mdd->InOnly(); // Input
1383
1384 Index wsvid; // Workspace variable id, is used to
1385 // access data in wsv_data.
1386
1387 for (ArrayOfIndex::const_iterator ins = vi.begin(); ins < vi.end(); ++ins) {
1388 String wsvname;
1389
1390 if (call_by_name) {
1391 Index this_arg_index;
1392
1393 wsvname = Workspace::wsv_data[*ins].Name();
1394
1395 get_argument_index_by_name(this_arg_index, named_args, wsvname);
1396
1397 if (this_arg_index != -1) {
1398 msource.SetPosition(named_args[this_arg_index].line,
1399 named_args[this_arg_index].column);
1400 named_args.erase(named_args.begin() + this_arg_index);
1401
1402 read_name_or_value(wsvname,
1403 auto_vars,
1404 auto_vars_values,
1405 Workspace::wsv_data[*ins].Name(),
1406 mdd,
1407 Workspace::wsv_data[*ins].Group());
1408 at_end_of_argument("specific input argument");
1409 }
1410 } else {
1411 if (first)
1412 first = false;
1413 else {
1414 try {
1416 } catch (const UnexpectedChar&) {
1417 ostringstream os;
1418 os << "Expected input WSV *" << Workspace::wsv_data[*ins].Name()
1419 << "*";
1420 }
1422 }
1423
1424 read_name_or_value(wsvname,
1425 auto_vars,
1426 auto_vars_values,
1427 Workspace::wsv_data[*ins].Name(),
1428 mdd,
1429 Workspace::wsv_data[*ins].Group());
1430 }
1431
1432 {
1433 // Find Wsv id:
1434 const map<String, Index>::const_iterator wsvit =
1435 Workspace::WsvMap.find(wsvname);
1436 if (wsvit == Workspace::WsvMap.end())
1437 throw UnknownWsv(
1438 wsvname, msource.File(), msource.Line(), msource.Column());
1439
1440 wsvid = wsvit->second;
1441 }
1442
1443 // Check that this Wsv belongs to the correct group:
1444 if (Workspace::wsv_data[wsvid].Group() !=
1445 Workspace::wsv_data[*ins].Group()) {
1446 throw WrongWsvGroup(
1447 wsvname + " is not " +
1448 wsv_group_names[Workspace::wsv_data[*ins].Group()] + ", it is " +
1450 msource.File(),
1451 msource.Line(),
1452 msource.Column());
1453 }
1454
1455 input.push_back(wsvid);
1456 }
1457
1459}
1460
1472 ArrayOfIndex& output,
1473 bool& first,
1474 NamedArguments& named_args,
1475 bool call_by_name) {
1477
1478 ArrayOfIndex vo = mdd->Out();
1479
1480 Index wsvid; // Workspace variable id, is used to
1481 // access data in wsv_data.
1482
1483 for (ArrayOfIndex::const_iterator outs = vo.begin(); outs < vo.end();
1484 ++outs) {
1485 String wsvname;
1486
1487 if (call_by_name) {
1488 Index this_arg_index = 0;
1489
1490 wsvname = Workspace::wsv_data[*outs].Name();
1491
1492 get_argument_index_by_name(this_arg_index, named_args, wsvname);
1493
1494 if (this_arg_index != -1) {
1495 msource.SetPosition(named_args[this_arg_index].line,
1496 named_args[this_arg_index].column);
1497 named_args.erase(named_args.begin() + this_arg_index);
1498
1499 read_name(wsvname);
1500 at_end_of_argument("specific output argument");
1501 }
1502 } else {
1503 if (first)
1504 first = false;
1505 else {
1506 try {
1508 } catch (const UnexpectedChar&) {
1509 ostringstream os;
1510 os << "Expected output WSV *" << Workspace::wsv_data[*outs].Name()
1511 << "*";
1512 throw ParseError(
1513 os.str(), msource.File(), msource.Line(), msource.Column());
1514 }
1516 }
1517
1518 read_name(wsvname);
1519 }
1520
1521 {
1522 wsvid = -1;
1523 // Find Wsv id:
1524 map<String, Index>::const_iterator wsvit =
1525 Workspace::WsvMap.find(wsvname);
1526 if (wsvit == Workspace::WsvMap.end()) {
1527 if (mdd->Name().length() > 6 &&
1528 mdd->Name().substr(mdd->Name().length() - 6) != "Create") {
1529 ostringstream os;
1530 os << "This might be either a typo or you have to create "
1531 << "the variable\nby calling "
1532 << wsv_group_names[Workspace::wsv_data[*outs].Group()]
1533 << "Create( " << wsvname << " ) first.\n";
1534
1535 throw UnknownWsv(
1536 os.str(), msource.File(), msource.Line(), msource.Column());
1537 } else {
1538 wsvid =
1539 Workspace::add_wsv(WsvRecord(wsvname.c_str(),
1540 "Automatically allocated variable.",
1541 Workspace::wsv_data[*outs].Group(),
1542 true));
1543 }
1544 }
1545
1546 if (wsvid == -1) wsvid = wsvit->second;
1547 }
1548
1549 // Check that this Wsv belongs to the correct group:
1550 if (Workspace::wsv_data[wsvid].Group() !=
1551 Workspace::wsv_data[*outs].Group()) {
1552 throw WrongWsvGroup(
1553 wsvname + " is not " +
1554 wsv_group_names[Workspace::wsv_data[*outs].Group()] + ", it is " +
1556 msource.File(),
1557 msource.Line(),
1558 msource.Column());
1559 }
1560
1561 output.push_back(wsvid);
1562 }
1563
1565}
1566
1581 const ArrayOfIndex& auto_vars,
1582 const Array<TokVal>& auto_vars_values,
1583 const Index method_type,
1584 Agenda& tasklist) {
1585 using global_data::MdMap;
1587
1588 for (Index i = 0; i < auto_vars.nelem(); i++) {
1589 map<String, Index>::const_iterator mdit;
1590 Index init_mdid;
1591 TokVal auto_keyword_value;
1592 ArrayOfIndex auto_output_var;
1593 ArrayOfIndex auto_input_var;
1594 Agenda auto_tasks;
1595
1596 const Index auto_group = Workspace::wsv_data[auto_vars[i]].Group();
1597 if (auto_group != get_wsv_group_id("Index") &&
1598 auto_group != get_wsv_group_id("Numeric") &&
1599 auto_group != get_wsv_group_id("ArrayOfIndex") &&
1600 auto_group != get_wsv_group_id("ArrayOfString") &&
1601 auto_group != get_wsv_group_id("ArrayOfSpeciesTag") &&
1602 auto_group != get_wsv_group_id("String") &&
1603 auto_group != get_wsv_group_id("Vector") &&
1604 auto_group != get_wsv_group_id("Matrix")) {
1605 ostringstream os;
1606 os << "Passing a "
1607 << wsv_group_names[Workspace::wsv_data[auto_vars[i]].Group()]
1608 << " constant to a WSM is not supported!";
1609 throw ParseError(
1610 os.str(), msource.File(), msource.Line(), msource.Column());
1611 }
1612
1613 String method_name;
1614 switch (method_type) {
1615 case 0:
1616 auto_keyword_value = auto_vars_values[i];
1617 auto_output_var.push_back(auto_vars[i]);
1618 method_name =
1619 wsv_group_names[Workspace::wsv_data[auto_vars[i]].Group()] + "Set";
1620 break;
1621 case 1:
1622 auto_input_var.push_back(auto_vars[i]);
1623 method_name =
1624 "Delete_sg_" +
1625 wsv_group_names[Workspace::wsv_data[auto_vars[i]].Group()];
1626 break;
1627 default:
1628 throw ParseError("Invalid method type.",
1629 msource.File(),
1630 msource.Line(),
1631 msource.Column());
1632 }
1633
1634 mdit = MdMap.find(method_name);
1635 ARTS_ASSERT(mdit != MdMap.end());
1636 init_mdid = mdit->second;
1637
1638 tasklist.push_back(MRecord(init_mdid,
1639 auto_output_var,
1640 auto_input_var,
1641 auto_keyword_value,
1642 auto_tasks,
1643 true));
1644 }
1645}
1646
1658 switch (c) {
1659 case ' ':
1660 case '\r':
1661 case '\t':
1662 case '#':
1663 return true;
1664 break;
1665 }
1666
1667 return false;
1668}
1669
1680 char dummy;
1681
1682 while (is_whitespace(dummy = msource.Current())) {
1683 switch (dummy) {
1684 case ' ':
1685 case '\r':
1686 case '\t':
1688 break;
1689 case '#':
1691 break;
1692 default: {
1693 ostringstream os;
1694 os << "Expected whitespace, but got `" << dummy << "'.";
1695 throw UnexpectedChar(
1696 os.str(), msource.File(), msource.Line(), msource.Column());
1697 break;
1698 }
1699 }
1700 }
1701}
1702
1709 while (pos < str.length() && is_whitespace(str[pos])) pos++;
1710}
1711
1724 bool stop = false;
1725 name = "";
1726
1727 if (!isalpha(msource.Current())) {
1728 ostringstream os;
1729 os << "Workspace variable names must start with a letter!";
1730 throw ParseError(
1731 os.str(), msource.File(), msource.Line(), msource.Column());
1732 }
1733
1734 while (!stop) {
1735 char dummy = msource.Current();
1736
1737 if (isalnum(dummy) || '_' == dummy) {
1738 name += dummy;
1739 // AdvanceChar sets LineBreak if a line break occured.
1740 msource.LineBreak() = false;
1742 if (msource.LineBreak()) stop = true;
1743 } else {
1744 stop = true;
1745 }
1746 }
1747}
1748
1769 ArrayOfIndex& auto_vars,
1770 Array<TokVal>& auto_vars_values,
1771 const String& default_name,
1772 const MdRecord* mdd,
1773 const Index group) {
1774 name = "";
1775
1776 if (isalpha(msource.Current())) {
1777 read_name(name);
1778 return -1;
1779 }
1780
1781 if (group == get_wsv_group_id("Any")) {
1782 ostringstream os;
1783 os << "Passing constants as supergeneric arguments is not supported.";
1784 throw ParseError(
1785 os.str(), msource.File(), msource.Line(), msource.Column());
1786 }
1787
1788 // If a value was given instead of a variable name, we create
1789 // a new variable in the workspace and fill it with the given
1790 // value
1791
1792 Index wsvid;
1793
1794 name = "auto_" + mdd->Name() + "_" + default_name;
1795 map<String, Index>::const_iterator wsvit = Workspace::WsvMap.find(name);
1796 if (wsvit == Workspace::WsvMap.end()) {
1798 name.c_str(), "Automatically allocated variable.", group, true));
1799 } else {
1800 wsvid = wsvit->second;
1801 }
1802
1803 auto_vars.push_back(wsvid);
1804
1805 // Now parse the value. This can be:
1806 // String_, Index_, Numeric_, Array_String_, Array_Index_, Vector_, Matrix_
1807 if (group == get_wsv_group_id("String")) {
1808 String dummy;
1809 parse_String(dummy);
1810 auto_vars_values.push_back(dummy);
1811 } else if (group == get_wsv_group_id("Index")) {
1812 Index n;
1813 parse_integer(n);
1814 auto_vars_values.push_back(n);
1815 } else if (group == get_wsv_group_id("Numeric")) {
1816 Numeric n;
1817 parse_numeric(n);
1818 auto_vars_values.push_back(n);
1819 } else if (group == get_wsv_group_id("ArrayOfString")) {
1820 ArrayOfString dummy;
1821 parse_Stringvector(dummy);
1822 auto_vars_values.push_back(dummy);
1823 } else if (group == get_wsv_group_id("ArrayOfIndex")) {
1824 ArrayOfIndex dummy;
1825 parse_intvector(dummy);
1826 auto_vars_values.push_back(dummy);
1827 } else if (group == get_wsv_group_id("ArrayOfSpeciesTag")) {
1828 String dummy;
1829 parse_String(dummy);
1830 ArrayOfSpeciesTag aost;
1831 if (dummy.nelem()) {
1832 aost = ArrayOfSpeciesTag(dummy);
1833 }
1834 auto_vars_values.push_back(aost);
1835 } else if (group == get_wsv_group_id("Vector")) {
1836 Vector dummy;
1837 parse_numvector(dummy);
1838 auto_vars_values.push_back(dummy);
1839 } else if (group == get_wsv_group_id("Matrix")) {
1840 Matrix dummy;
1841 parse_matrix(dummy);
1842 auto_vars_values.push_back(dummy);
1843 } else {
1845 ostringstream os;
1846 os << "Unsupported argument type: " << wsv_group_names[group];
1847 throw ParseError(
1848 os.str(), msource.File(), msource.Line(), msource.Column());
1849 }
1850
1851 return wsvid;
1852}
1853
1861 if (c != msource.Current()) {
1862 ostringstream os;
1863 os << "Expected '" << c << "', but got '" << msource.Current() << "'.";
1864 throw UnexpectedChar(
1865 os.str(), msource.File(), msource.Line(), msource.Column());
1866 }
1867
1869}
1870
1882 bool stop = false;
1883 res = "";
1884
1885 msource.LineBreak() = false;
1887 if (msource.LineBreak())
1888 throw IllegalLinebreak("Line break before end of String.",
1889 msource.File(),
1890 msource.Line(),
1891 msource.Column());
1892
1893 while (!stop) {
1894 char dummy = msource.Current();
1895 if (dummy != '"') {
1896 res += dummy;
1898
1899 if (msource.LineBreak())
1900 throw IllegalLinebreak("Line break before end of String.",
1901 msource.File(),
1902 msource.Line(),
1903 msource.Column());
1904 } else {
1905 stop = true;
1907 }
1908 }
1909}
1910
1924 bool stop = false;
1925 res = "";
1926 char dummy;
1927 msource.LineBreak() = false;
1928
1929 dummy = msource.Current();
1930 if ('+' == dummy || '-' == dummy) {
1931 res += dummy;
1933 if (msource.LineBreak())
1934 throw IllegalLinebreak("Line break after sign.",
1935 msource.File(),
1936 msource.Line(),
1937 msource.Column());
1938 }
1939
1940 if (!isdigit(msource.Current())) {
1941 ostringstream os;
1942 os << "Expected digit or variable name, but got `" << msource.Current()
1943 << "'.";
1944 throw UnexpectedChar(
1945 os.str(), msource.File(), msource.Line(), msource.Column());
1946 }
1947
1948 while (!stop) {
1949 char chtmp = msource.Current();
1950 if (isdigit(chtmp)) {
1951 res += chtmp;
1953 if (msource.LineBreak()) stop = true;
1954 } else {
1955 stop = true;
1956 }
1957 }
1958}
1959
1976 bool stop;
1977 res = "";
1978 char dummy;
1979 msource.LineBreak() = false;
1980
1981 // To make sure that there is at least one digit:
1982 bool found_digit = false;
1983
1984 // Check if there is a sign:
1985 dummy = msource.Current();
1986 if ('+' == dummy || '-' == dummy) {
1987 res += dummy;
1989 if (msource.LineBreak())
1990 throw IllegalLinebreak("Linebreak after sign.",
1991 msource.File(),
1992 msource.Line(),
1993 msource.Column());
1994 }
1995
1996 // There could be some digits here:
1997 stop = false;
1998 while (!stop) {
1999 char chtmp = msource.Current();
2000 if (isdigit(chtmp)) {
2001 found_digit = true;
2002 res += chtmp;
2004 if (msource.LineBreak()) return; // Line break ends scanning immediately.
2005 } else {
2006 stop = true;
2007 }
2008 }
2009
2010 // Next there can be a decimal point
2011 if ('.' == msource.Current()) {
2012 res += ".";
2014 if (msource.LineBreak()) {
2015 if (found_digit) {
2016 // Line break ends scanning immediately, if we have
2017 // already found at least one digit.
2018 return;
2019 } else {
2020 throw IllegalLinebreak("Expected at least one digit.",
2021 msource.File(),
2022 msource.Line(),
2023 msource.Column());
2024 }
2025 }
2026
2027 // ... followed by optional more digits
2028 stop = false;
2029 while (!stop) {
2030 char chtmp = msource.Current();
2031 if (isdigit(chtmp)) {
2032 found_digit = true;
2033 res += chtmp;
2035 if (msource.LineBreak())
2036 return; // Line break ends scanning immediately.
2037 } else {
2038 stop = true;
2039 }
2040 }
2041 }
2042
2043 // At this point, we must have found at least one digit.
2044 if (!found_digit)
2045 throw ParseError("Expected at least one digit.",
2046 msource.File(),
2047 msource.Line(),
2048 msource.Column());
2049
2050 // Now there could be a `e' or `E':
2051 dummy = msource.Current();
2052 if ('e' == dummy || 'E' == dummy) {
2053 res += dummy;
2055 if (msource.LineBreak())
2056 throw IllegalLinebreak("Linebreak after e/E.",
2057 msource.File(),
2058 msource.Line(),
2059 msource.Column());
2060
2061 // Now there must be an integer (with optional sign)
2062 {
2063 String s;
2064 read_integer(s);
2065 res += s;
2066 }
2067 }
2068}
2069
2075 String res;
2076 read_integer(res);
2077 istringstream is(res);
2078 is >> n;
2079}
2080
2086 String res;
2087 read_numeric(res);
2088 istringstream is(res);
2089 is >> double_imanip() >> n;
2090}
2091
2107 bool first = true; // To skip the first comma.
2108 res.resize(0); // Clear the result vector (just in case).
2109
2110 // Make sure that the current character really is `[' and proceed.
2112 // There might have occured a linebreak, which is fine.
2113
2115
2116 // Read the elements of the vector (`]' means that we have
2117 // reached the end):
2118 while (']' != msource.Current()) {
2119 String dummy;
2120
2121 if (first)
2122 first = false;
2123 else {
2126 }
2127
2128 parse_String(dummy);
2129 res.push_back(dummy);
2131 }
2132
2134}
2135
2148 bool first = true; // To skip the first comma.
2149 res.resize(0); // Clear the result vector (just in case).
2150
2151 // Make sure that the current character really is `[' and proceed.
2153 // There might have occured a linebreak, which is fine.
2154
2156
2157 // Read the elements of the vector (`]' means that we have
2158 // reached the end):
2159 while (']' != msource.Current()) {
2160 Index dummy;
2161
2162 if (first)
2163 first = false;
2164 else {
2167 }
2168
2169 parse_integer(dummy);
2170 res.push_back(dummy);
2172 }
2173
2175}
2176
2189 bool first = true; // To skip the first comma.
2190
2191 // We need a temporary Array<Numeric>, so that we can use push_back
2192 // to store the values. FIXME: Need also constructor for Vector from
2193 // Array<Numeric>.
2194 Array<Numeric> tres;
2195
2196 // Make sure that the current character really is `[' and proceed.
2198 // There might have occured a linebreak, which is fine.
2199
2201
2202 // Read the elements of the vector (`]' means that we have
2203 // reached the end):
2204 while (']' != msource.Current()) {
2205 Numeric dummy;
2206
2207 if (first)
2208 first = false;
2209 else {
2212 }
2213
2214 parse_numeric(dummy);
2215 tres.push_back(dummy);
2217 }
2218
2219 // Copy tres to res:
2220 res.resize(tres.nelem());
2221 for (int i = 0; i < tres.nelem(); i++) {
2222 res[i] = tres[i];
2223 }
2224
2226}
2227
2240 bool first = true; // To skip the first comma.
2241
2242 // We need a temporary Array<Numeric>, so that we can use push_back
2243 // to store the values. FIXME: Need also constructor for Vector from
2244 // Array<Numeric>.
2245 Array<Numeric> tres;
2246
2247 // Make sure that the current character really is `[' and proceed.
2249 // There might have occured a linebreak, which is fine.
2250
2252
2253 Index ncols = -1;
2254 Index nrows = 0;
2255 Index cur_ncols = 0;
2256 // Read the elements of the vector (`]' means that we have
2257 // reached the end):
2258 while (']' != msource.Current()) {
2259 Numeric dummy;
2260
2261 if (first) {
2262 first = false;
2263 cur_ncols = 1;
2264 nrows = 1;
2265 } else {
2266 if (',' == msource.Current()) {
2267 cur_ncols++;
2268 if (ncols != -1 && cur_ncols > ncols) {
2269 ostringstream os;
2270 os << "Expected ';', but got '" << msource.Current()
2271 << "'. Check Matrix dimensions.";
2272 throw UnexpectedChar(
2273 os.str(), msource.File(), msource.Line(), msource.Column());
2274 }
2277 } else if (';' == msource.Current()) {
2278 nrows++;
2279 if (ncols == -1) {
2280 ncols = cur_ncols;
2281 } else if (ncols != cur_ncols) {
2282 ostringstream os;
2283 os << "Expected ',', but got '" << msource.Current()
2284 << "'. Check Matrix dimensions.";
2285 throw UnexpectedChar(
2286 os.str(), msource.File(), msource.Line(), msource.Column());
2287 }
2288 cur_ncols = 1;
2291 } else {
2292 char c = ';';
2293 if (ncols > cur_ncols) c = ',';
2294 ostringstream os;
2295 os << "Expected '" << c << "', but got '" << msource.Current()
2296 << "'. Check Matrix dimensions.";
2297 throw UnexpectedChar(
2298 os.str(), msource.File(), msource.Line(), msource.Column());
2299 }
2300 }
2301
2302 parse_numeric(dummy);
2303 tres.push_back(dummy);
2305 }
2306
2307 if (ncols == -1) ncols = cur_ncols;
2308 if (ncols != cur_ncols) {
2309 throw ParseError("Missing element(s) in last row of matrix",
2310 msource.File(),
2311 msource.Line(),
2312 msource.Column());
2313 }
2314
2315 // Copy tres to res:
2316 res.resize(nrows, ncols);
2317 for (Index i = 0; i < nrows; i++)
2318 for (Index j = 0; j < ncols; j++) res(i, j) = tres[i * ncols + j];
2319
2321}
2322
2331 bool first = true; // To skip the first comma.
2332 size_t pos = 0;
2333
2334 // We need a temporary Array<Numeric>, so that we can use push_back
2335 // to store the values.
2336 Array<Index> tres;
2337
2339
2340 // Make sure that the current character really is `[' and proceed.
2341 if (str[pos] != '[') {
2342 throw ParseError("No opening bracket found while parsing ArrayOfIndex.",
2343 msource.File(),
2344 msource.Line(),
2345 msource.Column());
2346 }
2347
2348 pos++;
2349
2351
2352 // Read the elements of the vector (`]' means that we have
2353 // reached the end):
2354 while (pos < str.length() && str[pos] != ']') {
2355 if (first)
2356 first = false;
2357 else {
2358 if (str[pos] != ',') {
2359 return false;
2360 }
2361 pos++;
2363 }
2364
2365 Index dummy;
2366 istringstream is(str.substr(pos));
2367 is >> dummy;
2368 if (is.bad() || is.fail()) return false;
2369 tres.push_back(dummy);
2370 while (pos < str.length() &&
2371 (isdigit(str[pos]) || str[pos] == '-' || str[pos] == 'e'))
2372 pos++;
2374 }
2375
2376 // Copy tres to res:
2377 res.resize(tres.nelem());
2378 for (int i = 0; i < tres.nelem(); i++) {
2379 res[i] = tres[i];
2380 }
2381
2382 return true;
2383}
2384
2393 bool first = true; // To skip the first comma.
2394 size_t pos = 0;
2395
2396 // We need a temporary Array<Numeric>, so that we can use push_back
2397 // to store the values.
2398 Array<Numeric> tres;
2399
2401
2402 // Make sure that the current character really is `[' and proceed.
2403 if (str[pos] != '[') {
2404 throw ParseError("No opening bracket found while parsing Vector.",
2405 msource.File(),
2406 msource.Line(),
2407 msource.Column());
2408 }
2409
2410 pos++;
2411
2413
2414 // Read the elements of the vector (`]' means that we have
2415 // reached the end):
2416 while (pos < str.length() && str[pos] != ']') {
2417 if (first)
2418 first = false;
2419 else {
2420 if (str[pos] != ',') {
2421 return false;
2422 }
2423 pos++;
2425 }
2426
2427 Numeric dummy;
2428 istringstream is(str.substr(pos));
2429 is >> double_imanip() >> dummy;
2430 if (is.bad() || is.fail()) return false;
2431 tres.push_back(dummy);
2432 if (str[pos] == 'N' && str.find("NaN", pos) == pos) {
2433 pos += 3;
2434 } else {
2435 while (pos < str.length() && (isdigit(str[pos]) || str[pos] == '-' ||
2436 str[pos] == '.' || str[pos] == 'e'))
2437 pos++;
2438 }
2440 }
2441
2442 // Copy tres to res:
2443 res.resize(tres.nelem());
2444 for (int i = 0; i < tres.nelem(); i++) {
2445 res[i] = tres[i];
2446 }
2447
2448 return true;
2449}
2450
2460 String& str) {
2461 bool first = true; // To skip the first comma.
2462 size_t pos = 0;
2463
2464 // We need a temporary Array<Numeric>, so that we can use push_back
2465 // to store the values.
2466 ArrayOfString tres;
2467
2469
2470 // Make sure that the current character really is `[' and proceed.
2471 if (str[pos] != '[') {
2472 throw ParseError("No opening bracket found while parsing ArrayOfString.",
2473 msource.File(),
2474 msource.Line(),
2475 msource.Column());
2476 }
2477
2478 pos++;
2479
2481
2482 // Read the elements of the vector (`]' means that we have
2483 // reached the end):
2484 while (pos < str.length() && str[pos] != ']') {
2485 if (first)
2486 first = false;
2487 else {
2488 if (str[pos] != ',') {
2489 return false;
2490 }
2491 pos++;
2493 }
2494
2495 if (str[pos] != '"') {
2496 throw ParseError("Expected quotes while parsing ArrayOfString.",
2497 msource.File(),
2498 msource.Line(),
2499 msource.Column());
2500 }
2501
2502 pos++;
2503
2504 String dummy;
2505 while (pos < str.length() && str[pos] != '"') {
2506 dummy += str[pos];
2507 pos++;
2508 }
2509
2510 if (pos == str.length() || str[pos] != '"') return false;
2511
2512 tres.push_back(dummy);
2513
2515 }
2516
2517 // Copy tres to res:
2518 res.resize(tres.nelem());
2519 for (int i = 0; i < tres.nelem(); i++) {
2520 res[i] = tres[i];
2521 }
2522
2523 return true;
2524}
The global header file for ARTS.
Parameters parameters
Holds the command line parameters.
Definition: parameters.cc:41
Index nrows
type upp char * str
Index ncols
The Agenda class.
Definition: agenda_class.h:44
void push_back(const MRecord &n)
Append a new method to end of list.
Definition: agenda_class.h:274
void resize(Index n)
Resize the method list.
Definition: agenda_class.h:257
const Array< MRecord > & Methods() const
Definition: agenda_class.h:74
Index nelem() const
Return the number of agenda elements.
Definition: agenda_class.h:266
Index nelem() const ARTS_NOEXCEPT
Number of elements.
Definition: array.h:195
bool parse_stringarray_from_string(ArrayOfString &res, String &str)
Read an Array of Strings from a String.
Definition: parser.cc:2459
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:1471
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:2085
void parse_tasklist()
Public interface to the main function of the parser.
Definition: parser.cc:50
void read_name(String &name)
Reads name of method, keyword, or workspace variable.
Definition: parser.cc:1723
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:1580
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:990
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:2106
void parse_integer(Index &n)
Use a String stream to parse an integer number.
Definition: parser.cc:2074
void skip_to_next_argument()
Skips forward to the next argument.
Definition: parser.cc:91
void assertain_character(char c)
Make sure that the current character is equal to c and go to the next character.
Definition: parser.cc:1860
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:1371
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:1768
void find_named_arguments(vector< NamedArgument > &named_args)
Find named arguments.
Definition: parser.cc:60
bool parse_intvector_from_string(ArrayOfIndex &res, String &str)
Read an array of integers from a String.
Definition: parser.cc:2330
ArtsParser(Agenda &tasklist, String controlfile, const Verbosity &verbosity)
Constructs a new parser.
Definition: parser.cc:36
bool parse_numvector_from_string(Vector &res, String &str)
Read a vector of Numerics from a String.
Definition: parser.cc:2392
bool is_whitespace(const char c)
Returns true if this character is considered whitespace.
Definition: parser.cc:1657
void parse_method(Index &id, ArrayOfIndex &output, ArrayOfIndex &input, Agenda &tasks, ArrayOfIndex &auto_vars, Array< TokVal > &auto_vars_values, String &include_file, bool no_eot=false)
Parse the Contents of text as ARTS control input.
Definition: parser.cc:496
void eat_whitespace_from_string(String &str, size_t &pos)
Eats whitespace from a String.
Definition: parser.cc:1708
String set_gin_to_default(const MdRecord *mdd, ArrayOfIndex &auto_vars, Array< TokVal > &auto_vars_values, Index keyword_index)
Set generic input to default value.
Definition: parser.cc:603
void parse_agenda(Agenda &tasklist, const String &agenda_name)
Parse the Contents of text as ARTS control input.
Definition: parser.cc:333
void eat_whitespace()
Eats whitespace.
Definition: parser.cc:1679
void parse_main()
The main function of the parser.
Definition: parser.cc:184
void parse_String(String &res)
Reads a String, complete with quotation marks.
Definition: parser.cc:1881
void get_argument_index_by_name(Index &arg_index, NamedArguments &named_args, String name)
Return the index of the argument with the given name.
Definition: parser.cc:169
void read_numeric(String &res)
Reads a floating point number.
Definition: parser.cc:1975
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:759
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:1176
void parse_numvector(Vector &res)
Read a vector of Numerics.
Definition: parser.cc:2188
void read_integer(String &res)
Reads an integer.
Definition: parser.cc:1923
void parse_intvector(ArrayOfIndex &res)
Read a vector of integers.
Definition: parser.cc:2147
void parse_matrix(Matrix &res)
Read a Matrix.
Definition: parser.cc:2239
void at_end_of_argument(const String &argname)
Check if current position in controlfile is at the end of an argument.
Definition: parser.cc:154
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:1225
void resize(Index r, Index c)
Resize function.
Definition: matpackI.cc:1056
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
This stores arbitrary token values and remembers the type.
Definition: token.h:42
The Vector class.
Definition: matpackI.h:876
void resize(Index n)
Resize function.
Definition: matpackI.cc:408
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
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:227
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
#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:109
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.
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
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.