tryParseKeyword and createRawKeyword don't use anything non-public and
does not rely on any non-public parser state, so they are now
implemented as functions private/static in Parser.cpp
A getline implementation that carries mostly the same assumptions as
istream::getline. Requires ParserState::done() to always be checked (for
negative) to safely retrieve the next line.
Enables tryParseKeywords and friend to only maintain a high level view
of the parsing procedure, and not deal with stream positioning.
Moves the storage/lifetime components of ParserState into its own
helper utility class. Splits the implementation responsibility so that
all input data and state is handled by the InputStack, and "global"
information is managed directly by ParserState.
Perform a pre-pass over the input and remove everything that isn't
interesting. Preserves empty lines to provide accurate line number for
diagnostics/error output.
The use of string_view for keys allows comparison with keywords from the
file buffers to be compared directly, instead of having to go via
std::string. This removes the need for a series of (inherently)
unecessary copies.
Several inner parser functions modified to use string_view, to reduce
unecessary copying (and indirectly allocationg) related to passing
strings around.
Replaces the parser's dependence on streams with string_view, which
won't copy to its internal buffers. Involves hand-rolling std::getline
for string_view to preserve stream-like behaviour.
Replaces the external stream-support by reading the entire contents of
input files at once, rather than lazily through streams. Uses
stringstreams internally, but keeps the entire file in memory through
std::string
openString/File has been renamed to loadString/File
Rewrites ParseState to use an explicit stack of open file streams
instead of spawning multiple ParseState objects. While recursion is
*the* most elegant to solve a typical include-file system, the global
nature of eclipse declarations make this clumsy (at best). Instead,
maintain an explicit stack of open files and logically parse the input
as if it was all concatenated into one large file.
Also adds some convenient ways of accessing the current (and
interesting) top of the stack.
Restructures createRawKeyword to use multiple return statements over
if-else and updating variables, reducing indentation to have fewer
contemporary branches.
Changes the control flow of Parser::createRawKeyword to return on
failing to meet preconditions, rather than if-else block. Reduces
indentation and concurrent code paths.
Makes the actual effects of the various condtions more clear by
emphasising the return of the function rather than some possible action
after the loop.
Restructures the per-iteration check of whether or not to continue
parsing to happen first and be an early-break, instead of this flow
being handled by if-else.
The implementation has been rewritten to use iterators and renamed for
internal use. The public static function still exists for testability
and easy verification, but should be considered an internal part of the
parser.
The const_cast in Deck::get*UnitSystem are potentially undefined
behaviour under a series of (plausible) conditions, and are deprecated
in favour of mutable members. Removes initUnitSystem from the public
interface, as the initialisation is handled on the first getUnitSystem
anyway, cleaning up the Deck interface slightly.
Adds proper constness to the use of unit systems that don't actually
modify the internal state in any way.
The general loop through all raw records should be based on the iterator
interface of the RawKeyword, but to resolve INCLUDE statements we have
implemented a special case method to get the first record.
Since RawRecords now has automatic storage, managed by std::list,
offering iterators is feasible. The random access
RawKeyword::getRecord's real use was accessing the records in order,
which now is handled via iterators.
The accumulated strings are moved into RawRecords, which reduces
execution time (rough measurements indicates 4-8%). To facilitate this,
RawRecords are stored directly in the vector in favour of via
shared_ptrs.
boost::trim_right loses a lot of performance from being locale aware.
Since this is not a problem for our ASCII fortran-type files, ignore
this issue and use isspace for trimming.
Modifies RawRecord to internally use string_view instead of copies of
the substrings. This *vastly* reduces copying in the processing of each
record and subsequently improves performance. Reduces total memory usage
in Deck construction.
ECLIPSE resolves path aliases defined in an included file globally, i.e.
/
|> include.inc
|-- PATHS 'alias' 'path/to/dir'
|> main.data
|-- INCLUDE 'include.inc' /
| [...]
|-- INCLUDE '$alias/file.inc' /
will resolve as 'path/to/dir/file.inc'. This behaviour is now adopted by
opm-parser.
Removes shared_ptr< ParserKeyword > exchange in Parser interface and
replaces it with unique_ptr storage and raw pointers for return values.
This has some implications:
* addParserKeyword() no longer takes shared_ptr<>, but unique_ptr&&
addParserKeyword has been modified to create unique_ptr instead of
shared_ptr.
* generated-source/ParserKeyword* no longer use make_shared which had a
-massive- impact on compile times, which are now more-or-less
trivialised (on my machine: 7.5s -> 1s per file). This because the
compiler no longer generates a bunch of forwarding make_shared
instances of subclasses that are immediately thrown away, but rather
uses an inline make_unique that instantiates the -parent- class
unique_ptr.
The completely constructed Deck isn't supposed to have any relationship
with the Parser structures (which are completely stateless in terms of
input data), and ParserKeyword in DeckKeyword was an anomaly. With
recent refactorings this lead to subtle lifetime issues.
This patch breaks this dependency and cleans up DeckKeyword accordingly,
while changing checkDeck to now take the parser as an additional
argument, to look up whether or not some DeckKeyword is in the right
section. This now also means that Parser* objects can be destroyed once
the Deck is created.
The Section::checkSectionTopology has been moved to Parser.cpp. It is a
temporary home for the feature to make the project compile nicely (i.e.
createKeywordList can be compiled as before, without introducing a
circular dependency on itself via Parser.cpp), until some proper cleanup
of the parser code has been done. It never really fully belonged in
Section.cpp anyway, so this is a first step in the direction of some
slight renaming.
Since the Deck* family of classes have changed their interfaces to no
longer use shared_ptr, a lot of code broke. This patch fixes all
problems in tests, other signatures and accesses to now use the new Deck
interfaces.
Every header is self-contained and includes only what it must to
function, relying on users include what they need in source files,
adopting a pay-what-you-use model (in particular for internal
dependencies).
This is an effort to improve build performance. Several includes
scattered across the project are either unused or partially used (i.e.
just used to import a type name, not depending on the actual contents of
the header file).
Replaces a lot of these includes with forward declarations.