added: FunInfo<>::fun_data

now we have a pointer to FunData struct
         by default the pointer is null
         you can create an object of a class derived from FunData
         an set the pointer to the object
         those pointers will be kept on the [for] stack
         and will be auto removed
         (not finished yet -- need some testing)
added:   to FunInfo<>::
         bool is_if;
         bool is_is;
         bool is_normal;
         bool is_filter;
removed: from FunInfo<>:
         bool is_for_first_iter;
changed: in FunInfo<>:
         int iter -> size_t iter
         now it indicates the number of a current iteration for the [for] statement 
         for other statements than [for] this is always zero
         (the same old behaviour as before revision 331)
added:   in FunInfo<>:
         size_t last_iter
         it indicates the number of a previous [for] iteration
         for a [for] it returns not the current iterator but a value from a previous [for]



git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@391 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Tomasz Sowa 2012-02-24 12:04:36 +00:00
parent 4480268172
commit 8e85a398d6
2 changed files with 161 additions and 35 deletions

View File

@ -47,6 +47,19 @@
namespace Ezc
{
struct FunData
{
FunData()
{
}
virtual ~FunData()
{
}
};
template<class StreamType>
struct FunInfo
@ -75,21 +88,47 @@ struct FunInfo
// indicates that this function is from [for ...] statement
bool is_for;
// indicates that this function is from [for ...] statement
// and this is a first iteration (iter=0 too)
// this is only for convenience -- you don't have to check is_for and iter==0
// !! may a better name?
bool is_for_first_iter;
// indicates that this function is from [if ...] statement
// is true for all kind of if's: if-one, if-any, if-no....
bool is_if;
// indicates that this function is from [is ...] or [is-no ...] statements
bool is_is;
// indicates that this funcion is a normal statement e.g.: [funcion_name]
bool is_normal;
// indicates that this function is from a filter statement [filter ...]
bool is_filter;
// a pointer to FunData struct
// !! IMPROVE ME
// !! give some info here
// can be null
FunData * fun_data;
FunData * last_fun_data;
// this is set by Generator
// it indicates the number of a current iteration in the last [for] statement (the first is 0)
// it indicates the number of a current iteration for the [for] statement (the first iteration is 0)
// if there was not any [for] before the value is zero
int iter;
// for other statements than [for] this is always zero
size_t iter;
// this is set by Generator
// it indicates the number of a previous [for] iteration
// if there was not any [for] before the value is zero
// for a [for] it returns not the current iterator but a value from a previous [for]
size_t last_iter;
// return value from a user function (default false if not set directly by the user function)
// for a variable it is set to true if the variable is not empty
bool res;
// arguments: output_stream, table_of_parameters, the_first_parameter
FunInfo(StreamType & o,
std::vector<std::wstring> & pars,
@ -99,13 +138,20 @@ struct FunInfo
Clear();
}
void Clear()
{
res = false; // result is false by default
is_for = false;
is_for_first_iter = false;
iter = 0;
case_sensitive = true;
res = false; // result is false by default
is_for = false;
is_if = false;
is_is = false;
is_normal = false;
is_filter = false;
iter = 0;
last_iter = 0;
case_sensitive = true;
fun_data = 0;
last_fun_data = 0;
}
};

View File

