diff --git a/src/functions.h b/src/functions.h index 452a4f4..928c247 100755 --- a/src/functions.h +++ b/src/functions.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2007-2010, Tomasz Sowa + * Copyright (c) 2007-2011, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -64,8 +64,6 @@ public: UserFunction user_function; // used when type is 'function' std::wstring variable; // used when type is 'variable' - int iter; - bool is_for; // true if is used by a [for] statement bool is_running; // true if this function is currently executed Function(); @@ -103,8 +101,6 @@ Functions::Function::Function() { type = Functions::variable; user_function = 0; - iter = 0; - is_for = false; is_running = false; } diff --git a/src/funinfo.h b/src/funinfo.h index b917355..f1541ef 100755 --- a/src/funinfo.h +++ b/src/funinfo.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2007-2010, Tomasz Sowa + * Copyright (c) 2007-2011, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,16 +55,17 @@ struct FunInfo StreamType & out; // table of parameters + // the table can be empty std::vector & params; // the first parameter - // you can always use it even if there is not any parameters + // you can always use it even if there is not any parameters (params is empty) // in such a way the reference points to an empty string const std::wstring & par; // this is set by Generator - // normally is 0 - // in a [for] statement it indicates the number of the current iteration (the first is 0) + // it indicates the number of a current iteration in the last [for] statement (the first is 0) + // if there was not any [for] before the value is zero int iter; // return value from a user function (default false if not set directly by the user function) diff --git a/src/generator.h b/src/generator.h index 665651d..3cdf22e 100755 --- a/src/generator.h +++ b/src/generator.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2007-2010, Tomasz Sowa + * Copyright (c) 2007-2011, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -109,10 +109,21 @@ private: const std::wstring empty; + // a stack item for 'for' statements + // currently only one item (iteration) + struct StackItem + { + int iter; + }; + + // a stack for 'for' statements + std::vector stack_tab; + bool Find(const Item::Function & item_fun, typename Functions::Function ** function); void Call(typename Functions::Function * function, FunInfo & info); bool Call(Item::Function & function, bool * info_res = 0, typename Functions::Function ** pfun = 0); + void Call(typename Functions::Function * function, std::vector & params, bool * info_res = 0); void CallUserFunction(typename Functions::Function * function, FunInfo & info); void CallVariable(typename Functions::Function * function, FunInfo & info); @@ -131,7 +142,7 @@ private: void CreateUnknownMsg(const std::wstring & fun); void MakeTextIf_go(Item & item, bool result); - bool MakeTextIfindexnumber(Item & item, typename Functions::Function * function, bool & result); + bool MakeTextIfindexnumber(Item & item, bool & result); void MakeTextIf(Item & item); void MakeTextIfno(Item & item); void MakeTextIfany(Item & item); @@ -290,7 +301,11 @@ template void Generator::Call(typename Functions::Function * function, FunInfo & info) { info.Clear(); - info.iter = function->iter; + + if( stack_tab.empty() ) + info.iter = 0; + else + info.iter = stack_tab.back().iter; if( function->type == Functions::function ) CallUserFunction(function, info); @@ -344,6 +359,30 @@ return called; +// it calls the function pointed by pfun +template +void Generator::Call(typename Functions::Function * function, std::vector & params, bool * info_res) +{ + if( params.empty() ) + { + FunInfo info(*output_stream, params, empty); + Call(function, info); + + if( info_res ) + *info_res = info.res; + } + else + { + FunInfo info(*output_stream, params, params[0]); + Call(function, info); + + if( info_res ) + *info_res = info.res; + } +} + + + template wchar_t Generator::CreateSpecialChar(wchar_t c) @@ -746,12 +785,12 @@ bool info_res1, info_res2; template -bool Generator::MakeTextIfindexnumber(Item & item, typename Functions::Function * function, bool & result) +bool Generator::MakeTextIfindexnumber(Item & item, bool & result) { - if( item.functions.size() != 2 ) + if( item.functions.size() != 1 || stack_tab.empty() ) return false; - const wchar_t * number_text = item.functions[1].name.c_str(); + const wchar_t * number_text = item.functions[0].name.c_str(); const wchar_t * last_char; int number = StrToInt(number_text, &last_char); @@ -762,7 +801,7 @@ bool Generator::MakeTextIfindexnumber(Item & item, typename Function return false; } - result = (function->iter == number); + result = (stack_tab.back().iter == number); return true; } @@ -772,38 +811,32 @@ return true; template void Generator::MakeTextIfindex(Item & item) { - if( item.functions.size() != 2 ) - return; - - // we actually don't call a function (or variable) here - // but only reading the iterator - - typename Functions::Function * function; - - if( !Find(item.functions[0], &function) ) + if( item.functions.size() != 1 ) return; bool result = false; - - if( item.functions[1].name == L"odd" ) + if( !stack_tab.empty() ) { - result = (function->iter & 1) == 1; - } - else - if( item.functions[1].name == L"even" ) - { - result = (function->iter & 1) == 0; - } - else - if( item.functions[1].name == L"first" ) - { - result = function->iter == 0; - } - else - { - if( !MakeTextIfindexnumber(item, function, result) ) - return; + 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; + } } MakeTextIf_go(item, result); @@ -816,16 +849,16 @@ void Generator::MakeTextForLoop(Item & item, typename Functionsiter += 1 ) + for( ; !break_generating ; stack_tab.back().iter += 1 ) { - if( function->iter >= max_for_items ) + if( stack_tab.back().iter >= max_for_items ) { CreateMsg(item.functions[0].name.c_str(), L"function exceeded a limit for a [for] statement"); break; } - Call(item.functions[0], &info_res); + Call(function, item.functions[0].params, &info_res); if( !info_res ) break; @@ -847,20 +880,13 @@ void Generator::MakeTextFor(Item & item) if( !Find(item.functions[0], &function) ) return; - if( function->is_for ) - { - CreateMsg(item.functions[0].name.c_str(), - L"this function is already used in a [for] statement"); - return; - } - - function->is_for = true; - function->iter = 0; + StackItem s; + s.iter = 0; + stack_tab.push_back(s); MakeTextForLoop(item, function); - - function->is_for = false; - function->iter = 0; + + stack_tab.erase(--stack_tab.end()); } diff --git a/src/pattern.cpp b/src/pattern.cpp index 048096d..87d1065 100755 --- a/src/pattern.cpp +++ b/src/pattern.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2007-2010, Tomasz Sowa + * Copyright (c) 2007-2011, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -754,12 +754,6 @@ void Pattern::ReadDirectiveIfindex(Item & item) item.functions.clear(); temp_function.params.clear(); - // reading function name - if( !ReadName(temp_function.name) ) - return; - - item.functions.push_back(temp_function); - // reading: odd, even, first or a number (without quotes) if( !ReadName(temp_function.name) ) return;