OPAL (Object Oriented Parallel Accelerator Library) 2022.1
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
30#include "Parser/Statement.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
42MacroCmd::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