Skip to content

Commit

Permalink
ParmParse: Option to disable multi-line support
Browse files Browse the repository at this point in the history
By default, ParmParse supports multi-line values. For example,
```
    plot_vars = dens vx vy vx
                energy entropy
```

This can be disabled by calling setMultiLineSupport(false) before
amrex::Initialize(). This can avoid errors in inputs like,
```
    algo.current_deposition = direct

    # Enable galilean
    psatd.use_default_v_galilean # Unfortunately we forgot = 1
```
With multi-line support, this is unfortunately equivalent to
```
    algo.current_deposition = direct psatd.use_default_v_galilean
```
With multi-line support disabled, it will abort. Note that even
after multi-line support is disabled, one is still allowed to have
```
    f = "x + y
         + sin(z)"
```
because here what's inside the pair of double quotes is considered a single
string.
  • Loading branch information
WeiqunZhang committed Jul 20, 2023
1 parent dbfa3b0 commit 6216179
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 22 deletions.
31 changes: 31 additions & 0 deletions Src/Base/AMReX_ParmParse.H
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,37 @@ public:
//! Returns [prefix.]* parameters.
[[nodiscard]] static std::set<std::string> getEntries (const std::string& prefix = std::string());

/**
* \brief Control multi-line support
*
* By default, ParmParse supports multi-line values. For example,
\verbatim
plot_vars = dens vx vy vx
energy entropy
\endverbatim
* This can be disabled by calling this function setMultiLineSupport(false)
* before amrex::Initialize(). This can avoid errors in inputs like,
\verbatim
algo.current_deposition = direct
# Enable galilean
psatd.use_default_v_galilean # Unfortunately we forgot = 1
\endverbatim
* With multi-line support, this is equivalent to
\verbatim
algo.current_deposition = direct psatd.use_default_v_galilean
\endverbatim
* With multi-line support disabled, it will abort. Note that after
* multi-line support is disabled, one is still allowed to have
\verbatim
f = "x + y
+ sin(z)"
\endverbatim
* because here what's inside the pair of double quotes is considered a
* single string.
*/
static void setMultiLineSupport (bool b);

struct PP_entry;
using Table = std::list<PP_entry>;
static void appendTable(ParmParse::Table& tab);
Expand Down
89 changes: 67 additions & 22 deletions Src/Base/AMReX_ParmParse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <iostream>
#include <iterator>
#include <list>
#include <numeric>
#include <regex>
#include <set>
#include <sstream>
Expand All @@ -33,8 +34,17 @@ static bool finalize_verbose = false;
static bool finalize_verbose = true;
#endif

namespace {
bool g_multi_line_support = true;
}

std::string const ParmParse::FileKeyword = "FILE";

void ParmParse::setMultiLineSupport (bool b)
{
g_multi_line_support = b;
}

//
// Used by constructor to build table.
//
Expand Down Expand Up @@ -257,9 +267,10 @@ state_name[] =
"LIST"
};

void
int
eat_garbage (const char*& str)
{
int num_linefeeds = 0;
for (;;)
{
if ( *str == 0 ) break; // NOLINT
Expand All @@ -271,31 +282,26 @@ eat_garbage (const char*& str)
}
continue;
}
else if ( isspace(*str) )
else if ( std::isspace(*str) )
{
if (*str == '\n') { ++num_linefeeds; }
str++;
}
else
{
break;
}
}
return num_linefeeds;
}

