Skip to content

Commit

Permalink
ParmParse: Line Continuation
Browse files Browse the repository at this point in the history
In #3433, we added an option to disable multi-line support to avoid certain
types of errors. Since multi-line support seems to be desirable feature, we
add a new feature that uses `\` as line continuation. To avoid confusion, we
have decided to stop supporting the old style of multi-line values and make
it a runtime error. Hopefully it does not cause too much trouble for users.
  • Loading branch information
WeiqunZhang committed Jul 21, 2023
1 parent abc6696 commit ca4ca2e
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 60 deletions.
67 changes: 22 additions & 45 deletions Src/Base/AMReX_ParmParse.H
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,24 @@ class IntVect;
//
// Comments in an input file include all text from a '#' character to the
// end of the line. Here is an example input file:
//
// niter = 100 # niter is an integer
// title = "Double Wammy" # example of a string with spaces
// cell_size = 0.5 0.75 # cell spacing in each dimension
// plot.var = Density 1 10 # a list of values
// plot.var = Energy 5 12 # another list of values
// bigarray = 1 2 3 4 5 6 7 8 # first part of array
// 9 10 11 12 # continuation of bigarray
// test = apple "boy blue" 10 20 30 40
// FILE = prob_file # insert contents of this "prob_file" here
//
// The "FILE = <filename>" definition is special. Rather than just
/*
niter = 100 # niter is an integer
title = "Double Wammy" # example of a string with spaces
cell_size = 0.5 0.75 # cell spacing in each dimension
plot.var = Density 1 10 # a list of values
plot.var = Energy 5 12 # another list of values
bigarray = 1 2 3 4 5 6 7 8 \
9 10 11 12 # continuation of bigarray
multi_line_string = "This is a
multi-line string."
test = apple "boy blue" 10 20 30 40
FILE = prob_file # insert contents of this "prob_file" here
*/
// For values spanning multiple lines, one must use '\' at the end of a line
// for continuation, otherwise it's a runtime error. Note that there must be
// at least one space before the continuation character `\`. Multiple lines
// inside a pair of double quotes are considered a single string containing
// '\n's. The "FILE = <filename>" definition is special. Rather than just
// adding this entry to the database, it reads the contents of <filename>
// into the database.
//
Expand Down Expand Up @@ -229,10 +235,12 @@ class IntVect;
*
* plot.var = Energy 5 12
*
* bigarray = 1 2 3 4 5 6 7 8
*
* bigarray = 1 2 3 4 5 6 7 8 \
* 9 10 11 12
*
* multi_line_string = "This is a
* multi-line string."
*
* aBox = ((0,0) (5,5))
*
* test = apple "boy blue" 10 20 30 40
Expand Down Expand Up @@ -1052,37 +1060,6 @@ 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
36 changes: 21 additions & 15 deletions Src/Base/AMReX_ParmParse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,8 @@ 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 @@ -287,6 +278,21 @@ eat_garbage (const char*& str)
if (*str == '\n') { ++num_linefeeds; }
str++;
}
else if ( *str == '\\' ) // '\' followed by a line break is continuation to next line
{
// Unfortunately, a line break has three variants, \r, \n, and \r\n.
if (*(str+1) == '\n') {
str += 2;
} else if (*(str+1) == '\r') {
if (*(str+2) == '\n') {
str += 3;
} else {
str += 2;
}
} else {
break;
}
}
else
{
break;
Expand Down Expand Up @@ -703,14 +709,14 @@ bldTable (const char*& str,
}
AMREX_FALLTHROUGH;
case pEOF:
if (! g_multi_line_support &&
std::accumulate(cur_linefeeds.begin(), cur_linefeeds.end(), int(0)) > 0)
if (std::accumulate(cur_linefeeds.begin(), cur_linefeeds.end(), int(0)) > 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);
}
error_message.append(". Must use \\ for line continuation.");
amrex::Abort(error_message);
}
addDefn(cur_name,cur_list,tab);
Expand All @@ -725,14 +731,14 @@ bldTable (const char*& str,
tmp_str = cur_list.back();
cur_list.pop_back();
cur_linefeeds.pop_back();
if (! g_multi_line_support &&
std::accumulate(cur_linefeeds.begin(), cur_linefeeds.end(), int(0)) > 0)
if (std::accumulate(cur_linefeeds.begin(), cur_linefeeds.end(), int(0)) > 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);
}
error_message.append(". Must use \\ for line continuation.");
amrex::Abort(error_message);
}
addDefn(cur_name, cur_list, tab);
Expand All @@ -754,14 +760,14 @@ bldTable (const char*& str,
tmp_str = cur_list.back();
cur_list.pop_back();
cur_linefeeds.pop_back();
if (! g_multi_line_support &&
std::accumulate(cur_linefeeds.begin(), cur_linefeeds.end(), int(0)) > 0)
if (std::accumulate(cur_linefeeds.begin(), cur_linefeeds.end(), int(0)) > 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);
}
error_message.append(". Must use \\ for line continuation.");
amrex::Abort(error_message);
}
addDefn(cur_name,cur_list,tab);
Expand Down

0 comments on commit ca4ca2e

Please sign in to comment.