ARTS 2.5.10 (git: 2f1c442c)
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()),
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 String &methodname, ArrayOfIndex &output,
764 ArrayOfIndex &input, 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 auto md_raw_id = MdRawMap.find(methodname);
777 if (md_raw_id == MdRawMap.end())
778 throw UnknownMethod(methodname, msource.File(), msource.MarkedLine(),
780
781 id = md_raw_id->second;
782
783 // Get a convenient handle on the data record for this method. We
784 // have to use a pointer here, not a reference, because we later
785 // want to change where mdd is pointing!
786 mdd = &md_data_raw[id];
787
788 // Is this a supergeneric method? If not, take the record in
789 // md_data, rather than in md_data_raw:
790 if (!mdd->Supergeneric()) {
791 // Find explicit method id in MdMap:
792 const auto i2 = MdMap.find(methodname);
793 ARTS_ASSERT(i2 != MdMap.end());
794 id = i2->second;
795
796 mdd = &md_data[id];
797
798 still_supergeneric = false;
799 }
800
801 if (msource.Current() == '(') {
802 String supergeneric_args;
803 Index supergeneric_index = -1;
804 NamedArguments named_arguments;
805 Index this_method_end_line = -1;
806 Index this_method_end_column = -1;
807 bool call_by_name = false;
808
811 if (msource.Current() != ')') {
812 // Peak at the first method argument to determine if the method
813 // is called with positional or named arguments
814 if (isalpha(msource.Current())) {
817 String name = "";
818
819 read_name(name);
821
822 if (msource.Current() == '=') {
825
827 find_named_arguments(named_arguments);
828
829 call_by_name = true;
830
831 this_method_end_line = msource.LineRaw();
832 this_method_end_column = msource.ColumnRaw();
833 }
834
836 }
837
838 bool is_first_arg = true;
839 parse_specific_output(mdd, output, is_first_arg, named_arguments,
840 call_by_name);
841
842 parse_generic_output(mdd, id, methodname, output, is_first_arg,
843 still_supergeneric, supergeneric_args,
844 supergeneric_index, named_arguments, call_by_name);
845
846 parse_specific_input(mdd, input, auto_vars, auto_vars_values,
847 is_first_arg, named_arguments, call_by_name);
848
849 parse_generic_input(mdd, id, methodname, input, auto_vars,
850 auto_vars_values, is_first_arg, still_supergeneric,
851 supergeneric_args, supergeneric_index,
852 named_arguments, call_by_name);
853
854 // Named arguments are not parsed in order. We have to set the cursor
855 // to the end of the method call after all named arguments have been
856 // parsed.
857 if (call_by_name)
858 msource.SetPosition(this_method_end_line, this_method_end_column);
859
860 // If we're here and still have named arguments left means that
861 // the user specified too many for this method
862 if (call_by_name && named_arguments.size()) {
863 ostringstream os;
864
865 os << "Error in arguments passed to " << mdd->Name() << ":\n";
866 for (auto &argument_name : named_arguments) {
867 if (std::find(mdd->GIn().begin(), mdd->GIn().end(),
868 argument_name.name) == mdd->GIn().end() &&
869 std::find(mdd->GOut().begin(), mdd->GOut().end(),
870 argument_name.name) == mdd->GOut().end())
871 os << " Unkown argument: ";
872 else
873 os << " Duplicate argument: ";
874 os << argument_name.name << std::endl;
875 }
876 throw ParseError(os.str(), msource.File(), msource.Line(),
877 msource.Column());
878 }
879 ARTS_ASSERT(!still_supergeneric);
880 } else {
881 // Method call contains empty set of parenthesis
882 use_default_method_args(mdd, methodname, output, input, auto_vars,
883 auto_vars_values);
884 }
886 } else {
887 // Method call without parenthesis
888 use_default_method_args(mdd, methodname, output, input, auto_vars,
889 auto_vars_values);
890 }
891}
892
894
906 String &methodname,
907 ArrayOfIndex &output,
908 ArrayOfIndex &input,
909 ArrayOfIndex &auto_vars,
910 Array<TokVal> &auto_vars_values) {
911 if (mdd->GOut().nelem()) {
912 ostringstream os;
913 os << "This method has generic output. "
914 << "You have to pass a variable!";
915 throw ParseError(os.str(), msource.File(), msource.MarkedLine(),
917 }
918
919 // If all arguments were omitted we still have to add the implicit
920 // outputs and inputs to the methods input and output variable lists
921 ArrayOfIndex vo = mdd->Out();
922 for (auto outs = vo.begin(); outs < vo.end(); ++outs) {
923 output.push_back(*outs);
924 }
925
926 const ArrayOfIndex &vi = mdd->InOnly();
927 for (auto ins = vi.begin(); ins < vi.end(); ++ins) {
928 input.push_back(*ins);
929 }
930
931 {
932 // Make sure all keywords have default values, otherwise the
933 // user has to specify them in the controlfile.
934 bool all_gin_have_defaults = true;
935 for (Index gin = 0; all_gin_have_defaults && gin < mdd->GIn().nelem();
936 ++gin) {
937 Index wsvid; // Workspace variable id, is used to
938 // access data in wsv_data.
939
940 if (mdd->GInDefault()[gin] == NODEF)
941 all_gin_have_defaults = false;
942 else {
943 String wsvname;
944 wsvname = set_gin_to_default(mdd, auto_vars, auto_vars_values, gin);
945 {
946 // Find Wsv id:
947 const auto wsvit = ws->WsvMap_ptr->find(wsvname);
948 if (wsvit == ws->WsvMap_ptr->end()) {
949 throw UnknownWsv(wsvname, msource.File(), msource.MarkedLine(),
951 }
952
953 wsvid = wsvit->second;
954 }
955 input.push_back(wsvid);
956 }
957 }
958
959 if (!all_gin_have_defaults) {
960 ostringstream os;
961 os << "Not all generic inputs of the method *" << methodname
962 << "* have default values, you have to specify them!";
963 throw ParseError(os.str(), msource.File(), msource.MarkedLine(),
965 }
966 }
967}
968
986 Index& id,
987 String& methodname,
988 ArrayOfIndex& input,
989 ArrayOfIndex& auto_vars,
990 Array<TokVal>& auto_vars_values,
991 bool& first,
992 bool& still_supergeneric,
993 String& supergeneric_args,
994 Index& supergeneric_index _U_,
995 NamedArguments& named_args,
996 bool call_by_name) {
997 String wsvname;
998 Index wsvid;
1000 using global_data::MdMap;
1002
1003 // Then parse all generic input variables
1004 for (Index j = 0; j < mdd->GInType().nelem(); ++j) {
1005 Index this_arg_index = 0;
1006
1007 if (call_by_name) {
1008 get_argument_index_by_name(this_arg_index, named_args, mdd->GIn()[j]);
1009
1010 if (this_arg_index != -1) {
1011 msource.SetPosition(named_args[this_arg_index].line,
1012 named_args[this_arg_index].column);
1013 named_args.erase(named_args.begin() + this_arg_index);
1014 }
1015 } else {
1016 if (first)
1017 first = false;
1018 else {
1019 if (msource.Current() != ')') {
1022 }
1023 }
1024 }
1025
1026 // If no value was specified and we use the default value instead (if there is one)
1027 if ((call_by_name && this_arg_index == -1) || msource.Current() == ',' ||
1028 msource.Current() == ')') {
1029 wsvname = set_gin_to_default(mdd, auto_vars, auto_vars_values, j);
1030 } else {
1031 ostringstream os;
1032 os << j;
1033 if (read_name_or_value(wsvname,
1034 auto_vars,
1035 auto_vars_values,
1036 "generic" + os.str(),
1037 mdd,
1038 mdd->GInType()[j]) == -1 &&
1039 mdd->SetMethod()) {
1040 if (msource.Current() == '=') {
1041 throw UnexpectedChar(
1042 "Unexpected '=' sign encountered.\n"
1043 "Mixing positional and named arguments is not allowed.",
1044 msource.File(),
1045 msource.Line(),
1046 msource.Column());
1047 }
1048 throw ParseError(
1049 "Only constants can be passed to Set methods.\n"
1050 "You might want to use the *Copy* here.",
1051 msource.File(),
1052 msource.Line(),
1053 msource.Column());
1054 }
1055 if (call_by_name) at_end_of_argument("generic input argument");
1056 }
1057
1058 {
1059 // Find Wsv id:
1060 const auto wsvit =
1061 ws->WsvMap_ptr->find(wsvname);
1062 if (wsvit == ws->WsvMap_ptr->end()) {
1063 throw UnknownWsv(
1064 wsvname, msource.File(), msource.Line(), msource.Column());
1065 }
1066
1067 wsvid = wsvit->second;
1068 }
1069
1070 // Is the method data record still supergeneric? This could
1071 // be the case if there are no output arguments, only input
1072 // arguments. In that case, let's find out the actual group!
1073 if (still_supergeneric) {
1074 ostringstream os;
1075 if (wsv_groups[mdd->GInType()[j]] == "Any")
1076 supergeneric_args +=
1077 wsv_groups[(*ws->wsv_data_ptr)[wsvid].Group()].name;
1078 os << mdd->Name() << "_sg_" << supergeneric_args;
1079 methodname = os.str();
1080
1081 // Find explicit method id in MdMap:
1082 const auto mdit = MdMap.find(methodname);
1083 if (mdit != MdMap.end()) {
1084 id = mdit->second;
1085
1086 mdd = &md_data[id];
1087
1088 still_supergeneric = false;
1089 }
1090 }
1091
1092 // Now we have explicitly the method record for the right
1093 // group. From now on no special treatment of supergeneric
1094 // methods should be necessary.
1095
1096 // Check that this Wsv belongs to the correct group:
1097 if (mdd->GInType()[j] == get_wsv_group_id("Any") &&
1098 mdd->GInSpecType()[j].nelem()) {
1099 if (supergeneric_index == -1) {
1100 bool wrong_group_id = true;
1101 for (Index i = 0; wrong_group_id && i < mdd->GInSpecType()[j].nelem();
1102 i++) {
1103 if ((*ws->wsv_data_ptr)[wsvid].Group() == mdd->GInSpecType()[j][i]) {
1104 wrong_group_id = false;
1105 supergeneric_index = i;
1106 }
1107 }
1108
1109 if (wrong_group_id) {
1110 ostringstream os;
1111 bool firsttype = true;
1112 for (Index i = 0; i < mdd->GInSpecType()[j].nelem(); i++) {
1113 if (!firsttype)
1114 os << ", ";
1115 else
1116 firsttype = false;
1117 os << wsv_groups[mdd->GInSpecType()[j][i]];
1118 }
1119
1120 throw WrongWsvGroup(
1121 "*" + mdd->Name() + "* is not defined for " +
1122 wsv_groups[(*ws->wsv_data_ptr)[wsvid].Group()].name +
1123 " input. Check the online docs.",
1124 msource.File(),
1125 msource.Line(),
1126 msource.Column());
1127 }
1128 } else {
1129 if ((*ws->wsv_data_ptr)[wsvid].Group() !=
1130 mdd->GInSpecType()[j][supergeneric_index]) {
1131 throw WrongWsvGroup(
1132 wsvname + " is not " +
1133 wsv_groups[mdd->GInSpecType()[j][supergeneric_index]].name +
1134 ", it is " +
1135 wsv_groups[(*ws->wsv_data_ptr)[wsvid].Group()].name,
1136 msource.File(),
1137 msource.Line(),
1138 msource.Column());
1139 }
1140 }
1141 } else if ((*ws->wsv_data_ptr)[wsvid].Group() != mdd->GInType()[j]) {
1142 throw WrongWsvGroup(
1143 wsvname + " is not " + wsv_groups[mdd->GInType()[j]].name +
1144 ", it is " + wsv_groups[(*ws->wsv_data_ptr)[wsvid].Group()].name,
1145 msource.File(),
1146 msource.Line(),
1147 msource.Column());
1148 }
1149
1150 // Add this one to the list of input variables:
1151 input.push_back(wsvid);
1152
1154 }
1155}
1156
1172 Index& id,
1173 String& methodname,
1174 ArrayOfIndex& output,
1175 bool& first,
1176 bool& still_supergeneric,
1177 String& supergeneric_args,
1178 Index& supergeneric_index,
1179 NamedArguments& named_args,
1180 bool call_by_name) {
1181 String wsvname;
1182 Index wsvid;
1184 using global_data::MdMap;
1186
1187 // Parse all generic output variables
1188 for (Index j = 0; j < mdd->GOut().nelem(); ++j) {
1189 if (call_by_name) {
1190 Index this_arg_index;
1191
1192 get_argument_index_by_name(this_arg_index, named_args, mdd->GOut()[j]);
1193
1194 if (this_arg_index == -1) {
1195 ostringstream os;
1196 os << "This method has generic output. "
1197 << "You have to pass a variable!";
1198 throw ParseError(
1199 os.str(), msource.File(), msource.Line(), msource.Column());
1200 }
1201
1202 msource.SetPosition(named_args[this_arg_index].line,
1203 named_args[this_arg_index].column);
1204 named_args.erase(named_args.begin() + this_arg_index);
1205 } else {
1206 if (first)
1207 first = false;
1208 else {
1211 }
1212 }
1213
1214 read_name(wsvname);
1215 if (call_by_name) at_end_of_argument("generic output argument");
1216
1217 {
1218 wsvid = -1;
1219 // Find Wsv id:
1220 auto wsvit = ws->WsvMap_ptr->find(wsvname);
1221 if (wsvit == ws->WsvMap_ptr->end()) {
1222 if (still_supergeneric) {
1223 ostringstream os;
1224 os << "This might be either a typo or you have to create "
1225 << "the variable\nby calling TYPECreate(" << wsvname
1226 << ") first. Replace TYPE with the\n"
1227 << "WSV group your variable should belong to.";
1228
1229 throw UnknownWsv(
1230 os.str(), msource.File(), msource.Line(), msource.Column());
1231 }
1232
1233 if (mdd->Name().length() <= 6 ||
1234 mdd->Name().substr(mdd->Name().length() - 6) != "Create") {
1235 ostringstream os;
1236 os << "This might be either a typo or you have to create "
1237 << "the variable\nby calling "
1238 << wsv_groups[mdd->GOutType()[j]] << "Create( " << wsvname
1239 << " ) first.\n";
1240
1241 throw UnknownWsv(
1242 os.str(), msource.File(), msource.Line(), msource.Column());
1243 }
1244
1245 wsvid =
1246 ws->add_wsv(WsvRecord(wsvname.c_str(),
1247 "Automatically allocated variable.",
1248 mdd->GOutType()[j]));
1249 }
1250
1251 if (wsvid == -1) {
1252 if (mdd->Name().length() > 6 &&
1253 mdd->Name().find("Create") == mdd->Name().length() - 6) {
1254 const String& gn =
1255 wsv_groups[(*ws->wsv_data_ptr)[wsvit->second].Group()].name;
1256 if (mdd->Name().find(gn) not_eq 0) {
1257 throw WsvAlreadyExists(
1258 var_string(
1259 wsvname,
1260 " already exists of group ",
1261 gn,
1262 ". A variable cannot be redefined as a different group.\n"),
1263 msource.File(),
1264 msource.Line(),
1265 msource.Column());
1266 }
1267 }
1268 wsvid = wsvit->second;
1269 }
1270 }
1271
1272 // If this is a supergeneric method, now is the time to find
1273 // out the actual group of the argument(s)!
1274 // If the method also has supergeneric input arguments, we'll
1275 // look for a match later again.
1276 if (still_supergeneric) {
1277 ostringstream os;
1278 if (wsv_groups[mdd->GOutType()[j]] == "Any")
1279 supergeneric_args +=
1280 wsv_groups[(*ws->wsv_data_ptr)[wsvid].Group()].name;
1281 os << mdd->Name() << "_sg_" << supergeneric_args;
1282 methodname = os.str();
1283
1284 // Find explicit method id in MdMap:
1285 const auto mdit = MdMap.find(methodname);
1286 if (mdit != MdMap.end()) {
1287 id = mdit->second;
1288
1289 mdd = &md_data[id];
1290
1291 still_supergeneric = false;
1292 }
1293 }
1294
1295 // Now we have explicitly the method record for the right
1296 // group. From now on no special treatment of supergeneric
1297 // methods should be necessary.
1298
1299 // Check that this Wsv belongs to the correct group:
1300 if (mdd->GOutType()[j] == get_wsv_group_id("Any") &&
1301 mdd->GOutSpecType()[j].nelem()) {
1302 if (supergeneric_index == -1) {
1303 bool wrong_group_id = true;
1304 for (Index i = 0; wrong_group_id && i < mdd->GOutSpecType()[j].nelem();
1305 i++) {
1306 if ((*ws->wsv_data_ptr)[wsvid].Group() == mdd->GOutSpecType()[j][i]) {
1307 wrong_group_id = false;
1308 supergeneric_index = i;
1309 }
1310 }
1311
1312 if (wrong_group_id) {
1313 ostringstream os;
1314 bool firsttype = true;
1315 for (Index i = 0; i < mdd->GOutSpecType()[j].nelem(); i++) {
1316 if (!firsttype)
1317 os << ", ";
1318 else
1319 firsttype = false;
1320 os << wsv_groups[mdd->GOutSpecType()[j][i]];
1321 }
1322
1323 throw WrongWsvGroup(
1324 "*" + mdd->Name() + "* is not defined for " +
1325 wsv_groups[(*ws->wsv_data_ptr)[wsvid].Group()].name +
1326 " output. Check the online docs.",
1327 msource.File(),
1328 msource.Line(),
1329 msource.Column());
1330 }
1331 } else {
1332 if ((*ws->wsv_data_ptr)[wsvid].Group() !=
1333 mdd->GOutSpecType()[j][supergeneric_index]) {
1334 throw WrongWsvGroup(
1335 wsvname + " is not " +
1336 wsv_groups[mdd->GOutSpecType()[j][supergeneric_index]].name +
1337 ", it is " +
1338 wsv_groups[(*ws->wsv_data_ptr)[wsvid].Group()].name,
1339 msource.File(),
1340 msource.Line(),
1341 msource.Column());
1342 }
1343 }
1344 } else if ((*ws->wsv_data_ptr)[wsvid].Group() != mdd->GOutType()[j]) {
1345 throw WrongWsvGroup(
1346 wsvname + " is not " + wsv_groups[mdd->GOutType()[j]].name +
1347 ", it is " + wsv_groups[(*ws->wsv_data_ptr)[wsvid].Group()].name,
1348 msource.File(),
1349 msource.Line(),
1350 msource.Column());
1351 }
1352
1353 // Add this one to the list of output workspace variables:
1354 output.push_back(wsvid);
1355
1357 }
1358}
1359
1373 ArrayOfIndex& input,
1374 ArrayOfIndex& auto_vars,
1375 Array<TokVal>& auto_vars_values,
1376 bool& first,
1377 NamedArguments& named_args,
1378 bool call_by_name) {
1380
1381 // There are two lists of arguments that we have to read.
1382 ArrayOfIndex vo = mdd->Out(); // Output
1383 const ArrayOfIndex& vi = mdd->InOnly(); // Input
1384
1385 Index wsvid; // Workspace variable id, is used to
1386 // access data in wsv_data.
1387
1388 for (auto ins = vi.begin(); ins < vi.end(); ++ins) {
1389 String wsvname;
1390
1391 if (call_by_name) {
1392 Index this_arg_index;
1393
1394 wsvname = (*ws->wsv_data_ptr)[*ins].Name();
1395
1396 get_argument_index_by_name(this_arg_index, named_args, wsvname);
1397
1398 if (this_arg_index != -1) {
1399 msource.SetPosition(named_args[this_arg_index].line,
1400 named_args[this_arg_index].column);
1401 named_args.erase(named_args.begin() + this_arg_index);
1402
1403 read_name_or_value(wsvname,
1404 auto_vars,
1405 auto_vars_values,
1406 (*ws->wsv_data_ptr)[*ins].Name(),
1407 mdd,
1408 (*ws->wsv_data_ptr)[*ins].Group());
1409 at_end_of_argument("specific input argument");
1410 }
1411 } else {
1412 if (first)
1413 first = false;
1414 else {
1415 try {
1417 } catch (const UnexpectedChar&) {
1418 ostringstream os;
1419 os << "Expected input WSV *" << (*ws->wsv_data_ptr)[*ins].Name()
1420 << "*";
1421 }
1423 }
1424
1425 read_name_or_value(wsvname,
1426 auto_vars,
1427 auto_vars_values,
1428 (*ws->wsv_data_ptr)[*ins].Name(),
1429 mdd,
1430 (*ws->wsv_data_ptr)[*ins].Group());
1431 }
1432
1433 {
1434 // Find Wsv id:
1435 const auto wsvit =
1436 ws->WsvMap_ptr->find(wsvname);
1437 if (wsvit == ws->WsvMap_ptr->end())
1438 throw UnknownWsv(
1439 wsvname, msource.File(), msource.Line(), msource.Column());
1440
1441 wsvid = wsvit->second;
1442 }
1443
1444 // Check that this Wsv belongs to the correct group:
1445 if ((*ws->wsv_data_ptr)[wsvid].Group() !=
1446 (*ws->wsv_data_ptr)[*ins].Group()) {
1447 throw WrongWsvGroup(
1448 wsvname + " is not " +
1449 wsv_groups[(*ws->wsv_data_ptr)[*ins].Group()].name + ", it is " +
1450 wsv_groups[(*ws->wsv_data_ptr)[wsvid].Group()].name,
1451 msource.File(),
1452 msource.Line(),
1453 msource.Column());
1454 }
1455
1456 input.push_back(wsvid);
1457 }
1458
1460}
1461
1473 ArrayOfIndex& output,
1474 bool& first,
1475 NamedArguments& named_args,
1476 bool call_by_name) {
1478
1479 ArrayOfIndex vo = mdd->Out();
1480
1481 Index wsvid; // Workspace variable id, is used to
1482 // access data in wsv_data.
1483
1484 for (auto outs = vo.begin(); outs < vo.end();
1485 ++outs) {
1486 String wsvname;
1487
1488 if (call_by_name) {
1489 Index this_arg_index = 0;
1490
1491 wsvname = (*ws->wsv_data_ptr)[*outs].Name();
1492
1493 get_argument_index_by_name(this_arg_index, named_args, wsvname);
1494
1495 if (this_arg_index != -1) {
1496 msource.SetPosition(named_args[this_arg_index].line,
1497 named_args[this_arg_index].column);
1498 named_args.erase(named_args.begin() + this_arg_index);
1499
1500 read_name(wsvname);
1501 at_end_of_argument("specific output argument");
1502 }
1503 } else {
1504 if (first)
1505 first = false;
1506 else {
1507 try {
1509 } catch (const UnexpectedChar&) {
1510 ostringstream os;
1511 os << "Expected output WSV *" << (*ws->wsv_data_ptr)[*outs].Name()
1512 << "*";
1513 throw ParseError(
1514 os.str(), msource.File(), msource.Line(), msource.Column());
1515 }
1517 }
1518
1519 read_name(wsvname);
1520 }
1521
1522 {
1523 wsvid = -1;
1524 // Find Wsv id:
1525 auto wsvit =
1526 ws->WsvMap_ptr->find(wsvname);
1527 if (wsvit == ws->WsvMap_ptr->end()) {
1528 if (mdd->Name().length() > 6 &&
1529 mdd->Name().substr(mdd->Name().length() - 6) != "Create") {
1530 ostringstream os;
1531 os << "This might be either a typo or you have to create "
1532 << "the variable\nby calling "
1533 << wsv_groups[(*ws->wsv_data_ptr)[*outs].Group()]
1534 << "Create( " << wsvname << " ) first.\n";
1535
1536 throw UnknownWsv(
1537 os.str(), msource.File(), msource.Line(), msource.Column());
1538 }
1539 wsvid =
1540 ws->add_wsv(WsvRecord(wsvname.c_str(),
1541 "Automatically allocated variable.",
1542 (*ws->wsv_data_ptr)[*outs].Group()));
1543 }
1544
1545 if (wsvid == -1) wsvid = wsvit->second;
1546 }
1547
1548 // Check that this Wsv belongs to the correct group:
1549 if ((*ws->wsv_data_ptr)[wsvid].Group() !=
1550 (*ws->wsv_data_ptr)[*outs].Group()) {
1551 throw WrongWsvGroup(
1552 wsvname + " is not " +
1553 wsv_groups[(*ws->wsv_data_ptr)[*outs].Group()].name + ", it is " +
1554 wsv_groups[(*ws->wsv_data_ptr)[wsvid].Group()].name,
1555 msource.File(),
1556 msource.Line(),
1557 msource.Column());
1558 }
1559
1560 output.push_back(wsvid);
1561 }
1562
1564}
1565
1580 const ArrayOfIndex& auto_vars,
1581 const Array<TokVal>& auto_vars_values,
1582 const Index method_type,
1583 Agenda& tasklist) {
1584 using global_data::MdMap;
1586
1587 for (Index i = 0; i < auto_vars.nelem(); i++) {
1588 map<String, Index>::const_iterator mdit;
1589 Index init_mdid;
1590 TokVal auto_keyword_value;
1591 ArrayOfIndex auto_output_var;
1592 ArrayOfIndex auto_input_var;
1593 Agenda auto_tasks{*ws};
1594
1595 const Index auto_group = (*ws->wsv_data_ptr)[auto_vars[i]].Group();
1596 if (auto_group != get_wsv_group_id("Index") &&
1597 auto_group != get_wsv_group_id("Numeric") &&
1598 auto_group != get_wsv_group_id("ArrayOfIndex") &&
1599 auto_group != get_wsv_group_id("ArrayOfString") &&
1600 auto_group != get_wsv_group_id("ArrayOfSpeciesTag") &&
1601 auto_group != get_wsv_group_id("String") &&
1602 auto_group != get_wsv_group_id("Vector") &&
1603 auto_group != get_wsv_group_id("Matrix")) {
1604 ostringstream os;
1605 os << "Passing a "
1606 << wsv_groups[(*ws->wsv_data_ptr)[auto_vars[i]].Group()]
1607 << " constant to a WSM is not supported!";
1608 throw ParseError(
1609 os.str(), msource.File(), msource.Line(), msource.Column());
1610 }
1611
1612 String method_name;
1613 switch (method_type) {
1614 case 0:
1615 auto_keyword_value = auto_vars_values[i];
1616 auto_output_var.push_back(auto_vars[i]);
1617 method_name =
1618 wsv_groups[(*ws->wsv_data_ptr)[auto_vars[i]].Group()].name + "Set";
1619 break;
1620 case 1:
1621 auto_input_var.push_back(auto_vars[i]);
1622 method_name =
1623 "Delete_sg_" +
1624 wsv_groups[(*ws->wsv_data_ptr)[auto_vars[i]].Group()].name;
1625 break;
1626 default:
1627 throw ParseError("Invalid method type.",
1628 msource.File(),
1629 msource.Line(),
1630 msource.Column());
1631 }
1632
1633 mdit = MdMap.find(method_name);
1634 ARTS_ASSERT(mdit != MdMap.end());
1635 init_mdid = mdit->second;
1636
1637 tasklist.push_back(MRecord(init_mdid,
1638 auto_output_var,
1639 auto_input_var,
1640 auto_keyword_value,
1641 auto_tasks,
1642 true));
1643 }
1644}
1645
1657 switch (c) {
1658 case ' ':
1659 case '\r':
1660 case '\t':
1661 case '#':
1662 return true;
1663 break;
1664 }
1665
1666 return false;
1667}
1668
1679 char dummy;
1680
1681 while (is_whitespace(dummy = msource.Current())) {
1682 switch (dummy) {
1683 case ' ':
1684 case '\r':
1685 case '\t':
1687 break;
1688 case '#':
1690 break;
1691 default: {
1692 ostringstream os;
1693 os << "Expected whitespace, but got `" << dummy << "'.";
1694 throw UnexpectedChar(
1695 os.str(), msource.File(), msource.Line(), msource.Column());
1696 break;
1697 }
1698 }
1699 }
1700}
1701
1708 while (pos < str.length() && is_whitespace(str[pos])) pos++;
1709}
1710
1723 bool stop = false;
1724 name = "";
1725
1726 if (!isalpha(msource.Current())) {
1727 ostringstream os;
1728 os << "Workspace variable names must start with a letter!";
1729 throw ParseError(
1730 os.str(), msource.File(), msource.Line(), msource.Column());
1731 }
1732
1733 while (!stop) {
1734 char dummy = msource.Current();
1735
1736 if (isalnum(dummy) || '_' == dummy) {
1737 name += dummy;
1738 // AdvanceChar sets LineBreak if a line break occured.
1739 msource.LineBreak() = false;
1741 if (msource.LineBreak()) stop = true;
1742 } else {
1743 stop = true;
1744 }
1745 }
1746}
1747
1768 ArrayOfIndex& auto_vars,
1769 Array<TokVal>& auto_vars_values,
1770 const String& default_name,
1771 const MdRecord* mdd,
1772 const Index group) {
1773 name = "";
1774
1775 if (isalpha(msource.Current())) {
1776 read_name(name);
1777 return -1;
1778 }
1779
1780 if (group == get_wsv_group_id("Any")) {
1781 ostringstream os;
1782 os << "Passing constants as supergeneric arguments is not supported.";
1783 throw ParseError(
1784 os.str(), msource.File(), msource.Line(), msource.Column());
1785 }
1786
1787 // If a value was given instead of a variable name, we create
1788 // a new variable in the workspace and fill it with the given
1789 // value
1790
1791 Index wsvid;
1792
1793 name = "auto_" + mdd->Name() + "_" + default_name;
1794 auto wsvit = ws->WsvMap_ptr->find(name);
1795 if (wsvit == ws->WsvMap_ptr->end()) {
1796 wsvid = ws->add_wsv(WsvRecord(
1797 name.c_str(), "Automatically allocated variable.", group));
1798 } else {
1799 wsvid = wsvit->second;
1800 }
1801
1802 auto_vars.push_back(wsvid);
1803
1804 // Now parse the value. This can be:
1805 // String_, Index_, Numeric_, Array_String_, Array_Index_, Vector_, Matrix_
1806 if (group == get_wsv_group_id("String")) {
1807 String dummy;
1808 parse_String(dummy);
1809 auto_vars_values.push_back(dummy);
1810 } else if (group == get_wsv_group_id("Index")) {
1811 Index n;
1812 parse_integer(n);
1813 auto_vars_values.push_back(n);
1814 } else if (group == get_wsv_group_id("Numeric")) {
1815 Numeric n;
1816 parse_numeric(n);
1817 auto_vars_values.push_back(n);
1818 } else if (group == get_wsv_group_id("ArrayOfString")) {
1819 ArrayOfString dummy;
1820 parse_Stringvector(dummy);
1821 auto_vars_values.push_back(dummy);
1822 } else if (group == get_wsv_group_id("ArrayOfIndex")) {
1823 ArrayOfIndex dummy;
1824 parse_intvector(dummy);
1825 auto_vars_values.push_back(dummy);
1826 } else if (group == get_wsv_group_id("ArrayOfSpeciesTag")) {
1827 String dummy;
1828 parse_String(dummy);
1829 ArrayOfSpeciesTag aost;
1830 if (dummy.nelem()) {
1831 aost = ArrayOfSpeciesTag(dummy);
1832 }
1833 auto_vars_values.push_back(aost);
1834 } else if (group == get_wsv_group_id("Vector")) {
1835 Vector dummy;
1836 parse_numvector(dummy);
1837 auto_vars_values.push_back(dummy);
1838 } else if (group == get_wsv_group_id("Matrix")) {
1839 Matrix dummy;
1840 parse_matrix(dummy);
1841 auto_vars_values.push_back(dummy);
1842 } else {
1844 ostringstream os;
1845 os << "Unsupported argument type: " << wsv_groups[group];
1846 throw ParseError(
1847 os.str(), msource.File(), msource.Line(), msource.Column());
1848 }
1849
1850 return wsvid;
1851}
1852
1860 if (c != msource.Current()) {
1861 ostringstream os;
1862 os << "Expected '" << c << "', but got '" << msource.Current() << "'.";
1863 throw UnexpectedChar(
1864 os.str(), msource.File(), msource.Line(), msource.Column());
1865 }
1866
1868}
1869
1881 bool stop = false;
1882 res = "";
1883
1884 msource.LineBreak() = false;
1886 if (msource.LineBreak())
1887 throw IllegalLinebreak("Line break before end of String.",
1888 msource.File(),
1889 msource.Line(),
1890 msource.Column());
1891
1892 while (!stop) {
1893 char dummy = msource.Current();
1894 if (dummy != '"') {
1895 res += dummy;
1897
1898 if (msource.LineBreak())
1899 throw IllegalLinebreak("Line break before end of String.",
1900 msource.File(),
1901 msource.Line(),
1902 msource.Column());
1903 } else {
1904 stop = true;
1906 }
1907 }
1908}
1909
1923 bool stop = false;
1924 res = "";
1925 char dummy;
1926 msource.LineBreak() = false;
1927
1928 dummy = msource.Current();
1929 if ('+' == dummy || '-' == dummy) {
1930 res += dummy;
1932 if (msource.LineBreak())
1933 throw IllegalLinebreak("Line break after sign.",
1934 msource.File(),
1935 msource.Line(),
1936 msource.Column());
1937 }
1938
1939 if (!isdigit(msource.Current())) {
1940 ostringstream os;
1941 os << "Expected digit or variable name, but got `" << msource.Current()
1942 << "'.";
1943 throw UnexpectedChar(
1944 os.str(), msource.File(), msource.Line(), msource.Column());
1945 }
1946
1947 while (!stop) {
1948 char chtmp = msource.Current();
1949 if (isdigit(chtmp)) {
1950 res += chtmp;
1952 if (msource.LineBreak()) stop = true;
1953 } else {
1954 stop = true;
1955 }
1956 }
1957}
1958
1975 bool stop;
1976 res = "";
1977 char dummy;
1978 msource.LineBreak() = false;
1979
1980 // To make sure that there is at least one digit:
1981 bool found_digit = false;
1982
1983 // Check if there is a sign:
1984 dummy = msource.Current();
1985 if ('+' == dummy || '-' == dummy) {
1986 res += dummy;
1988 if (msource.LineBreak())
1989 throw IllegalLinebreak("Linebreak after sign.",
1990 msource.File(),
1991 msource.Line(),
1992 msource.Column());
1993 }
1994
1995 // There could be some digits here:
1996 stop = false;
1997 while (!stop) {
1998 char chtmp = msource.Current();
1999 if (isdigit(chtmp)) {
2000 found_digit = true;
2001 res += chtmp;
2003 if (msource.LineBreak()) return; // Line break ends scanning immediately.
2004 } else {
2005 stop = true;
2006 }
2007 }
2008
2009 // Next there can be a decimal point
2010 if ('.' == msource.Current()) {
2011 res += ".";
2013 if (msource.LineBreak()) {
2014 if (found_digit) {
2015 // Line break ends scanning immediately, if we have
2016 // already found at least one digit.
2017 return;
2018 }
2019 throw IllegalLinebreak("Expected at least one digit.",
2020 msource.File(),
2021 msource.Line(),
2022 msource.Column());
2023 }
2024
2025 // ... followed by optional more digits
2026 stop = false;
2027 while (!stop) {
2028 char chtmp = msource.Current();
2029 if (isdigit(chtmp)) {
2030 found_digit = true;
2031 res += chtmp;
2033 if (msource.LineBreak())
2034 return; // Line break ends scanning immediately.
2035 } else {
2036 stop = true;
2037 }
2038 }
2039 }
2040
2041 // At this point, we must have found at least one digit.
2042 if (!found_digit)
2043 throw ParseError("Expected at least one digit.",
2044 msource.File(),
2045 msource.Line(),
2046 msource.Column());
2047
2048 // Now there could be a `e' or `E':
2049 dummy = msource.Current();
2050 if ('e' == dummy || 'E' == dummy) {
2051 res += dummy;
2053 if (msource.LineBreak())
2054 throw IllegalLinebreak("Linebreak after e/E.",
2055 msource.File(),
2056 msource.Line(),
2057 msource.Column());
2058
2059 // Now there must be an integer (with optional sign)
2060 {
2061 String s;
2062 read_integer(s);
2063 res += s;
2064 }
2065 }
2066}
2067
2073 String res;
2074 read_integer(res);
2075 istringstream is(res);
2076 is >> n;
2077}
2078
2084 String res;
2085 read_numeric(res);
2086 istringstream is(res);
2087 is >> double_imanip() >> n;
2088}
2089
2105 bool first = true; // To skip the first comma.
2106 res.resize(0); // Clear the result vector (just in case).
2107
2108 // Make sure that the current character really is `[' and proceed.
2110 // There might have occured a linebreak, which is fine.
2111
2113
2114 // Read the elements of the vector (`]' means that we have
2115 // reached the end):
2116 while (']' != msource.Current()) {
2117 String dummy;
2118
2119 if (first)
2120 first = false;
2121 else {
2124 }
2125
2126 parse_String(dummy);
2127 res.push_back(dummy);
2129 }
2130
2132}
2133
2146 bool first = true; // To skip the first comma.
2147 res.resize(0); // Clear the result vector (just in case).
2148
2149 // Make sure that the current character really is `[' and proceed.
2151 // There might have occured a linebreak, which is fine.
2152
2154
2155 // Read the elements of the vector (`]' means that we have
2156 // reached the end):
2157 while (']' != msource.Current()) {
2158 Index dummy;
2159
2160 if (first)
2161 first = false;
2162 else {
2165 }
2166
2167 parse_integer(dummy);
2168 res.push_back(dummy);
2170 }
2171
2173}
2174
2187 bool first = true; // To skip the first comma.
2188
2189 // We need a temporary Array<Numeric>, so that we can use push_back
2190 // to store the values. FIXME: Need also constructor for Vector from
2191 // Array<Numeric>.
2192 Array<Numeric> tres;
2193
2194 // Make sure that the current character really is `[' and proceed.
2196 // There might have occured a linebreak, which is fine.
2197
2199
2200 // Read the elements of the vector (`]' means that we have
2201 // reached the end):
2202 while (']' != msource.Current()) {
2203 Numeric dummy;
2204
2205 if (first)
2206 first = false;
2207 else {
2210 }
2211
2212 parse_numeric(dummy);
2213 tres.push_back(dummy);
2215 }
2216
2217 // Copy tres to res:
2218 res.resize(tres.nelem());
2219 for (int i = 0; i < tres.nelem(); i++) {
2220 res[i] = tres[i];
2221 }
2222
2224}
2225
2238 bool first = true; // To skip the first comma.
2239
2240 // We need a temporary Array<Numeric>, so that we can use push_back
2241 // to store the values. FIXME: Need also constructor for Vector from
2242 // Array<Numeric>.
2243 Array<Numeric> tres;
2244
2245 // Make sure that the current character really is `[' and proceed.
2247 // There might have occured a linebreak, which is fine.
2248
2250
2251 Index ncols = -1;
2252 Index nrows = 0;
2253 Index cur_ncols = 0;
2254 // Read the elements of the vector (`]' means that we have
2255 // reached the end):
2256 while (']' != msource.Current()) {
2257 Numeric dummy;
2258
2259 if (first) {
2260 first = false;
2261 cur_ncols = 1;
2262 nrows = 1;
2263 } else {
2264 if (',' == msource.Current()) {
2265 cur_ncols++;
2266 if (ncols != -1 && cur_ncols > ncols) {
2267 ostringstream os;
2268 os << "Expected ';', but got '" << msource.Current()
2269 << "'. Check Matrix dimensions.";
2270 throw UnexpectedChar(
2271 os.str(), msource.File(), msource.Line(), msource.Column());
2272 }
2275 } else if (';' == msource.Current()) {
2276 nrows++;
2277 if (ncols == -1) {
2278 ncols = cur_ncols;
2279 } else if (ncols != cur_ncols) {
2280 ostringstream os;
2281 os << "Expected ',', but got '" << msource.Current()
2282 << "'. Check Matrix dimensions.";
2283 throw UnexpectedChar(
2284 os.str(), msource.File(), msource.Line(), msource.Column());
2285 }
2286 cur_ncols = 1;
2289 } else {
2290 char c = ';';
2291 if (ncols > cur_ncols) c = ',';
2292 ostringstream os;
2293 os << "Expected '" << c << "', but got '" << msource.Current()
2294 << "'. Check Matrix dimensions.";
2295 throw UnexpectedChar(
2296 os.str(), msource.File(), msource.Line(), msource.Column());
2297 }
2298 }
2299
2300 parse_numeric(dummy);
2301 tres.push_back(dummy);
2303 }
2304
2305 if (ncols == -1) ncols = cur_ncols;
2306 if (ncols != cur_ncols) {
2307 throw ParseError("Missing element(s) in last row of matrix",
2308 msource.File(),
2309 msource.Line(),
2310 msource.Column());
2311 }
2312
2313 // Copy tres to res:
2314 res.resize(nrows, ncols);
2315 for (Index i = 0; i < nrows; i++)
2316 for (Index j = 0; j < ncols; j++) res(i, j) = tres[i * ncols + j];
2317
2319}
2320
2329 bool first = true; // To skip the first comma.
2330 size_t pos = 0;
2331
2332 // We need a temporary Array<Numeric>, so that we can use push_back
2333 // to store the values.
2334 Array<Index> tres;
2335
2337
2338 // Make sure that the current character really is `[' and proceed.
2339 if (str[pos] != '[') {
2340 throw ParseError("No opening bracket found while parsing ArrayOfIndex.",
2341 msource.File(),
2342 msource.Line(),
2343 msource.Column());
2344 }
2345
2346 pos++;
2347
2349
2350 // Read the elements of the vector (`]' means that we have
2351 // reached the end):
2352 while (pos < str.length() && str[pos] != ']') {
2353 if (first)
2354 first = false;
2355 else {
2356 if (str[pos] != ',') {
2357 return false;
2358 }
2359 pos++;
2361 }
2362
2363 Index dummy;
2364 istringstream is(str.substr(pos));
2365 is >> dummy;
2366 if (is.bad() || is.fail()) return false;
2367 tres.push_back(dummy);
2368 while (pos < str.length() &&
2369 (isdigit(str[pos]) || str[pos] == '-' || str[pos] == 'e'))
2370 pos++;
2372 }
2373
2374 // Copy tres to res:
2375 res.resize(tres.nelem());
2376 for (int i = 0; i < tres.nelem(); i++) {
2377 res[i] = tres[i];
2378 }
2379
2380 return true;
2381}
2382
2391 bool first = true; // To skip the first comma.
2392 size_t pos = 0;
2393
2394 // We need a temporary Array<Numeric>, so that we can use push_back
2395 // to store the values.
2396 Array<Numeric> tres;
2397
2399
2400 // Make sure that the current character really is `[' and proceed.
2401 if (str[pos] != '[') {
2402 throw ParseError("No opening bracket found while parsing Vector.",
2403 msource.File(),
2404 msource.Line(),
2405 msource.Column());
2406 }
2407
2408 pos++;
2409
2411
2412 // Read the elements of the vector (`]' means that we have
2413 // reached the end):
2414 while (pos < str.length() && str[pos] != ']') {
2415 if (first)
2416 first = false;
2417 else {
2418 if (str[pos] != ',') {
2419 return false;
2420 }
2421 pos++;
2423 }
2424
2425 Numeric dummy;
2426 istringstream is(str.substr(pos));
2427 is >> double_imanip() >> dummy;
2428 if (is.bad() || is.fail()) return false;
2429 tres.push_back(dummy);
2430 if (str[pos] == 'N' && str.find("NaN", pos) == pos) {
2431 pos += 3;
2432 } else {
2433 while (pos < str.length() && (isdigit(str[pos]) || str[pos] == '-' ||
2434 str[pos] == '.' || str[pos] == 'e'))
2435 pos++;
2436 }
2438 }
2439
2440 // Copy tres to res:
2441 res.resize(tres.nelem());
2442 for (int i = 0; i < tres.nelem(); i++) {
2443 res[i] = tres[i];
2444 }
2445
2446 return true;
2447}
2448
2458 String& str) {
2459 bool first = true; // To skip the first comma.
2460 size_t pos = 0;
2461
2462 // We need a temporary Array<Numeric>, so that we can use push_back
2463 // to store the values.
2464 ArrayOfString tres;
2465
2467
2468 // Make sure that the current character really is `[' and proceed.
2469 if (str[pos] != '[') {
2470 throw ParseError("No opening bracket found while parsing ArrayOfString.",
2471 msource.File(),
2472 msource.Line(),
2473 msource.Column());
2474 }
2475
2476 pos++;
2477
2479
2480 // Read the elements of the vector (`]' means that we have
2481 // reached the end):
2482 while (pos < str.length() && str[pos] != ']') {
2483 if (first)
2484 first = false;
2485 else {
2486 if (str[pos] != ',') {
2487 return false;
2488 }
2489 pos++;
2491 }
2492
2493 if (str[pos] != '"') {
2494 throw ParseError("Expected quotes while parsing ArrayOfString.",
2495 msource.File(),
2496 msource.Line(),
2497 msource.Column());
2498 }
2499
2500 pos++;
2501
2502 String dummy;
2503 while (pos < str.length() && str[pos] != '"') {
2504 dummy += str[pos];
2505 pos++;
2506 }
2507
2508 if (pos == str.length() || str[pos] != '"') return false;
2509
2510 tres.push_back(dummy);
2511
2513 }
2514
2515 // Copy tres to res:
2516 res.resize(tres.nelem());
2517 for (int i = 0; i < tres.nelem(); i++) {
2518 res[i] = tres[i];
2519 }
2520
2521 return true;
2522}
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:2457
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:1472
const Verbosity & verbosity
Definition: parser.h:176
void parse_numeric(Numeric &n)
Use a String stream to parse a floating point number.
Definition: parser.cc:2083
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:1722
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:1579
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:985
Agenda & mtasklist
Definition: parser.h:166
String mcfile
Definition: parser.h:170
void parse_Stringvector(ArrayOfString &res)
Read a vector of Strings.
Definition: parser.cc:2104
void parse_integer(Index &n)
Use a String stream to parse an integer number.
Definition: parser.cc:2072
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:1859
SourceText msource
Definition: parser.h:172
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:1372
std::shared_ptr< Workspace > ws
Definition: parser.h:168
{ 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:1767
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:2328
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:2390
void use_default_method_args(const MdRecord *mdd, String &methodname, ArrayOfIndex &output, ArrayOfIndex &input, ArrayOfIndex &auto_vars, Array< TokVal > &auto_vars_values)
Set defaults if method is called without any arguments.
Definition: parser.cc:905
bool is_whitespace(const char c)
Returns true if this character is considered whitespace.
Definition: parser.cc:1656
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:1707
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:1678
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:1880
void read_numeric(String &res)
Reads a floating point number.
Definition: parser.cc:1974
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:1171
void parse_numvector(Vector &res)
Read a vector of Numerics.
Definition: parser.cc:2186
void read_integer(String &res)
Reads an integer.
Definition: parser.cc:1922
void parse_intvector(ArrayOfIndex &res)
Read a vector of integers.
Definition: parser.cc:2145
void parse_matrix(Matrix &res)
Read a Matrix.
Definition: parser.cc:2237
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:174
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:142
The Matrix class.
Definition: matpackI.h:1285
void resize(Index r, Index c)
Resize function.
Definition: matpackI.cc:1011
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:245
The Vector class.
Definition: matpackI.h:910
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:102
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:301
String get_dirname(const std::string_view path)
Return the parent directory of a path.
Definition: file.cc:461
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
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
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.