OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
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
25#include "Lines/Sequence.h"
28#include "Parser/Statement.h"
31#include "Utilities/Options.h"
33
34
35// Class SequenceParser
36// ------------------------------------------------------------------------
37
39 itsSequence(seq), okFlag(true), itsLine()
40{}
41
42
44{}
45
46
48 if (stat.keyword("ENDSEQUENCE")) {
49 // Finish setting up of sequence.
50 if (okFlag) {
51 try {
52 // Finish parsing the ENDSEQUENCE statement.
53 itsSequence->Object::parse(stat);
54 parseEnd(stat);
55
56 // Finish setting up of sequence.
62 } catch(...) {
63 // In case of error, erase sequence and return to previous parser.
64 itsLine.clear();
65 stop();
66 throw;
67 }
68 }
69
70 // Return to previous parser.
71 itsLine.clear();
72 stop();
73 } else {
74 // Backtrack to start and parse new member.
75 try {
76 stat.start();
77 parseMember(stat);
78 } catch(...) {
79 okFlag = false;
80 throw;
81 }
82 }
83}
84
85
89
90 while(! references.empty()) {
91 int count = 0;
92
93 for (RefList::iterator i = references.begin();
94 i != references.end();) {
95 if (i->fromPosition != 0 &&
96 i->fromPosition->itsFlag == SequenceMember::ABSOLUTE) {
97 for (std::list<SequenceMember *>::iterator j = i->itsList.begin();
98 j != i->itsList.end(); ++j) {
99 (*j)->itsPosition += i->fromPosition->itsPosition;
100 (*j)->itsFlag = SequenceMember::ABSOLUTE;
101 }
102
103 ++count;
104 i = references.erase(i);
105 } else {
106 ++i;
107 }
108 }
109
110 if (count == 0) {
111 throw OpalException("SequenceParser::fillPositions()",
112 "Circular \"FROM\" clauses.");
113 }
114 }
115}
116
117
119 for (RefList::iterator i = references.begin(); i != references.end(); ++i) {
121
122 if (pos != itsLine.end()) {
123 i->fromPosition = &(*pos);
124 } else {
125 throw OpalException("SequenceParser::findFromPositions()",
126 "Not all FROM clauses resolved.");
127 }
128 }
129}
130
131
134 Attribute *attr = itsSequence->findAttribute("REFER");
135 std::string ref = Attributes::getString(*attr);
136
137 if (ref == "ENTRY") {
139 } else if (ref == "CENTRE" || ref.empty()) {
141 } else if (ref == "EXIT") {
143 } else {
144 throw OpalException("SequenceParser::findNeighbourPositions()",
145 "Unknown reference flag \"" + ref +
146 "\" in <sequence> \"" +
147 itsSequence->getOpalName() + "\".");
148 }
149
150 for (TLine::iterator i = itsLine.begin(); i != itsLine.end(); ++i) {
151 TLine::iterator j = i;
152 switch(i->itsFlag) {
153
156 // Add scaled length of current.
157 if (type != Sequence::IS_ENTRY) {
158 std::string name = i->getElement()->getName();
159 Element *elem = Element::find(name);
160 double length = elem->getLength();
161
162 if (type == Sequence::IS_CENTRE) {
163 i->itsPosition += length / 2.0;
164 } else if (type == Sequence::IS_EXIT) {
165 i->itsPosition += length;
166 }
167 }
168
169 // Add scaled length of previous.
170 if (j != itsLine.begin()) {
171 --j;
172 if (type != Sequence::IS_EXIT) {
173 std::string name = j->getElement()->getName();
174 Element *elem = Element::find(name);
175 double length = elem->getLength();
176
177 if (type == Sequence::IS_ENTRY) {
178 i->itsPosition += length;
179 } else if (type == Sequence::IS_CENTRE) {
180 i->itsPosition += length / 2.0;
181 }
182 }
183
184 // Current position is relative to previous.
185 Reference ref("DRIFT", &(*i));
186 ref.fromPosition = &(*j);
187 references.push_back(ref);
188 } else {
189 // Current position is relative to sequence begin.
190 i->itsFlag = SequenceMember::ABSOLUTE;
191 }
192 break;
193
195 if (j != itsLine.begin()) {
196 --j;
197 Reference ref("PREVIOUS", &(*i));
198 ref.fromPosition = &(*j);
199 references.push_back(ref);
200 } else {
201 i->itsFlag = SequenceMember::ABSOLUTE;
202 }
203 break;
204
206 ++j;
207 if (j != itsLine.end()) {
208 // Current position is relative to *j;
209 Reference ref("NEXT", &(*i));
210 ref.fromPosition = &(*j);
211 references.push_back(ref);
212 } else {
213 // Current position is relative to end of sequence.
214 Attribute *attr = itsSequence->findAttribute("L");
215 i->itsPosition += Attributes::getReal(*attr);
216 i->itsFlag = SequenceMember::ABSOLUTE;
217 }
218 break;
219
220 case SequenceMember::END: {
221 // Current position is relative to end of sequence.
222 Attribute *attr = itsSequence->findAttribute("L");
223 i->itsPosition += Attributes::getReal(*attr);
224 i->itsFlag = SequenceMember::ABSOLUTE;
225 }
226 break;
227
228 default:
229 ;
230 }
231 }
232}
233
234
236 std::string objName;
237 std::string clsName;
238 SequenceMember member;
239
240 // Read object identifier.
241 if (stat.delimiter('-')) {
242 member.setReflectionFlag(true);
243 clsName = Expressions::parseString(stat, "Class name expected.");
245 } else {
246 clsName = Expressions::parseString(stat, "Object or class name expected.");
247
248 if (stat.delimiter(':')) {
250 member.setReflectionFlag(stat.delimiter('-'));
251 objName = clsName;
252 clsName = Expressions::parseString(stat, "Class name expected.");
253 } else {
255 }
256 }
257
258 // Find exemplar object.
259 if (Object *obj = OpalData::getInstance()->find(clsName)) {
260 Pointer<Object> copy;
261 if (obj) {
262 if (member.itsType == SequenceMember::LOCAL) {
263 // We must make a copy or a macro instance.
264 if (objName == itsSequence->getOpalName()) {
265 throw ParseError("SequenceParser::parseMember()",
266 "You cannot redefine \"" + objName +
267 "\" within the sequence of the same name.");
268 } else if (clsName == itsSequence->getOpalName()) {
269 throw ParseError("SequenceParser::parseMember()",
270 "You cannot refer to \"" + objName +
271 "\" within the sequence of the same name.");
272 } else if (OpalData::getInstance()->find(objName)) {
273 throw ParseError("SequenceParser::parseMember()",
274 "You cannot redefine \"" + objName +
275 "\" within a sequence.");
276 }
277
278 if (stat.delimiter('(')) {
279 copy = obj->makeInstance(objName, stat, this);
280 } else if (BeamSequence *line = dynamic_cast<BeamSequence *>(obj)) {
281 copy = line->copy(objName);
282 } else {
283 copy = obj->clone(objName);
284 }
285 } else {
286 // We can use the global object.
287 copy = obj;
288 }
289 }
290
291 // Test for correct object type.
292 if (Element *elem = dynamic_cast<Element *>(&*copy)) {
293 ElementBase *base = elem->getElement();
294 member.setElement(base->copyStructure());
295
296 // ada 4.5 2000 to speed up matching, add a pointer to
297 // opal elements in order to avoid serching the opal elements
298 member.OpalElement = elem;
299
300 itsLine.push_back(member);
301
302 // Parse position and attributes.
303 parsePosition(stat, *copy, member.itsType == SequenceMember::LOCAL);
304 parseEnd(stat);
305
306 // For local instantiation define element.
308 } else {
309 throw ParseError("SequenceParser::parseMember()", "Object \"" +
310 objName + "\" is not an element.");
311 }
312 } else {
313 throw ParseError("SequenceParser::parseMember()",
314 "Element class name \"" + clsName + "\" is unknown.");
315 }
316}
317
318
320(Statement &stat, Object &elem, bool defined) const {
321 SequenceMember &member = itsLine.back();
322 double position = 0.0;
323 std::string fromName;
324 int flag = 0;
325
326 while(stat.delimiter(',')) {
327 std::string name =
328 Expressions::parseString(stat, "Attribute name expected.");
329
330 if (name == "AT") {
332 position = Expressions::parseRealConst(stat);
333 flag |= (flag & 0x0001) ? 0x0008 : 0x0001;
334 } else if (name == "DRIFT") {
336 position = Expressions::parseRealConst(stat);
337 flag |= (flag & 0x0002) ? 0x0008 : 0x0002;
338 } else if (name == "FROM") {
340 if (stat.delimiter('#')) {
341 if (stat.keyword("S")) {
342 fromName = "#S";
343 } else if (stat.keyword("E")) {
344 fromName = "#E";
345 } else {
346 throw ParseError("SequenceParser::parsePosition()",
347 "Expected 'S' or 'E'.");
348 }
349 } else {
350 fromName = Expressions::parseString
351 (stat, "Expected <name>, \"#S\", or \"#E\".");
352 }
353 flag |= (flag & 0x0004) ? 0x0008 : 0x0004;
354 } else if (defined) {
355 // May be element attribute.
356 if (Attribute *attr = elem.findAttribute(name)) {
357 if (stat.delimiter('=')) {
358 attr->parse(stat, true);
359 } else if (stat.delimiter(":=")) {
360 attr->parse(stat, false);
361 } else {
362 throw ParseError("SequenceParser::parsePosition()",
363 "Delimiter \"=\" or \":=\" expected.");
364 }
365 } else {
366 throw ParseError("SequenceParser::parsePosition()",
367 "Element \"" + elem.getOpalName() +
368 "\" has no attribute \"" + name + "\".");
369 }
370 } else {
371 throw ParseError("SequenceParser::parsePosition()",
372 "Overriding attributes not permitted here.");
373 }
374 }
375
376 // Check for valid data and store.
377 member.itsPosition = 0.0;
378
379 switch(flag) {
380
381 case 0x0001:
382 // "at=...".
383 member.itsPosition = position;
384 break;
385
386 case 0x0002:
387 // "drift=...". Set distance to drift length.
388 member.itsPosition = position;
390 break;
391
392 case 0x0000:
393 // No position data.
394 member.itsPosition = 0.0;
396 break;
397
398 case 0x0005:
399 // "at=...,from=...".
400 member.itsPosition = position;
401
402 if (fromName == "PREVIOUS") {
403 // Position refers to previous element.
405 } else if (fromName == "NEXT") {
406 // Position refers to next element.
408 } else if (fromName == "#S") {
409 // Position refers to begin of sequence.
411 } else if (fromName == "#E") {
412 // Position refers to end of sequence.
414 } else {
415 // Position refers to named element.
417
418 // Find reference to fromName.
419 for (RefList::iterator i = references.begin();
420 i != references.end(); ++i) {
421 if (i->fromName == fromName) {
422 // Build reference to a new "FROM" name.
423 i->itsList.push_back(&member);
424 return;
425 }
426 }
427
428 // Add reference to an already known "FROM" name.
430 ref.fromName = fromName;
431 ref.itsList.push_back(&member);
432 references.push_back(ref);
433 }
434
435 break;
436
437 default:
438 throw ParseError("SequenceParser:parsePosition()",
439 "Conflicting keywords.");
440 }
441}
const std::string name
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.
double getReal(const Attribute &attr)
Return real value.
Definition: Attributes.cpp:252
std::string getString(const Attribute &attr)
Get string value.
Definition: Attributes.cpp:343
std::string::iterator iterator
Definition: MSLang.h:16
boost::function< boost::tuple< double, bool >(arguments_t)> type
Definition: function.hpp:21
A representation of an Object attribute.
Definition: Attribute.h:52
The base class for all OPAL beam lines and sequences.
Definition: BeamSequence.h:32
virtual double getLength() const =0
Return element length.
static Element * find(const std::string &name)
Find named Element.
Definition: Element.cpp:45
ReferenceType
Reference for element positioning.
Definition: Element.h:44
@ IS_EXIT
Definition: Element.h:47
@ IS_ENTRY
Definition: Element.h:45
@ IS_CENTRE
Definition: Element.h:46
The base class for all OPAL objects.
Definition: Object.h:48
virtual Object * clone(const std::string &name)=0
Return a clone.
virtual Object * makeInstance(const std::string &name, Statement &, const Parser *)
Macro handler function.
Definition: Object.cpp:91
const std::string & getOpalName() const
Return object name.
Definition: Object.cpp:310
virtual Attribute * findAttribute(const std::string &name)
Find an attribute by name.
Definition: Object.cpp:64
void makeDirty(Object *object)
Invalidate expressions.
Definition: OpalData.cpp:574
static OpalData * getInstance()
Definition: OpalData.cpp:196
void define(Object *newObject)
Define a new object.
Definition: OpalData.cpp:489
virtual ElementBase * copyStructure()
Make a structural copy.
void setElement(ElementBase *)
Set the element pointer.
Definition: ElmPtr.h:63
void setReflectionFlag(bool flag) const
Set reflection flag.
Reference-counted pointer.
Definition: Pointer.h:38
Interface for statements.
Definition: Statement.h:38
bool keyword(const char *s)
Test for keyword.
Definition: Statement.cpp:121
bool delimiter(char c)
Test for delimiter.
Definition: Statement.cpp:101
void start()
Return to start.
Definition: Statement.cpp:180
Parse exception.
Definition: ParseError.h:32
void insertDrifts(TLine &line)
Definition: Sequence.cpp:368
TLine::iterator findNamedPosition(TLine &, const std::string &) const
Definition: Sequence.cpp:124
void storeLine(TLine &line)
Store sequence line.
Definition: Sequence.cpp:283
void addEndMarkers(TLine &line) const
Definition: Sequence.cpp:312
A member of a SEQUENCE.
MemberType itsType
Type word.
Pointer< 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
virtual void parseEnd(Statement &) const
Check for end of statement.
Definition: OpalParser.cpp:373
virtual Object * find(const std::string &) const
Find object by name in the main directory.
Definition: OpalParser.cpp:151
void stop() const
Set stop flag.
Definition: OpalParser.cpp:638
The base class for all OPAL exceptions.
Definition: OpalException.h:28