Commit e2087a7a authored by GILLES Sebastien's avatar GILLES Sebastien
Browse files

#1468 Refactor of the new code in progress.

parent 003f9f9b
......@@ -35,27 +35,85 @@ namespace MoReFEM
//! Defines 'value_in' for the user. It checks whether an element is in a table.
void AddValueIn(lua_State* lua_state);
/*!
* \brief Just concatenate the section (and eventually subsections and so forth...) and the parameter name.
*
* e.g. if hierarchy is { "Solid", "YoungModulus"} and param_name is "LuaFunction" this function will yield
* "Solid.YoungModulus.LuaFunction", aka the keyword identifier in the input data file.
*/
std::string GenerateSectionNameFromHierarchy(const std::vector<std::string>& hierarchy,
const std::string& param_name);
//! Structure which holds the name of the data or section found and the position of the companion equal sign.
struct EntryOrSection
{
EntryOrSection(const std::string& name, std::size_t position);
std::string name;
std::size_t equal_position;
};
struct Section
{
std::string name;
std::size_t min;
std::size_t max;
};
/*!
* \brief Parse the file to extract all the keys in it.
*
* \param[in] path Path to the input Lua file.
*
* \internal Lua is not involved at all here; it is done in pure C++ by parsing manually the file.
*
* \return All the keys found in the input file.
* The point of this class is to compute all the keys found in the input file.
*/
std::vector<std::string> ExtractKeysFromFile(const std::string& path);
class ExtractKeysFromFile
{
public:
//! Constructor.
//! \param[in] file Path to the input Lua file.
ExtractKeysFromFile(const std::string& path);
std::vector<std::string> GetEntryKeyList() const;
private:
//! Interpret the file as a big string; comments are excluded from it.
//! Reason fo this is that by former implementation (prior to #1468) didn't do that this way and I ended
//! up with side effects depending whether a brace ended on the same line as another or not.
void FileAsString();
//! Compute the positions of the relevant '{', '}' and '='.
//! At this point map are correctly filtered out but not vectors (it is done at a further step).
void ComputeDelimiterPositions();
//! Extract the names of the data and the section (not knowing yet which is which).
void ComputeEntryOrSectionNames();
void Stuff();
private:
const std::string& file_;
std::string content_;
// Convention: we do not count equals which last seen character was a ']'
// Because '=' in maps (such as { [1] = 0., [3] = 14.5, [4] = -31.231 }} ) shouldn't be considered to
// determine keywords.
std::vector<std::size_t> equal_position_list_;
// convention: '{' positions are stored as positive values.
// '}' positions are stored as negative values..
std::vector<int> brace_position_list_;
std::vector<EntryOrSection> entry_or_section_list_;
std::vector<Section> section_list_;
};
......@@ -95,10 +153,8 @@ namespace MoReFEM
void LuaOptionFile::Open(const std::string& filename, const char* invoking_file, int invoking_line)
{
SetEntryKeyList(ExtractKeysFromFile(filename));
std::cout << "TMP"<<std::endl;
Utilities::PrintContainer<>::Do(GetEntryKeyList());
ExtractKeysFromFile entry_keys_list(filename);
SetEntryKeyList(entry_keys_list.GetEntryKeyList());
if (luaL_dofile(state_, filename.c_str()))
{
......@@ -119,25 +175,6 @@ namespace MoReFEM
{
struct NameAndPos
{
std::string name;
std::size_t position;
};
struct Section
{
std::string name;
std::size_t min;
std::size_t max;
};
void AddValueIn(lua_State* lua_state)
{
......@@ -155,46 +192,53 @@ namespace MoReFEM
}
std::vector<std::string> ExtractKeysFromFile(const std::string& path)
ExtractKeysFromFile::ExtractKeysFromFile(const std::string& file)
: file_(file)
{
FileAsString();
ComputeDelimiterPositions();
ComputeEntryOrSectionNames();
Stuff();
}
void ExtractKeysFromFile::FileAsString()
{
std::ifstream stream;
FilesystemNS::File::Read(stream, path, __FILE__, __LINE__);
FilesystemNS::File::Read(stream, file_, __FILE__, __LINE__);
constexpr auto npos = std::string::npos;
std::ostringstream oconv;
std::string content;
// First we load all the content into a single string (barring the comments): we want to identify the
// braces without side effects due to line break present or not.
std::string line;
while (getline(stream, line))
{
std::string line;
while (getline(stream, line))
{
auto pos = line.find("--");
if (pos != npos)
line.erase(pos, npos);
oconv << line;
}
auto pos = line.find("--");
content = oconv.str();
oconv.str("");
if (pos != npos)
line.erase(pos, npos);
oconv << line;
}
// Then we want to work on the braces
content_ = oconv.str();
}
// Convention: we do not count equals which last seen character was a ']'
// Because '=' in maps (such as { [1] = 0., [3] = 14.5, [4] = -31.231 }} ) shouldn't be considered to
// determine keywords.
std::vector<std::size_t> equal_position_list;
std::vector<int> brace_position_list; // convention: '{' positions are stored as positive values.
// '}' positions are stored as negative values.
EntryOrSection::EntryOrSection(const std::string& a_name, std::size_t a_position)
: name(a_name),
equal_position(a_position)
{ }
const auto size = content.size();
void ExtractKeysFromFile::ComputeDelimiterPositions()
{
const auto size = content_.size();
bool is_last_non_space_character_close_bracket = false;
......@@ -202,126 +246,116 @@ namespace MoReFEM
for (auto i = 0ul; i < size; ++i)
{
if (content[i] == '=')
if (content_[i] == '=')
{
if (!is_last_non_space_character_close_bracket)
equal_position_list.push_back(i);
equal_position_list_.push_back(i);
else
++inside_map;
if (inside_map == 1)
brace_position_list.pop_back(); // cancel the last opening brace.
brace_position_list_.pop_back(); // cancel the last opening brace.
}
else if (content[i] == '{')
brace_position_list.push_back(static_cast<int>(i));
else if (content[i] == '}')
else if (content_[i] == '{')
brace_position_list_.push_back(static_cast<int>(i));
else if (content_[i] == '}')
{
if (inside_map)
inside_map = 0;
else
brace_position_list.push_back(-static_cast<int>(i));
brace_position_list_.push_back(-static_cast<int>(i));
}
if (content[i] == ']')
if (content_[i] == ']')
is_last_non_space_character_close_bracket = true;
else if (content[i] == ' ')
else if (content_[i] == ' ')
;
else
is_last_non_space_character_close_bracket = false;
}
}
// If there are no '=' signs between braces, it is a vector... So remove it
std::cout << "TMP EQUAL POSITION = ";
Utilities::PrintContainer<>::Do(equal_position_list);
std::cout << "TMP BRACE POSITION = ";
Utilities::PrintContainer<>::Do(brace_position_list);
std::cout << "SIZES = " << content.size() << " ====== " << equal_position_list.size() << " and " << brace_position_list.size() << std::endl;
void ExtractKeysFromFile::ComputeEntryOrSectionNames()
{
// For each equal, grab the name beforehand (sections will be reconstructed later).
std::vector<NameAndPos> name_list;
for (auto equal_pos : equal_position_list)
for (auto equal_pos : equal_position_list_)
{
auto pos = equal_pos;
while (content[pos] == ' ' && pos > 0)
while (content_[pos] == ' ' && pos > 0)
--pos;
if (pos == 0)
{
oconv << "Unable to find name before the first equal sign in file " << path;
std::ostringstream oconv;
oconv << "Unable to find name before the first equal sign in file " << file_;
throw Exception(oconv.str(), __FILE__, __LINE__);
}
std::string name;
// Keep doing it while reconstruct the name backwards.
while (!std::isalnum(content[pos]) && pos > 0)
while (!std::isalnum(content_[pos]) && pos > 0)
--pos;
if (pos == 0)
{
oconv << "Unable to find name before the first equal sign in file " << path;
std::ostringstream oconv;
oconv << "Unable to find name before the first equal sign in file " << file_;
throw Exception(oconv.str(), __FILE__, __LINE__);
}
bool letter_already_read = false;
while (std::isalnum(content[pos]) && pos > 0)
while (std::isalnum(content_[pos]) && pos > 0)
{
if (letter_already_read && !std::isalpha(content[pos]))
if (letter_already_read && !std::isalpha(content_[pos]))
break;
if (std::isalpha(content[pos]))
if (std::isalpha(content_[pos]))
letter_already_read = true;
// Numeric are allowed at the end, but as soon a letter is met numeric are forbidden.
name.push_back(content[pos]);
name.push_back(content_[pos]);
--pos;
}
if (pos == 0)
name.push_back(content[pos]);
name.push_back(content_[pos]);
if (name.empty())
{
oconv << "Unable to figure out a variable name in file " << path;
std::ostringstream oconv;
oconv << "Unable to figure out a variable name in file " << file_;
throw Exception(oconv.str(), __FILE__, __LINE__);
}
std::reverse(name.begin(), name.end());
std::cout << "Name = |" << name << '|'<< std::endl;
NameAndPos name_and_pos;
name_and_pos.name = name;
name_and_pos.position = equal_pos;
name_list.push_back(name_and_pos);
entry_or_section_list_.emplace_back(EntryOrSection(name, equal_pos));
}
assert(name_list.size() == equal_position_list.size());
assert(entry_or_section_list_.size() == equal_position_list_.size());
std::cout << "TMP EQUAL POSITION = ";
Utilities::PrintContainer<>::Do(equal_position_list);
}
std::cout << "TMP BRACE POSITION = ";
Utilities::PrintContainer<>::Do(brace_position_list);
void ExtractKeysFromFile::Stuff()
{
if (!brace_position_list.empty()) // the emptiness case might happen for VERY simple cases...
if (!brace_position_list_.empty()) // the emptiness case might happen for VERY simple cases...
{
if (brace_position_list.front() < 0)
if (brace_position_list_.front() < 0)
{
oconv << "First brace found in the file " << path << " is a closing one!";
std::ostringstream oconv;
oconv << "First brace found in the file " << file_ << " is a closing one!";
throw Exception(oconv.str(), __FILE__, __LINE__);
}
if (brace_position_list.back() > 0)
if (brace_position_list_.back() > 0)
{
oconv << "Last brace found in the file " << path << " is an opening one!";
std::ostringstream oconv;
oconv << "Last brace found in the file " << file_ << " is an opening one!";
throw Exception(oconv.str(), __FILE__, __LINE__);
}
......@@ -333,15 +367,14 @@ namespace MoReFEM
std::vector<std::pair<int, int>> pair_list;
// [43, 57, -117, 131, 274, -312, -313, -315, 336, 350, -410, 424, 567, -605, -607, 624, 644, -648, -675, -676]
auto copy = brace_position_list;
auto copy = brace_position_list_;
while (!copy.empty())
{
if (copy.front() < 0)
{
oconv << "Unbalanced braces in file " << path;
std::ostringstream oconv;
oconv << "Unbalanced braces in file " << file_;
throw Exception(oconv.str(), __FILE__, __LINE__);
}
......@@ -377,7 +410,7 @@ namespace MoReFEM
const auto opening = pair.first;
const auto closing = pair.second;
for (const auto equal_pos : equal_position_list)
for (const auto equal_pos : equal_position_list_)
{
if (equal_pos > opening && equal_pos < closing)
{
......@@ -397,22 +430,21 @@ namespace MoReFEM
// There should be as many pair as there are names
assert (name_list.size() >= pair_list.size());
assert (entry_or_section_list_.size() >= pair_list.size());
// Each brace pair is associated to the closer equal before it.
const auto Npair = filtered_pair_list.size();
for (const auto& foo : name_list)
for (const auto& foo : entry_or_section_list_)
{
std::cout << "Name " << foo.name << " found relared to equal " << foo.position << std::endl;
std::cout << "Name " << foo.name << " found relared to equal " << foo.equal_position << std::endl;
}
std::vector<Section> section_list;
for (auto i = 0ul; i < Npair; ++i)
{
......@@ -420,14 +452,14 @@ namespace MoReFEM
// Using standard iterators instead of reverse ones as I want to use erase and conversion with
// normal iterators is shall we say headache prone...
auto it = name_list.end();
auto it = entry_or_section_list_.end();
--it;
auto end = name_list.begin();
auto end = entry_or_section_list_.begin();
--end;
for (; it != end; --it)
{
if (it->position < opening_brace)
if (it->equal_position < opening_brace)
break;
}
std::cout << it->name << "\n";
......@@ -439,43 +471,31 @@ namespace MoReFEM
section.max = filtered_pair_list[i].second;
section.name = it->name;
section_list.push_back(section);
std::cout << "PAIR " << opening_brace << " => lower = " << it->position << " and " << it->name << std::endl;
name_list.erase(it);
// std::cout << name_list[it - equal_position_list.cbegin()] << " -> ";
// Utilities::PrintTuple(pair_list[i]);
// std::cout << std::endl;
// equal_position_list.erase(it);
section_list_.push_back(section);
entry_or_section_list_.erase(it);
}
std::sort(section_list.begin(),
section_list.end(),
std::sort(section_list_.begin(),
section_list_.end(),
[](const auto& lhs, const auto& rhs)
{
return lhs.min < rhs.min;
});
}
// Reconstruct names.
std::vector<std::string> ExtractKeysFromFile::GetEntryKeyList() const
{
std::vector<std::string> ret;
for (const auto& name : name_list)
for (const auto& name : entry_or_section_list_)
{
std::ostringstream oconv;
oconv.str("");
for (const auto& section : section_list)
for (const auto& section : section_list_)
{
if (name.position > section.min && name.position < section.max)
if (name.equal_position > section.min && name.equal_position < section.max)
oconv << section.name << '.';
}
......@@ -487,21 +507,6 @@ namespace MoReFEM
}
std::string GenerateSectionNameFromHierarchy(const std::vector<std::string>& hierarchy,
const std::string& param_name)
{
std::ostringstream oconv;
for (const auto& item : hierarchy)
oconv << item << ".";
oconv << param_name;
return oconv.str();
}
} // namespace anonymous
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment