OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
MacroCmd.cpp
Go to the documentation of this file.
1//
2// Class MacroCmd
3//
4// This class parses the MACRO command.
5// Encapsulate the buffer for the ``archetypes'' of all macros.
6// The macro is stored as a MacroStream. For execution, first the
7// parameters are replaced, then the resulting stream is sent to the parser.
8//
9// Copyright (c) 2008 - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
10//
11// All rights reserved
12//
13// This file is part of OPAL.
14//
15// OPAL is free software: you can redistribute it and/or modify
16// it under the terms of the GNU General Public License as published by
17// the Free Software Foundation, either version 3 of the License, or
18// (at your option) any later version.
19//
20// You should have received a copy of the GNU General Public License
21// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
22//
23
24#include "OpalParser/MacroCmd.h"
25
26#include "Utility/PAssert.h"
27
28#include <vector>
33
35 : Macro(0u, "MACRO",
36 "A \"MACRO\" command defines a subroutine:\n"
37 "\t<name>(<arguments>):MACRO{<body>}"),
38 body(0) {}
39
40MacroCmd::MacroCmd(const std::string& name, MacroCmd* parent) : Macro(name, parent), body() {
41 body = std::make_shared<MacroStream>(name);
42}
43
45
47 body->start();
48 itsParser->run(&*body);
49}
50
52 const std::string& name, Statement& statement, const Parser* parser) {
53 parseActuals(statement);
54
55 // Check for consistency in argument number.
56 if (formals.size() != actuals.size()) {
57 throw ParseError("MacroCmd::makeInstance()", "Inconsistent number of macro arguments.");
58 }
59
60 // Substitute the actual arguments.
61 MacroCmd* macro = new MacroCmd(name, this);
62 macro->itsParser = parser;
63 body->start();
64 Token token = body->readToken();
65
66 while (!token.isEOF()) {
67 bool found = false;
68
69 if (token.isWord()) {
70 std::string word = token.getWord();
71
72 for (std::vector<std::string>::size_type i = 0; i < formals.size(); i++) {
73 if (word == formals[i]) {
74 std::vector<Token> act = actuals[i];
75 for (Token t : act) {
76 macro->body->append(t);
77 }
78 found = true;
79 break;
80 }
81 }
82 }
83
84 if (!found) macro->body->append(token);
85 token = body->readToken();
86 }
87
88 return macro;
89}
90
91Object* MacroCmd::makeTemplate(const std::string& name, TokenStream&, Statement& statement) {
92 MacroCmd* macro = new MacroCmd(name, this);
93 macro->parseFormals(statement);
94
95 // Parse macro body->
96 bool isMacro = statement.keyword("MACRO");
97 PAssert(isMacro);
98 Token token;
99
100 if (statement.delimiter('{')) {
101 int level = 1;
102 while (true) {
103 if (statement.atEnd()) {
104 throw ParseError("MacroCmd::makeTemplate()", "MACRO body is not closed.");
105 } else {
106 token = statement.getCurrent();
107
108 if (token.isDel('{')) {
109 ++level;
110 } else if (token.isDel('}')) {
111 if (--level == 0) break;
112 }
113
114 macro->body->append(token);
115 }
116 }
117 } else {
118 throw ParseError("MacroCmd::makeTemplate()", "Missing MACRO body, should be \"{...}\".");
119 }
120
121 return macro;
122}
virtual Object * makeInstance(const std::string &name, Statement &, const Parser *)
Make a macro instance.
Definition MacroCmd.cpp:51
virtual Object * makeTemplate(const std::string &, TokenStream &, Statement &)
Make a macro template.
Definition MacroCmd.cpp:91
std::shared_ptr< MacroStream > body
Definition MacroCmd.h:60
const Parser * itsParser
Definition MacroCmd.h:63
virtual ~MacroCmd()
Definition MacroCmd.cpp:44
virtual void execute()
Execute the macro command.
Definition MacroCmd.cpp:46
Abstract base class for macros.
Definition Macro.h:33
std::vector< std::vector< Token > > actuals
The actual argument list.
Definition Macro.h:77
virtual void parseFormals(Statement &)
Parse formal arguments.
Definition Macro.cpp:82
std::vector< std::string > formals
The formal argument list.
Definition Macro.h:73
virtual void parseActuals(Statement &)
Parse actual arguments.
Definition Macro.cpp:47
The base class for all OPAL objects.
Definition Object.h:45
Parse exception.
Definition ParseError.h:31
Interface for abstract language parser.
Definition Parser.h:30
virtual void run(TokenStream *ts) const =0
Read statements and parse.
Interface for statements.
Definition Statement.h:37
Token & getCurrent()
Return current token and skip it.
Definition Statement.cpp:61
bool keyword(const char *s)
Test for keyword.
bool atEnd() const
Test for end of command.
Definition Statement.cpp:41
bool delimiter(char c)
Test for delimiter.
Definition Statement.cpp:83
Abstract interface for a stream of input tokens.
Definition TokenStream.h:30
Representation of a single input token.
Definition Token.h:32
bool isDel(char del) const
Test for delimiter.
Definition Token.cpp:81
bool isWord() const
Test for word.
Definition Token.cpp:97
bool isEOF() const
Test for end of file.
Definition Token.cpp:89
std::string getWord() const
Return word value.
Definition Token.cpp:147