OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
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 
29 #include "OpalParser/OpalParser.h"
30 #include "Parser/Statement.h"
31 #include "Utilities/ParseError.h"
32 #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 {}
40 
41 
42 MacroCmd::MacroCmd(const std::string &name, MacroCmd *parent):
43  Macro(name, parent), body() {
44  body = new MacroStream(name);
45 }
46 
47 
49 {}
50 
51 
53  body->start();
54  itsParser->run(&*body);
55 }
56 
57 
59 (const std::string &name, Statement &statement, const Parser *parser) {
60  parseActuals(statement);
61 
62  // Check for consistency in argument number.
63  if(formals.size() != actuals.size()) {
64  throw ParseError("MacroCmd::makeInstance()",
65  "Inconsistent number of macro arguments.");
66  }
67 
68  // Substitute the actual arguments.
69  MacroCmd *macro = new MacroCmd(name, this);
70  macro->itsParser = parser;
71  body->start();
72  Token token = body->readToken();
73 
74  while(! token.isEOF()) {
75  bool found = false;
76 
77  if(token.isWord()) {
78  std::string word = token.getWord();
79 
80  for(std::vector<std::string>::size_type i = 0;
81  i < formals.size(); i++) {
82  if(word == formals[i]) {
83  std::vector<Token> act = actuals[i];
84  for(Token t : act) {
85  macro->body->append(t);
86  }
87  found = true;
88  break;
89  }
90  }
91  }
92 
93  if(! found) macro->body->append(token);
94  token = body->readToken();
95  }
96 
97  return macro;
98 }
99 
100 
102 (const std::string &name, TokenStream &, Statement &statement) {
103  MacroCmd *macro = new MacroCmd(name, this);
104  macro->parseFormals(statement);
105 
106  // Parse macro body->
107  bool isMacro = statement.keyword("MACRO");
108  PAssert(isMacro);
109  Token token;
110 
111  if(statement.delimiter('{')) {
112  int level = 1;
113  while(true) {
114  if(statement.atEnd()) {
115  throw ParseError("MacroCmd::makeTemplate()",
116  "MACRO body is not closed.");
117  } else {
118  token = statement.getCurrent();
119 
120  if(token.isDel('{')) {
121  ++level;
122  } else if(token.isDel('}')) {
123  if(--level == 0) break;
124  }
125 
126  macro->body->append(token);
127  }
128  }
129  } else {
130  throw ParseError("MacroCmd::makeTemplate()",
131  "Missing MACRO body, should be \"{...}\".");
132  }
133 
134  return macro;
135 }
#define PAssert(c)
Definition: PAssert.h:102
const std::string name
The base class for all OPAL objects.
Definition: Object.h:48
Interface for abstract language parser.
Definition: Parser.h:31
virtual void run(TokenStream *ts) const =0
Read statements and parse.
Interface for statements.
Definition: Statement.h:38
Token & getCurrent()
Return current token and skip it.
Definition: Statement.cpp:74
bool keyword(const char *s)
Test for keyword.
Definition: Statement.cpp:121
bool atEnd() const
Test for end of command.
Definition: Statement.cpp:50
bool delimiter(char c)
Test for delimiter.
Definition: Statement.cpp:101
Representation of a single input token.
Definition: Token.h:33
bool isDel(char del) const
Test for delimiter.
Definition: Token.cpp:92
bool isWord() const
Test for word.
Definition: Token.cpp:127
bool isEOF() const
Test for end of file.
Definition: Token.cpp:107
std::string getWord() const
Return word value.
Definition: Token.cpp:190
Abstract interface for a stream of input tokens.
Definition: TokenStream.h:33
Parse exception.
Definition: ParseError.h:32
Abstract base class for macros.
Definition: Macro.h:34
virtual void parseFormals(Statement &)
Parse formal arguments.
Definition: Macro.cpp:100
std::vector< std::string > formals
The formal argument list.
Definition: Macro.h:78
std::vector< std::vector< Token > > actuals
The actual argument list.
Definition: Macro.h:82
virtual void parseActuals(Statement &)
Parse actual arguments.
Definition: Macro.cpp:64
virtual Object * makeInstance(const std::string &name, Statement &, const Parser *)
Make a macro instance.
Definition: MacroCmd.cpp:59
virtual Object * makeTemplate(const std::string &, TokenStream &, Statement &)
Make a macro template.
Definition: MacroCmd.cpp:102
Pointer< MacroStream > body
Definition: MacroCmd.h:64
const Parser * itsParser
Definition: MacroCmd.h:67
virtual ~MacroCmd()
Definition: MacroCmd.cpp:48
virtual void execute()
Execute the macro command.
Definition: MacroCmd.cpp:52
MacroCmd()
Definition: MacroCmd.cpp:34
An input buffer for macro commands.
Definition: MacroStream.h:31
void append(Token &)
Append a token to the stream.
Definition: MacroStream.cpp:36
void start()
Reset stream to start.
Definition: MacroStream.cpp:53
virtual Token readToken()
Read a token from the stream.
Definition: MacroStream.cpp:41