changed: now [for] statements with the same function can be nested

sample:
[for my_function]
 [for my_function]
   foo
 [end]
[end]

changed: FunInfo::iter has a value from the last [for] statement now
sample:
[for my_function]
 [other_function]
[end]

void other_function(Info &i)
{
// here i.iter is the number of iteration
// previously was always zero
}

changed: small optimization in [for]
the proper function is being looking for only once at the beginning
previously it was searched in each iteration



git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@331 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Tomasz Sowa 2011-01-14 23:59:30 +00:00
parent c4f5f79218
commit fd2194623a
4 changed files with 82 additions and 65 deletions

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2007-2010, Tomasz Sowa * Copyright (c) 2007-2011, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -64,8 +64,6 @@ public:
UserFunction user_function; // used when type is 'function' UserFunction user_function; // used when type is 'function'
std::wstring variable; // used when type is 'variable' 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 bool is_running; // true if this function is currently executed
Function(); Function();
@ -103,8 +101,6 @@ Functions<StreamType>::Function::Function()
{ {
type = Functions::variable; type = Functions::variable;
user_function = 0; user_function = 0;
iter = 0;
is_for = false;
is_running = false; is_running = false;
} }

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2007-2010, Tomasz Sowa * Copyright (c) 2007-2011, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -55,16 +55,17 @@ struct FunInfo
StreamType & out; StreamType & out;
// table of parameters // table of parameters
// the table can be empty
std::vector<std::wstring> & params; std::vector<std::wstring> & params;
// the first parameter // 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 // in such a way the reference points to an empty string
const std::wstring & par; const std::wstring & par;
// this is set by Generator // this is set by Generator
// normally is 0 // it indicates the number of a current iteration in the last [for] statement (the first is 0)
// in a [for] statement it indicates the number of the current iteration (the first is 0) // if there was not any [for] before the value is zero
int iter; int iter;
// return value from a user function (default false if not set directly by the user function) // return value from a user function (default false if not set directly by the user function)

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2007-2010, Tomasz Sowa * Copyright (c) 2007-2011, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -109,10 +109,21 @@ private:
const std::wstring empty; 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<StackItem> stack_tab;
bool Find(const Item::Function & item_fun, typename Functions<StreamType>::Function ** function); bool Find(const Item::Function & item_fun, typename Functions<StreamType>::Function ** function);
void Call(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info); void Call(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info);
bool Call(Item::Function & function, bool * info_res = 0, typename Functions<StreamType>::Function ** pfun = 0); bool Call(Item::Function & function, bool * info_res = 0, typename Functions<StreamType>::Function ** pfun = 0);
void Call(typename Functions<StreamType>::Function * function, std::vector<std::wstring> & params, bool * info_res = 0);
void CallUserFunction(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info); void CallUserFunction(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info);
void CallVariable(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info); void CallVariable(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info);
@ -131,7 +142,7 @@ private:
void CreateUnknownMsg(const std::wstring & fun); void CreateUnknownMsg(const std::wstring & fun);
void MakeTextIf_go(Item & item, bool result); void MakeTextIf_go(Item & item, bool result);
bool MakeTextIfindexnumber(Item & item, typename Functions<StreamType>::Function * function, bool & result); bool MakeTextIfindexnumber(Item & item, bool & result);
void MakeTextIf(Item & item); void MakeTextIf(Item & item);
void MakeTextIfno(Item & item); void MakeTextIfno(Item & item);
void MakeTextIfany(Item & item); void MakeTextIfany(Item & item);
@ -290,7 +301,11 @@ template<class StreamType>
void Generator<StreamType>::Call(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info) void Generator<StreamType>::Call(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info)
{ {
info.Clear(); info.Clear();
info.iter = function->iter;
if( stack_tab.empty() )
info.iter = 0;
else
info.iter = stack_tab.back().iter;
if( function->type == Functions<StreamType>::function ) if( function->type == Functions<StreamType>::function )
CallUserFunction(function, info); CallUserFunction(function, info);
@ -344,6 +359,30 @@ return called;
// it calls the function pointed by pfun
template<class StreamType>
void Generator<StreamType>::Call(typename Functions<StreamType>::Function * function, std::vector<std::wstring> & params, bool * info_res)
{
if( params.empty() )
{
FunInfo<StreamType> info(*output_stream, params, empty);
Call(function, info);
if( info_res )
*info_res = info.res;
}
else
{
FunInfo<StreamType> info(*output_stream, params, params[0]);
Call(function, info);
if( info_res )
*info_res = info.res;
}
}
template<class StreamType> template<class StreamType>
wchar_t Generator<StreamType>::CreateSpecialChar(wchar_t c) wchar_t Generator<StreamType>::CreateSpecialChar(wchar_t c)
@ -746,12 +785,12 @@ bool info_res1, info_res2;
template<class StreamType> template<class StreamType>
bool Generator<StreamType>::MakeTextIfindexnumber(Item & item, typename Functions<StreamType>::Function * function, bool & result) bool Generator<StreamType>::MakeTextIfindexnumber(Item & item, bool & result)
{ {
if( item.functions.size() != 2 ) if( item.functions.size() != 1 || stack_tab.empty() )
return false; 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; const wchar_t * last_char;
int number = StrToInt(number_text, &last_char); int number = StrToInt(number_text, &last_char);
@ -762,7 +801,7 @@ bool Generator<StreamType>::MakeTextIfindexnumber(Item & item, typename Function
return false; return false;
} }
result = (function->iter == number); result = (stack_tab.back().iter == number);
return true; return true;
} }
@ -772,38 +811,32 @@ return true;
template<class StreamType> template<class StreamType>
void Generator<StreamType>::MakeTextIfindex(Item & item) void Generator<StreamType>::MakeTextIfindex(Item & item)
{ {
if( item.functions.size() != 2 ) if( item.functions.size() != 1 )
return;
// we actually don't call a function (or variable) here
// but only reading the iterator
typename Functions<StreamType>::Function * function;
if( !Find(item.functions[0], &function) )
return; return;
bool result = false; bool result = false;
if( !stack_tab.empty() )
if( item.functions[1].name == L"odd" )
{ {
result = (function->iter & 1) == 1; if( item.functions[0].name == L"odd" )
} {
else result = (stack_tab.back().iter & 1) == 1;
if( item.functions[1].name == L"even" ) }
{ else
result = (function->iter & 1) == 0; if( item.functions[0].name == L"even" )
} {
else result = (stack_tab.back().iter & 1) == 0;
if( item.functions[1].name == L"first" ) }
{ else
result = function->iter == 0; if( item.functions[0].name == L"first" )
} {
else result = stack_tab.back().iter == 0;
{ }
if( !MakeTextIfindexnumber(item, function, result) ) else
return; {
if( !MakeTextIfindexnumber(item, result) )
return;
}
} }
MakeTextIf_go(item, result); MakeTextIf_go(item, result);
@ -816,16 +849,16 @@ void Generator<StreamType>::MakeTextForLoop(Item & item, typename Functions<Stre
{ {
bool info_res; bool info_res;
for( ; !break_generating ; function->iter += 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(), CreateMsg(item.functions[0].name.c_str(),
L"function exceeded a limit for a [for] statement"); L"function exceeded a limit for a [for] statement");
break; break;
} }
Call(item.functions[0], &info_res); Call(function, item.functions[0].params, &info_res);
if( !info_res ) if( !info_res )
break; break;
@ -847,20 +880,13 @@ void Generator<StreamType>::MakeTextFor(Item & item)
if( !Find(item.functions[0], &function) ) if( !Find(item.functions[0], &function) )
return; return;
if( function->is_for ) StackItem s;
{ s.iter = 0;
CreateMsg(item.functions[0].name.c_str(), stack_tab.push_back(s);
L"this function is already used in a [for] statement");
return;
}
function->is_for = true;
function->iter = 0;
MakeTextForLoop(item, function); MakeTextForLoop(item, function);
function->is_for = false; stack_tab.erase(--stack_tab.end());
function->iter = 0;
} }

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2007-2010, Tomasz Sowa * Copyright (c) 2007-2011, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -754,12 +754,6 @@ void Pattern::ReadDirectiveIfindex(Item & item)
item.functions.clear(); item.functions.clear();
temp_function.params.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) // reading: odd, even, first or a number (without quotes)
if( !ReadName(temp_function.name) ) if( !ReadName(temp_function.name) )
return; return;