LCOV - code coverage report
Current view: top level - src/parser - Syntax.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: fef103 Lines: 162 179 90.5 %
Date: 2025-09-03 20:01:23 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       68465 : Syntax::Syntax() : _actions_to_syntax_valid(false) {}
      18             : 
      19             : void
      20     9926095 : Syntax::registerTaskName(const std::string & task, bool should_auto_build)
      21             : {
      22     9926095 :   if (_registered_tasks.count(task) > 0)
      23      136918 :     return;
      24     9789177 :   _tasks.addItem(task);
      25     9789177 :   _registered_tasks[task] = should_auto_build;
      26             : }
      27             : 
      28             : void
      29     4492441 : Syntax::registerTaskName(const std::string & task,
      30             :                          const std::string & moose_object_type,
      31             :                          bool should_auto_build)
      32             : {
      33     4492441 :   auto range = _moose_systems_to_tasks.equal_range(moose_object_type);
      34     5290367 :   for (auto it = range.first; it != range.second; ++it)
      35      797926 :     if (it->second == task)
      36           0 :       return;
      37             : 
      38     4492441 :   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     4492439 :   registerTaskName(task, should_auto_build);
      42     4492439 :   _moose_systems_to_tasks.insert(std::make_pair(moose_object_type, task));
      43             : }
      44             : 
      45             : void
      46      911263 : Syntax::appendTaskName(const std::string & task,
      47             :                        const std::string & moose_object_type,
      48             :                        bool deprecated)
      49             : {
      50      911263 :   if (_registered_tasks.find(task) == _registered_tasks.end())
      51           1 :     mooseError("A ", task, " is not a registered task name.");
      52             : 
      53      911262 :   if (!deprecated)
      54      705885 :     _moose_systems_to_tasks.insert(std::make_pair(moose_object_type, task));
      55             :   else
      56      205377 :     _deprecated_list_moose_systems_to_tasks.insert(std::make_pair(moose_object_type, task));
      57      911262 : }
      58             : 
      59             : void
      60    12043251 : Syntax::addDependency(const std::string & task, const std::string & pre_req)
      61             : {
      62    12043251 :   if (_registered_tasks.find(task) == _registered_tasks.end())
      63           1 :     mooseError("A ", task, " is not a registered task name.");
      64             : 
      65    12043250 :   _tasks.insertDependency(task, pre_req);
      66    12043250 : }
      67             : 
      68             : void
      69       68459 : Syntax::addDependencySets(const std::string & action_sets)
      70             : {
      71       68459 :   std::vector<std::string> sets, prev_names, tasks;
      72       68459 :   MooseUtils::tokenize(action_sets, sets, 1, "()");
      73             : 
      74     6845900 :   for (unsigned int i = 0; i < sets.size(); ++i)
      75             :   {
      76     6777441 :     tasks.clear();
      77     6777441 :     MooseUtils::tokenize(sets[i], tasks, 0, ", ");
      78    15745570 :     for (unsigned int j = 0; j < tasks.size(); ++j)
      79             :     {
      80             :       // Each line should depend on each item in the previous line
      81    20058487 :       for (unsigned int k = 0; k < prev_names.size(); ++k)
      82    11090358 :         addDependency(tasks[j], prev_names[k]);
      83             :     }
      84             :     // Copy the the current items to the previous items for the next iteration
      85     6777441 :     std::swap(tasks, prev_names);
      86             :   }
      87       68459 : }
      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       67647 : Syntax::getSortedTask()
     106             : {
     107             :   try
     108             :   {
     109       67647 :     return _tasks.getSortedValues();
     110             :   }
     111           1 :   catch (CyclicDependencyException<std::string> & e)
     112             :   {
     113           1 :     const auto & cycle = e.getCyclicDependencies();
     114           3 :     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     5192847 : Syntax::hasTask(const std::string & task) const
     126             : {
     127     5192847 :   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     9672881 : Syntax::shouldAutoBuild(const std::string & task) const
     139             : {
     140     9672881 :   auto map_pair = _registered_tasks.find(task);
     141             :   mooseAssert(map_pair != _registered_tasks.end(), std::string("Unregistered task: ") + task);
     142             : 
     143    19345762 :   return map_pair->second;
     144             : }
     145             : 
     146             : void
     147     8186346 : 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     8186346 :   auto range = _syntax_to_actions.equal_range(syntax);
     154     9829513 :   for (auto it = range.first; it != range.second; ++it)
     155     1643167 :     if (it->second._action == action && it->second._task == task)
     156           0 :       return;
     157             : 
     158     8186346 :   _syntax_to_actions.insert(std::make_pair(syntax, ActionInfo{action, task}));
     159     8186346 :   _syntax_to_line.addInfo(syntax, action, task, file, line);
     160     8186346 :   _actions_to_syntax_valid = false;
     161             : }
     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     1793237 : Syntax::isDeprecatedSyntax(const std::string & syntax) const
     206             : {
     207     1793237 :   return _deprecated_syntax.find(syntax) != _deprecated_syntax.end();
     208             : }
     209             : 
     210             : std::vector<std::string>
     211      532692 : 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      532692 :   if (!_actions_to_syntax_valid)
     215             :   {
     216      135800 :     std::transform(_syntax_to_actions.begin(),
     217             :                    _syntax_to_actions.end(),
     218       67900 :                    std::inserter(_actions_to_syntax, _actions_to_syntax.begin()),
     219     8121952 :                    [](const std::pair<std::string, ActionInfo> pair) {
     220     8121952 :                      return std::make_pair(pair.second._action,
     221     8121952 :                                            std::make_pair(pair.first, pair.second._task));
     222             :                    });
     223       67900 :     _actions_to_syntax_valid = true;
     224             :   }
     225             : 
     226      532692 :   std::vector<std::string> syntax;
     227      532692 :   auto it_pair = _actions_to_syntax.equal_range(action);
     228     1065442 :   for (const auto & syntax_pair : as_range(it_pair))
     229             :     // If task is blank, return all syntax, otherwise filter by task
     230      532750 :     if (task == "" || syntax_pair.second.second == task)
     231      532750 :       syntax.emplace_back(syntax_pair.second.first);
     232             : 
     233     1065384 :   return syntax;
     234           0 : }
     235             : 
     236             : std::vector<std::string>
     237      273534 : Syntax::getNonDeprecatedSyntaxByAction(const std::string & action, const std::string & task)
     238             : {
     239      273534 :   auto syntaxes = getSyntaxByAction(action, task);
     240      820660 :   for (auto syntax_it = begin(syntaxes); syntax_it != end(syntaxes);)
     241             :   {
     242      273592 :     if (isDeprecatedSyntax(*syntax_it))
     243           0 :       syntax_it = syntaxes.erase(syntax_it);
     244             :     else
     245      273592 :       ++syntax_it;
     246             :   }
     247      273534 :   return syntaxes;
     248           0 : }
     249             : 
     250             : std::string
     251     3926941 : 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     3926941 :   std::set<std::string> syntax_to_traverse;
     257     3926941 :   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     3926934 :     std::transform(_syntax_to_actions.begin(),
     264             :                    _syntax_to_actions.end(),
     265             :                    std::inserter(syntax_to_traverse, syntax_to_traverse.end()),
     266   469755672 :                    [](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     3926941 :   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     3926941 :   std::vector<std::string> real_elements, reg_elements;
     279     3926941 :   std::string return_value;
     280             : 
     281     3926941 :   MooseUtils::tokenize(real_id, real_elements);
     282             : 
     283     3926941 :   *is_parent = false;
     284   275825900 :   for (auto it = syntax_to_traverse.rbegin(); it != syntax_to_traverse.rend(); ++it)
     285             :   {
     286   274192066 :     std::string reg_id = *it;
     287   274192066 :     if (reg_id == real_id)
     288             :     {
     289     1176710 :       *is_parent = false;
     290     1176710 :       return reg_id;
     291             :     }
     292   273015356 :     reg_elements.clear();
     293   273015356 :     MooseUtils::tokenize(reg_id, reg_elements);
     294   273015356 :     if (real_elements.size() <= reg_elements.size())
     295             :     {
     296   259219578 :       bool keep_going = true;
     297   514085550 :       for (unsigned int j = 0; keep_going && j < real_elements.size(); ++j)
     298             :       {
     299   750898716 :         if (real_elements[j] != reg_elements[j] && reg_elements[j] != std::string("*"))
     300   245924908 :           keep_going = false;
     301             :       }
     302   259219578 :       if (keep_going)
     303             :       {
     304    13294670 :         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     1837943 :           *is_parent = true;
     309     1837943 :           return_value = reg_id;
     310             :         }
     311    11456727 :         else if (real_elements.size() == reg_elements.size())
     312             :         {
     313     1116397 :           *is_parent = false;
     314     1116397 :           return reg_id;
     315             :         }
     316             :       }
     317             :     }
     318   274192066 :   }
     319             : 
     320     1633834 :   if (*is_parent)
     321      342047 :     return return_value;
     322             :   else
     323     2583574 :     return "";
     324     3926941 : }
     325             : 
     326             : std::pair<std::multimap<std::string, Syntax::ActionInfo>::const_iterator,
     327             :           std::multimap<std::string, Syntax::ActionInfo>::const_iterator>
     328     4229818 : Syntax::getActions(const std::string & syntax) const
     329             : {
     330     4229818 :   return _syntax_to_actions.equal_range(syntax);
     331             : }
     332             : 
     333             : bool
     334    22673162 : Syntax::verifyMooseObjectTask(const std::string & base, const std::string & task) const
     335             : {
     336    22673162 :   auto iters = _moose_systems_to_tasks.equal_range(base);
     337             : 
     338    49072188 :   for (const auto & task_it : as_range(iters))
     339    28013714 :     if (task == task_it.second)
     340     1614688 :       return true;
     341             : 
     342    21058474 :   iters = _deprecated_list_moose_systems_to_tasks.equal_range(base);
     343    21624139 :   for (const auto & task_it : as_range(iters))
     344      576289 :     if (task == task_it.second)
     345             :     {
     346       10624 :       std::string object_tasks = "";
     347       21248 :       for (const auto & other_task : as_range(_moose_systems_to_tasks.equal_range(base)))
     348       10624 :         object_tasks += (object_tasks == "" ? "" : " ") + other_task.second;
     349             : 
     350       10624 :       mooseDeprecated(
     351       21248 :           "Adding objects from system '" + base + "' through task '" + task +
     352       21248 :           "' 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       10624 :       return true;
     356       10624 :     }
     357             : 
     358    21047850 :   return false;
     359             : }
     360             : 
     361             : void
     362     1779934 : Syntax::registerSyntaxType(const std::string & syntax, const std::string & type)
     363             : {
     364     1779934 :   _associated_types.insert(std::make_pair(syntax, type));
     365     1779934 : }
     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