From 77da1ae28c6e0dfbbd1c5b989d1c5c6f95b0728a Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Wed, 6 Sep 2023 15:05:42 +0300 Subject: [PATCH] Refactor handling of actions in Loader Auxiliary loaders now work with the binary format and the flow control structures are more clear in general. --- source/loader.cpp | 45 ++++++++++++++++++++++++++++--------------- source/loader.h | 4 +++- source/loaderaction.h | 9 +++++++++ 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/source/loader.cpp b/source/loader.cpp index 7e910b8..8f443c3 100644 --- a/source/loader.cpp +++ b/source/loader.cpp @@ -1,3 +1,4 @@ +#include #include #include #include "except.h" @@ -92,15 +93,16 @@ void Loader::load_direct(Parser &p, unsigned l) if(!key) break; - LoaderAction *act = find_action(*key); - if(act) + if(LoaderAction *act = find_action(*key)) { SetFlag set_direct(direct); if(!p.parse_and_load(l, *this, *act)) throw logic_error("direct load failed"); } + else if(Loader *ldr = find_auxiliary_loader(*key)) + ldr->load_direct(p, l); else - load_statement(p.parse()); + unrecognized(*key); } } @@ -112,21 +114,17 @@ void Loader::load_statement(const Statement &st) { StatementKey key(st.keyword, st.get_signature()); - if(!aux_loaders.empty() && !has_action(key)) - { - for(Loader *l: aux_loaders) - if(l->has_action(key)) - return l->load_statement(st); - } - - LoaderAction *act = find_action(key); - if(act) + if(LoaderAction *act = find_action(key)) { sub_loaded = false; act->execute(*this, st); if(check_sub_loads && !st.sub.empty() && !sub_loaded) throw logic_error("substatements ignored"); } + else if(Loader *ldr = find_auxiliary_loader(key)) + ldr->load_statement(st); + else + unrecognized(key); } catch(const data_error &e) { @@ -174,7 +172,7 @@ void Loader::add(const string &kwd, LoaderAction *act) if(!actions) actions = &local_actions; - StatementKey key(kwd, (act ? act->get_signature() : "*")); + StatementKey key(kwd, act->get_signature()); ActionMap::iterator i = actions->find(key); if(i!=actions->end()) { @@ -211,7 +209,7 @@ LoaderAction *Loader::find_action(const StatementKey &key) const auto end = actions->upper_bound(StatementKey(key.keyword, "~")); if(begin==end) - throw unknown_keyword(key.keyword); + return nullptr; LoaderAction *act = nullptr; int match = 0; @@ -225,10 +223,25 @@ LoaderAction *Loader::find_action(const StatementKey &key) const } } - if(!match) + return act; +} + +Loader *Loader::find_auxiliary_loader(const StatementKey &key) const +{ + auto i = find_if(aux_loaders, [&key](Loader *l){ return l->has_action(key); }); + return (i!=aux_loaders.end() ? *i : nullptr); +} + +void Loader::unrecognized(const StatementKey &key) const +{ + if(!actions) + throw logic_error("no actions"); + + auto i = actions->lower_bound(StatementKey(key.keyword, string())); + if(i!=actions->end() && i->first.keyword==key.keyword) throw invalid_signature(key.keyword, key.signature); - return act; + throw unknown_keyword(key.keyword); } const string &Loader::get_source() const diff --git a/source/loader.h b/source/loader.h index 5b96cb0..59ebc23 100644 --- a/source/loader.h +++ b/source/loader.h @@ -135,7 +135,7 @@ protected: /** Adds a keyword that is recognized but ignored. */ void add(const std::string &k) - { add(k, nullptr); } + { add(k, new LoaderDiscard); } private: void add(const std::string &, LoaderAction *); @@ -146,6 +146,8 @@ protected: private: bool has_action(const StatementKey &) const; LoaderAction *find_action(const StatementKey &) const; + Loader *find_auxiliary_loader(const StatementKey &) const; + void unrecognized(const StatementKey &) const; protected: /** Returns the source of the statement being processed. This can be used diff --git a/source/loaderaction.h b/source/loaderaction.h index 9e08dac..0c56eab 100644 --- a/source/loaderaction.h +++ b/source/loaderaction.h @@ -37,6 +37,15 @@ public: }; +class LoaderDiscard: public LoaderAction +{ +public: + void execute(Loader &, const Statement &) const override { } + void execute(Loader &, const ArgumentStore &) const override { } + std::string get_signature() const override { return "*"; }; +}; + + /** Loads a statement by calling a function that takes no arguments. */ -- 2.45.2