"platforms/reference/include/ReferenceKernels.h" did not exist on "85bf8e99fd448f76d3a2c2c35e5df5b755a18825"
Commit a0bdc698 authored by peastman's avatar peastman
Browse files

Merge pull request #808 from peastman/parse

Lepton exceptions have more informative messages
parents e9b7c563 418ceabd
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2009 Stanford University and the Authors. * * Portions copyright (c) 2009-2015 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -38,25 +38,25 @@ using namespace std; ...@@ -38,25 +38,25 @@ using namespace std;
ExpressionTreeNode::ExpressionTreeNode(Operation* operation, const vector<ExpressionTreeNode>& children) : operation(operation), children(children) { ExpressionTreeNode::ExpressionTreeNode(Operation* operation, const vector<ExpressionTreeNode>& children) : operation(operation), children(children) {
if (operation->getNumArguments() != children.size()) if (operation->getNumArguments() != children.size())
throw Exception("Parse error: wrong number of arguments to function: "+operation->getName()); throw Exception("wrong number of arguments to function: "+operation->getName());
} }
ExpressionTreeNode::ExpressionTreeNode(Operation* operation, const ExpressionTreeNode& child1, const ExpressionTreeNode& child2) : operation(operation) { ExpressionTreeNode::ExpressionTreeNode(Operation* operation, const ExpressionTreeNode& child1, const ExpressionTreeNode& child2) : operation(operation) {
children.push_back(child1); children.push_back(child1);
children.push_back(child2); children.push_back(child2);
if (operation->getNumArguments() != children.size()) if (operation->getNumArguments() != children.size())
throw Exception("Parse error: wrong number of arguments to function: "+operation->getName()); throw Exception("wrong number of arguments to function: "+operation->getName());
} }
ExpressionTreeNode::ExpressionTreeNode(Operation* operation, const ExpressionTreeNode& child) : operation(operation) { ExpressionTreeNode::ExpressionTreeNode(Operation* operation, const ExpressionTreeNode& child) : operation(operation) {
children.push_back(child); children.push_back(child);
if (operation->getNumArguments() != children.size()) if (operation->getNumArguments() != children.size())
throw Exception("Parse error: wrong number of arguments to function: "+operation->getName()); throw Exception("wrong number of arguments to function: "+operation->getName());
} }
ExpressionTreeNode::ExpressionTreeNode(Operation* operation) : operation(operation) { ExpressionTreeNode::ExpressionTreeNode(Operation* operation) : operation(operation) {
if (operation->getNumArguments() != children.size()) if (operation->getNumArguments() != children.size())
throw Exception("Parse error: wrong number of arguments to function: "+operation->getName()); throw Exception("wrong number of arguments to function: "+operation->getName());
} }
ExpressionTreeNode::ExpressionTreeNode(const ExpressionTreeNode& node) : operation(&node.getOperation() == NULL ? NULL : node.getOperation().clone()), children(node.getChildren()) { ExpressionTreeNode::ExpressionTreeNode(const ExpressionTreeNode& node) : operation(&node.getOperation() == NULL ? NULL : node.getOperation().clone()), children(node.getChildren()) {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Biological Structures at Stanford, funded under the NIH Roadmap for * * Biological Structures at Stanford, funded under the NIH Roadmap for *
* Medical Research, grant U54 GM072970. See https://simtk.org. * * Medical Research, grant U54 GM072970. See https://simtk.org. *
* * * *
* Portions copyright (c) 2009-2013 Stanford University and the Authors. * * Portions copyright (c) 2009-2015 Stanford University and the Authors. *
* Authors: Peter Eastman * * Authors: Peter Eastman *
* Contributors: * * Contributors: *
* * * *
...@@ -150,51 +150,56 @@ ParsedExpression Parser::parse(const string& expression) { ...@@ -150,51 +150,56 @@ ParsedExpression Parser::parse(const string& expression) {
} }
ParsedExpression Parser::parse(const string& expression, const map<string, CustomFunction*>& customFunctions) { ParsedExpression Parser::parse(const string& expression, const map<string, CustomFunction*>& customFunctions) {
// First split the expression into subexpressions. try {
// First split the expression into subexpressions.
string primaryExpression = expression; string primaryExpression = expression;
vector<string> subexpressions; vector<string> subexpressions;
while (true) { while (true) {
string::size_type pos = primaryExpression.find_last_of(';'); string::size_type pos = primaryExpression.find_last_of(';');
if (pos == string::npos) if (pos == string::npos)
break; break;
string sub = trim(primaryExpression.substr(pos+1)); string sub = trim(primaryExpression.substr(pos+1));
if (sub.size() > 0) if (sub.size() > 0)
subexpressions.push_back(sub); subexpressions.push_back(sub);
primaryExpression = primaryExpression.substr(0, pos); primaryExpression = primaryExpression.substr(0, pos);
} }
// Parse the subexpressions.
map<string, ExpressionTreeNode> subexpDefs;
for (int i = 0; i < (int) subexpressions.size(); i++) {
string::size_type equalsPos = subexpressions[i].find('=');
if (equalsPos == string::npos)
throw Exception("subexpression does not specify a name");
string name = trim(subexpressions[i].substr(0, equalsPos));
if (name.size() == 0)
throw Exception("subexpression does not specify a name");
vector<ParseToken> tokens = tokenize(subexpressions[i].substr(equalsPos+1));
int pos = 0;
subexpDefs[name] = parsePrecedence(tokens, pos, customFunctions, subexpDefs, 0);
if (pos != tokens.size())
throw Exception("unexpected text at end of subexpression: "+tokens[pos].getText());
}
// Parse the subexpressions. // Now parse the primary expression.
map<string, ExpressionTreeNode> subexpDefs; vector<ParseToken> tokens = tokenize(primaryExpression);
for (int i = 0; i < (int) subexpressions.size(); i++) {
string::size_type equalsPos = subexpressions[i].find('=');
if (equalsPos == string::npos)
throw Exception("Parse error: subexpression does not specify a name");
string name = trim(subexpressions[i].substr(0, equalsPos));
if (name.size() == 0)
throw Exception("Parse error: subexpression does not specify a name");
vector<ParseToken> tokens = tokenize(subexpressions[i].substr(equalsPos+1));
int pos = 0; int pos = 0;
subexpDefs[name] = parsePrecedence(tokens, pos, customFunctions, subexpDefs, 0); ExpressionTreeNode result = parsePrecedence(tokens, pos, customFunctions, subexpDefs, 0);
if (pos != tokens.size()) if (pos != tokens.size())
throw Exception("Parse error: unexpected text at end of subexpression: "+tokens[pos].getText()); throw Exception("unexpected text at end of expression: "+tokens[pos].getText());
return ParsedExpression(result);
}
catch (Exception& ex) {
throw Exception("Parse error in expression \""+expression+"\": "+ex.what());
} }
// Now parse the primary expression.
vector<ParseToken> tokens = tokenize(primaryExpression);
int pos = 0;
ExpressionTreeNode result = parsePrecedence(tokens, pos, customFunctions, subexpDefs, 0);
if (pos != tokens.size())
throw Exception("Parse error: unexpected text at end of expression: "+tokens[pos].getText());
return ParsedExpression(result);
} }
ExpressionTreeNode Parser::parsePrecedence(const vector<ParseToken>& tokens, int& pos, const map<string, CustomFunction*>& customFunctions, ExpressionTreeNode Parser::parsePrecedence(const vector<ParseToken>& tokens, int& pos, const map<string, CustomFunction*>& customFunctions,
const map<string, ExpressionTreeNode>& subexpressionDefs, int precedence) { const map<string, ExpressionTreeNode>& subexpressionDefs, int precedence) {
if (pos == tokens.size()) if (pos == tokens.size())
throw Exception("Parse error: unexpected end of expression"); throw Exception("unexpected end of expression");
// Parse the next value (number, variable, function, parenthesized expression) // Parse the next value (number, variable, function, parenthesized expression)
...@@ -220,7 +225,7 @@ ExpressionTreeNode Parser::parsePrecedence(const vector<ParseToken>& tokens, int ...@@ -220,7 +225,7 @@ ExpressionTreeNode Parser::parsePrecedence(const vector<ParseToken>& tokens, int
pos++; pos++;
result = parsePrecedence(tokens, pos, customFunctions, subexpressionDefs, 0); result = parsePrecedence(tokens, pos, customFunctions, subexpressionDefs, 0);
if (pos == tokens.size() || tokens[pos].getType() != ParseToken::RightParen) if (pos == tokens.size() || tokens[pos].getType() != ParseToken::RightParen)
throw Exception("Parse error: unbalanced parentheses"); throw Exception("unbalanced parentheses");
pos++; pos++;
} }
else if (token.getType() == ParseToken::Function) { else if (token.getType() == ParseToken::Function) {
...@@ -234,7 +239,7 @@ ExpressionTreeNode Parser::parsePrecedence(const vector<ParseToken>& tokens, int ...@@ -234,7 +239,7 @@ ExpressionTreeNode Parser::parsePrecedence(const vector<ParseToken>& tokens, int
pos++; pos++;
} while (moreArgs); } while (moreArgs);
if (pos == tokens.size() || tokens[pos].getType() != ParseToken::RightParen) if (pos == tokens.size() || tokens[pos].getType() != ParseToken::RightParen)
throw Exception("Parse error: unbalanced parentheses"); throw Exception("unbalanced parentheses");
pos++; pos++;
Operation* op = getFunctionOperation(token.getText(), customFunctions); Operation* op = getFunctionOperation(token.getText(), customFunctions);
try { try {
...@@ -251,7 +256,7 @@ ExpressionTreeNode Parser::parsePrecedence(const vector<ParseToken>& tokens, int ...@@ -251,7 +256,7 @@ ExpressionTreeNode Parser::parsePrecedence(const vector<ParseToken>& tokens, int
result = ExpressionTreeNode(new Operation::Negate(), toNegate); result = ExpressionTreeNode(new Operation::Negate(), toNegate);
} }
else else
throw Exception("Parse error: unexpected token: "+token.getText()); throw Exception("unexpected token: "+token.getText());
// Now deal with the next binary operator. // Now deal with the next binary operator.
...@@ -288,7 +293,7 @@ Operation* Parser::getOperatorOperation(const std::string& name) { ...@@ -288,7 +293,7 @@ Operation* Parser::getOperatorOperation(const std::string& name) {
case Operation::POWER: case Operation::POWER:
return new Operation::Power(); return new Operation::Power();
default: default:
throw Exception("Parse error: unknown operator"); throw Exception("unknown operator");
} }
} }
...@@ -334,7 +339,7 @@ Operation* Parser::getFunctionOperation(const std::string& name, const map<strin ...@@ -334,7 +339,7 @@ Operation* Parser::getFunctionOperation(const std::string& name, const map<strin
map<string, Operation::Id>::const_iterator iter = opMap.find(trimmed); map<string, Operation::Id>::const_iterator iter = opMap.find(trimmed);
if (iter == opMap.end()) if (iter == opMap.end())
throw Exception("Parse error: unknown function: "+trimmed); throw Exception("unknown function: "+trimmed);
switch (iter->second) { switch (iter->second) {
case Operation::SQRT: case Operation::SQRT:
return new Operation::Sqrt(); return new Operation::Sqrt();
...@@ -387,6 +392,6 @@ Operation* Parser::getFunctionOperation(const std::string& name, const map<strin ...@@ -387,6 +392,6 @@ Operation* Parser::getFunctionOperation(const std::string& name, const map<strin
case Operation::ABS: case Operation::ABS:
return new Operation::Abs(); return new Operation::Abs();
default: default:
throw Exception("Parse error: unknown function"); throw Exception("unknown function");
} }
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment