Skip to content

Commit

Permalink
Add error check, homogenize parse methods (Argonne-National-Laborator…
Browse files Browse the repository at this point in the history
  • Loading branch information
dschwen committed Apr 7, 2021
1 parent 4b9a347 commit f259658
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 55 deletions.
77 changes: 37 additions & 40 deletions src/parse.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace neml {

void recurseSubstitute(rapidxml::xml_node<> * node, std::map<std::string, std::string> substitutions)
void recurseSubstitute(rapidxml::xml_node<> * node, const std::map<std::string, std::string> & substitutions, std::set<std::string> & used_keys)
{
auto * doc = node->document();

Expand All @@ -21,6 +21,7 @@ void recurseSubstitute(rapidxml::xml_node<> * node, std::map<std::string, std::s
if (sub == substitutions.end())
throw UnknownVariableXML(attr, var);
value = value.replace(open, close - open, sub->second);
used_keys.insert(var);

open = value.find("{", open + 1);
close = value.find("}", open);
Expand All @@ -40,21 +41,41 @@ void recurseSubstitute(rapidxml::xml_node<> * node, std::map<std::string, std::s
}

// iterate over all child nodes
for (rapidxml::xml_node<> * child = node->first_node(); child; child = child->next_sibling())
recurseSubstitute(child, substitutions);
for (rapidxml::xml_node<> * child = node->first_node(); child; child = child->next_sibling())
recurseSubstitute(child, substitutions, used_keys);
}

std::shared_ptr<NEMLModel> parse_string(std::string input, std::map<std::string, std::string> substitutions)
rapidxml::xml_node<> * processNode(rapidxml::xml_document<> & doc, std::string mname, const std::map<std::string, std::string> & substitutions)
{
// Parse the string to the rapidxml representation
rapidxml::xml_document<> doc;
doc.parse<0>(&input[0]);
// Grab the root node
rapidxml::xml_node<> * root = doc.first_node();

// The model is the root node
rapidxml::xml_node<> * found = doc.first_node();
// Find the node with the right name
rapidxml::xml_node<> * found = (mname == "" ? root->first_node(mname.c_str()) : root);
if (!found)
throw ModelNotFound(mname);

// make a set of used substitutions
std::set<std::string> used_keys;

// substitute {variables} in DOM tree
recurseSubstitute(found, substitutions);
recurseSubstitute(found, substitutions, used_keys);

// check if all keys were used
if (used_keys.size() < substitutions.size())
{

}

return found;
}

std::shared_ptr<NEMLModel> parse_string(std::string input, std::string mname, const std::map<std::string, std::string> & substitutions)
{
// Parse the string to the rapidxml representation
rapidxml::xml_document<> doc;
doc.parse<0>(&input[0]);
auto found = processNode(doc, mname, substitutions);

// Get the NEMLObject
std::shared_ptr<NEMLObject> obj = get_object(found);
Expand All @@ -69,20 +90,12 @@ std::shared_ptr<NEMLModel> parse_string(std::string input, std::map<std::string,
}
}

std::unique_ptr<NEMLModel> parse_string_unique(std::string input, std::string mname, std::map<std::string, std::string> substitutions)
std::unique_ptr<NEMLModel> parse_string_unique(std::string input, std::string mname, const std::map<std::string, std::string> & substitutions)
{
// Parse the string to the rapidxml representation
rapidxml::xml_document<> doc;
doc.parse<0>(&input[0]);

// Grab the root node
rapidxml::xml_node<> * root = doc.first_node();

// Find the node with the right name
rapidxml::xml_node<> * found = root->first_node(mname.c_str());

// substitute {variables} in DOM tree
recurseSubstitute(found, substitutions);
auto found = processNode(doc, mname, substitutions);

// Get the NEMLObject
std::unique_ptr<NEMLObject> obj = get_object_unique(found);
Expand All @@ -97,21 +110,13 @@ std::unique_ptr<NEMLModel> parse_string_unique(std::string input, std::string mn
}
}

std::shared_ptr<NEMLModel> parse_xml(std::string fname, std::string mname, std::map<std::string, std::string> substitutions)
std::shared_ptr<NEMLModel> parse_xml(std::string fname, std::string mname, const std::map<std::string, std::string> & substitutions)
{
// Parse the XML file
rapidxml::file <> xmlFile(fname.c_str());
rapidxml::xml_document<> doc;
doc.parse<0>(xmlFile.data());

// Grab the root node
rapidxml::xml_node<> * root = doc.first_node();

// Find the node with the right name
rapidxml::xml_node<> * found = root->first_node(mname.c_str());

// substitute {variables} in DOM tree
recurseSubstitute(found, substitutions);
auto found = processNode(doc, mname, substitutions);

// Get the NEMLObject
std::shared_ptr<NEMLObject> obj = get_object(found);
Expand All @@ -126,21 +131,13 @@ std::shared_ptr<NEMLModel> parse_xml(std::string fname, std::string mname, std::
}
}

std::unique_ptr<NEMLModel> parse_xml_unique(std::string fname, std::string mname, std::map<std::string, std::string> substitutions)
std::unique_ptr<NEMLModel> parse_xml_unique(std::string fname, std::string mname, const std::map<std::string, std::string> & substitutions)
{
// Parse the XML file
rapidxml::file <> xmlFile(fname.c_str());
rapidxml::xml_document<> doc;
doc.parse<0>(xmlFile.data());

// Grab the root node
rapidxml::xml_node<> * root = doc.first_node();

// Find the node with the right name
rapidxml::xml_node<> * found = root->first_node(mname.c_str());

// substitute {variables} in DOM tree
recurseSubstitute(found, substitutions);
auto found = processNode(doc, mname, substitutions);

// Get the NEMLObject
std::unique_ptr<NEMLObject> obj = get_object_unique(found);
Expand Down
68 changes: 53 additions & 15 deletions src/parse.h
Original file line number Diff line number Diff line change
@@ -1,38 +1,41 @@
#ifndef PARSE_H
#define PARSE_H

#include "objects.h"
#include "models.h"
#include "damage.h"
#include "models.h"
#include "objects.h"

#include "windows.h"

#include "rapidxml.hpp"
#include "rapidxml_utils.hpp"

#include <algorithm>
#include <exception>
#include <memory>
#include <string>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
#include <exception>

namespace neml {

/// perform {variable} substitution in DOM tree
void recurseSubstitute(rapidxml::xml_node<> * node, std::map<std::string, std::string> substitutions);
void recurseSubstitute(rapidxml::xml_node<> * node, const std::map<std::string, std::string> & substitutions, std::set<std::string> & used_keys);

/// perform {variable} substitution in DOM tree
rapidxml::xml_node<> * processNode(rapidxml::xml_document<> & doc, std::string mname, const std::map<std::string, std::string> & substitutions);

/// Parse from a string to a shared_ptr
std::shared_ptr<NEMLModel> parse_string(std::string input, std::map<std::string, std::string> substitutions = std::map<std::string, std::string>());
NEML_EXPORT std::shared_ptr<NEMLModel> parse_string(std::string input, std::string mname = "", const std::map<std::string, std::string> & substitutions = std::map<std::string, std::string>());

/// Parse from a string to a unique_ptr
std::unique_ptr<NEMLModel> parse_string_unique(std::string input, std::string mname, std::map<std::string, std::string> substitutions = std::map<std::string, std::string>());
NEML_EXPORT std::unique_ptr<NEMLModel> parse_string_unique(std::string input, std::string mname = "", const std::map<std::string, std::string> & substitutions = std::map<std::string, std::string>());

/// Parse from file to a shared_ptr
NEML_EXPORT std::shared_ptr<NEMLModel> parse_xml(std::string fname, std::string mname, std::map<std::string, std::string> substitutions = std::map<std::string, std::string>());
NEML_EXPORT std::shared_ptr<NEMLModel> parse_xml(std::string fname, std::string mname = "", const std::map<std::string, std::string> & substitutions = std::map<std::string, std::string>());

/// Parse from file to a unique_ptr
NEML_EXPORT std::unique_ptr<NEMLModel> parse_xml_unique(std::string fname, std::string mname, std::map<std::string, std::string> substitutions = std::map<std::string, std::string>());
NEML_EXPORT std::unique_ptr<NEMLModel> parse_xml_unique(std::string fname, std::string mname = "", const std::map<std::string, std::string> & substitutions = std::map<std::string, std::string>());

/// Extract a NEMLObject from a xml node as a unique_ptr
NEML_EXPORT std::unique_ptr<NEMLObject> get_object_unique(const rapidxml::xml_node<> * node);
Expand Down Expand Up @@ -113,6 +116,26 @@ class NodeNotFound: public std::exception {
std::string message_;
};

/// If a model is not found
class ModelNotFound: public std::exception {
public:
ModelNotFound(std::string model_name)
{
std::stringstream ss;
ss << "Model with name " << model_name
<< " was not found in the supplied XML!";
message_ = ss.str();
};

const char * what() const throw ()
{
return message_.c_str();
};

private:
std::string message_;
};

/// If a node is not unique (and it should be)
class DuplicateNode: public std::exception {
public:
Expand Down Expand Up @@ -161,13 +184,29 @@ class InvalidType: public std::exception {
/// If a parameter doesn't exist
class UnknownParameterXML: public std::exception {
public:
UnknownParameterXML(std::string name, std::string param) :
name_(name), param_(param)
UnknownParameterXML(std::string name, std::string param)
{
std::stringstream ss;
ss << "Object " << name << " does not have an XML variable called '" << param << "'!";
message_ = ss.str();
};

ss << "Object " << name_ << " does not have a parameter called " << param_ << "!";
const char * what() const throw ()
{
return message_.c_str();
};

private:
std::string message_;
};

/// If a parameter doesn't exist
class UnusedParameterXML: public std::exception {
public:
UnusedParameterXML(std::string name, std::string params)
{
std::stringstream ss;
ss << "XML variables '" << params << "' supplied to object '" << name << "' were unused!";
message_ = ss.str();
};

Expand All @@ -177,8 +216,7 @@ class UnknownParameterXML: public std::exception {
};

private:
std::string name_, param_, message_;

std::string message_;
};

/// The object isn't in the factory
Expand Down

0 comments on commit f259658

Please sign in to comment.