@ -63,7 +63,7 @@ public:
~Generator();
void SetMax(int max_items_, int max_for_items_);
void SetMax(size_t max_items_, size_t max_for_items_);
// recognizing some special characters in text patterns (item_text in Patterns)
// \r will be a carriage return (13)
@ -106,9 +106,9 @@ private:
std::wstring temp_msg;
bool break_generating;
int current_item;
int max_items;
int max_for_items;
size_t current_item;
size_t max_items;
size_t max_for_items;
bool special_chars;
bool trim_white;
bool skip_new_line;
@ -132,8 +132,12 @@ private:
// true if this Generator is working now
bool is_generator_working;
// true if the Generator is working with [for ...] statement
// true if the Generator is working with [for ...], [if ...] etc.
bool is_generating_for;
bool is_generating_if;
bool is_generating_is;
bool is_generating_normal;
bool is_generating_filter;
// an empty string for FunInfo objects
// when there is no any parameters
@ -143,7 +147,14 @@ private:
// currently only one item (iterator)
struct StackItem
{
int iter;
size_t iter;
FunData * fun_data;
StackItem()
{
iter = 0;
fun_data = 0;
}
};
// a stack for [for] statements
@ -152,6 +163,7 @@ private:
void ResizeFilterTab();
void ClearFilterTab();
void ClearForStack();
void ClearStream(StreamType & str);
template<class CharType>
@ -179,7 +191,7 @@ private:
void PrintNormalText(const wchar_t * start, const wchar_t * end);
void TrimWhite(const wchar_t *& start, const wchar_t *& end);
void SkipWhite(const wchar_t *& str);
int StrToInt(const wchar_t * str, const wchar_t ** str_end);
size_t StrToSize(const wchar_t * str, const wchar_t ** str_end);
void CreateMsg(StreamType & out, const wchar_t * type, const wchar_t * arg = 0);
void CreateMsg(const wchar_t * type, const wchar_t * arg = 0);
@ -257,7 +269,10 @@ Generator<StreamType> & Generator<StreamType>::operator=(const Generator<StreamT
skip_new_line = n.skip_new_line;
// don't copy filter tab
filter_tab.clear();
ClearFilterTab();
// don't copy [for] stack
ClearForStack();
// don't copy 'is_generator_working' flag
is_generator_working = false;
@ -271,6 +286,7 @@ template<class StreamType>
Generator<StreamType>::~Generator()
{
ClearFilterTab();
ClearForStack();
}
@ -305,6 +321,16 @@ void Generator<StreamType>::ClearFilterTab()
}
template<class StreamType>
void Generator<StreamType>::ClearForStack()
{
for(size_t i=0 ; i<stack_tab.size() ; ++i)
delete stack_tab[i].fun_data;
stack_tab.clear();
}
template<class StreamType>
void Generator<StreamType>::ClearStream(StreamType & str)
{
@ -362,7 +388,7 @@ bool Generator<StreamType>::AreStreamsEqual(StreamType & str1, StreamType & str2
template<class StreamType>
void Generator<StreamType>::SetMax(int max_items_, int max_for_items_)
void Generator<StreamType>::SetMax(size_t max_items_, size_t max_for_items_)
{
max_items = max_items_;
max_for_items = max_for_items_;
@ -415,7 +441,7 @@ void Generator<StreamType>::Generate(StreamType * o, Pattern * p, Functions<Stre
break_generating = false;
current_item = 0;
stack_tab.clear();
ClearForStack();
ResizeFilterTab();
filter_index = 0;
@ -490,13 +516,31 @@ void Generator<StreamType>::Call(typename Functions<StreamType>::Function * func
{
info.Clear();
if( stack_tab.empty() )
info.iter = 0;
else
info.iter = stack_tab.back().iter;
info.is_for = is_generating_for;
info.is_if = is_generating_if;
info.is_is = is_generating_is;
info.is_normal = is_generating_normal;
info.is_filter = is_generating_filter;
info.is_for = is_generating_for;
info.is_for_first_iter = (info.is_for && info.iter == 0);
if( info.is_for )
{
if( !stack_tab.empty() )
info.iter = stack_tab.back().iter;
if( stack_tab.size() >= 2 )
info.last_iter = stack_tab[stack_tab.size()-2].iter;
}
else
{
if( !stack_tab.empty() )
info.last_iter = stack_tab.back().iter;
}
if( !stack_tab.empty() )
info.fun_data = stack_tab.back().fun_data;
if( stack_tab.size() >= 2 )
info.last_fun_data = stack_tab[stack_tab.size()-2].fun_data;
if( function->type == Functions<StreamType>::function )
{
@ -508,6 +552,22 @@ void Generator<StreamType>::Call(typename Functions<StreamType>::Function * func
info.res = !function->variable.empty();
}
if( info.fun_data )
{
if( !stack_tab.empty() )
{
if( stack_tab.back().fun_data != info.fun_data )
{
delete stack_tab.back().fun_data;
stack_tab.back().fun_data = info.fun_data;
}
}
else
{
delete info.fun_data;
}
}
last_res = info.res;
last_case_sensitive = info.case_sensitive;
}
@ -699,12 +759,13 @@ void Generator<StreamType>::SkipWhite(const wchar_t *& str)
template<class StreamType>
int Generator<StreamType>::StrToInt(const wchar_t * str, const wchar_t ** str_end)
size_t Generator<StreamType>::StrToSize(const wchar_t * str, const wchar_t ** str_end)
{
int res = 0;
size_t res = 0;
SkipWhite(str);
// !! IMPROVE ME
// overflow is not checked
while( *str>='0' && *str<='9' )
@ -797,6 +858,7 @@ void Generator<StreamType>::MakeTextNormal(Item & item)
if( item.functions.size() != 1 )
return;
is_generating_normal = true;
Call(item.functions[0], *output_stream, false);
}
@ -826,6 +888,8 @@ void Generator<StreamType>::MakeTextIf(Item & item)
if( item.functions.size() != 1 )
return;
is_generating_if = true;
if( !Call(item.functions[0]) )
return;
@ -839,6 +903,8 @@ void Generator<StreamType>::MakeTextIfno(Item & item)
if( item.functions.size() != 1 )
return;
is_generating_if = true;
if( !Call(item.functions[0]) )
return;
@ -852,6 +918,8 @@ void Generator<StreamType>::MakeTextIfany(Item & item)
std::vector<typename Item::Function>::iterator d = item.functions.begin();
unsigned how_many_true = 0;
is_generating_if = true;
for( ; d != item.functions.end() ; ++d )
{
if( !Call(*d) )
@ -871,6 +939,8 @@ void Generator<StreamType>::MakeTextIfone(Item & item)
std::vector<typename Item::Function>::iterator d = item.functions.begin();
unsigned how_many_true = 0;
is_generating_if = true;
for( ; d != item.functions.end() ; ++d )
{
if( Call(*d) )
@ -893,6 +963,8 @@ void Generator<StreamType>::MakeTextIfanyno(Item & item)
std::vector<typename Item::Function>::iterator d = item.functions.begin();
unsigned how_many_true = 0;
is_generating_if = true;
for( ; d != item.functions.end() ; ++d )
{
if( !Call(*d) )
@ -912,6 +984,8 @@ void Generator<StreamType>::MakeTextIfoneno(Item & item)
std::vector<typename Item::Function>::iterator d = item.functions.begin();
unsigned how_many_false = 0;
is_generating_if = true;
for( ; d != item.functions.end() ; ++d )
{
if( Call(*d) )
@ -935,6 +1009,8 @@ void Generator<StreamType>::MakeTextIs(Item & item, bool equal)
if( item.functions.size() != 2 )
return;
is_generating_is = true;
// if one of these two functions has set case_sensitive to false
// then we compare in case insensitive mode
bool case_sensitive = true;
@ -990,7 +1066,7 @@ bool Generator<StreamType>::MakeTextIfindexnumber(Item & item, bool & result)
const wchar_t * number_text = item.functions[0].name.c_str();
const wchar_t * last_char;
int number = StrToInt(number_text, &last_char);
size_t number = StrToSize(number_text, &last_char);
if( *last_char != '\0' )
{
@ -1078,12 +1154,11 @@ void Generator<StreamType>::MakeTextFor(Item & item)
if( !Find(item.functions[0], &function) )
return;
StackItem s;
s.iter = 0;
stack_tab.push_back(s);
stack_tab.push_back(StackItem());
MakeTextForLoop(item, function);
delete stack_tab.back().fun_data;
stack_tab.erase(--stack_tab.end());
}
@ -1154,6 +1229,7 @@ void Generator<StreamType>::MakeTextFilter(Item & item)
if( !item.item_tab.empty() )
MakeText( *item.item_tab[0] ); // should be only one item - item_container
is_generating_filter = true;
Call(function, item.functions[0].params, *old_stream, false, *output_stream);
output_stream = old_stream;
@ -1175,7 +1251,11 @@ void Generator<StreamType>::MakeText(Item & item)
return;
}
is_generating_for = false;
is_generating_for = false;
is_generating_if = false;
is_generating_is = false;
is_generating_normal = false;
is_generating_filter = false;
if ( item.type == Item::item_text ) MakeItemText(item);
else if( item.type == Item::item_container )MakeTextContainer(item);