Loading [MathJax]/extensions/tex2jax.js

Search Results

 /*
  *  MoMEMta: a modular implementation of the Matrix Element Method
  *  Copyright (C) 2016  Universite catholique de Louvain (UCL), Belgium
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation, either version 3 of the License, or
  *  (at your option) any later version.
  *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <momemta/ModuleDefBuilder.h>
 
 #include <momemta/Logging.h>
 
 #include <ModuleDefUtils.h>
 #include <strings/Scanner.h>
 
 namespace momemta {
 namespace registration {
 
 namespace {
 
 class invalid_name: public std::runtime_error {
     using std::runtime_error::runtime_error;
 };
 
 class invalid_type: public std::runtime_error {
     using std::runtime_error::runtime_error;
 };
 
 class missing_attribute: public std::runtime_error {
     using std::runtime_error::runtime_error;
 };
 
 void finalizeInputOrOutput(StringPiece spec, bool is_output, ModuleRegistrationData& data) {
     using namespace strings;
 
     ArgDef def;
     StringPiece out;
 
     // An optional input starts with a '?'
 
     def.optional = spec.Consume("?");
 
     def.many = spec.Consume("*");
 
     if (! is_output) {
         // This can be a nested input declaration
         // Format is `<attr>/[<attr>/]*<name>`
         while (true) {
             if (! Scanner(spec)
                 .RestartCapture()
                 .ScanUntil('/')
                 .StopCapture()
                 .OneLiteral("/")
                 .GetResult(&spec, &out)) {
                 // No (more) match, exiting the loop
                 break;
             }
 
             auto nested_attribute = out.ToString();
 
             // Ensure attribute exists
             auto attr = momemta::findAttr(nested_attribute, data.module_def);
             if (! attr) {
                 std::string error = "Input definition for module " + data.module_def.name + " references a non-existing "
                             "attribute: " + nested_attribute;
                 LOG(fatal) << error;
                 throw missing_attribute(error);
             } else {
                 def.nested_attributes.push_back(*attr);
             }
         }
     }
 
     // Parse <name>
     if (!Scanner(spec)
             .One(Scanner::LETTER)
             .Any(Scanner::LETTER_DIGIT_UNDERSCORE)
             .StopCapture()
             .AnySpace()
             .GetResult(&spec, &out)) {
         throw invalid_name(std::string("Invalid ") +
                 ((is_output) ? "output" : "input") +
                 " name format (<name>:) for module " + data.module_def.name);
     }
 
     def.name = out.ToString();
 
     if (!is_output) {
         // Parse default value
         bool has_default = spec.Consume("=");
         if (has_default) {
             Scanner(spec)
                     .Any(Scanner::LETTER_DIGIT_UNDERSCORE_COLON)
                     .StopCapture()
                     .AnySpace()
                     .GetResult(&spec, &out);
 
             def.default_value = out.ToString();
             def.optional = true;
         }
     }
 
     if (is_output) {
         data.module_def.outputs.emplace_back(def);
     } else {
         data.module_def.inputs.emplace_back(def);
     }
 }
 
 void finalizeAttr(StringPiece spec, ModuleRegistrationData& data) {
     using namespace strings;
 
     AttrDef def;
 
     // A global attribute starts with a '^'.
     def.global = spec.Consume("^");
 
     // An optional attribute starts with '?'
     def.optional = spec.Consume("?");
 
     StringPiece out;
 
     // Parse `<name>:`
     if (! Scanner(spec)
             .One(Scanner::LETTER)
             .Any(Scanner::LETTER_DIGIT_UNDERSCORE)
             .StopCapture()
             .AnySpace()
             .OneLiteral(":")
             .AnySpace()
             .GetResult(&spec, &out)) {
         throw invalid_name("Invalid attribute name format (<name>:) for module " + data.module_def.name);
     }
 
     def.name = out.ToString();
 
     // Read "<type>" or "list(<type>)".
     bool is_list = Scanner(spec)
             .OneLiteral("list")
             .AnySpace()
             .OneLiteral("(")
             .AnySpace()
             .GetResult(&spec);
 
     // Consume type
     if (!Scanner(spec)
         .Any(Scanner::LOWERLETTER)
         .StopCapture()
         .AnySpace()
         .GetResult(&spec, &out)) {
         throw invalid_type("Invalid type format for attribute " + def.name + " for module " + data.module_def.name);
     }
 
     // TODO: Validate type against a list of acceptable types
 
     if (is_list) {
         def.type = "list(" + out.ToString() + ")";
     } else {
         def.type = out.ToString();
     }
 
     if (is_list) {
         spec.Consume(")");
     }
 
     // Check if there's a default value, and parse it
     if (spec.Consume("=")) {
         Scanner(spec)
             .Any(Scanner::LETTER_DIGIT_DASH_DOT_SLASH_UNDERSCORE)
             .StopCapture()
             .AnySpace()
             .GetResult(&spec, &out);
         def.default_value = out.ToString();
         def.optional = true;
     }
 
     data.module_def.attributes.emplace_back(def);
 }
 
 }
 
 ModuleDefBuilder::ModuleDefBuilder(const std::string& name) {
     reg_data.module_def.name = name;
 
     if (name.length() > 1 && name[0] == '_')
         reg_data.module_def.internal = true;
 }
 
 ModuleDefBuilder& ModuleDefBuilder::Input(const std::string& spec) {
     inputs.emplace_back(spec);
     return *this;
 }
 
 ModuleDefBuilder& ModuleDefBuilder::OptionalInput(const std::string& spec) {
     // Prefix spec with '?' to indicate an optional input
     inputs.emplace_back("?" + spec);
     return *this;
 }
 
 ModuleDefBuilder& ModuleDefBuilder::Inputs(const std::string& spec) {
     // Prefix spec with '*' to indicate a list of inputs
     inputs.emplace_back("*" + spec);
     return *this;
 }
 
 ModuleDefBuilder& ModuleDefBuilder::OptionalInputs(const std::string& spec) {
     // Prefix spec with '?*' to indicate optional inputs
     inputs.emplace_back("?*" + spec);
     return *this;
 }
 
 ModuleDefBuilder& ModuleDefBuilder::Output(const std::string& spec) {
     outputs.emplace_back(spec);
     return *this;
 }
 
 ModuleDefBuilder& ModuleDefBuilder::Attr(const std::string& spec) {
     attrs.emplace_back(spec);
     return *this;
 }
 
 ModuleDefBuilder& ModuleDefBuilder::GlobalAttr(const std::string& spec) {
     // Prefix spec with '^' to indicate a global attribute
     attrs.emplace_back("^" + spec);
     return *this;
 }
 
 ModuleDefBuilder& ModuleDefBuilder::OptionalAttr(const std::string& spec) {
     // Prefix spec with '?' to indicate an optional attribute
     attrs.emplace_back("?" + spec);
     return *this;
 }
 
 ModuleDefBuilder& ModuleDefBuilder::Sticky() {
     reg_data.module_def.sticky = true;
     return *this;
 }
 
 std::string ModuleDefBuilder::name() const {
     return reg_data.module_def.name;
 }
 
 ModuleRegistrationData ModuleDefBuilder::Build() const {
 
     auto data = reg_data;
 
     for (const auto& spec: attrs) {
         finalizeAttr(spec, data);
     }
 
     for (const auto& spec: inputs) {
         finalizeInputOrOutput(spec, false, data);
     }
 
     for (const auto& spec: outputs) {
         finalizeInputOrOutput(spec, true, data);
     }
 
     return data;
 }
 
 }
 }
All Classes Namespaces Files Functions Variables Enumerations Enumerator Macros Modules Pages