OPAL (Object Oriented Parallel Accelerator Library)  2024.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 
19 #include "Lines/SequenceParser.h"
24 #include "Attributes/Attributes.h"
25 #include "Lines/Sequence.h"
26 #include "OpalParser/OpalParser.h"
28 #include "Parser/Statement.h"
31 #include "Utilities/Options.h"
32 #include "Utilities/ParseError.h"
33 
34 
35 // Class SequenceParser
36 // ------------------------------------------------------------------------
37 
39  itsSequence(seq), okFlag(true), itsLine()
40 {}
41 
42 
44 {}
45 
46 
47 void SequenceParser::parse(Statement &stat) const {
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.
58  fillPositions();
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") {
138  type = Sequence::IS_ENTRY;
139  } else if (ref == "CENTRE" || ref.empty()) {
140  type = Sequence::IS_CENTRE;
141  } else if (ref == "EXIT") {
142  type = Sequence::IS_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)) {
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.
307  if (member.itsType == SequenceMember::LOCAL) OpalData::getInstance()->define(&*copy);
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") {
331  Expressions::parseDelimiter(stat, '=');
332  position = Expressions::parseRealConst(stat);
333  flag |= (flag & 0x0001) ? 0x0008 : 0x0001;
334  } else if (name == "DRIFT") {
335  Expressions::parseDelimiter(stat, '=');
336  position = Expressions::parseRealConst(stat);
337  flag |= (flag & 0x0002) ? 0x0008 : 0x0002;
338  } else if (name == "FROM") {
339  Expressions::parseDelimiter(stat, '=');
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.
407  member.itsFlag = SequenceMember::NEXT;
408  } else if (fromName == "#S") {
409  // Position refers to begin of sequence.
411  } else if (fromName == "#E") {
412  // Position refers to end of sequence.
413  member.itsFlag = SequenceMember::END;
414  } else {
415  // Position refers to named element.
416  member.itsFlag = SequenceMember::FROM;
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.
429  Reference ref;
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 }
SequenceMember * fromPosition
static OpalData * getInstance()
Definition: OpalData.cpp:196
and give any other recipients of the Program a copy of this License along with the Program You may charge a fee for the physical act of transferring a copy
Definition: LICENSE:87
The base class for all OPAL objects.
Definition: Object.h:48
Reference-counted pointer.
Definition: Pointer.h:38
std::string getString(const Attribute &attr)
Get string value.
Definition: Attributes.cpp:343
void parseDelimiter(Statement &stat, char delim)
Test for one-character delimiter.
void start()
Return to start.
Definition: Statement.cpp:180
void insertDrifts(TLine &line)
Definition: Sequence.cpp:368
void define(Object *newObject)
Define a new object.
Definition: OpalData.cpp:489
PositionType itsFlag
Flag word.
void makeDirty(Object *object)
Invalidate expressions.
Definition: OpalData.cpp:579
Parse exception.
Definition: ParseError.h:32
A member of a SEQUENCE.
ReferenceType
Reference for element positioning.
Definition: Element.h:44
Pointer< Element > OpalElement
void fillPositions() const
void addEndMarkers(TLine &line) const
Definition: Sequence.cpp:312
std::list< SequenceMember * > itsList
virtual ~SequenceParser()
std::string::iterator iterator
Definition: MSLang.h:15
void storeLine(TLine &line)
Store sequence line.
Definition: Sequence.cpp:283
TLine::iterator findNamedPosition(TLine &, const std::string &) const
Definition: Sequence.cpp:124
The base class for all OPAL exceptions.
Definition: OpalException.h:28
The base class for all OPAL beam lines and sequences.
Definition: BeamSequence.h:32
void setReflectionFlag(bool flag) const
Set reflection flag.
Interface for statements.
Definition: Statement.h:38
void findFromPositions() const
void parsePosition(Statement &, Object &, bool defined) const
bool delimiter(char c)
Test for delimiter.
Definition: Statement.cpp:101
void findNeighbourPositions() const
std::string parseString(Statement &, const char msg[])
Parse string value.
const std::string & getOpalName() const
Return object name.
Definition: Object.cpp:310
virtual Object * makeInstance(const std::string &name, Statement &, const Parser *)
Macro handler function.
Definition: Object.cpp:91
MemberType itsType
Type word.
static Element * find(const std::string &name)
Find named Element.
Definition: Element.cpp:45
Sequence * itsSequence
virtual ElementBase * copyStructure()
Make a structural copy.
virtual void parse(Statement &) const
Parse sequence member.
const std::string name
double parseRealConst(Statement &)
Parse real constant.
double getReal(const Attribute &attr)
Return real value.
Definition: Attributes.cpp:252
void stop() const
Set stop flag.
Definition: OpalParser.cpp:638
bool keyword(const char *s)
Test for keyword.
Definition: Statement.cpp:121
virtual double getLength() const =0
Return element length.
void setElement(ElementBase *)
Set the element pointer.
Definition: ElmPtr.h:63
virtual Attribute * findAttribute(const std::string &name)
Find an attribute by name.
Definition: Object.cpp:64
void parseMember(Statement &) const
double itsPosition
The position attribute (&quot;AT&quot; or &quot;DRIFT&quot;).
virtual Object * find(const std::string &) const
Find object by name in the main directory.
Definition: OpalParser.cpp:151
SDDS1 &description type
Definition: test.stat:4
virtual Object * clone(const std::string &name)=0
Return a clone.
virtual void parseEnd(Statement &) const
Check for end of statement.
Definition: OpalParser.cpp:373
A representation of an Object attribute.
Definition: Attribute.h:52