OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
SequenceParser.cpp
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2// $RCSfile: SequenceParser.cpp,v $
3// ------------------------------------------------------------------------
4// $Revision: 1.2 $
5// ------------------------------------------------------------------------
6// Copyright: see Copyright.readme
7// ------------------------------------------------------------------------
8//
9// Definitions for class: SequenceParser
10// This class defines the OPAL sequence parser.
11//
12// ------------------------------------------------------------------------
13//
14// $Date: 2001/08/13 15:16:16 $
15// $Author: jowett $
16//
17// ------------------------------------------------------------------------
18
20#include <memory>
26#include "Lines/Sequence.h"
30#include "Utilities/Options.h"
32
33// Class SequenceParser
34// ------------------------------------------------------------------------
35
36SequenceParser::SequenceParser(Sequence* seq) : itsSequence(seq), okFlag(true), itsLine() {}
37
39
41 if (stat.keyword("ENDSEQUENCE")) {
42 // Finish setting up of sequence.
43 if (okFlag) {
44 try {
45 // Finish parsing the ENDSEQUENCE statement.
46 itsSequence->Object::parse(stat);
47 parseEnd(stat);
48
49 // Finish setting up of sequence.
55 } catch (...) {
56 // In case of error, erase sequence and return to previous parser.
57 itsLine.clear();
58 stop();
59 throw;
60 }
61 }
62
63 // Return to previous parser.
64 itsLine.clear();
65 stop();
66 } else {
67 // Backtrack to start and parse new member.
68 try {
69 stat.start();
70 parseMember(stat);
71 } catch (...) {
72 okFlag = false;
73 throw;
74 }
75 }
76}
77
81
82 while (!references.empty()) {
83 int count = 0;
84
85 for (RefList::iterator i = references.begin(); i != references.end();) {
86 if (i->fromPosition != 0 && i->fromPosition->itsFlag == SequenceMember::ABSOLUTE) {
87 for (std::list<SequenceMember*>::iterator j = i->itsList.begin();
88 j != i->itsList.end(); ++j) {
89 (*j)->itsPosition += i->fromPosition->itsPosition;
90 (*j)->itsFlag = SequenceMember::ABSOLUTE;
91 }
92
93 ++count;
94 i = references.erase(i);
95 } else {
96 ++i;
97 }
98 }
99
100 if (count == 0) {
101 throw OpalException("SequenceParser::fillPositions()", "Circular \"FROM\" clauses.");
102 }
103 }
104}
105
107 for (RefList::iterator i = references.begin(); i != references.end(); ++i) {
108 TLine::iterator pos = itsSequence->findNamedPosition(itsLine, i->fromName);
109
110 if (pos != itsLine.end()) {
111 i->fromPosition = &(*pos);
112 } else {
113 throw OpalException(
114 "SequenceParser::findFromPositions()", "Not all FROM clauses resolved.");
115 }
116 }
117}
118
121 Attribute* attr = itsSequence->findAttribute("REFER");
122 std::string ref = Attributes::getString(*attr);
123
124 if (ref == "ENTRY") {
125 type = Sequence::IS_ENTRY;
126 } else if (ref == "CENTRE" || ref.empty()) {
127 type = Sequence::IS_CENTRE;
128 } else if (ref == "EXIT") {
129 type = Sequence::IS_EXIT;
130 } else {
131 throw OpalException(
132 "SequenceParser::findNeighbourPositions()",
133 "Unknown reference flag \"" + ref + "\" in <sequence> \""
134 + itsSequence->getOpalName() + "\".");
135 }
136
137 for (TLine::iterator i = itsLine.begin(); i != itsLine.end(); ++i) {
138 TLine::iterator j = i;
139 switch (i->itsFlag) {
142 // Add scaled length of current.
143 if (type != Sequence::IS_ENTRY) {
144 std::string name = i->getElement()->getName();
145 Element* elem = Element::find(name);
146 double length = elem->getLength();
147
148 if (type == Sequence::IS_CENTRE) {
149 i->itsPosition += length / 2.0;
150 } else if (type == Sequence::IS_EXIT) {
151 i->itsPosition += length;
152 }
153 }
154
155 // Add scaled length of previous.
156 if (j != itsLine.begin()) {
157 --j;
158 if (type != Sequence::IS_EXIT) {
159 std::string name = j->getElement()->getName();
160 Element* elem = Element::find(name);
161 double length = elem->getLength();
162
163 if (type == Sequence::IS_ENTRY) {
164 i->itsPosition += length;
165 } else if (type == Sequence::IS_CENTRE) {
166 i->itsPosition += length / 2.0;
167 }
168 }
169
170 // Current position is relative to previous.
171 Reference ref("DRIFT", &(*i));
172 ref.fromPosition = &(*j);
173 references.push_back(ref);
174 } else {
175 // Current position is relative to sequence begin.
177 }
178 break;
179
181 if (j != itsLine.begin()) {
182 --j;
183 Reference ref("PREVIOUS", &(*i));
184 ref.fromPosition = &(*j);
185 references.push_back(ref);
186 } else {
188 }
189 break;
190
192 ++j;
193 if (j != itsLine.end()) {
194 // Current position is relative to *j;
195 Reference ref("NEXT", &(*i));
196 ref.fromPosition = &(*j);
197 references.push_back(ref);
198 } else {
199 // Current position is relative to end of sequence.
200 Attribute* attr = itsSequence->findAttribute("L");
201 i->itsPosition += Attributes::getReal(*attr);
202 i->itsFlag = SequenceMember::ABSOLUTE;
203 }
204 break;
205
206 case SequenceMember::END: {
207 // Current position is relative to end of sequence.
208 Attribute* attr = itsSequence->findAttribute("L");
209 i->itsPosition += Attributes::getReal(*attr);
210 i->itsFlag = SequenceMember::ABSOLUTE;
211 } break;
212
213 default:;
214 }
215 }
216}
217
219 std::string objName;
220 std::string clsName;
221 SequenceMember member;
222
223 // Read object identifier.
224 if (stat.delimiter('-')) {
225 member.setReflectionFlag(true);
226 clsName = Expressions::parseString(stat, "Class name expected.");
228 } else {
229 clsName = Expressions::parseString(stat, "Object or class name expected.");
230
231 if (stat.delimiter(':')) {
233 member.setReflectionFlag(stat.delimiter('-'));
234 objName = clsName;
235 clsName = Expressions::parseString(stat, "Class name expected.");
236 } else {
238 }
239 }
240
241 // Find exemplar object.
242 if (Object* obj = OpalData::getInstance()->find(clsName)) {
243 std::shared_ptr<Object> copy;
244 if (obj) {
245 if (member.itsType == SequenceMember::LOCAL) {
246 // We must make a copy or a macro instance.
247 if (objName == itsSequence->getOpalName()) {
248 throw ParseError(
249 "SequenceParser::parseMember()",
250 "You cannot redefine \"" + objName
251 + "\" within the sequence of the same name.");
252 } else if (clsName == itsSequence->getOpalName()) {
253 throw ParseError(
254 "SequenceParser::parseMember()",
255 "You cannot refer to \"" + objName
256 + "\" within the sequence of the same name.");
257 } else if (OpalData::getInstance()->find(objName)) {
258 throw ParseError(
259 "SequenceParser::parseMember()",
260 "You cannot redefine \"" + objName + "\" within a sequence.");
261 }
262
263 if (stat.delimiter('(')) {
264 copy = std::shared_ptr<Object>(obj->makeInstance(objName, stat, this));
265 } else if (BeamSequence* line = dynamic_cast<BeamSequence*>(obj)) {
266 copy = std::shared_ptr<Object>(line->copy(objName));
267 } else {
268 copy = std::shared_ptr<Object>(obj->clone(objName));
269 }
270 } else {
271 // We can use the global object.
272 copy = std::shared_ptr<Object>(obj);
273 }
274 }
275
276 // Test for correct object type.
277 if (Element* elem = dynamic_cast<Element*>(&*copy)) {
278 ElementBase* base = elem->getElement();
279 member.setElement(base->copyStructure());
280
281 // ada 4.5 2000 to speed up matching, add a pointer to
282 // opal elements in order to avoid serching the opal elements
283 member.OpalElement = std::shared_ptr<Element>(elem);
284
285 itsLine.push_back(member);
286
287 // Parse position and attributes.
288 parsePosition(stat, *copy, member.itsType == SequenceMember::LOCAL);
289 parseEnd(stat);
290
291 // For local instantiation define element.
293 } else {
294 throw ParseError(
295 "SequenceParser::parseMember()",
296 "Object \"" + objName + "\" is not an element.");
297 }
298 } else {
299 throw ParseError(
300 "SequenceParser::parseMember()",
301 "Element class name \"" + clsName + "\" is unknown.");
302 }
303}
304
305void SequenceParser::parsePosition(Statement& stat, Object& elem, bool defined) const {
306 SequenceMember& member = itsLine.back();
307 double position = 0.0;
308 std::string fromName;
309 int flag = 0;
310
311 while (stat.delimiter(',')) {
312 std::string name = Expressions::parseString(stat, "Attribute name expected.");
313
314 if (name == "AT") {
316 position = Expressions::parseRealConst(stat);
317 flag |= (flag & 0x0001) ? 0x0008 : 0x0001;
318 } else if (name == "DRIFT") {
320 position = Expressions::parseRealConst(stat);
321 flag |= (flag & 0x0002) ? 0x0008 : 0x0002;
322 } else if (name == "FROM") {
324 if (stat.delimiter('#')) {
325 if (stat.keyword("S")) {
326 fromName = "#S";
327 } else if (stat.keyword("E")) {
328 fromName = "#E";
329 } else {
330 throw ParseError("SequenceParser::parsePosition()", "Expected 'S' or 'E'.");
331 }
332 } else {
333 fromName = Expressions::parseString(stat, "Expected <name>, \"#S\", or \"#E\".");
334 }
335 flag |= (flag & 0x0004) ? 0x0008 : 0x0004;
336 } else if (defined) {
337 // May be element attribute.
338 if (Attribute* attr = elem.findAttribute(name)) {
339 if (stat.delimiter('=')) {
340 attr->parse(stat, true);
341 } else if (stat.delimiter(":=")) {
342 attr->parse(stat, false);
343 } else {
344 throw ParseError(
345 "SequenceParser::parsePosition()",
346 "Delimiter \"=\" or \":=\" expected.");
347 }
348 } else {
349 throw ParseError(
350 "SequenceParser::parsePosition()", "Element \"" + elem.getOpalName()
351 + "\" has no attribute \"" + name
352 + "\".");
353 }
354 } else {
355 throw ParseError(
356 "SequenceParser::parsePosition()", "Overriding attributes not permitted here.");
357 }
358 }
359
360 // Check for valid data and store.
361 member.itsPosition = 0.0;
362
363 switch (flag) {
364 case 0x0001:
365 // "at=...".
366 member.itsPosition = position;
367 break;
368
369 case 0x0002:
370 // "drift=...". Set distance to drift length.
371 member.itsPosition = position;
373 break;
374
375 case 0x0000:
376 // No position data.
377 member.itsPosition = 0.0;
379 break;
380
381 case 0x0005:
382 // "at=...,from=...".
383 member.itsPosition = position;
384
385 if (fromName == "PREVIOUS") {
386 // Position refers to previous element.
388 } else if (fromName == "NEXT") {
389 // Position refers to next element.
391 } else if (fromName == "#S") {
392 // Position refers to begin of sequence.
394 } else if (fromName == "#E") {
395 // Position refers to end of sequence.
397 } else {
398 // Position refers to named element.
400
401 // Find reference to fromName.
402 for (RefList::iterator i = references.begin(); i != references.end(); ++i) {
403 if (i->fromName == fromName) {
404 // Build reference to a new "FROM" name.
405 i->itsList.push_back(&member);
406 return;
407 }
408 }
409
410 // Add reference to an already known "FROM" name.
411 Reference ref;
412 ref.fromName = fromName;
413 ref.itsList.push_back(&member);
414 references.push_back(ref);
415 }
416
417 break;
418
419 default:
420 throw ParseError("SequenceParser:parsePosition()", "Conflicting keywords.");
421 }
422}
A representation of an Object attribute.
Definition Attribute.h:52
The base class for all OPAL beam lines and sequences.
virtual ElementBase * copyStructure()
Make a structural copy.
virtual double getLength() const =0
Return element length.
static Element * find(const std::string &name)
Find named Element.
Definition Element.cpp:39
ReferenceType
Reference for element positioning.
Definition Element.h:43
@ IS_EXIT
Definition Element.h:46
@ IS_ENTRY
Definition Element.h:44
@ IS_CENTRE
Definition Element.h:45
void setElement(ElementBase *)
Set the element pointer.
Definition ElmPtr.h:58
void setReflectionFlag(bool flag) const
Set reflection flag.
The base class for all OPAL objects.
Definition Object.h:45
const std::string & getOpalName() const
Return object name.
Definition Object.cpp:267
virtual Attribute * findAttribute(const std::string &name)
Find an attribute by name.
Definition Object.cpp:56
void makeDirty(Object *object)
Invalidate expressions.
Definition OpalData.cpp:481
static OpalData * getInstance()
Definition OpalData.cpp:193
void define(Object *newObject)
Define a new object.
Definition OpalData.cpp:400
virtual void parseEnd(Statement &) const
Check for end of statement.
virtual Object * find(const std::string &) const
Find object by name in the main directory.
void stop() const
Set stop flag.
Parse exception.
Definition ParseError.h:31
A member of a SEQUENCE.
MemberType itsType
Type word.
std::shared_ptr< Element > OpalElement
double itsPosition
The position attribute ("AT" or "DRIFT").
PositionType itsFlag
Flag word.
void findFromPositions() const
void fillPositions() const
Sequence * itsSequence
void parseMember(Statement &) const
virtual ~SequenceParser()
void findNeighbourPositions() const
virtual void parse(Statement &) const
Parse sequence member.
void parsePosition(Statement &, Object &, bool defined) const
void insertDrifts(TLine &line)
Definition Sequence.cpp:336
TLine::iterator findNamedPosition(TLine &, const std::string &) const
Definition Sequence.cpp:116
void storeLine(TLine &line)
Store sequence line.
Definition Sequence.cpp:255
void addEndMarkers(TLine &line) const
Definition Sequence.cpp:283
Interface for statements.
Definition Statement.h:37
bool keyword(const char *s)
Test for keyword.
bool delimiter(char c)
Test for delimiter.
Definition Statement.cpp:83
void start()
Return to start.
double getReal(const Attribute &attr)
Return real value.
std::string getString(const Attribute &attr)
Get string value.
std::string parseString(Statement &, const char msg[])
Parse string value.
void parseDelimiter(Statement &stat, char delim)
Test for one-character delimiter.
double parseRealConst(Statement &)
Parse real constant.
SequenceMember * fromPosition
std::list< SequenceMember * > itsList