OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
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
29#include "Lines/Line.h"
32#include <vector>
33
35 Macro(0, "LINE",
36 "This object defines a beamline list with arguments.\n"
37 "\t<name>(<args>);"),
38 body("LINE")
39{}
40
41
42LineTemplate::LineTemplate(const std::string &name, Object *parent):
43 Macro(name, parent), body(name)
44{}
45
46
48{}
49
50
51LineTemplate *LineTemplate::clone(const std::string &/*name*/) {
52 throw ParseError("LineTemplate::clone()",
53 "You cannot use this object without attributes.");
54}
55
56
58(const std::string &name, Statement &statement, const Parser *) {
59 Line *instance = 0;
60
61 try {
62 // Parse actuals and check their number.
63 parseActuals(statement);
64 if(formals.size() != actuals.size()) {
65 throw ParseError("LineTemplate::makeInstance()",
66 "Inconsistent number of macro arguments.");
67 }
68
69 // Expand the LINE macro in token form.
70 body.start();
71 Token token = body.readToken();
72 SimpleStatement expansion(getOpalName(), 1);
73 while(! token.isEOF()) {
74 bool found = false;
75 if(token.isWord()) {
76 std::string word = token.getWord();
77
78 for(std::vector<std::string>::size_type i = 0;
79 i < formals.size(); i++) {
80 if(word == formals[i]) {
81 std::vector<Token> act = actuals[i];
82 for(Token t : act) {
83 expansion.append(t);
84 }
85 found = true;
86 break;
87 }
88 }
89 }
90 if(! found) expansion.append(token);
91 token = body.readToken();
92 }
93
94 // Parse the modified line.
95 Line *model = dynamic_cast<Line *>(OpalData::getInstance()->find("LINE"));
96 instance = model->clone(name);
97 instance->copyAttributes(*this);
98 expansion.start();
99 instance->parse(expansion);
100 } catch(...) {
101 delete instance;
102 throw;
103 }
104
105 return instance;
106}
107
108
110 // Should not be called.
111 return 0;
112}
113
114
116 parseFormals(statement);
117 bool isLine = statement.keyword("LINE");
118 PAssert(isLine);
119
120 // Store the template list.
121 Token token = statement.getCurrent();
122 if(token.isDel('=')) {
123 body.append(token);
124 int level = 0;
125 while(! statement.atEnd()) {
126 token = statement.getCurrent();
127 if(token.isDel('(')) {
128 level++;
129 } else if(token.isDel(')')) {
130 body.append(token);
131 if(--level == 0) break;
132 }
133 body.append(token);
134 }
135 } else {
136 throw ParseError("LineTemplate::parseTemplate()",
137 "Equals sign '=' expected.");
138 }
139}
#define PAssert(c)
Definition: PAssert.h:102
const std::string name
The base class for all OPAL objects.
Definition: Object.h:48
const std::string & getOpalName() const
Return object name.
Definition: Object.cpp:310
void copyAttributes(const Object &)
Copy attributes from another object.
Definition: Object.cpp:54
Object * find(const std::string &name)
Find entry.
Definition: OpalData.cpp:566
static OpalData * getInstance()
Definition: OpalData.cpp:196
Interface for abstract language parser.
Definition: Parser.h:31
A simple input statement in token form.
Interface for statements.
Definition: Statement.h:38
Token & getCurrent()
Return current token and skip it.
Definition: Statement.cpp:74
void append(const Token &)
Append a token.
Definition: Statement.cpp:45
bool keyword(const char *s)
Test for keyword.
Definition: Statement.cpp:121
bool atEnd() const
Test for end of command.
Definition: Statement.cpp:50
void start()
Return to start.
Definition: Statement.cpp:180
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
Definition: Line.h:32
virtual void parse(Statement &stat)
Parse the line object.
Definition: Line.cpp:150
virtual Line * clone(const std::string &name)
Make clone.
Definition: Line.cpp:117
MacroStream body
Definition: LineTemplate.h:71
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.
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
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