Reduce memory usage by omitting labels in normal parsers

Labels are only used to add meaningful text to states in Graphviz DOT
graphs.  But these strings can take lots of time and memory to generate
especially in large grammars like that for PostgreSQL.  Therefore only
generate labels when they will be used.
This commit is contained in:
Charles Baker 2023-05-28 16:21:19 +12:00 • committed by Charles Baker
parent c7eea3b698
commit 1f572973c3
3 changed files with 17 additions and 2 deletions

View file

@ -41,6 +41,7 @@ GrammarCompiler::GrammarCompiler()
, lexer_()
, whitespace_lexer_()
, parser_state_machine_()
, labels_enabled_{ false }
{
lexer_.reset( new RegexCompiler );
whitespace_lexer_.reset( new RegexCompiler );
@ -67,6 +68,11 @@ const ParserStateMachine* GrammarCompiler::parser_state_machine() const
return parser_state_machine_.get();
}
void GrammarCompiler::labels_enabled( bool enabled )
{
labels_enabled_ = enabled;
}
int GrammarCompiler::compile( const char* begin, const char* end, ErrorPolicy* error_policy )
{
Grammar grammar;
@ -239,7 +245,7 @@ void GrammarCompiler::populate_parser_state_machine( const Grammar& grammar, con
state->index = state_index;
state->length = grammar_state->count_valid_transitions();
state->transitions = &transitions[transition_index];
state->label = add_string( generator.label_state(*grammar_state) );
state->label = labels_enabled_ ? add_string( generator.label_state(*grammar_state) ) : nullptr;
if ( grammar_state == generator.start_state() )
{
start_state = state;

View file

@ -30,6 +30,7 @@ class GrammarCompiler
std::unique_ptr<RegexCompiler> lexer_; ///< Allocated lexer state machine.
std::unique_ptr<RegexCompiler> whitespace_lexer_; ///< Allocated whitespace lexer state machine.
std::unique_ptr<ParserStateMachine> parser_state_machine_; ///< Allocated parser state machine.
bool labels_enabled_; ///< True to generate labels for states and symbols.
public:
GrammarCompiler();
@ -37,6 +38,7 @@ public:
const RegexCompiler* lexer() const;
const RegexCompiler* whitespace_lexer() const;
const ParserStateMachine* parser_state_machine() const;
void labels_enabled( bool enabled );
int compile( const char* begin, const char* end, ErrorPolicy* error_policy = nullptr );
private:

View file

@ -135,7 +135,14 @@ int main( int argc, char** argv )
return EXIT_FAILURE;
}
// Enable state labels only when generating Graphviz DOT graphs
// because generating so many strings takes lots of time and memory.
GrammarCompiler compiler;
if ( dot )
{
compiler.labels_enabled( true );
}
ErrorPolicy error_policy;
int errors = compiler.compile( &grammar_source[0], &grammar_source[0] + grammar_source.size(), &error_policy );
if ( errors != 0 )
@ -344,7 +351,7 @@ void generate_cxx_parser_state_machine( const ParserStateMachine* state_machine
state->index,
state->length,
state->transitions->index,
sanitize( state->label ).c_str()
state->label ? sanitize( state->label ).c_str() : nullptr
);
}
write( " {-1, 0, nullptr}\n" );