OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
LineTemplate.cpp
Go to the documentation of this file.
1//
2// Class LineTemplate
3//
4// An ``archetype'' for a OPAL beam line with arguments.
5// The model is stored in form of a MacroStream. A call to the macro line
6// is expanded by first replacing the arguments, and then parsing the
7// resulting stream as a LINE definition.
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 "Lines/LineTemplate.h"
25
26#include "Utility/PAssert.h"
27
28#include <vector>
30#include "Lines/Line.h"
33
35 : Macro(0, "LINE",
36 "This object defines a beamline list with arguments.\n"
37 "\t<name>(<args>);"),
38 body("LINE") {}
39
40LineTemplate::LineTemplate(const std::string& name, Object* parent)
41 : Macro(name, parent), body(name) {}
42
44
45LineTemplate* LineTemplate::clone(const std::string& /*name*/) {
46 throw ParseError("LineTemplate::clone()", "You cannot use this object without attributes.");
47}
48
49Object* LineTemplate::makeInstance(const std::string& name, Statement& statement, const Parser*) {
50 Line* instance = 0;
51
52 try {
53 // Parse actuals and check their number.
54 parseActuals(statement);
55 if (formals.size() != actuals.size()) {
56 throw ParseError(
57 "LineTemplate::makeInstance()", "Inconsistent number of macro arguments.");
58 }
59
60 // Expand the LINE macro in token form.
61 body.start();
62 Token token = body.readToken();
63 SimpleStatement expansion(getOpalName(), 1);
64 while (!token.isEOF()) {
65 bool found = false;
66 if (token.isWord()) {
67 std::string word = token.getWord();
68
69 for (std::vector<std::string>::size_type i = 0; i < formals.size(); i++) {
70 if (word == formals[i]) {
71 std::vector<Token> act = actuals[i];
72 for (Token t : act) {
73 expansion.append(t);
74 }
75 found = true;
76 break;
77 }
78 }
79 }
80 if (!found) expansion.append(token);
81 token = body.readToken();
82 }
83
84 // Parse the modified line.
85 Line* model = dynamic_cast<Line*>(OpalData::getInstance()->find("LINE"));
86 instance = model->clone(name);
87 instance->copyAttributes(*this);
88 expansion.start();
89 instance->parse(expansion);
90 } catch (...) {
91 delete instance;
92 throw;
93 }
94
95 return instance;
96}
97
99 // Should not be called.
100 return 0;
101}
102
104 parseFormals(statement);
105 bool isLine = statement.keyword("LINE");
106 PAssert(isLine);
107
108 // Store the template list.
109 Token token = statement.getCurrent();
110 if (token.isDel('=')) {
111 body.append(token);
112 int level = 0;
113 while (!statement.atEnd()) {
114 token = statement.getCurrent();
115 if (token.isDel('(')) {
116 level++;
117 } else if (token.isDel(')')) {
118 body.append(token);
119 if (--level == 0) break;
120 }
121 body.append(token);
122 }
123 } else {
124 throw ParseError("LineTemplate::parseTemplate()", "Equals sign '=' expected.");
125 }
126}
MacroStream body
virtual ~LineTemplate()
void parseTemplate(TokenStream &is, Statement &stat)
Parse the line template.
virtual Object * makeInstance(const std::string &name, Statement &stat, const Parser *)
Make line instance.
virtual LineTemplate * clone(const std::string &name)
Make clone.
virtual Object * makeTemplate(const std::string &, TokenStream &, Statement &)
Make a line template.
Definition Line.h:30
virtual void parse(Statement &stat)
Parse the line object.
Definition Line.cpp:135
virtual Line * clone(const std::string &name)
Make clone.
Definition Line.cpp:110
void append(Token &)
Append a token to the stream.
void start()
Reset stream to start.
virtual Token readToken()
Read a token from the stream.
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
const std::string & getOpalName() const
Return object name.
Definition Object.cpp:267
void copyAttributes(const Object &)
Copy attributes from another object.
Definition Object.cpp:50
Object * find(const std::string &name)
Find entry.
Definition OpalData.cpp:477
static OpalData * getInstance()
Definition OpalData.cpp:193
Parse exception.
Definition ParseError.h:31
Interface for abstract language parser.
Definition Parser.h:30
A simple input statement in token form.
Interface for statements.
Definition Statement.h:37
Token & getCurrent()
Return current token and skip it.
Definition Statement.cpp:61
void append(const Token &)
Append a token.
Definition Statement.cpp:39
bool keyword(const char *s)
Test for keyword.
bool atEnd() const
Test for end of command.
Definition Statement.cpp:41
void start()
Return to start.
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