PType
getToken (const char*& str,
std::string& ostr)
{
#define ERROR_MESS \
amrex::ErrorStream() << "ParmParse::getToken(): invalid string = " << ostr << '\n'; \
amrex::ErrorStream() << "STATE = " << state_name[state] \
<< ", next char = " << ch << '\n'; \
amrex::ErrorStream() << ", rest of input = \n" << str << '\n'; \
amrex::Abort()
getToken (const char*& str, std::string& ostr, int& num_linefeeds)
{
//
// Eat white space and comments.
//
eat_garbage(str);
num_linefeeds = eat_garbage(str);
//
// Check for end of file.
//
Expand Down Expand Up @@ -343,7 +349,7 @@ getToken (const char*& str,
str++;
return pCloseBracket;
}
else if ( isalpha(ch) )
else if ( std::isalpha(ch) )
{
ostr += ch; str++;
state = IDENTIFIER;
Expand All @@ -355,11 +361,11 @@ getToken (const char*& str,
}
break;
case IDENTIFIER:
if ( isalnum(ch) || ch == '_' || ch == '.' || ch == '[' || ch == ']' || ch == '+' || ch == '-' )
if ( std::isalnum(ch) || ch == '_' || ch == '.' || ch == '[' || ch == ']' || ch == '+' || ch == '-' )
{
ostr += ch; str++;
}
else if ( isspace(ch) || ch == '=' )
else if ( std::isspace(ch) || ch == '=' )
{
return pDefn;
}
Expand Down Expand Up @@ -388,7 +394,7 @@ getToken (const char*& str,
}
break;
case STRING:
if ( isspace(ch) || ch == '=' )
if ( std::isspace(ch) || ch == '=' )
{
return pValue;
}
Expand All @@ -409,10 +415,13 @@ getToken (const char*& str,
}
break;
default:
ERROR_MESS;
amrex::ErrorStream() << "ParmParse::getToken(): invalid string = " << ostr << '\n'
<< "STATE = " << state_name[state]
<< ", next char = " << ch << '\n'
<< ", rest of input = \n" << str << '\n';
amrex::Abort();
}
}
#undef ERROR_MESS
}


Expand Down Expand Up @@ -676,12 +685,14 @@ bldTable (const char*& str,
std::list<std::string> cur_list;
ParmParse::Table cur_table;
std::string tmp_str;
std::vector<int> cur_linefeeds;

for (;;)
{
std::string tokname;
int num_linefeeds;

PType token = getToken(str,tokname);
PType token = getToken(str,tokname, num_linefeeds);

switch (token)
{
Expand All @@ -692,6 +703,16 @@ bldTable (const char*& str,
}
AMREX_FALLTHROUGH;
case pEOF:
if (! g_multi_line_support &&
std::reduce(cur_linefeeds.begin(), cur_linefeeds.end()) > 0)
{
std::string error_message("ParmParse: Multiple lines in ");
error_message.append(cur_name).append(" =");
for (auto const& x : cur_list) {
error_message.append(" ").append(x);
}
amrex::Abort(error_message);
}
addDefn(cur_name,cur_list,tab);
return;
case pOpenBracket:
Expand All @@ -703,6 +724,17 @@ bldTable (const char*& str,
{
tmp_str = cur_list.back();
cur_list.pop_back();
cur_linefeeds.pop_back();
if (! g_multi_line_support &&
std::reduce(cur_linefeeds.begin(), cur_linefeeds.end()) > 0)
{
std::string error_message("ParmParse: Multiple lines in ");
error_message.append(cur_name).append(" =");
for (auto const& x : cur_list) {
error_message.append(" ").append(x);
}
amrex::Abort(error_message);
}
addDefn(cur_name, cur_list, tab);
cur_name = tmp_str;
}
Expand All @@ -716,14 +748,26 @@ bldTable (const char*& str,
}
if ( !cur_list.empty() )
{
//
// Read one too far, remove last name on list.
//
tmp_str = cur_list.back();
cur_list.pop_back();
cur_linefeeds.pop_back();
if (! g_multi_line_support &&
std::reduce(cur_linefeeds.begin(), cur_linefeeds.end()) > 0)
{
std::string error_message("ParmParse: Multiple lines in ");
error_message.append(cur_name).append(" =");
for (auto const& x : cur_list) {
error_message.append(" ").append(x);
}
amrex::Abort(error_message);
}
addDefn(cur_name,cur_list,tab);
cur_name = tmp_str;
}
//
// Read one too far, remove last name on list.
//
cur_linefeeds.clear();
break;
case pDefn:
if ( cur_name.empty() )
Expand All @@ -743,6 +787,7 @@ bldTable (const char*& str,
amrex::Abort(msg.c_str());
}
cur_list.push_back(tokname);
cur_linefeeds.push_back(num_linefeeds);
break;
}
}
Expand Down

0 comments on commit 6216179

Please sign in to comment.