changed: [is...] statements use only the output string now (when comparing)

previously they used FunInfo::res, now they use FunInfo::out
         and the out string is not put to the main output stream
added:   FunInfo<>::case_sensitive (default true)
         when false then [is] statement is comparing in case insensitive manner
changed: the out stream in [if...] [for] statements
         the output text is ingored now



git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@344 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Tomasz Sowa 2011-04-26 17:17:06 +00:00
parent 542e50d757
commit 861269383e
3 changed files with 162 additions and 84 deletions

View File

@ -54,6 +54,11 @@ struct FunInfo
// output stream
StreamType & out;
// the out stream is treated in case sensitive
// used only in [is...] statements
// default: true
bool case_sensitive;
// table of parameters
// the table can be empty
std::vector<std::wstring> & params;
@ -89,6 +94,7 @@ struct FunInfo
{
res = false; // false by default
iter = 0;
case_sensitive = true;
}
};

View File

@ -120,37 +120,54 @@ private:
std::vector<StreamType*> filter_tab;
const StreamType empty_stream;
// temporary streams used in [if..] [is...] or [for...]
StreamType stream_temp1, stream_temp2;
bool is_used;
// whether last function has put its content in case_sensitive (set FunInfo::case_sensitive)
bool last_case_sensitive;
// last result from a user function (FunInfo::res)
bool last_res;
// an empty string for info objects
// true if this Generator is working now
bool is_generator_working;
// an empty string for FunInfo objects
// when there is no any parameters
const std::wstring empty;
// a stack item for 'for' statements
// currently only one item (iteration)
// a stack item for [for] statements
// currently only one item (iterator)
struct StackItem
{
int iter;
};
// a stack for 'for' statements
// a stack for [for] statements
std::vector<StackItem> stack_tab;
void ResizeFilterTab();
void ClearFilterTab();
void ClearStream(StreamType & str);
template<class CharType>
CharType ToLower(CharType c);
template<class CharType>
bool StrCmpNc(CharType * str1, CharType * str2);
bool AreStreamsEqual(StreamType & str1, StreamType & str2, bool case_sensitive);
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, std::vector<std::wstring> & params,
StreamType & out_stream, const StreamType & in_stream, bool * info_res = 0);
StreamType & out_stream, bool clear_out_stream, const StreamType & in_stream);
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);
bool Call(Item::Function & item_fun, StreamType & out_stream, bool clear_out_stream);
bool Call(Item::Function & function);
wchar_t CreateSpecialChar(wchar_t c);
@ -181,6 +198,7 @@ private:
void MakeItemText(Item & item);
void MakeTextContainer(Item & item);
void MakeTextNormal(Item & item);
void MakeTextIs(Item & item, bool equal);
void MakeTextIs(Item & item);
void MakeTextIsno(Item & item);
void MakeTextDefine(Item & item);
@ -209,7 +227,7 @@ Generator<StreamType>::Generator()
special_chars = false;
trim_white = false;
skip_new_line = false;
is_used = false;
is_generator_working = false;
}
@ -238,8 +256,8 @@ Generator<StreamType> & Generator<StreamType>::operator=(const Generator<StreamT
// don't copy filter tab
filter_tab.clear();
// don't copy 'is_used' flag
is_used = false;
// don't copy 'is_generator_working' flag
is_generator_working = false;
return *this;
}
@ -295,6 +313,51 @@ void Generator<StreamType>::ClearStream(StreamType & str)
}
template<class StreamType>
template<class CharType>
CharType Generator<StreamType>::ToLower(CharType c)
{
if( c>='A' && c<='Z' )
return c - 'A' + 'a';
return c;
}
template<class StreamType>
template<class CharType>
bool Generator<StreamType>::StrCmpNc(CharType * str1, CharType * str2)
{
for( ; ToLower(*str1) == ToLower(*str2) ; ++str1, ++str2)
if( *str1 == 0 )
return true;
return false;
}
template<class StreamType>
bool Generator<StreamType>::AreStreamsEqual(StreamType & str1, StreamType & str2, bool case_sensitive)
{
if( case_sensitive )
{
#ifdef EZC_HAS_SPECIAL_STREAM
return str1.Str() == str2.Str();
#else
return str1.str() == str2.str();
#endif
}
else
{
#ifdef EZC_HAS_SPECIAL_STREAM
return StrCmpNc(str1.CStr(), str2.CStr());
#else
return StrCmpNc(str1.str().c_str(), str2.str().c_str());
#endif
}
}
template<class StreamType>
void Generator<StreamType>::SetMax(int max_items_, int max_for_items_)
{
@ -335,7 +398,7 @@ void Generator<StreamType>::SetMaxFilters(size_t new_len)
template<class StreamType>
void Generator<StreamType>::Generate(StreamType * o, Pattern * p, Functions<StreamType> * f)
{
if( is_used )
if( is_generator_working )
{
if( o )
CreateMsg(*o, L"generator busy");
@ -357,13 +420,13 @@ void Generator<StreamType>::Generate(StreamType * o, Pattern * p, Functions<Stre
{
try
{
is_used = true;
is_generator_working = true;
MakeText( pattern->item_root );
is_used = false;
is_generator_working = false;
}
catch(...)
{
is_used = false;
is_generator_working = false;
throw;
}
}
@ -430,9 +493,18 @@ void Generator<StreamType>::Call(typename Functions<StreamType>::Function * func
info.iter = stack_tab.back().iter;
if( function->type == Functions<StreamType>::function )
{
(function->user_function)(info);
}
else
{
info.out << function->variable;
info.res = !function->variable.empty();
info.case_sensitive = true;
}
last_res = info.res;
last_case_sensitive = info.case_sensitive;
}
@ -440,54 +512,49 @@ void Generator<StreamType>::Call(typename Functions<StreamType>::Function * func
template<class StreamType>
void Generator<StreamType>::Call(typename Functions<StreamType>::Function * function,
std::vector<std::wstring> & params,
StreamType & out_stream, const StreamType & in_stream,
bool * info_res)
StreamType & out_stream,
bool clear_out_stream,
const StreamType & in_stream)
{
if( clear_out_stream )
ClearStream(out_stream);
if( params.empty() )
{
FunInfo<StreamType> info(out_stream, params, empty, in_stream);
Call(function, info);
if( info_res )
*info_res = info.res;
}
else
{
FunInfo<StreamType> info(out_stream, params, params[0], in_stream);
Call(function, info);
}
}
if( info_res )
*info_res = info.res;
}
}
// return: true if a function or variable was found and called
template<class StreamType>
bool Generator<StreamType>::Call(Item::Function & item_fun, bool * info_res, typename Functions<StreamType>::Function ** pfun)
bool Generator<StreamType>::Call(Item::Function & item_fun, StreamType & out_stream, bool clear_out_stream)
{
typename Functions<StreamType>::Function * fun;
if( !Find(item_fun, &fun) )
return false;
Call(fun, item_fun.params, *output_stream, empty_stream, info_res);
if( pfun )
*pfun = fun;
Call(fun, item_fun.params, out_stream, clear_out_stream, empty_stream);
return true;
}
// it calls the function pointed by pfun
// return: true if a function or variable was found and called
template<class StreamType>
void Generator<StreamType>::Call(typename Functions<StreamType>::Function * function, std::vector<std::wstring> & params, bool * info_res)
bool Generator<StreamType>::Call(Item::Function & item_fun)
{
Call(function, params, *output_stream, empty_stream, info_res);
return Call(item_fun, stream_temp1, true);
}
@ -725,11 +792,7 @@ void Generator<StreamType>::MakeTextNormal(Item & item)
if( item.functions.size() != 1 )
return;
typename Functions<StreamType>::Function * pfun;
bool called = Call(item.functions[0], 0, &pfun);
if( called && pfun->type == Functions<StreamType>::variable )
(*output_stream) << pfun->variable;
Call(item.functions[0], *output_stream, false);
}
@ -755,30 +818,26 @@ void Generator<StreamType>::MakeTextIf_go(Item & item, bool result)
template<class StreamType>
void Generator<StreamType>::MakeTextIf(Item & item)
{
bool info_res;
if( item.functions.size() != 1 )
return;
if( !Call(item.functions[0], &info_res) )
if( !Call(item.functions[0]) )
return;
MakeTextIf_go(item, info_res);
MakeTextIf_go(item, last_res);
}
template<class StreamType>
void Generator<StreamType>::MakeTextIfno(Item & item)
{
bool info_res;
if( item.functions.size() != 1 )
return;
if( !Call(item.functions[0], &info_res) )
if( !Call(item.functions[0]) )
return;
MakeTextIf_go(item, !info_res);
MakeTextIf_go(item, !last_res);
}
@ -787,14 +846,13 @@ void Generator<StreamType>::MakeTextIfany(Item & item)
{
std::vector<typename Item::Function>::iterator d = item.functions.begin();
unsigned how_many_true = 0;
bool info_res;
for( ; d != item.functions.end() ; ++d )
{
if( !Call(*d, &info_res) )
if( !Call(*d) )
return;
if( info_res )
if( last_res )
++how_many_true;
}
@ -807,15 +865,16 @@ void Generator<StreamType>::MakeTextIfone(Item & item)
{
std::vector<typename Item::Function>::iterator d = item.functions.begin();
unsigned how_many_true = 0;
bool info_res;
for( ; d != item.functions.end() ; ++d )
{
if( Call(*d, &info_res) && info_res )
if( Call(*d) )
{
if( last_res )
{
// there is no sense to go through all functions
++how_many_true;
break;
break; // there is no sense to go through all functions
}
}
}
@ -828,14 +887,13 @@ void Generator<StreamType>::MakeTextIfanyno(Item & item)
{
std::vector<typename Item::Function>::iterator d = item.functions.begin();
unsigned how_many_true = 0;
bool info_res;
for( ; d != item.functions.end() ; ++d )
{
if( !Call(*d, &info_res) )
if( !Call(*d) )
return;
if( info_res )
if( last_res )
++how_many_true;
}
@ -848,12 +906,17 @@ void Generator<StreamType>::MakeTextIfoneno(Item & item)
{
std::vector<typename Item::Function>::iterator d = item.functions.begin();
unsigned how_many_false = 0;
bool info_res;
for( ; d != item.functions.end() ; ++d )
{
if( Call(*d, &info_res) && !info_res )
if( Call(*d) )
{
if( !last_res )
{
++how_many_false;
break;
}
}
}
MakeTextIf_go(item, how_many_false > 0);
@ -862,38 +925,49 @@ void Generator<StreamType>::MakeTextIfoneno(Item & item)
template<class StreamType>
void Generator<StreamType>::MakeTextIs(Item & item)
void Generator<StreamType>::MakeTextIs(Item & item, bool equal)
{
bool info_res1, info_res2;
if( item.functions.size() != 2 )
return;
if( !Call(item.functions[0], &info_res1) )
// if one of these two functions has set case_sensitive to false
// then we compare in case insensitive mode
bool case_sensitive = true;
if( !Call(item.functions[0], stream_temp1, true) )
return;
if( !Call(item.functions[1], &info_res2) )
if( !last_case_sensitive )
case_sensitive = false;
if( !Call(item.functions[1], stream_temp2, true) )
return;
MakeTextIf_go(item, info_res1 == info_res2);
if( !last_case_sensitive )
case_sensitive = false;
bool res = AreStreamsEqual(stream_temp1, stream_temp2, case_sensitive);
if( !equal )
res = !res;
MakeTextIf_go(item, res);
}
template<class StreamType>
void Generator<StreamType>::MakeTextIs(Item & item)
{
MakeTextIs(item, true);
}
template<class StreamType>
void Generator<StreamType>::MakeTextIsno(Item & item)
{
bool info_res1, info_res2;
if( item.functions.size() != 2 )
return;
if( !Call(item.functions[0], &info_res1) )
return;
if( !Call(item.functions[1], &info_res2) )
return;
MakeTextIf_go(item, info_res1 != info_res2);
MakeTextIs(item, false);
}
@ -965,8 +1039,6 @@ void Generator<StreamType>::MakeTextIfindex(Item & item)
template<class StreamType>
void Generator<StreamType>::MakeTextForLoop(Item & item, typename Functions<StreamType>::Function * function)
{
bool info_res;
for( ; !break_generating ; stack_tab.back().iter += 1 )
{
if( stack_tab.back().iter >= max_for_items )
@ -976,9 +1048,9 @@ bool info_res;
break;
}
Call(function, item.functions[0].params, &info_res);
Call(function, item.functions[0].params, stream_temp1, true, empty_stream);
if( !info_res )
if( !last_res )
break;
if( !item.item_tab.empty() )
@ -1074,7 +1146,7 @@ void Generator<StreamType>::MakeTextFilter(Item & item)
if( !item.item_tab.empty() )
MakeText( *item.item_tab[0] ); // should be only one item - item_container
Call(function, item.functions[0].params, *old_stream, *output_stream);
Call(function, item.functions[0].params, *old_stream, false, *output_stream);
output_stream = old_stream;
filter_index -= 1;

View File

@ -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