Commit f30888a0 authored by Florent Jacquemard's avatar Florent Jacquemard
Browse files

define classes of stacks of runs (for parse table) - for push emplace

refactor Run Factory
bug in KeySIP RunsTerminal (dangling pointer) : MUST BE FIXED in other Keys
bugs with shared_from_this() : std::make_shared<...> must be used with public inheritance
parent eb8893c8
......@@ -1480,6 +1480,8 @@
43C6CF1425839F4E002BE3F5 /* PartEng.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = PartEng.hpp; sourceTree = "<group>"; };
43C7232F2362E2D800D5E20E /* DuraList.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DuraList.cpp; sourceTree = "<group>"; };
43C723302362E2D800D5E20E /* DuraList.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DuraList.hpp; sourceTree = "<group>"; };
43CBB2A62695B57D00208E9E /* RunStack.tpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; path = RunStack.tpp; sourceTree = "<group>"; };
43CBB2A72695B57E00208E9E /* RunStack.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = RunStack.hpp; sourceTree = "<group>"; };
43CDB7932577899500956DDF /* KeySIO.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = KeySIO.cpp; sourceTree = "<group>"; };
43CDB7942577899500956DDF /* KeySIO.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = KeySIO.hpp; sourceTree = "<group>"; };
43CEA93825EFD1E5007C355B /* ValueFile.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ValueFile.cpp; sourceTree = "<group>"; };
......@@ -2249,6 +2251,8 @@
430046F12604CF97000E9898 /* RunInner.tpp */,
434F406422FB198300C3940E /* RunRanked.hpp */,
434F406322FB198300C3940E /* RunRanked.tpp */,
43CBB2A72695B57E00208E9E /* RunStack.hpp */,
43CBB2A62695B57D00208E9E /* RunStack.tpp */,
433278E2260DC6CA00D6AD17 /* RunFactory.hpp */,
433278E1260DC6CA00D6AD17 /* RunFactory.tpp */,
431864B123099B5900940ECB /* RunCompare.hpp */,
......
......@@ -85,6 +85,7 @@ bool KeyS::operator==(const KeyS& k) const
return (k._state == _state);
}
bool KeyS::operator!=(const KeyS& k) const
{
return (! (*this == k));
......@@ -116,10 +117,10 @@ void KeyS::runs(StackInner<KeyS>& si,
}
std::shared_ptr<RunTerm> KeyS::failRun(const ParsingEnv& env) const
{
return RunFactory<KeyS>::failRun(*this, env);
}
//std::shared_ptr<RunTerm> KeyS::failRun(const ParsingEnv& env) const
//{
// return RunFactory<KeyS>::failRun(*this, env);
//}
// protected
......@@ -132,7 +133,7 @@ void KeyS::RunsTerminal(const Transition& t,
std::shared_ptr<RunTerm> r = std::make_shared<RunTerm>(t, 0); // length = 0
TRACE("NEW terminal run {} -> {} for {}", *r, *this, t);
st.push(std::make_pair(*this, r)); // this key is complete
st.emplace(*this, r); // this key is complete
}
......@@ -145,7 +146,7 @@ void KeyS::RunsInner(const Transition& t,
{
assert(State::isWTA(_state));
// generic method
RunFactory<KeyS>::innerRun(*this, t, si);
RunFactory<KeyS>::RunInnermk(*this, t, si);
}
......
......@@ -86,6 +86,7 @@ namespace parsing{
class KeyS
{
/// @todo use Curiously Recurring Template Pattern instead?
template<typename> friend class RunFactory;
public:
......@@ -166,10 +167,10 @@ public:
/// @return a pointer to a newly allocated fail run, with
/// - transition with dummy symbol, empty body, weight zero in the
/// domain of the base wta in the passed environment.
/// - fail symbol
/// - weight zero (in the domain of the base wta).
/// This returned run will answer succesfully to Run.fail().
std::shared_ptr<RunTerm> failRun(const ParsingEnv& env) const;
// - fail symbol
// - weight zero (in the domain of the base wta).
// This returned run will answer succesfully to Run.fail().
// std::shared_ptr<RunTerm> failRun(const ParsingEnv& env) const;
friend std::ostream& operator<<(std::ostream& o, const KeyS& k);
......
......@@ -315,7 +315,7 @@ void KeySI::RunsTerminal(const Transition& t,
// 0 or -1 point to read in interval
Weight w = terminalWeight(a, t, env);
size_t len = 0;
RunFactory<KeySI>::terminalRun(*this, t, a, w, len, st);
RunFactory<KeySI>::RunTermmk(*this, t, a, w, len, st);
}
}
/// one single offset point aligned to left bound of interval
......@@ -329,7 +329,7 @@ void KeySI::RunsTerminal(const Transition& t,
// 0 or -1 points to read
Weight w = terminalWeight(a, t, env);
size_t len = _interval->lsize();;
RunFactory<KeySI>::terminalRun(*this, t, a, w, len, st);
RunFactory<KeySI>::RunTermmk(*this, t, a, w, len, st);
}
}
/// all points aligned to left bound of interval
......@@ -342,7 +342,7 @@ void KeySI::RunsTerminal(const Transition& t,
// _interval->lsize() = gn + grace-rests + 1 notev or -1 points to read
Weight w = terminalWeight(a, t, env);
size_t len = _interval->lsize();
RunFactory<KeySI>::terminalRun(*this, t, a, w, len, st);
RunFactory<KeySI>::RunTermmk(*this, t, a, w, len, st);
}
}
/// double bar (end of score)
......@@ -354,7 +354,7 @@ void KeySI::RunsTerminal(const Transition& t,
// 0 or -1 point to read in interval
Weight w = terminalWeight(a, t, env);
assert(! w.unknown());
RunFactory<KeySI>::terminalRun(*this, t, a, w, 0, st);
RunFactory<KeySI>::RunTermmk(*this, t, a, w, 0, st);
}
}
else if (SymbLabel::dummy(a))
......@@ -382,7 +382,7 @@ void KeySI::RunsInner(const Transition& t,
assert(_interval);
// we do not divide empty intervals
if (_interval->inhabited())
RunFactory<KeySI>::innerRun(*this, t, si);
RunFactory<KeySI>::RunInnermk(*this, t, si);
}
else if (SymbLabel::grace(a))
{
......@@ -401,7 +401,7 @@ void KeySI::RunsInner(const Transition& t,
assert(SymbLabel::arity(a) == 2);
// end of input segment not reached (condition of termination)
if ((_interval->rduration() >= _barlen) || _interval->inhabited())
RunFactory<KeySI>::innerRun(*this, t, si);
RunFactory<KeySI>::RunInnermk(*this, t, si);
}
else
{
......
......@@ -460,7 +460,7 @@ void KeySIO::addTerminalRun(//const KeySIO& k,
const label_t& a = t.label();
Weight w = terminalWeight(a, t, env);
assert(! w.unknown());
RunFactory<KeySIO>::terminalRun(*this, t, a, w, n, st);
RunFactory<KeySIO>::RunTermmk(*this, t, a, w, n, st);
}
......@@ -563,7 +563,7 @@ void KeySIO::RunsInner(const Transition& t,
assert(_interval);
// we do not divide empty intervals
if (_interval->inhabited())
RunFactory<KeySIO>::innerRun(*this, t, si);
RunFactory<KeySIO>::RunInnermk(*this, t, si);
else
TRACE("RunsInner: empy interval, do not divide {}", *this);
}
......@@ -584,7 +584,7 @@ void KeySIO::RunsInner(const Transition& t,
assert(SymbLabel::arity(a) == 2);
assert(_interval);
if ((_interval->rduration() >= _barlen) || _interval->inhabited())
RunFactory<KeySIO>::innerRun(*this, t, si);
RunFactory<KeySIO>::RunInnermk(*this, t, si);
else
TRACE("RunsInner: do not add bar (fine) {}", *this);
}
......
......@@ -248,14 +248,12 @@ void KeySIP::runs(StackInner<KeySIP>& si,
void KeySIP::RunsTerminal(const Transition& t,
StackTerm<KeySIP>& st,
// std::stack<std::pair<const KeySIP*, RunTerm*>>& st,
const ParsingEnv& env) const
{
assert(P_KNOWN(_pre));
assert(_interval);
const label_t& a = t.label();
assert(SymbLabel::terminal(a));
const KeySIP* knew = nullptr;
if (! _interval->aligned())
{
......@@ -266,23 +264,41 @@ void KeySIP::RunsTerminal(const Transition& t,
_interval->align(env.segment);
}
// this key is complete
if (P_KNOWN(_post))
{
WARN("KeySIP : instance as leaf of complete key {}", *this);
if (_post == _interval->rsize())
{
knew = this;
RunsTerminalComplete(t, st, env);
}
else
{
ERROR("KeySIP : error in complete key {}", *this);
return;
}
}
// this key is partial
else
{
//copy with _post = _interval->rsize();
knew = new KeySIP(*this, _interval->rsize());
KeySIP knew(*this, _interval->rsize());
assert(knew.complete());
knew.RunsTerminalComplete(t, st, env);
}
assert(knew);
assert(P_KNOWN(knew->_post));
}
void KeySIP::RunsTerminalComplete(const Transition& t,
StackTerm<KeySIP>& st,
const ParsingEnv& env) const
{
assert(P_KNOWN(_pre));
assert(P_KNOWN(_post));
assert(_interval);
const label_t& a = t.label();
assert(SymbLabel::terminal(a));
/// filter term label
if (SymbLabel::note(a) || SymbLabel::rest(a) ||
......@@ -295,31 +311,29 @@ void KeySIP::RunsTerminal(const Transition& t,
size_t n = SymbLabel::nbEvents(a);
if (n == _pre + _interval->lsize())
{
Weight w = knew->terminalWeight(a, t, env);
Weight w = terminalWeight(a, t, env);
assert(! w.unknown());
// n points = grace-notes + grace-rests + 1 note or -1
RunFactory<KeySIP>::terminalRun(*knew, t, a, w, n, st);
RunFactory<KeySIP>::RunTermmk(*this, t, a, w, n, st);
}
}
/// double bar (end of score)
else if (SymbLabel::bar(a) && (SymbLabel::arity(a) == 0))
{
TRACE("KeySIP: terminal bar interval: {} ({}aligned) for transition {}",
*(_interval),
((! _interval->aligned())?"not ":""),
t);
*(_interval), ((! _interval->aligned())?"not ":""), t);
// && (DBL_APPROX_EQUAL(_interval->rend(), _interval->rbegin()))
if ((_interval->rduration() < _barlen) && (! _interval->inhabited()))
{
Weight w = knew->terminalWeight(a, t, env);
Weight w = terminalWeight(a, t, env);
assert(! w.unknown());
// 0 or -1 point to read in interval
RunFactory<KeySIP>::terminalRun(*knew, t, a, w, 0, st);
RunFactory<KeySIP>::RunTermmk(*this, t, a, w, 0, st);
}
}
else if (SymbLabel::dummy(a))
{
ERROR("KeySIP: dummy symbol unexpected");
ERROR("KeySIP: unexpected dummy symbol");
}
else
{
......@@ -403,7 +417,7 @@ void KeySIP::RunsInner(const Transition& t,
assert(_interval);
// we do not divide empty intervals
if (_interval->inhabited())
RunFactory<KeySIP>::innerRun(*this, t, si);
RunFactory<KeySIP>::RunInnermk(*this, t, si);
}
else if (SymbLabel::grace(a))
{
......@@ -422,7 +436,7 @@ void KeySIP::RunsInner(const Transition& t,
assert(SymbLabel::arity(a) == 2);
assert(_interval);
if ((_interval->rduration() >= _barlen) || _interval->inhabited())
RunFactory<KeySIP>::innerRun(*this, t, si);
RunFactory<KeySIP>::RunInnermk(*this, t, si);
else
TRACE("RunsInner: do not add bar (fine) {}", *this);
}
......
......@@ -194,7 +194,13 @@ private:
/// @brief copy and instanciate. for internal use.
KeySIP(const KeySIP& k, pre_t post);
/// add to the given stack some terminal runs built from the given transition.
/// @param t transition to build terminal runs. must be terminal and complete.
/// @param st a stack to be filled with pairs containing terminal runs.
/// @warning this key must be complete
virtual void RunsTerminalComplete(const Transition& t,
StackTerm<KeySIP>& st,
const ParsingEnv& env) const;
};
......
......@@ -276,7 +276,7 @@ void KeySV::RunsTerminal(const Transition& t,
(_list.event())?"(event)":"");
Weight w = t.weight();
size_t len = 0;
RunFactory<KeySV>::terminalRun(*this, t, a, w, len, st);
RunFactory<KeySV>::RunTermmk(*this, t, a, w, len, st);
}
}
// case of single event (no grace notes, no continuation)
......@@ -292,7 +292,7 @@ void KeySV::RunsTerminal(const Transition& t,
(_list.event())?"(event)":"");
Weight w = t.weight();
size_t len = 1;
RunFactory<KeySV>::terminalRun(*this, t, a, w, len, st);
RunFactory<KeySV>::RunTermmk(*this, t, a, w, len, st);
}
}
// case of 1 note and grace notes (no continuation)
......@@ -308,7 +308,7 @@ void KeySV::RunsTerminal(const Transition& t,
(_list.event())?"(event)":"");
Weight w = t.weight();
size_t len = _list.nbevent();
RunFactory<KeySV>::terminalRun(*this, t, a, w, len, st);
RunFactory<KeySV>::RunTermmk(*this, t, a, w, len, st);
}
}
// case of double bar (end of score)
......@@ -321,7 +321,7 @@ void KeySV::RunsTerminal(const Transition& t,
_list, t);
Weight w = t.weight();
size_t len = 0;
RunFactory<KeySV>::terminalRun(*this, t, a, w, len, st);
RunFactory<KeySV>::RunTermmk(*this, t, a, w, len, st);
}
}
else if (SymbLabel::dummy(a))
......@@ -352,7 +352,7 @@ void KeySV::RunsInner(const Transition& t,
{
// we do not divide empty intervals
if (! _list.empty())
RunFactory<KeySV>::innerRun(*this, t, si);
RunFactory<KeySV>::RunInnermk(*this, t, si);
}
else if (SymbLabel::grace(a))
{
......@@ -373,7 +373,7 @@ void KeySV::RunsInner(const Transition& t,
{
DEBUGU("KeySV: binary bar interval: {} for transition {}",
_list, t);
RunFactory<KeySV>::innerRun(*this, t, si);
RunFactory<KeySV>::RunInnermk(*this, t, si);
}
}
else
......
......@@ -5,13 +5,16 @@
// Created by Florent Jacquemard on 26/03/2021.
// Copyright © 2021 Florent Jacquemard. All rights reserved.
//
/// @addtogroup parsing
/// @{
#ifndef RunFactory_hpp
#define RunFactory_hpp
#include <stdio.h>
#include <iostream>
#include <memory>
#include <memory> // shared_ptr
#include <assert.h>
#include <stack>
//#include <queue>
......@@ -24,18 +27,10 @@
#include "Runey.hpp"
#include "RunInner.hpp"
#include "RunTerm.hpp"
#include "RunStack.hpp"
namespace parsing{
/// type of stack of terminal runs with key of type K
template<class K> using StackTerm =
std::stack<std::pair<const K&, std::shared_ptr<RunTerm>>>;
/// type of stack of inner runs with key of type K
template<class K> using StackInner =
std::stack<std::shared_ptr<RunInner<K>>>;
/// methods for the generation of runs common to several key classes KeyX.
/// Every Run object represents an augmented transition built by extension of
/// - a transitios of a base WTA, for the parsing inside a bar, or
......@@ -81,7 +76,7 @@ public:
ParsingEnv& env);
/// add to the stacks runs corresponding to the extension
/// of a base WTA transition.
/// of a base WTA transition from the given parsing environment.
/// @param si a stack to be filled with inner runs.
/// @param st a stack to be filled with pairs containing terminal runs.
/// @param env parsing environment, containing a wta.
......@@ -91,7 +86,7 @@ public:
const ParsingEnv& env);
/// construct base "over-the-bar transitions" (nullary and binary),
/// extend them and add them to the stacks.
/// extend them and add new associated runs to the stacks.
static void runsBar(const K& k,
StackInner<K>& si,
StackTerm<K>& st,
......@@ -107,12 +102,12 @@ public:
/// see RunTerm.
/// @param st a stack to be filled with pairs containing terminal runs.
/// @warning default case only for complete keys.
static void terminalRun(const K& k,
const Transition& t,
label_t lab,
const Weight& w,
size_t len,
StackTerm<K>& st);
static void RunTermmk(const K& k,
const Transition& t,
label_t lab,
const Weight& w,
size_t len,
StackTerm<K>& st);
/// generic method adding to the given stack one inner runs built from the
/// given transition.
......@@ -122,9 +117,9 @@ public:
/// @param si a stack to be filled with inner runs.
/// @warning the runs constructed are added to the given stack.
/// They must be deallocate elsewhere.
static void innerRun(const K& k,
const Transition& t,
StackInner<K>& si);
static void RunInnermk(const K& k,
const Transition& t,
StackInner<K>& si);
/// unique outside-the-bar base transition or given arity
/// targeting the embedded state.
......@@ -146,16 +141,15 @@ public:
/// @todo delete, replaced by barTransition
static const Transition& barTransition2(state_t state, ParsingEnv& env);
/// allocate and return a special Run representing a parse failure for this key.
/// @param env parsing environment.
/// @return a pointer to a newly allocated FAIL run, with
/// - transition with dummy symbol, empty body, weight zero in the
/// domain of the base wta in the passed environment.
/// - fail symbol
/// - weight zero (in the domain of the base wta).
/// This returned run will answer succesfully to Run.fail().
static std::shared_ptr<RunTerm> failRun(const K& k,
const ParsingEnv& env);
// allocate and return a special Run representing a parse failure for this key.
// @param env parsing environment.
// @return a pointer to a newly allocated FAIL run, with
// - transition with dummy symbol, empty body, weight zero in the
// domain of the base wta in the passed environment.
// - fail symbol
// - weight zero (in the domain of the base wta).
// This returned run will answer succesfully to Run.fail().
// static std::shared_ptr<RunTerm> failRun(const ParsingEnv& env);
private:
......
......@@ -95,19 +95,17 @@ void RunFactory<K>::runsBar(const K& k,
const Transition& t2 = barTransition(k.state(), 2, env);
// let the key class extend this transition and add extension to stack
k.RunsInner(t2, si, env);
// innerRuns(k, t2, si);
}
// default
template<class K>
void RunFactory<K>::terminalRun(const K& k,
const Transition& t,
label_t a,
const Weight& w,
size_t len,
StackTerm<K>& st)
// std::stack<std::pair<const K*, RunTerm*>>& st)
void RunFactory<K>::RunTermmk(const K& k,
const Transition& t,
label_t a,
const Weight& w,
size_t len,
StackTerm<K>& st)
{
assert(k.complete()); // ONLY FOR COMPLETE KEY !
assert(t.arity() == SymbLabel::arity(a));
......@@ -117,22 +115,23 @@ void RunFactory<K>::terminalRun(const K& k,
WARN("RunFactory: weight zero for term. transition {}, skip", t);
return;
}
// new terminal run
std::shared_ptr<RunTerm> r = std::make_shared<RunTerm>(t, a, w, len);
TRACE("NEW terminal run {} -> {} for {}", *r, k, t);
st.push(std::make_pair(k, r)); // key k is complete
TRACE("NEW terminal run {} -> {} for transition {}", *r, k, t);
st.emplace(k, r); // key k is complete
}
template<class K>
void RunFactory<K>::innerRun(const K& k,
const Transition& t,
StackInner<K>& si)
//std::stack<RunInner<K>*>& si)
void RunFactory<K>::RunInnermk(const K& k,
const Transition& t,
StackInner<K>& si)
//std::stack<RunInner<K>*>& si)
{
assert(t.inner());
assert(t.arity() == SymbLabel::arity(t.label()));
std::shared_ptr<RunInner<K>> r = std::make_shared<RunInner<K>>(t);
TRACE("NEW empty inner run {} -> {} for {}", *r, k, t);
TRACE("NEW empty inner run {} -> {} for transition {}", *r, k, t);
assert(r->arity() == t.arity());
assert(r->size() == 0);
assert(r->label() == t.label());
......@@ -271,20 +270,18 @@ const Transition& RunFactory<K>::barTransition2(state_t state, ParsingEnv& env)
}
template<class K>
std::shared_ptr<RunTerm> RunFactory<K>::failRun(const K& k,
const ParsingEnv& env)
{
assert(env.wta);
const Transition& t0 = env.dummyTransition_zero();
assert(t0.weight().is_zero());
size_t length = 0; // number of input symbols parsed
label_t a = SymbLabel::make_fail(length);
std::shared_ptr<RunTerm> r =
std::make_shared<RunTerm>(t0, a, t0.weight(), length);
return r;
}
//template<class K>
//std::shared_ptr<RunTerm> RunFactory<K>::failRun(const ParsingEnv& env)
//{
// assert(env.wta);
// const Transition& t0 = env.dummyTransition_zero();
// assert(t0.weight().is_zero());
// size_t length = 0; // number of input symbols parsed
// label_t a = SymbLabel::make_fail(length);
// std::shared_ptr<RunTerm> r =
// std::make_shared<RunTerm>(t0, a, t0.weight(), length);
// return r;
//}
} // end namespace parsing
//
// RunStack.hpp
// squant2
//
// Created by Florent Jacquemard on 07/07/2021.
// Copyright © 2021 Florent Jacquemard. All rights reserved.
//
/// @addtogroup parsing
/// @{
#ifndef RunStack_hpp
#define RunStack_hpp
#include <stdio.h>
#include <iostream>
#include <memory> // shared_ptr
#include <assert.h>
#include <stack>
//#include <queue>
//#include "RunTerm.hpp"
namespace parsing{
class RunTerm;
/// pair made of a complete terminal run and its target,
/// a complete key of type K.
template<class K>
class RunTermTargeted
{
public:
/// @param k target of run
/// @param r pointer to run, must be non-null.
RunTermTargeted(const K& k, std::shared_ptr<RunTerm> r);
inline const K& target() const { return _target; }
inline std::shared_ptr<RunTerm> run() const { return _run; }
private:
const K _target;
std::shared_ptr<RunTerm> _run;
};
/// type of temporary stack of terminal runs with key of type K
template<class K> using StackTerm =
std::stack<RunTermTargeted<K>>;
//std::stack<std::pair<const K&, std::shared_ptr<RunTerm>>>;
/// type of temporary stack of inner runs with key of type K
template<class K> using StackInner = std::stack<std::shared_ptr<RunInner<K>>>;
} // end namespace parsing
// separated definition of template class
#include "RunStack.tpp"
</