changed: the way how functions' arguments are parsed
now this [fun1 fun2 "something" fun3] will call fun1 with three arguments: fun2, "something" and fun3 and this [fun1 [fun2 "something"] fun3] will call fun1 with two arguments: [fun2 "something] and fun3 "something" is an argument for fun2 function removed: statements: [if-one] [if-any] [if-no] [if-any-no] [if-one-no] git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@1004 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
257
src/generator.h
257
src/generator.h
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007-2014, Tomasz Sowa
|
||||
* Copyright (c) 2007-2015, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -130,7 +130,6 @@ private:
|
||||
typedef std::map<std::wstring, Var> Vars;
|
||||
Vars vars;
|
||||
|
||||
Var temp_var;
|
||||
|
||||
struct BlockStack
|
||||
{
|
||||
@@ -238,6 +237,8 @@ private:
|
||||
void ClearStream(StreamType & str);
|
||||
void RemoveStackFunData(Stack & sitem);
|
||||
|
||||
bool ConvertToBool(const std::wstring & str);
|
||||
|
||||
template<class CharType>
|
||||
CharType ToLower(CharType c);
|
||||
|
||||
@@ -297,11 +298,6 @@ private:
|
||||
|
||||
void MakeTextIf_go(Item & item, bool result);
|
||||
void MakeTextIf(Item & item);
|
||||
void MakeTextIfno(Item & item);
|
||||
void MakeTextIfany(Item & item);
|
||||
void MakeTextIfone(Item & item);
|
||||
void MakeTextIfanyno(Item & item);
|
||||
void MakeTextIfoneno(Item & item);
|
||||
void MakeTextFor(Item & item);
|
||||
void MakeItemText(Item & item);
|
||||
void MakeTextContainer(Item & item);
|
||||
@@ -619,6 +615,15 @@ return c;
|
||||
}
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
bool Generator<StreamType>::ConvertToBool(const std::wstring & str)
|
||||
{
|
||||
if( str == L"true" )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::SetMax(size_t max_items_, size_t max_for_items_)
|
||||
@@ -715,7 +720,6 @@ void Generator<StreamType>::Generate()
|
||||
WriteTmpStreamToStreams();
|
||||
|
||||
vars.clear();
|
||||
temp_var.str.clear();
|
||||
is_generator_working = false;
|
||||
}
|
||||
catch(...)
|
||||
@@ -894,7 +898,7 @@ void Generator<StreamType>::CallFunction(typename Functions<StreamType>::UserFun
|
||||
info.is_normal = is_generating_normal;
|
||||
info.is_filter = is_generating_filter;
|
||||
info.iter = info.stack.iter;
|
||||
info.stack_tab = stack_tab.data();
|
||||
info.stack_tab = &stack_tab[0];//stack_tab.data();/////////////////////////////////////////////////////////
|
||||
info.stack_index = stack_index-1;
|
||||
|
||||
(*function)(info);
|
||||
@@ -954,7 +958,7 @@ bool Generator<StreamType>::CallBlock(Item & item_block,
|
||||
#endif
|
||||
|
||||
out_stream.write(str.c_str(), str.size());
|
||||
// last_res is set by [return ...] statement
|
||||
// last_res is set by [return ...] statement or other last evaluated function
|
||||
|
||||
ClearStream(*output_stream);
|
||||
output_stream = old_stream;
|
||||
@@ -964,7 +968,7 @@ return true;
|
||||
}
|
||||
|
||||
|
||||
// return: true if a function or variable was found and called
|
||||
// return: true if a function, variable or block was found and called
|
||||
template<class StreamType>
|
||||
bool Generator<StreamType>::Call(Item::Function & item_fun,
|
||||
StreamType & out_stream,
|
||||
@@ -988,7 +992,7 @@ std::vector<Var> parameters;
|
||||
{
|
||||
Item::Function & fun_child = *item_fun.parameters[i];
|
||||
|
||||
if( !fun_child.name.empty() )
|
||||
if( fun_child.is_function )
|
||||
{
|
||||
StreamType local_temp_stream;
|
||||
Call(fun_child, local_temp_stream, true, empty_stream);
|
||||
@@ -1003,8 +1007,8 @@ std::vector<Var> parameters;
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters[i].str = fun_child.par;
|
||||
parameters[i].res = !fun_child.par.empty();
|
||||
parameters[i].str = fun_child.name;
|
||||
parameters[i].res = ConvertToBool(fun_child.name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1319,18 +1323,15 @@ void Generator<StreamType>::MakeTextContainer(Item & item)
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::MakeTextNormal(Item & item)
|
||||
{
|
||||
if( item.functions.size() != 1 )
|
||||
return;
|
||||
|
||||
is_generating_normal = true;
|
||||
|
||||
if( output_stream )
|
||||
{
|
||||
Call(item.functions[0], *output_stream, false, empty_stream);
|
||||
Call(item.function, *output_stream, false, empty_stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
Call(item.functions[0], stream_temp1, false, empty_stream);
|
||||
Call(item.function, stream_temp1, false, empty_stream);
|
||||
ClearStream(stream_temp1);
|
||||
}
|
||||
}
|
||||
@@ -1358,137 +1359,27 @@ void Generator<StreamType>::MakeTextIf_go(Item & item, bool result)
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::MakeTextIf(Item & item)
|
||||
{
|
||||
if( item.functions.size() != 1 )
|
||||
return;
|
||||
|
||||
is_generating_if = true;
|
||||
|
||||
if( !Call(item.functions[0]) )
|
||||
if( !Call(item.function) )
|
||||
return;
|
||||
|
||||
MakeTextIf_go(item, last_res);
|
||||
}
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::MakeTextIfno(Item & item)
|
||||
{
|
||||
if( item.functions.size() != 1 )
|
||||
return;
|
||||
|
||||
is_generating_if = true;
|
||||
|
||||
if( !Call(item.functions[0]) )
|
||||
return;
|
||||
|
||||
MakeTextIf_go(item, !last_res);
|
||||
}
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::MakeTextIfany(Item & item)
|
||||
{
|
||||
std::vector<typename Item::Function>::iterator d = item.functions.begin();
|
||||
unsigned how_many_true = 0;
|
||||
|
||||
is_generating_if = true;
|
||||
|
||||
for( ; d != item.functions.end() ; ++d )
|
||||
{
|
||||
if( !Call(*d) )
|
||||
return;
|
||||
|
||||
if( last_res )
|
||||
++how_many_true;
|
||||
}
|
||||
|
||||
MakeTextIf_go(item, how_many_true == item.functions.size());
|
||||
}
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::MakeTextIfone(Item & item)
|
||||
{
|
||||
std::vector<typename Item::Function>::iterator d = item.functions.begin();
|
||||
unsigned how_many_true = 0;
|
||||
|
||||
is_generating_if = true;
|
||||
|
||||
for( ; d != item.functions.end() ; ++d )
|
||||
{
|
||||
if( Call(*d) )
|
||||
{
|
||||
if( last_res )
|
||||
{
|
||||
++how_many_true;
|
||||
break; // there is no sense to go through all functions
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MakeTextIf_go(item, how_many_true > 0);
|
||||
}
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::MakeTextIfanyno(Item & item)
|
||||
{
|
||||
std::vector<typename Item::Function>::iterator d = item.functions.begin();
|
||||
unsigned how_many_true = 0;
|
||||
|
||||
is_generating_if = true;
|
||||
|
||||
for( ; d != item.functions.end() ; ++d )
|
||||
{
|
||||
if( !Call(*d) )
|
||||
return;
|
||||
|
||||
if( last_res )
|
||||
++how_many_true;
|
||||
}
|
||||
|
||||
MakeTextIf_go(item, how_many_true == 0);
|
||||
}
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::MakeTextIfoneno(Item & item)
|
||||
{
|
||||
std::vector<typename Item::Function>::iterator d = item.functions.begin();
|
||||
unsigned how_many_false = 0;
|
||||
|
||||
is_generating_if = true;
|
||||
|
||||
for( ; d != item.functions.end() ; ++d )
|
||||
{
|
||||
if( Call(*d) )
|
||||
{
|
||||
if( !last_res )
|
||||
{
|
||||
++how_many_false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MakeTextIf_go(item, how_many_false > 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::MakeTextFor(Item & item)
|
||||
{
|
||||
if( item.functions.size() != 1 )
|
||||
return;
|
||||
|
||||
stack_tab[stack_index-1].is_for = true;
|
||||
|
||||
for( ; !break_generating ; stack_tab[stack_index-1].iter += 1 )
|
||||
{
|
||||
if( stack_tab[stack_index-1].iter >= max_for_items )
|
||||
{
|
||||
CreateMsg(item.functions[0].name.c_str(),
|
||||
CreateMsg(item.function.name.c_str(),
|
||||
L"function exceeded a limit for a [for] statement");
|
||||
break;
|
||||
}
|
||||
@@ -1496,7 +1387,7 @@ void Generator<StreamType>::MakeTextFor(Item & item)
|
||||
// is_generating_for will be changed by next call to MakeText()
|
||||
// so we should set it in each iterations
|
||||
is_generating_for = true;
|
||||
Call(item.functions[0], stream_temp1, true, empty_stream);
|
||||
Call(item.function, stream_temp1, true, empty_stream);
|
||||
|
||||
if( !last_res )
|
||||
break;
|
||||
@@ -1511,53 +1402,40 @@ void Generator<StreamType>::MakeTextFor(Item & item)
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::MakeTextDefine(Item & item)
|
||||
{
|
||||
Item::Function * pfun = 0;
|
||||
|
||||
if( !can_use_vars )
|
||||
{
|
||||
CreateMsg(L"[def] statement not available");
|
||||
return;
|
||||
}
|
||||
|
||||
if( item.functions.size() == 1 &&
|
||||
item.functions[0].parameters.size() == 1 )
|
||||
{
|
||||
if( item.functions[0].parameters[0]->name.empty() )
|
||||
{
|
||||
// it is [def name "string"]
|
||||
temp_var.str = item.functions[0].parameters[0]->par;
|
||||
temp_var.res = !temp_var.str.empty();
|
||||
vars[item.functions[0].name] = temp_var;
|
||||
}
|
||||
else
|
||||
{
|
||||
// it is [def name [function "funpar"]]
|
||||
pfun = item.functions[0].parameters[0];
|
||||
}
|
||||
}
|
||||
|
||||
if( item.functions.size() == 2 )
|
||||
{
|
||||
// is is [def name function "funpar"]
|
||||
pfun = &item.functions[1];
|
||||
}
|
||||
|
||||
if( pfun )
|
||||
{
|
||||
if( Call(*pfun, stream_temp_define, true, empty_stream) )
|
||||
{
|
||||
#ifdef EZC_HAS_SPECIAL_STREAM
|
||||
temp_var.str = stream_temp_define.Str();
|
||||
#else
|
||||
temp_var.str = stream_temp_define.str();
|
||||
#endif
|
||||
|
||||
temp_var.res = last_res;
|
||||
vars[item.functions[0].name] = temp_var;
|
||||
Var & var = vars[item.function.name];
|
||||
var.str.clear();
|
||||
var.res = false;
|
||||
|
||||
for(size_t i=0 ; i < item.function.parameters.size() ; ++i)
|
||||
{
|
||||
if( !item.function.parameters[i]->is_function )
|
||||
{
|
||||
var.str += item.function.parameters[i]->name;
|
||||
var.res = ConvertToBool(item.function.parameters[i]->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateMsg(L"[def] unknown function/block/variable", pfun->name);
|
||||
// it is a function parameter
|
||||
if( Call(*item.function.parameters[i], stream_temp_define, true, empty_stream) )
|
||||
{
|
||||
#ifdef EZC_HAS_SPECIAL_STREAM
|
||||
var.str += stream_temp_define.Str();
|
||||
#else
|
||||
var.str += stream_temp_define.str();
|
||||
#endif
|
||||
|
||||
var.res = last_res;
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateMsg(L"[def] unknown function/block/variable", item.function.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1568,14 +1446,11 @@ Item::Function * pfun = 0;
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::MakeTextFilter(Item & item)
|
||||
{
|
||||
if( item.functions.size() != 1 )
|
||||
return;
|
||||
|
||||
typename Functions<StreamType>::UserFunction * function;
|
||||
Item * item_block;
|
||||
std::wstring * variable;
|
||||
|
||||
if( !Find(item.functions[0], &function, &item_block, &variable) )
|
||||
if( !Find(item.function, &function, &item_block, &variable) )
|
||||
return;
|
||||
|
||||
// IMPROVE ME
|
||||
@@ -1605,13 +1480,11 @@ void Generator<StreamType>::MakeTextFilter(Item & item)
|
||||
|
||||
if( old_stream )
|
||||
{
|
||||
//Call(function, item.functions[0].params, *old_stream, false, *output_stream);
|
||||
Call(item.functions[0], *old_stream, false, *output_stream);
|
||||
Call(item.function, *old_stream, false, *output_stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Call(function, item.functions[0].params, stream_temp1, true, *output_stream);
|
||||
Call(item.functions[0], stream_temp1, true, *output_stream);
|
||||
Call(item.function, stream_temp1, true, *output_stream);
|
||||
ClearStream(stream_temp1);
|
||||
}
|
||||
|
||||
@@ -1632,7 +1505,7 @@ void Generator<StreamType>::MakeEzcStream(Item::Function & fun)
|
||||
|
||||
for(size_t i=0 ; i<fun.parameters.size() ; ++i)
|
||||
{
|
||||
size_t index = StrToSize(fun.parameters[i]->par.c_str()); // !! CHECK ME or ->name ?
|
||||
size_t index = StrToSize(fun.parameters[i]->name.c_str());
|
||||
|
||||
if( index < output_stream_tab.size() )
|
||||
{
|
||||
@@ -1665,15 +1538,12 @@ void Generator<StreamType>::MakeEzcStream(Item::Function & fun)
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::MakeTextEzc(Item & item)
|
||||
{
|
||||
for(size_t i=0 ; i<item.functions.size() ; ++i)
|
||||
{
|
||||
if( item.functions[i].name == L"stream" )
|
||||
MakeEzcStream(item.functions[i]);
|
||||
else
|
||||
CreateMsg(L"incorrect argument to [ezc] statement");
|
||||
if( item.function.name == L"stream" )
|
||||
MakeEzcStream(item.function);
|
||||
else
|
||||
CreateMsg(L"incorrect argument to [ezc] statement");
|
||||
|
||||
// in the future we can use more builtin functions
|
||||
}
|
||||
// in the future we can use more builtin functions
|
||||
}
|
||||
|
||||
|
||||
@@ -1692,11 +1562,11 @@ void Generator<StreamType>::MakeTextReturn(Item & item)
|
||||
BlockStack & block_stack = block_stack_tab[block_stack_index - 1];
|
||||
block_stack.was_return = true;
|
||||
|
||||
if( !item.functions.empty() )
|
||||
if( item.has_function )
|
||||
{
|
||||
// output stream in [return] statement is ignored
|
||||
// output stream in [return] statement is ignored (we use only the stream produced by the whole block)
|
||||
// this Call() sets last_res which is used later when we return to CallBlock()
|
||||
Call(item.functions[0], stream_temp1, false, empty_stream);
|
||||
Call(item.function, stream_temp1, false, empty_stream);
|
||||
ClearStream(stream_temp1);
|
||||
}
|
||||
}
|
||||
@@ -1751,13 +1621,8 @@ void Generator<StreamType>::MakeText(Item & item)
|
||||
|
||||
if ( item.type == Item::item_text ) MakeItemText(item);
|
||||
else if( item.type == Item::item_container )MakeTextContainer(item);
|
||||
else if( item.type == Item::item_normal ) MakeTextNormal(item);
|
||||
else if( item.type == Item::item_function ) MakeTextNormal(item);
|
||||
else if( item.type == Item::item_if ) MakeTextIf(item);
|
||||
else if( item.type == Item::item_ifno ) MakeTextIfno(item);
|
||||
else if( item.type == Item::item_ifany ) MakeTextIfany(item);
|
||||
else if( item.type == Item::item_ifone ) MakeTextIfone(item);
|
||||
else if( item.type == Item::item_ifanyno ) MakeTextIfanyno(item);
|
||||
else if( item.type == Item::item_ifoneno ) MakeTextIfoneno(item);
|
||||
else if( item.type == Item::item_def ) MakeTextDefine(item);
|
||||
else if( item.type == Item::item_for ) MakeTextFor(item);
|
||||
else if( item.type == Item::item_filter ) MakeTextFilter(item);
|
||||
|
Reference in New Issue
Block a user