added filters:

a new statement [filter]
 syntax:
 [filter funcion_name]....[end]
 everything which is between [filter] and [end] is processed normally and
 at the end it is passed to the function (function_name)
 FunInfo struct has 'in' input stream now



git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@333 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
2011-01-26 12:42:49 +00:00
parent 3c85fa1a75
commit 542e50d757
6 changed files with 269 additions and 99 deletions

View File

@@ -43,6 +43,8 @@
#include "functions.h"
#include <sstream>
#include <fstream>
#include <vector>
namespace Ezc
{
@@ -56,6 +58,10 @@ class Generator
public:
Generator();
Generator(const Generator & n);
Generator & operator=(const Generator & n);
~Generator();
void SetMax(int max_items_, int max_for_items_);
@@ -80,6 +86,9 @@ public:
// default: false
void SkipNewLine(bool skip);
// default: 20
void SetMaxFilters(size_t new_len);
// the main methods for generating
void Generate(StreamType & o, Pattern & p, Functions<StreamType> & f);
@@ -103,6 +112,17 @@ private:
bool special_chars;
bool trim_white;
bool skip_new_line;
size_t filter_index;
size_t filter_size;
// we have to use a pointers table because standard streams such
// as std::wostringstream are not copyable
std::vector<StreamType*> filter_tab;
const StreamType empty_stream;
bool is_used;
// an empty string for info objects
// when there is no any parameters
@@ -119,15 +139,20 @@ private:
// a stack for 'for' statements
std::vector<StackItem> stack_tab;
void ResizeFilterTab();
void ClearFilterTab();
void ClearStream(StreamType & str);
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);
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 CallVariable(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info);
wchar_t CreateSpecialChar(wchar_t c);
const wchar_t * PrintSpecialChar(const wchar_t * start, const wchar_t * end);
void PrintSpecialText(const wchar_t * start, const wchar_t * end);
@@ -136,6 +161,7 @@ private:
void SkipWhite(const wchar_t *& str);
int StrToInt(const wchar_t * str, const wchar_t ** str_end);
void CreateMsg(StreamType & out, const wchar_t * type, const wchar_t * arg = 0);
void CreateMsg(const wchar_t * type, const wchar_t * arg = 0);
void CreateMsg(const std::wstring & type, const std::wstring & arg);
void CreateMsg(const std::wstring & type);
@@ -158,8 +184,11 @@ private:
void MakeTextIs(Item & item);
void MakeTextIsno(Item & item);
void MakeTextDefine(Item & item);
void MakeTextFilter(Item & item);
void MakeText(Item & item);
void Generate(StreamType * o, Pattern * p, Functions<StreamType> * f);
}; // class Generator
@@ -176,12 +205,94 @@ Generator<StreamType>::Generator()
max_items = 50000;
max_for_items = 5000;
filter_size = 20;
special_chars = false;
trim_white = false;
skip_new_line = false;
is_used = false;
}
template<class StreamType>
Generator<StreamType>::Generator(const Generator<StreamType> & n)
{
operator=(n);
}
template<class StreamType>
Generator<StreamType> & Generator<StreamType>::operator=(const Generator<StreamType> & n)
{
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;
// don't copy filter tab
filter_tab.clear();
// don't copy 'is_used' flag
is_used = false;
return *this;
}
template<class StreamType>
Generator<StreamType>::~Generator()
{
ClearFilterTab();
}
template<class StreamType>
void Generator<StreamType>::ResizeFilterTab()
{
if( filter_tab.size() != filter_size )
{
if( filter_tab.size() < filter_size )
{
for(size_t i=filter_tab.size() ; i<filter_size ; ++i)
filter_tab.push_back( new StreamType() );
}
else
{
for(size_t i=filter_size ; i<filter_tab.size() ; ++i)
delete filter_tab[i];
filter_tab.resize(filter_size);
}
}
}
template<class StreamType>
void Generator<StreamType>::ClearFilterTab()
{
for(size_t i=0 ; i<filter_tab.size() ; ++i)
delete filter_tab[i];
filter_tab.clear();
}
template<class StreamType>
void Generator<StreamType>::ClearStream(StreamType & str)
{
#ifdef EZC_HAS_SPECIAL_STREAM
str.Clear();
#else
str.str(L"");
#endif
}
template<class StreamType>
@@ -214,30 +325,64 @@ void Generator<StreamType>::SkipNewLine(bool skip)
template<class StreamType>
void Generator<StreamType>::Generate(StreamType & o, Pattern & p, Functions<StreamType> & f)
void Generator<StreamType>::SetMaxFilters(size_t new_len)
{
output_stream = &o;
pattern = &p;
functions = &f;
// the table will be resized when Generate() method is called
filter_size = new_len;
}
template<class StreamType>
void Generator<StreamType>::Generate(StreamType * o, Pattern * p, Functions<StreamType> * f)
{
if( is_used )
{
if( o )
CreateMsg(*o, L"generator busy");
return;
}
output_stream = o;
pattern = p;
functions = f;
break_generating = false;
current_item = 0;
stack_tab.clear();
ResizeFilterTab();
filter_index = 0;
MakeText( pattern->item_root );
if( output_stream && pattern )
{
try
{
is_used = true;
MakeText( pattern->item_root );
is_used = false;
}
catch(...)
{
is_used = false;
throw;
}
}
}
template<class StreamType>
void Generator<StreamType>::Generate(StreamType & o, Pattern & p, Functions<StreamType> & f)
{
Generate(&o, &p, &f);
}
template<class StreamType>
void Generator<StreamType>::Generate(StreamType & o, Pattern & p)
{
output_stream = &o;
pattern = &p;
functions = 0;
break_generating = false;
current_item = 0;
MakeText( pattern->item_root );
Generate(&o, &p, 0);
}
@@ -272,29 +417,6 @@ return true;
}
template<class StreamType>
void Generator<StreamType>::CallUserFunction(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info)
{
if( function->is_running )
{
// recurrences are not allowed
CreateMsg(L"the function is being executed");
return;
}
function->is_running = true;
(function->user_function)(info);
function->is_running = false;
}
template<class StreamType>
void Generator<StreamType>::CallVariable(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info)
{
info.res = !function->variable.empty();
}
template<class StreamType>
@@ -308,52 +430,54 @@ void Generator<StreamType>::Call(typename Functions<StreamType>::Function * func
info.iter = stack_tab.back().iter;
if( function->type == Functions<StreamType>::function )
CallUserFunction(function, info);
(function->user_function)(info);
else
CallVariable(function, info);
info.res = !function->variable.empty();
}
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)
{
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)
{
typename Functions<StreamType>::Function * fun;
bool called = false;
if( item_fun.params.empty() )
{
FunInfo<StreamType> info(*output_stream, item_fun.params, empty);
if( !Find(item_fun, &fun) )
return false;
if( Find(item_fun, &fun) )
{
Call(fun, info);
called = true;
}
Call(fun, item_fun.params, *output_stream, empty_stream, info_res);
if( info_res )
*info_res = info.res;
}
else
{
FunInfo<StreamType> info(*output_stream, item_fun.params, item_fun.params[0]);
if( Find(item_fun, &fun) )
{
Call(fun, info);
called = true;
}
if( info_res )
*info_res = info.res;
}
if( called && pfun )
if( pfun )
*pfun = fun;
return called;
return true;
}
@@ -363,27 +487,13 @@ return called;
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;
}
Call(function, params, *output_stream, empty_stream, info_res);
}
template<class StreamType>
wchar_t Generator<StreamType>::CreateSpecialChar(wchar_t c)
{
@@ -540,12 +650,20 @@ return res;
template<class StreamType>
void Generator<StreamType>::CreateMsg(StreamType & out, const wchar_t * type, const wchar_t * arg)
{
pattern->CreateMsg(temp_msg, type, arg);
out.write(temp_msg.c_str(), temp_msg.size());
}
template<class StreamType>
void Generator<StreamType>::CreateMsg(const wchar_t * type, const wchar_t * arg)
{
pattern->CreateMsg(temp_msg, type, arg);
output_stream->write(temp_msg.c_str(), temp_msg.size());
CreateMsg(*output_stream, type, arg);
}
@@ -896,7 +1014,7 @@ void Generator<StreamType>::MakeTextDefine(Item & item)
{
if( !functions )
{
CreateMsg(L"def statement is not available when used without functions set");
CreateMsg(L"[def] statement is not available when used without functions set");
return;
}
@@ -930,6 +1048,40 @@ void Generator<StreamType>::MakeTextDefine(Item & item)
template<class StreamType>
void Generator<StreamType>::MakeTextFilter(Item & item)
{
if( item.functions.size() != 1 )
return;
typename Functions<StreamType>::Function * function;
if( !Find(item.functions[0], &function) )
return;
if( filter_index >= filter_tab.size() )
{
CreateMsg(L"Generator exceeded allowed number of filters");
return;
}
StreamType * old_stream = output_stream;
output_stream = filter_tab[filter_index];
ClearStream(*output_stream);
filter_index += 1;
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);
output_stream = old_stream;
filter_index -= 1;
}
template<class StreamType>
void Generator<StreamType>::MakeText(Item & item)
{
@@ -957,6 +1109,7 @@ void Generator<StreamType>::MakeText(Item & 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_filter ) MakeTextFilter(item);
else if( item.type == Item::item_err )
CreateMsg(L"a wrong directive");
}