LCOV - code coverage report
Current view: top level - src/parser - Syntax.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 163 180 90.6 %
Date: 2025-07-17 01:28:37 Functions: 29 32 90.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #include "Syntax.h"
      11             : #include "MooseUtils.h"
      12             : 
      13             : #include "libmesh/simple_range.h"
      14             : 
      15             : #include <algorithm>
      16             : 
      17       62760 : Syntax::Syntax() : _actions_to_syntax_valid(false) {}
      18             : 
      19             : void
      20     8963991 : Syntax::registerTaskName(const std::string & task, bool should_auto_build)
      21             : {
      22     8963991 :   if (_registered_tasks.count(task) > 0)
      23      125508 :     return;
      24     8838483 :   _tasks.addItem(task);
      25     8838483 :   _registered_tasks[task] = should_auto_build;
      26             : }
      27             : 
      28             : void
      29     4111874 : Syntax::registerTaskName(const std::string & task,
      30             :                          const std::string & moose_object_type,
      31             :                          bool should_auto_build)
      32             : {
      33     4111874 :   auto range = _moose_systems_to_tasks.equal_range(moose_object_type);
      34     4841757 :   for (auto it = range.first; it != range.second; ++it)
      35      729883 :     if (it->second == task)
      36           0 :       return;
      37             : 
      38     4111874 :   if (_registered_tasks.find(task) != _registered_tasks.end())
      39           2 :     mooseError("A ", task, " is already registered.  Do you need to use appendTaskName instead?");
      40             : 
      41     4111872 :   registerTaskName(task, should_auto_build);
      42     4111872 :   _moose_systems_to_tasks.insert(std::make_pair(moose_object_type, task));
      43             : }
      44             : 
      45             : void
      46      832227 : Syntax::appendTaskName(const std::string & task,
      47             :                        const std::string & moose_object_type,
      48             :                        bool deprecated)
      49             : {
      50      832227 :   if (_registered_tasks.find(task) == _registered_tasks.end())
      51           1 :     mooseError("A ", task, " is not a registered task name.");
      52             : 
      53      832226 :   if (!deprecated)
      54      643964 :     _moose_systems_to_tasks.insert(std::make_pair(moose_object_type, task));
      55             :   else
      56      188262 :     _deprecated_list_moose_systems_to_tasks.insert(std::make_pair(moose_object_type, task));
      57      832226 : }
      58             : 
      59             : void
      60    10909178 : Syntax::addDependency(const std::string & task, const std::string & pre_req)
      61             : {
      62    10909178 :   if (_registered_tasks.find(task) == _registered_tasks.end())
      63           1 :     mooseError("A ", task, " is not a registered task name.");
      64             : 
      65    10909177 :   _tasks.insertDependency(task, pre_req);
      66    10909177 : }
      67             : 
      68             : void
      69       62754 : Syntax::addDependencySets(const std::string & action_sets)
      70             : {
      71       62754 :   std::vector<std::string> sets, prev_names, tasks;
      72       62754 :   MooseUtils::tokenize(action_sets, sets, 1, "()");
      73             : 
      74     6149892 :   for (unsigned int i = 0; i < sets.size(); ++i)
      75             :   {
      76     6087138 :     tasks.clear();
      77     6087138 :     MooseUtils::tokenize(sets[i], tasks, 0, ", ");
      78    14182404 :     for (unsigned int j = 0; j < tasks.size(); ++j)
      79             :     {
      80             :       // Each line should depend on each item in the previous line
      81    18198660 :       for (unsigned int k = 0; k < prev_names.size(); ++k)
      82    10103394 :         addDependency(tasks[j], prev_names[k]);
      83             :     }
      84             :     // Copy the the current items to the previous items for the next iteration
      85     6087138 :     std::swap(tasks, prev_names);
      86             :   }
      87       62754 : }
      88             : 
      89             : void
      90           0 : Syntax::deleteTaskDependencies(const std::string & task)
      91             : {
      92           0 :   if (_registered_tasks.find(task) == _registered_tasks.end())
      93           0 :     mooseError("A ", task, " is not a registered task name.");
      94             : 
      95           0 :   _tasks.deleteDependenciesOfKey(task);
      96           0 : }
      97             : 
      98             : void
      99           0 : Syntax::clearTaskDependencies()
     100             : {
     101           0 :   _tasks.clear();
     102           0 : }
     103             : 
     104             : const std::vector<std::string> &
     105       61935 : Syntax::getSortedTask()
     106             : {
     107             :   try
     108             :   {
     109       61935 :     return _tasks.getSortedValues();
     110             :   }
     111           1 :   catch (CyclicDependencyException<std::string> & e)
     112             :   {
     113           1 :     const auto & cycle = e.getCyclicDependencies();
     114           4 :     mooseError("Cyclic dependencies detected: ", MooseUtils::join(cycle, " <- "));
     115           1 :   }
     116             : }
     117             : 
     118             : const std::vector<std::vector<std::string>> &
     119          20 : Syntax::getSortedTaskSet()
     120             : {
     121          20 :   return _tasks.getSortedValuesSets();
     122             : }
     123             : 
     124             : bool
     125     4665771 : Syntax::hasTask(const std::string & task) const
     126             : {
     127     4665771 :   return (_registered_tasks.find(task) != _registered_tasks.end());
     128             : }
     129             : 
     130             : bool
     131           0 : Syntax::isActionRequired(const std::string & task) const
     132             : {
     133           0 :   mooseDeprecated("Syntax::isActionRequired is deprecated, use shouldAutoBuild() instead");
     134           0 :   return shouldAutoBuild(task);
     135             : }
     136             : 
     137             : bool
     138     8722836 : Syntax::shouldAutoBuild(const std::string & task) const
     139             : {
     140     8722836 :   auto map_pair = _registered_tasks.find(task);
     141             :   mooseAssert(map_pair != _registered_tasks.end(), std::string("Unregistered task: ") + task);
     142             : 
     143     8722836 :   return map_pair->second;
     144             : }
     145             : 
     146             : void
     147     7497712 : Syntax::registerActionSyntax(const std::string & action,
     148             :                              const std::string & syntax,
     149             :                              const std::string & task,
     150             :                              const std::string & file,
     151             :                              int line)
     152             : {
     153     7497712 :   auto range = _syntax_to_actions.equal_range(syntax);
     154     9004004 :   for (auto it = range.first; it != range.second; ++it)
     155     1506292 :     if (it->second._action == action && it->second._task == task)
     156           0 :       return;
     157             : 
     158     7497712 :   _syntax_to_actions.insert(std::make_pair(syntax, ActionInfo{action, task}));
     159     7497712 :   _syntax_to_line.addInfo(syntax, action, task, file, line);
     160     7497712 :   _actions_to_syntax_valid = false;
     161     7497712 : }
     162             : 
     163             : void
     164           1 : Syntax::replaceActionSyntax(const std::string & action,
     165             :                             const std::string & syntax,
     166             :                             const std::string & task,
     167             :                             const std::string & file,
     168             :                             int line)
     169             : {
     170           1 :   _syntax_to_actions.erase(syntax);
     171           1 :   registerActionSyntax(action, syntax, task, file, line);
     172           1 : }
     173             : 
     174             : void
     175           1 : Syntax::removeAllActionsForSyntax(const std::string & syntax)
     176             : {
     177           1 :   _syntax_to_actions.erase(syntax);
     178           1 : }
     179             : 
     180             : void
     181           1 : Syntax::deprecateActionSyntax(const std::string & syntax)
     182             : {
     183           1 :   const std::string message = "\"[" + syntax + "]\" is deprecated.";
     184           1 :   deprecateActionSyntax(syntax, message);
     185           1 : }
     186             : 
     187             : void
     188          50 : Syntax::deprecateActionSyntax(const std::string & syntax, const std::string & message)
     189             : {
     190          50 :   _deprecated_syntax.insert(std::make_pair(syntax, message));
     191          50 : }
     192             : 
     193             : std::string
     194           2 : Syntax::deprecatedActionSyntaxMessage(const std::string syntax)
     195             : {
     196           2 :   auto it = _deprecated_syntax.find(syntax);
     197             : 
     198           2 :   if (it != _deprecated_syntax.end())
     199           4 :     return it->second;
     200             :   else
     201           0 :     mooseError("The action syntax ", syntax, " is not deprecated");
     202             : }
     203             : 
     204             : bool
     205     1638865 : Syntax::isDeprecatedSyntax(const std::string & syntax) const
     206             : {
     207     1638865 :   return _deprecated_syntax.find(syntax) != _deprecated_syntax.end();
     208             : }
     209             : 
     210             : std::vector<std::string>
     211      487754 : Syntax::getSyntaxByAction(const std::string & action, const std::string & task)
     212             : {
     213             :   // See if the reverse multimap has been built yet, if not build it now
     214      487754 :   if (!_actions_to_syntax_valid)
     215             :   {
     216      124368 :     std::transform(_syntax_to_actions.begin(),
     217             :                    _syntax_to_actions.end(),
     218       62184 :                    std::inserter(_actions_to_syntax, _actions_to_syntax.begin()),
     219     7432014 :                    [](const std::pair<std::string, ActionInfo> pair) {
     220     7432014 :                      return std::make_pair(pair.second._action,
     221    14864028 :                                            std::make_pair(pair.first, pair.second._task));
     222             :                    });
     223       62184 :     _actions_to_syntax_valid = true;
     224             :   }
     225             : 
     226      487754 :   std::vector<std::string> syntax;
     227      487754 :   auto it_pair = _actions_to_syntax.equal_range(action);
     228      975562 :   for (const auto & syntax_pair : as_range(it_pair))
     229             :     // If task is blank, return all syntax, otherwise filter by task
     230      487808 :     if (task == "" || syntax_pair.second.second == task)
     231      487808 :       syntax.emplace_back(syntax_pair.second.first);
     232             : 
     233      975508 :   return syntax;
     234           0 : }
     235             : 
     236             : std::vector<std::string>
     237      250437 : Syntax::getNonDeprecatedSyntaxByAction(const std::string & action, const std::string & task)
     238             : {
     239      250437 :   auto syntaxes = getSyntaxByAction(action, task);
     240      500928 :   for (auto syntax_it = begin(syntaxes); syntax_it != end(syntaxes);)
     241             :   {
     242      250491 :     if (isDeprecatedSyntax(*syntax_it))
     243           0 :       syntax_it = syntaxes.erase(syntax_it);
     244             :     else
     245      250491 :       ++syntax_it;
     246             :   }
     247      250437 :   return syntaxes;
     248           0 : }
     249             : 
     250             : std::string
     251     3526568 : Syntax::isAssociated(const std::string & real_id,
     252             :                      bool * is_parent,
     253             :                      const std::map<std::string, std::set<std::string>> & alt_map) const
     254             : {
     255             :   // if non-empty alt_map was provided then traverse its syntax instead of _syntax_to_actions
     256     3526568 :   std::set<std::string> syntax_to_traverse;
     257     3526568 :   if (!alt_map.empty())
     258           7 :     std::transform(alt_map.begin(),
     259             :                    alt_map.end(),
     260             :                    std::inserter(syntax_to_traverse, syntax_to_traverse.end()),
     261         437 :                    [](auto pair) { return pair.first; });
     262             :   else
     263     3526561 :     std::transform(_syntax_to_actions.begin(),
     264             :                    _syntax_to_actions.end(),
     265             :                    std::inserter(syntax_to_traverse, syntax_to_traverse.end()),
     266   421477716 :                    [](auto pair) { return pair.first; });
     267             : 
     268             :   /**
     269             :    * This implementation assumes that wildcards can occur in the place of an entire token but not as
     270             :    * part of a token (i.e.  'Variables/ * /InitialConditions' is valid but not 'Variables/Partial*
     271             :    * /InitialConditions'. Since maps are ordered, a reverse traversal through the registered list
     272             :    * will always select a more specific match before a wildcard match ('*' == char(42)).
     273             :    */
     274             :   bool local_is_parent;
     275     3526568 :   if (is_parent == nullptr)
     276           6 :     is_parent = &local_is_parent; // Just so we don't have to keep checking below when we want to
     277             :                                   // set the value
     278     3526568 :   std::vector<std::string> real_elements, reg_elements;
     279     3526568 :   std::string return_value;
     280             : 
     281     3526568 :   MooseUtils::tokenize(real_id, real_elements);
     282             : 
     283     3526568 :   *is_parent = false;
     284   245847396 :   for (auto it = syntax_to_traverse.rbegin(); it != syntax_to_traverse.rend(); ++it)
     285             :   {
     286   244405805 :     std::string reg_id = *it;
     287   244405805 :     if (reg_id == real_id)
     288             :     {
     289     1069899 :       *is_parent = false;
     290     1069899 :       return reg_id;
     291             :     }
     292   243335906 :     reg_elements.clear();
     293   243335906 :     MooseUtils::tokenize(reg_id, reg_elements);
     294   243335906 :     if (real_elements.size() <= reg_elements.size())
     295             :     {
     296   230829995 :       bool keep_going = true;
     297   341218371 :       for (unsigned int j = 0; keep_going && j < real_elements.size(); ++j)
     298             :       {
     299   110388376 :         if (real_elements[j] != reg_elements[j] && reg_elements[j] != std::string("*"))
     300   102257993 :           keep_going = false;
     301             :       }
     302   230829995 :       if (keep_going)
     303             :       {
     304   128572002 :         if (real_elements.size() < reg_elements.size() && !*is_parent)
     305             :         {
     306             :           // We found a parent, the longest parent in fact but we need to keep
     307             :           // looking to make sure that the real thing isn't registered
     308     2786735 :           *is_parent = true;
     309     2786735 :           return_value = reg_id;
     310             :         }
     311   125785267 :         else if (real_elements.size() == reg_elements.size())
     312             :         {
     313     1015078 :           *is_parent = false;
     314     1015078 :           return reg_id;
     315             :         }
     316             :       }
     317             :     }
     318   244405805 :   }
     319             : 
     320     1441591 :   if (*is_parent)
     321     1425921 :     return return_value;
     322             :   else
     323       15670 :     return "";
     324     3526568 : }
     325             : 
     326             : std::pair<std::multimap<std::string, Syntax::ActionInfo>::const_iterator,
     327             :           std::multimap<std::string, Syntax::ActionInfo>::const_iterator>
     328     3861447 : Syntax::getActions(const std::string & syntax) const
     329             : {
     330     3861447 :   return _syntax_to_actions.equal_range(syntax);
     331             : }
     332             : 
     333             : bool
     334    22343153 : Syntax::verifyMooseObjectTask(const std::string & base, const std::string & task) const
     335             : {
     336    22343153 :   auto iters = _moose_systems_to_tasks.equal_range(base);
     337             : 
     338    48420043 :   for (const auto & task_it : as_range(iters))
     339    27585573 :     if (task == task_it.second)
     340     1508683 :       return true;
     341             : 
     342    20834470 :   iters = _deprecated_list_moose_systems_to_tasks.equal_range(base);
     343    21372417 :   for (const auto & task_it : as_range(iters))
     344      548045 :     if (task == task_it.second)
     345             :     {
     346       10098 :       std::string object_tasks = "";
     347       20196 :       for (const auto & other_task : as_range(_moose_systems_to_tasks.equal_range(base)))
     348       10098 :         object_tasks += (object_tasks == "" ? "" : " ") + other_task.second;
     349             : 
     350       10098 :       mooseDeprecated(
     351       20196 :           "Adding objects from system '" + base + "' through task '" + task +
     352       20196 :           "' is deprecated. This object should only be added from task(s): " + object_tasks +
     353             :           ". This is likely caused by adding objects in a block they no longer belong to. For "
     354             :           "example, FunctorMaterials should no longer be added in the [Materials] block.");
     355       10098 :       return true;
     356       10098 :     }
     357             : 
     358    20824372 :   return false;
     359             : }
     360             : 
     361             : void
     362     1631604 : Syntax::registerSyntaxType(const std::string & syntax, const std::string & type)
     363             : {
     364     1631604 :   _associated_types.insert(std::make_pair(syntax, type));
     365     1631604 : }
     366             : 
     367             : const std::multimap<std::string, std::string> &
     368         250 : Syntax::getAssociatedTypes() const
     369             : {
     370         250 :   return _associated_types;
     371             : }
     372             : 
     373             : const std::multimap<std::string, Syntax::ActionInfo> &
     374         205 : Syntax::getAssociatedActions() const
     375             : {
     376         205 :   return _syntax_to_actions;
     377             : }
     378             : 
     379             : FileLineInfo
     380       21738 : Syntax::getLineInfo(const std::string & syntax,
     381             :                     const std::string & action,
     382             :                     const std::string & task) const
     383             : {
     384       21738 :   return _syntax_to_line.getInfo(syntax, action, task);
     385             : }

Generated by: LCOV version 1.14