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:
parent
542e50d757
commit
861269383e
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
236
src/generator.h
236
src/generator.h
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue