32#include <boost/algorithm/string.hpp>
45#include "Utility/Inform.h"
46#include "Utility/IpplInfo.h"
73 std::string name =
parseString(stat,
"Identifier or keyword expected.");
92 std::string objName =
parseString(stat,
"Object name expected.");
97 std::string name = tok.
getLex();
98 std::string hint =
getHint(name);
99 unsigned int position = stat.
position();
100 std::string positionIndicator = std::string(position,
' ') +
"^\n";
101 std::ostringstream statStr;
105 "OpalParser::parse()",
106 statStr.str() + positionIndicator
107 +
"Syntax error, either the keyword REAL is missing or\n" + hint);
110 "OpalParser::parse()", statStr.str() + positionIndicator
111 +
"Syntax error, the keyword REAL is missing\n");
122 double time = double(clock()) / double(CLOCKS_PER_SEC);
123 *
gmsg <<
"\nBegin execution: \"" << name <<
"\", CPU time = " << time <<
" seconds.\n"
137 double time = double(clock()) / double(CLOCKS_PER_SEC);
138 *
gmsg <<
"\nEnd execution: \"" << name <<
"\", CPU time = " << time <<
" seconds.\n"
149 std::string cmdName =
parseString(stat,
"Command name expected");
151 if (cmdName ==
"STOP") {
153 }
else if (cmdName ==
"QUIT") {
155 }
else if (cmdName ==
"HELP" && stat.
delimiter(
',')) {
156 cmdName =
parseString(stat,
"Object name expected");
161 copy =
object->
clone(
"");
171 std::string hint =
getHint(cmdName,
"command");
173 throw ParseError(
"OpalParser::parseAction()",
"Syntax error, " + hint);
176 throw ParseError(
"OpalParser::parseAction()",
"Command \"" + cmdName +
"\" is unknown.");
200 }
else if (stat.
keyword(
"BOOL")) {
202 }
else if (stat.
keyword(
"REAL")) {
204 }
else if (stat.
keyword(
"STRING")) {
206 }
else if (stat.
keyword(
"VECTOR")) {
213 std::string objName =
parseString(stat,
"Object name expected.");
216 std::string attrName;
220 attrName =
parseString(stat,
"Attribute name expected.");
224 "OpalParser::parseAssign()",
"Invalid type specification for this value.");
227 "OpalParser::parseAssign()",
"The object \"" + objName +
"\" is unknown.");
236 model = realConstant;
240 model = boolConstant;
244 model = realVariable;
254 model = stringConstant;
261 object = model->
clone(objName);
264 throw ParseError(
"OpalParser::parseAssign()",
"Invalid <type> field.");
268 "OpalParser::parseAssign()",
269 "You cannot redefine the constant \"" + objName +
"\".");
283 throw ParseError(
"Expressions::parseReference()",
"Index must be positive.");
291 attr->parseComponent(stat,
true, index);
293 attr->parse(stat,
true);
297 attr->parseComponent(stat,
false, index);
299 attr->parse(stat,
false);
304 "OpalParser::parseAssign()",
305 "Object \"" + objName +
"\" has no attribute \"" + attrName +
"\".");
315 bool isShared = stat.
keyword(
"SHARED");
316 std::string objName =
parseString(stat,
"Object name expected.");
319 std::string clsName =
parseString(stat,
"Class name expected.");
322 if (classObject == 0) {
323 if (clsName ==
"SURFACEPHYSICS")
325 "OpalParser::parseDefine()",
326 "The object \"" + clsName +
"\" is changed to \"PARTICLEMATTERINTERACTION\".");
329 "OpalParser::parseDefine()",
"The object \"" + clsName +
"\" is unknown.");
339 copy = classObject->
clone(objName);
362 unsigned int position = stat.
position();
363 std::string positionIndicator = std::string(position + 1,
' ') +
"^\n";
364 std::ostringstream statStr;
368 "OpalParser::parseEnd()", statStr.str() + positionIndicator
369 +
"Syntax error (maybe missing comma or semicolon ? )");
383 if (--par_level == 0)
392 std::string className =
parseString(stat,
"Class name expected.");
402 "OpalParser::parseMacro()",
403 "Command \"" + macName +
"\" cannot be defined with arguments.");
407 "OpalParser::parseMacro()",
"Object \"" + className +
"\" is unknown.");
423 throw ParseError(
"OpalParser::parseMacro()",
"Macro \"" + macName +
"\" is unknown.");
432 *
gmsg <<
"\nOpalParser::printHelp(): Unknown object \"" << cmdName <<
"\".\n" << endl;
434 object->printHelp(std::cerr);
441 while (!token.
isEOF()) {
444 if (token.
isDel(
'(')) {
446 }
else if (token.
isDel(
'[')) {
448 }
else if (token.
isDel(
'{')) {
450 }
else if (token.
isDel(close)) {
461 while (!token.
isEOF()) {
463 if (token.
isDel(
';'))
467 if (token.
isDel(
'(')) {
469 }
else if (token.
isDel(
'[')) {
471 }
else if (token.
isDel(
'{')) {
492 if (token.
isDel(
'{')) {
496 }
else if (token.
isKey(
"IF")) {
500 }
else if (token.
isKey(
"WHILE")) {
510 if (!token.
isEOF()) {
511 if (token.
isDel(
'(')) {
522 if (!token.
isEOF()) {
524 if (token.
isKey(
"MACRO")) {
532 "OpalParser::readStatement()",
533 "MACRO definition lacks \"{...}\".");
539 }
else if (!token.
isDel(
';')) {
541 "OpalParser::readStatement()",
"MACRO call is not terminated by ';'.");
543 }
else if (!token.
isDel(
';')) {
549 }
else if (token.
isDel(
';')) {
552 }
else if (token.
isDel(
'?')) {
554 *
gmsg <<
"\ntry typing \"HELP\" for help.\n" << endl;
556 }
else if (!token.
isEOF()) {
561 throw ParseError(
"OpalParser::readStatement()",
"Command should begin with a <name>.");
564 *ippl::Error <<
"\n*** Parse error detected by function \""
565 <<
"OpalParser::readStatement()"
569 std::string what = ex.
what();
570 boost::replace_all(what,
"\n",
"\n ");
572 *ippl::Error <<
" " << *stat <<
" a" << what <<
'\n' << endl;
587 stat->execute(*
this);
589 Inform errorMsg(
"Error", std::cerr);
590 errorMsg <<
"\n*** Parse error detected by function \"" << ex.
where() <<
"\"\n";
591 stat->printWhere(errorMsg,
true);
592 std::string what = ex.
what();
593 size_t pos = what.find_first_of(
'\n');
595 errorMsg <<
" " << what.substr(0, pos) << endl;
596 what = what.substr(pos + 1, std::string::npos);
597 pos = what.find_first_of(
'\n');
598 }
while (pos != std::string::npos);
599 errorMsg <<
" " << what << endl;
601 MPI_Abort(MPI_COMM_WORLD, -100);
611 inputStack.push_back(std::shared_ptr<TokenStream>(is));
623 return std::string();
626 std::string hint =
"the " + type +
" '" + name +
"' could belong to\n";
630 if (its.first != its.second) {
632 bool any = (its.first)->second ==
"Any";
633 for (
auto it = std::next(its.first); it != its.second && !any; ++it) {
635 any = it->second ==
"Any";
638 hint += std::string(
" - any element\n");
640 hint += std::string(
" - the element")
641 + (std::distance(its.first, its.second) > 1 ?
"s " :
" ") +
elements +
"\n";
646 std::string commands;
648 if (its.first != its.second) {
649 commands = (its.first)->second;
650 for (
auto it = std::next(its.first); it != its.second; ++it) {
651 commands +=
", " + it->second;
653 hint += std::string(
" - the command")
654 + (std::distance(its.first, its.second) > 1 ?
"s " :
" ") + commands +
"\n";
658 std::string sub_commands;
660 if (its.first != its.second) {
661 sub_commands = (its.first)->second;
662 for (
auto it = std::next(its.first); it != its.second; ++it) {
663 sub_commands +=
", " + it->second;
665 hint += std::string(
" - the sub-command")
666 + (std::distance(its.first, its.second) > 1 ?
"s " :
" ") + sub_commands +
"\n";
670 std::string statements;
672 if (its.first != its.second) {
673 statements = (its.first)->second;
674 for (
auto it = std::next(its.first); it != its.second; ++it) {
675 statements +=
", " + it->second;
677 hint += std::string(
" - the statement")
678 + (std::distance(its.first, its.second) > 1 ?
"s " :
" ") + statements +
"\n";
682 hint +=
"but it's not present!";
Representation objects and parsers for attribute expressions.
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.
A representation of an Object attribute.
static std::multimap< OwnerType, std::string > getOwner(const std::string &att)
The base class for all OPAL objects.
virtual bool shouldTrace() const =0
Trace flag.
virtual Object * makeTemplate(const std::string &, TokenStream &, Statement &)
Macro handler function.
virtual Object * clone(const std::string &name)=0
Return a clone.
virtual Object * makeInstance(const std::string &name, Statement &, const Parser *)
Macro handler function.
virtual void setShared(bool)
Set/reset shared flag.
virtual Attribute * findAttribute(const std::string &name)
Find an attribute by name.
virtual bool shouldUpdate() const =0
Update flag.
bool isTreeMember(const Object *subTree) const
Test for tree membership.
virtual void parse(Statement &)
Parse the object.
void makeDirty(Object *object)
Invalidate expressions.
void update()
Update all objects.
Object * find(const std::string &name)
Find entry.
static OpalData * getInstance()
void define(Object *newObject)
Define a new object.
virtual void parseAssign(Statement &) const
Parse assignment statement.
static Token readToken()
Return next input token.
static void parseTokenList(Statement &)
static std::vector< std::shared_ptr< TokenStream > > inputStack
virtual void parseEnd(Statement &) const
Check for end of statement.
virtual void run() const
Read current stream.
virtual Object * find(const std::string &) const
Find object by name in the main directory.
virtual void parseMacro(const std::string &name, Statement &) const
Parse macro definition or call.
static void parseBracketList(char close, Statement &)
virtual Statement * readStatement(TokenStream *) const
Read complete statement from a token stream.
virtual void printHelp(const std::string &) const
Print help on named command.
void execute(Object *, const std::string &) const
Execute or check the current command.
static std::string getHint(const std::string &, const std::string &="attribute")
virtual void parse(Statement &) const
Parse and execute current statement.
void stop() const
Set stop flag.
virtual void parseDefine(Statement &) const
Parse definition.
virtual void parseAction(Statement &) const
Parse executable command.
A simple input statement in token form.
Interface for statements.
Token & getCurrent()
Return current token and skip it.
void append(const Token &)
Append a token.
unsigned int position() const
Return current character number in line.
void restore()
Return to marked position.
bool keyword(const char *s)
Test for keyword.
void mark()
Mark position in command.
virtual void print(std::ostream &os) const
Print statement.
bool atEnd() const
Test for end of command.
bool delimiter(char c)
Test for delimiter.
void start()
Return to start.
Representation of a single input token.
bool isString() const
Test for string.
bool isDel(char del) const
Test for delimiter.
bool isWord() const
Test for word.
bool isEOF() const
Test for end of file.
const std::string & getLex() const
Return the lexeme.
bool isKey(const char *key) const
Test for keyword.
int getLine() const
Return the token's line number.
const std::string & getFile() const
Return the token's file name.
Abstract interface for a stream of input tokens.
virtual Token readToken()=0
Read single token from stream.
virtual const std::string & what() const
Return the message string for the exception.
virtual const std::string & where() const
Return the name of the method or function which detected the exception.