OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
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 == "") {
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 
229  default:
230  ;
231  }
232  }
233 }
234 
235 
237  std::string objName;
238  std::string clsName;
239  SequenceMember member;
240 
241  // Read object identifier.
242  if(stat.delimiter('-')) {
243  member.setReflectionFlag(true);
244  clsName = Expressions::parseString(stat, "Class name expected.");
246  } else {
247  clsName = Expressions::parseString(stat, "Object or class name expected.");
248 
249  if(stat.delimiter(':')) {
251  member.setReflectionFlag(stat.delimiter('-'));
252  objName = clsName;
253  clsName = Expressions::parseString(stat, "Class name expected.");
254  } else {
256  }
257  }
258 
259  // Find exemplar object.
260  if(Object *obj = OpalData::getInstance()->find(clsName)) {
261  Pointer<Object> copy;
262  if(obj) {
263  if(member.itsType == SequenceMember::LOCAL) {
264  // We must make a copy or a macro instance.
265  if(objName == itsSequence->getOpalName()) {
266  throw ParseError("SequenceParser::parseMember()",
267  "You cannot redefine \"" + objName +
268  "\" within the sequence of the same name.");
269  } else if(clsName == itsSequence->getOpalName()) {
270  throw ParseError("SequenceParser::parseMember()",
271  "You cannot refer to \"" + objName +
272  "\" within the sequence of the same name.");
273  } else if(OpalData::getInstance()->find(objName)) {
274  throw ParseError("SequenceParser::parseMember()",
275  "You cannot redefine \"" + objName +
276  "\" within a sequence.");
277  }
278 
279  if(stat.delimiter('(')) {
280  copy = obj->makeInstance(objName, stat, this);
281  } else if(BeamSequence *line = dynamic_cast<BeamSequence *>(obj)) {
282  copy = line->copy(objName);
283  } else {
284  copy = obj->clone(objName);
285  }
286  } else {
287  // We can use the global object.
288  copy = obj;
289  }
290  }
291 
292  // Test for correct object type.
293  if(Element *elem = dynamic_cast<Element *>(&*copy)) {
294  ElementBase *base = elem->getElement();
295  member.setElement(base->copyStructure());
296 
297  // ada 4.5 2000 to speed up matching, add a pointer to
298  // opal elements in order to avoid serching the opal elements
299  member.OpalElement = elem;
300 
301  itsLine.push_back(member);
302 
303  // Parse position and attributes.
304  parsePosition(stat, *copy, member.itsType == SequenceMember::LOCAL);
305  parseEnd(stat);
306 
307  // For local instantiation define element.
309  } else {
310  throw ParseError("SequenceParser::parseMember()", "Object \"" +
311  objName + "\" is not an element.");
312  }
313  } else {
314  throw ParseError("SequenceParser::parseMember()",
315  "Element class name \"" + clsName + "\" is unknown.");
316  }
317 }
318 
319 
321 (Statement &stat, Object &elem, bool defined) const {
322  SequenceMember &member = itsLine.back();
323  double position = 0.0;
324  std::string fromName;
325  int flag = 0;
326 
327  while(stat.delimiter(',')) {
328  std::string name =
329  Expressions::parseString(stat, "Attribute name expected.");
330 
331  if(name == "AT") {
332  Expressions::parseDelimiter(stat, '=');
333  position = Expressions::parseRealConst(stat);
334  flag |= (flag & 0x0001) ? 0x0008 : 0x0001;
335  } else if(name == "DRIFT") {
336  Expressions::parseDelimiter(stat, '=');
337  position = Expressions::parseRealConst(stat);
338  flag |= (flag & 0x0002) ? 0x0008 : 0x0002;
339  } else if(name == "FROM") {
340  Expressions::parseDelimiter(stat, '=');
341  if(stat.delimiter('#')) {
342  if(stat.keyword("S")) {
343  fromName = "#S";
344  } else if(stat.keyword("E")) {
345  fromName = "#E";
346  } else {
347  throw ParseError("SequenceParser::parsePosition()",
348  "Expected 'S' or 'E'.");
349  }
350  } else {
351  fromName = Expressions::parseString
352  (stat, "Expected <name>, \"#S\", or \"#E\".");
353  }
354  flag |= (flag & 0x0004) ? 0x0008 : 0x0004;
355  } else if(defined) {
356  // May be element attribute.
357  if(Attribute *attr = elem.findAttribute(name)) {
358  if(stat.delimiter('=')) {
359  attr->parse(stat, true);
360  } else if(stat.delimiter(":=")) {
361  attr->parse(stat, false);
362  } else {
363  throw ParseError("SequenceParser::parsePosition()",
364  "Delimiter \"=\" or \":=\" expected.");
365  }
366  } else {
367  throw ParseError("SequenceParser::parsePosition()",
368  "Element \"" + elem.getOpalName() +
369  "\" has no attribute \"" + name + "\".");
370  }
371  } else {
372  throw ParseError("SequenceParser::parsePosition()",
373  "Overriding attributes not permitted here.");
374  }
375  }
376 
377  // Check for valid data and store.
378  member.itsPosition = 0.0;
379 
380  switch(flag) {
381 
382  case 0x0001:
383  // "at=...".
384  member.itsPosition = position;
385  break;
386 
387  case 0x0002:
388  // "drift=...". Set distance to drift length.
389  member.itsPosition = position;
391  break;
392 
393  case 0x0000:
394  // No position data.
395  member.itsPosition = 0.0;
397  break;
398 
399  case 0x0005:
400  // "at=...,from=...".
401  member.itsPosition = position;
402 
403  if(fromName == "PREVIOUS") {
404  // Position refers to previous element.
406  } else if(fromName == "NEXT") {
407  // Position refers to next element.
408  member.itsFlag = SequenceMember::NEXT;
409  } else if(fromName == "#S") {
410  // Position refers to begin of sequence.
412  } else if(fromName == "#E") {
413  // Position refers to end of sequence.
414  member.itsFlag = SequenceMember::END;
415  } else {
416  // Position refers to named element.
417  member.itsFlag = SequenceMember::FROM;
418 
419  // Find reference to fromName.
420  for(RefList::iterator i = references.begin();
421  i != references.end(); ++i) {
422  if(i->fromName == fromName) {
423  // Build reference to a new "FROM" name.
424  i->itsList.push_back(&member);
425  return;
426  }
427  }
428 
429  // Add reference to an already known "FROM" name.
430  Reference ref;
431  ref.fromName = fromName;
432  ref.itsList.push_back(&member);
433  references.push_back(ref);
434  }
435 
436  break;
437 
438  default:
439  throw ParseError("SequenceParser:parsePosition()",
440  "Conflicting keywords.");
441  }
442 }
std::list< SequenceMember * > itsList
double parseRealConst(Statement &)
Parse real constant.
bool keyword(const char *s)
Test for keyword.
Definition: Statement.cpp:123
Interface for basic beam line object.
Definition: ElementBase.h:128
Parse exception.
Definition: ParseError.h:32
void define(Object *newObject)
Define a new object.
Definition: OpalData.cpp:538
void parsePosition(Statement &, Object &, bool defined) const
The base class for all OPAL exceptions.
Definition: OpalException.h:28
virtual Attribute * findAttribute(const std::string &name)
Find an attribute by name.
virtual ~SequenceParser()
TLine::iterator findNamedPosition(TLine &, const std::string &) const
Definition: Sequence.cpp:125
double itsPosition
The position attribute (&quot;AT&quot; or &quot;DRIFT&quot;).
void findNeighbourPositions() const
void insertDrifts(TLine &line)
Definition: Sequence.cpp:369
void stop() const
Set stop flag.
Definition: OpalParser.cpp:637
void findFromPositions() const
void parseDelimiter(Statement &stat, char delim)
Test for one-character delimiter.
static OpalData * getInstance()
Definition: OpalData.cpp:209
const std::string & getOpalName() const
Return object name.
Definition: Object.cpp:284
MemberType itsType
Type word.
The base class for all OPAL elements.
Definition: Element.h:46
A representation of an Object attribute.
Definition: Attribute.h:55
ReferenceType
Reference for element positioning.
Definition: Element.h:52
void addEndMarkers(TLine &line) const
Definition: Sequence.cpp:313
Interface for statements.
Definition: Statement.h:38
Reference-counted pointer.
Definition: Pointer.h:38
void storeLine(TLine &line)
Store sequence line.
Definition: Sequence.cpp:284
The SEQUENCE definition.
Definition: Sequence.h:38
void start()
Return to start.
Definition: Statement.cpp:182
virtual Object * makeInstance(const std::string &name, Statement &, const Parser *)
Macro handler function.
Definition: Object.cpp:94
virtual ElementBase * copyStructure()
Make a structural copy.
The base class for all OPAL beam lines and sequences.
Definition: BeamSequence.h:32
static Element * find(const std::string &name)
Find named Element.
Definition: Element.cpp:37
virtual double getLength() const =0
Return element length.
SequenceMember * fromPosition
Sequence * itsSequence
The base class for all OPAL objects.
Definition: Object.h:48
virtual void parseEnd(Statement &) const
Check for end of statement.
Definition: OpalParser.cpp:372
virtual Object * clone(const std::string &name)=0
Return a clone.
PositionType itsFlag
Flag word.
const std::string name
void fillPositions() const
std::string::iterator iterator
Definition: MSLang.h:16
double getReal(const Attribute &attr)
Return real value.
Definition: Attributes.cpp:217
std::string parseString(Statement &, const char msg[])
Parse string value.
bool delimiter(char c)
Test for delimiter.
Definition: Statement.cpp:103
void parseMember(Statement &) const
virtual void parse(Statement &) const
Parse sequence member.
void makeDirty(Object *object)
Invalidate expressions.
Definition: OpalData.cpp:629
Pointer< Element > OpalElement
void setElement(ElementBase *)
Set the element pointer.
Definition: ElmPtr.h:63
A member of a SEQUENCE.
virtual Object * find(const std::string &) const
Find object by name in the main directory.
Definition: OpalParser.cpp:150
std::string getString(const Attribute &attr)
Get string value.
Definition: Attributes.cpp:307
void setReflectionFlag(bool flag) const
Set reflection flag.