From 787b5e99b2d9cc847a033dac06539b1435be9ad6 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Mon, 27 Feb 2012 17:39:46 +0000 Subject: [PATCH] changed: in Generator: now we have a stack item for all statements [if...] [normal_fun] etc. previously was only for [for ...] statements changed: FunInfo<> has a pointer to the current stack item changed: now we have a static number of stack items (default: 300) so you can remember a pointer to a stack item and this pointer is always valid git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@393 e52654a7-88a9-db11-a3e9-0013d4bc506e --- src/funinfo.h | 73 +++++++++------ src/generator.h | 239 ++++++++++++++++++++++++------------------------ 2 files changed, 166 insertions(+), 146 deletions(-) diff --git a/src/funinfo.h b/src/funinfo.h index 01bb0f0..a2237ee 100755 --- a/src/funinfo.h +++ b/src/funinfo.h @@ -39,7 +39,6 @@ #ifndef headerfile_ezc_funinfo #define headerfile_ezc_funinfo - #include @@ -47,10 +46,12 @@ namespace Ezc { + +/* + a base class for your own function data class +*/ struct FunData { - - FunData() { } @@ -61,6 +62,40 @@ struct FunData }; + +/* + a generator's stack item + each statement ([if ...] [for ...] [normal_funcion]) have its own stack item + iter - is used only in [for...] - it is the current iteration (start from zero) + for other statements it is always zero + fun_data - by default this is null pointer, you can set it to a pointer + to an object derived from FunData + (this have sense only in [for...] statement because in other statements + this object would be immediately removed) + remove - when true it means that object pointing by fun_data should be automatically + removed -- (by using delete fun_data) +*/ +struct Stack +{ + size_t iter; + FunData * fun_data; + bool remove; + + Stack() + { + Clear(); + } + + void Clear() + { + iter = 0; + fun_data = 0; + remove = true; + } +}; + + + template struct FunInfo { @@ -101,30 +136,19 @@ struct FunInfo // 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; + // a pointer to a stack's item from generator's stack + // it is never null + // each function has a new stack item + // on this stack you have iter (description below) and fun_data pointer + // you can assign to it your own object derived from FunData + Stack * stack; - FunData * last_fun_data; - - bool remove_fun_data; - - - // this is set by Generator + // the same as stack->iter (this is mainly for backward compatibility) // 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 // 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) + // return value from a user's function (default false if not set directly by the function) // for a variable it is set to true if the variable is not empty bool res; @@ -147,12 +171,9 @@ struct FunInfo is_is = false; is_normal = false; is_filter = false; + stack = 0; iter = 0; - last_iter = 0; case_sensitive = true; - remove_fun_data = true; - fun_data = 0; - last_fun_data = 0; } }; diff --git a/src/generator.h b/src/generator.h index f2b7a38..357937a 100755 --- a/src/generator.h +++ b/src/generator.h @@ -48,6 +48,9 @@ namespace Ezc { + + + /* StreamType we use only method write(const wchar_t * str, size_t len) from the stream @@ -89,6 +92,9 @@ public: // default: 20 void SetMaxFilters(size_t new_len); + // default stack size: 300 + void SetStackSize(size_t new_stack_size); + // the main methods for generating void Generate(StreamType & o, Pattern & p, Functions & f); @@ -112,7 +118,10 @@ private: bool special_chars; bool trim_white; bool skip_new_line; - + + size_t stack_index; + size_t stack_size; + size_t filter_index; size_t filter_size; // we have to use a pointers table because standard streams such @@ -143,31 +152,16 @@ private: // when there is no any parameters const std::wstring empty; - // a stack item for [for] statements - // currently only one item (iterator) - struct StackItem - { - size_t iter; - FunData * fun_data; - bool remove; - - StackItem() - { - iter = 0; - fun_data = 0; - remove = true; - } - }; - // a stack for [for] statements - std::vector stack_tab; + std::vector stack_tab; void ResizeFilterTab(); + void ResizeStack(); void ClearFilterTab(); - void ClearForStack(); + void ClearForStack(bool resize_stack = true); void ClearStream(StreamType & str); - void RemoveStackFunData(StackItem & sitem); + void RemoveStackFunData(Stack & sitem); template CharType ToLower(CharType c); @@ -180,7 +174,6 @@ private: bool Find(const Item::Function & item_fun, typename Functions::Function ** function); - void PrepareInfo(FunInfo & info); void Call(typename Functions::Function * function, FunInfo & info); void Call(typename Functions::Function * function, std::vector & params, StreamType & out_stream, bool clear_out_stream, const StreamType & in_stream); @@ -202,6 +195,7 @@ private: void CreateMsg(const std::wstring & type, const std::wstring & arg); void CreateMsg(const std::wstring & type); void CreateUnknownMsg(const std::wstring & fun); + bool LimitAchieved(); void MakeTextIf_go(Item & item, bool result); bool MakeTextIfindexnumber(Item & item, bool & result); @@ -247,6 +241,7 @@ Generator::Generator() trim_white = false; skip_new_line = false; is_generator_working = false; + stack_size = 300; } @@ -261,23 +256,22 @@ Generator::Generator(const Generator & n) template Generator & Generator::operator=(const Generator & n) { - output_stream = n.output_stream; - pattern = n.pattern; - functions = n.functions; + output_stream = n.output_stream; + pattern = n.pattern; + functions = n.functions; - max_items = n.max_items; - max_for_items = n.max_for_items; - filter_size = n.filter_size; - special_chars = n.special_chars; - trim_white = n.trim_white; - skip_new_line = n.skip_new_line; + max_items = n.max_items; + max_for_items = n.max_for_items; + special_chars = n.special_chars; + trim_white = n.trim_white; + skip_new_line = n.skip_new_line; + + // filter and stack will be auto resized after next call to Generate() method + filter_size = n.filter_size; + stack_size = n.stack_size; - // !! IMROVE ME - // does we really need to clear those two stacks? // don't copy filter tab - ClearFilterTab(); - // don't copy [for] stack - ClearForStack(); + // don't copy stack // !! CHECK ME // may copying should be denied when generator is working? @@ -318,6 +312,22 @@ void Generator::ResizeFilterTab() } +template +void Generator::ResizeStack() +{ + if( stack_tab.size() != stack_size ) + { + if( stack_tab.size() > stack_size ) + { + for(size_t i=stack_size ; i void Generator::ClearFilterTab() { @@ -329,12 +339,13 @@ void Generator::ClearFilterTab() template -void Generator::ClearForStack() +void Generator::ClearForStack(bool resize_stack) { for(size_t i=0 ; i::ClearStream(StreamType & str) template -void Generator::RemoveStackFunData(StackItem & sitem) +void Generator::RemoveStackFunData(Stack & s) { - if( sitem.fun_data && sitem.remove ) + if( s.fun_data && s.remove ) { - delete sitem.fun_data; - sitem.fun_data = 0; + delete s.fun_data; + s.fun_data = 0; } } @@ -443,6 +454,14 @@ void Generator::SetMaxFilters(size_t new_len) } +template +void Generator::SetStackSize(size_t new_stack_size) +{ + // the stack will be resized when Generate() method is called + stack_size = new_stack_size; +} + + template void Generator::Generate(StreamType * o, Pattern * p, Functions * f) { @@ -460,9 +479,16 @@ void Generator::Generate(StreamType * o, Pattern * p, Functions -void Generator::PrepareInfo(FunInfo & info) +void Generator::Call(typename Functions::Function * function, FunInfo & info) { info.Clear(); @@ -539,35 +566,8 @@ void Generator::PrepareInfo(FunInfo & info) info.is_normal = is_generating_normal; info.is_filter = is_generating_filter; - 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; - info.remove_fun_data = stack_tab.back().remove; - } - - if( stack_tab.size() >= 2 ) - info.last_fun_data = stack_tab[stack_tab.size()-2].fun_data; -} - - -template -void Generator::Call(typename Functions::Function * function, FunInfo & info) -{ - PrepareInfo(info); + info.stack = &stack_tab[stack_index-1]; + info.iter = stack_tab[stack_index-1].iter; if( function->type == Functions::function ) { @@ -579,22 +579,6 @@ void Generator::Call(typename Functions::Function * func info.res = !function->variable.empty(); } - if( !stack_tab.empty() ) - { - if( stack_tab.back().fun_data != info.fun_data ) - { - RemoveStackFunData(stack_tab.back()); - stack_tab.back().fun_data = info.fun_data; - } - - stack_tab.back().remove = info.remove_fun_data; - } - else - { - if( info.remove_fun_data ) - delete info.fun_data; - } - last_res = info.res; last_case_sensitive = info.case_sensitive; } @@ -1087,7 +1071,7 @@ void Generator::MakeTextIsno(Item & item) template bool Generator::MakeTextIfindexnumber(Item & item, bool & result) { - if( item.functions.size() != 1 || stack_tab.empty() ) + if( item.functions.size() != 1 ) return false; const wchar_t * number_text = item.functions[0].name.c_str(); @@ -1101,7 +1085,7 @@ bool Generator::MakeTextIfindexnumber(Item & item, bool & result) return false; } - result = (stack_tab.back().iter == number); + result = (stack_tab[stack_index-1].iter == number); return true; } @@ -1116,27 +1100,24 @@ void Generator::MakeTextIfindex(Item & item) bool result = false; - if( !stack_tab.empty() ) + if( item.functions[0].name == L"odd" ) { - if( item.functions[0].name == L"odd" ) - { - result = (stack_tab.back().iter & 1) == 1; - } - else - if( item.functions[0].name == L"even" ) - { - result = (stack_tab.back().iter & 1) == 0; - } - else - if( item.functions[0].name == L"first" ) - { - result = stack_tab.back().iter == 0; - } - else - { - if( !MakeTextIfindexnumber(item, result) ) - return; - } + result = (stack_tab[stack_index-1].iter & 1) == 1; + } + else + if( item.functions[0].name == L"even" ) + { + result = (stack_tab[stack_index-1].iter & 1) == 0; + } + else + if( item.functions[0].name == L"first" ) + { + result = stack_tab[stack_index-1].iter == 0; + } + else + { + if( !MakeTextIfindexnumber(item, result) ) + return; } MakeTextIf_go(item, result); @@ -1147,9 +1128,9 @@ void Generator::MakeTextIfindex(Item & item) template void Generator::MakeTextForLoop(Item & item, typename Functions::Function * function) { - for( ; !break_generating ; stack_tab.back().iter += 1 ) + for( ; !break_generating ; stack_tab[stack_index-1].iter += 1 ) { - if( stack_tab.back().iter >= max_for_items ) + if( stack_tab[stack_index-1].iter >= max_for_items ) { CreateMsg(item.functions[0].name.c_str(), L"function exceeded a limit for a [for] statement"); @@ -1181,10 +1162,7 @@ void Generator::MakeTextFor(Item & item) if( !Find(item.functions[0], &function) ) return; - stack_tab.push_back(StackItem()); MakeTextForLoop(item, function); - RemoveStackFunData(stack_tab.back()); - stack_tab.erase(--stack_tab.end()); } @@ -1262,26 +1240,44 @@ void Generator::MakeTextFilter(Item & item) } - template -void Generator::MakeText(Item & item) +bool Generator::LimitAchieved() { if( break_generating ) - return; + return true; if( ++current_item > max_items ) { break_generating = true; CreateMsg(L"Generator exceeded allowed number of elements"); - return; + return true; } + if( ++stack_index > stack_tab.size() ) + { + break_generating = true; + CreateMsg(L"Generator exceeded the stack size"); + return true; + } + +return false; +} + + +template +void Generator::MakeText(Item & item) +{ + if( LimitAchieved() ) + return; + is_generating_for = false; is_generating_if = false; is_generating_is = false; is_generating_normal = false; is_generating_filter = false; + stack_tab[stack_index-1].Clear(); + if ( item.type == Item::item_text ) MakeItemText(item); else if( item.type == Item::item_container )MakeTextContainer(item); else if( item.type == Item::item_normal ) MakeTextNormal(item); @@ -1294,11 +1290,14 @@ void Generator::MakeText(Item & item) else if( item.type == Item::item_ifindex ) MakeTextIfindex(item); else if( item.type == Item::item_is ) MakeTextIs(item); else if( item.type == Item::item_isno ) MakeTextIsno(item); - else if( item.type == Item::item_for ) MakeTextFor(item); else if( item.type == Item::item_def ) MakeTextDefine(item); + else if( item.type == Item::item_for ) MakeTextFor(item); else if( item.type == Item::item_filter ) MakeTextFilter(item); else if( item.type == Item::item_err ) CreateMsg(L"a wrong directive"); + + RemoveStackFunData(stack_tab[stack_index-1]); + stack_index -=1; }