added: an optional string parameter to normal statement e.g. [function "parameter"]

parameters to "for" statement  [for function "parameter"]
changed: in Info struct there is a "par" std::string reference now
changed: Info::result to Info::res
removed: Info::is


git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@295 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
2010-05-30 21:07:15 +00:00
parent f65178dd0e
commit b89c6daa7d
4 changed files with 231 additions and 111 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2007, Tomasz Sowa Copyright (c) 2007-2010, 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
+1 -1
View File
@@ -1,3 +1,3 @@
# DO NOT DELETE # DO NOT DELETE
edanticezc.o: ezc.h /home/tomek/roboczy/winix/core/log.h ezc.o: ezc.h
+196 -91
View File
@@ -523,10 +523,18 @@ void Pattern::ReadDirectiveFor(Item & item)
Item::Directive directive = ReadDirective(); Item::Directive directive = ReadDirective();
if( !directive.name.empty() ) if( !directive.name.empty() )
{
item.directives.push_back(directive); item.directives.push_back(directive);
else
item.type = Item::item_err;
Item::Directive parameter = ReadString();
if( !parameter.name.empty() )
item.directives.push_back(parameter);
}
else
{
item.type = Item::item_err;
}
} }
@@ -571,6 +579,20 @@ void Pattern::ReadDirectiveDef(Item & item)
} }
void Pattern::ReadDirectiveNormal(Item::Directive & directive, Item & item)
{
// user defined directive
item.directives.push_back(directive);
item.type = Item::item_normal;
// an optional parameter
Item::Directive parameter = ReadString();
if( !parameter.name.empty() )
item.directives.push_back(parameter);
}
void Pattern::CreateTreeReadItemDirective(Item & item) void Pattern::CreateTreeReadItemDirective(Item & item)
{ {
@@ -614,11 +636,7 @@ void Pattern::CreateTreeReadItemDirective(Item & item)
if( directive.name == "#" ) if( directive.name == "#" )
ReadDirectiveComment(item); ReadDirectiveComment(item);
else else
{ ReadDirectiveNormal(directive, item);
// user defined
item.directives.push_back(directive);
item.type = Item::item_normal;
}
CreateTreeReadItemDirectiveCheckEnding(item); CreateTreeReadItemDirectiveCheckEnding(item);
} }
@@ -865,6 +883,9 @@ Pattern::Item::~Item()
} }
/* /*
* *
* Info * Info
@@ -874,14 +895,12 @@ Pattern::Item::~Item()
void Info::Clear() void Info::Clear()
{ {
// default settings indicate 'false' res = false; // false by default
result = false; iter = 0;
is = 0;
iter = 0;
} }
Info::Info(std::ostringstream & o) : out(o) Info::Info(std::ostringstream & o, const std::string & p) : out(o), par(p)
{ {
Clear(); Clear();
} }
@@ -889,6 +908,7 @@ Info::Info(std::ostringstream & o) : out(o)
/* /*
* *
* Functions * Functions
@@ -967,12 +987,72 @@ void Functions::Clear()
*/ */
Generator::Generator()
{
output_stream = 0;
pattern = 0;
functions = 0;
max_items = 50000;
max_for_items = 5000;
}
Generator::Generator(std::ostringstream & o, Pattern & p, Functions & f)
{
output_stream = &o;
pattern = &p;
functions = &f;
max_items = 50000;
max_for_items = 5000;
}
void Generator::SetOutStream(std::ostringstream & o)
{
output_stream = &o;
}
void Generator::SetPattern(Pattern & p)
{
pattern = &p;
}
void Generator::SetFunctions(Functions & f)
{
functions = &f;
}
void Generator::SetMax(int max_items_, int max_for_items_)
{
max_items = max_items_;
max_for_items = max_for_items_;
}
void Generator::Generate()
{
if( !output_stream || !pattern || !functions )
return;
current_item = 0;
MakeText( pattern->item_root );
}
bool Generator::Find(const std::string & key, Functions::Function ** function) bool Generator::Find(const std::string & key, Functions::Function ** function)
{ {
if( !functions.Find(key, function) ) if( !functions->Find(key, function) )
{ {
CreateMsg(output_stream, "can't find", key.c_str() ); CreateMsg(*output_stream, "can't find", key.c_str() );
return false; return false;
} }
@@ -986,7 +1066,7 @@ void Generator::CallUserFunction(Functions::Function * function, Info & info)
if( function->is_running ) if( function->is_running )
{ {
// recurrences are not allowed // recurrences are not allowed
CreateMsg(output_stream, "the function is currently running" ); CreateMsg(*output_stream, "the function is being executed" );
return; return;
} }
@@ -996,21 +1076,18 @@ void Generator::CallUserFunction(Functions::Function * function, Info & info)
} }
void Generator::CallVariable(Functions::Function * function, Info & info) void Generator::CallVariable(Functions::Function * function, Info & info)
{ {
if( info.is || function->is_for ) info.res = !function->variable.empty();
return;
info.out << function->variable;
} }
void Generator::Call(Functions::Function * function, Info & info, const std::string * is) void Generator::Call(Functions::Function * function, Info & info)
{ {
info.Clear(); info.Clear();
info.iter = function->iter; info.iter = function->iter;
info.is = is;
if( function->type == Functions::function ) if( function->type == Functions::function )
CallUserFunction(function, info); CallUserFunction(function, info);
@@ -1020,13 +1097,13 @@ void Generator::Call(Functions::Function * function, Info & info, const std::str
// return: true if a function or variable was found and called // return: true if a function or variable was found and called
bool Generator::Call(const std::string & name, Info & info, Functions::Function ** pfun, const std::string * is) bool Generator::Call(const std::string & name, Info & info, Functions::Function ** pfun)
{ {
Functions::Function * function; Functions::Function * function;
if( Find(name, &function) ) if( Find(name, &function) )
{ {
Call(function, info, is); Call(function, info);
if( pfun ) if( pfun )
*pfun = function; *pfun = function;
@@ -1034,24 +1111,12 @@ bool Generator::Call(const std::string & name, Info & info, Functions::Function
return true; return true;
} }
return false; return false;
} }
Generator::Generator(std::ostringstream & o, Pattern & p, Functions & f) : output_stream(o), pattern(p), functions(f), info1(o), info2(o)
{
}
void Generator::Generate()
{
loop = 0;
MakeText( pattern.item_root );
}
@@ -1059,26 +1124,37 @@ void Generator::MakeTextContainer(Pattern::Item & item)
{ {
std::vector<Pattern::Item*>::iterator i = item.item_table.begin(); std::vector<Pattern::Item*>::iterator i = item.item_table.begin();
for( ; i != item.item_table.end() ; ++i ) for( ; i != item.item_table.end() && current_item != -1 ; ++i )
{
MakeText(**i); MakeText(**i);
if( loop < 0 )
break;
}
} }
void Generator::MakeTextNormal(Pattern::Item & item) void Generator::MakeTextNormal(Pattern::Item & item)
{ {
if( item.directives.size() != 1 ) if( item.directives.empty() )
return; return;
Call(item.directives[0].name, info1); Functions::Function * pfun;
bool called;
if( item.directives.size() == 2 )
{
Info info(*output_stream, item.directives[1].name);
called = Call(item.directives[0].name, info, &pfun);
}
else
{
Info info(*output_stream, empty);
called = Call(item.directives[0].name, info, &pfun);
}
if( called && pfun->type == Functions::variable )
*output_stream << pfun->variable;
} }
void Generator::MakeTextIf_go(Pattern::Item & item, bool result) void Generator::MakeTextIf_go(Pattern::Item & item, bool result)
{ {
if( result ) if( result )
@@ -1102,11 +1178,12 @@ void Generator::MakeTextIfany(Pattern::Item & item)
for( ; d != item.directives.end() ; ++d ) for( ; d != item.directives.end() ; ++d )
{ {
if( !Call(d->name, info1) ) Info info(*output_stream, empty);
// maybe it should only be treated as a false? (when there is no such a function/variable)
if( !Call(d->name, info) )
return; return;
if( info1.result ) if( info.res )
++how_many_true; ++how_many_true;
} }
@@ -1121,7 +1198,9 @@ void Generator::MakeTextIfno(Pattern::Item & item)
for( ; d != item.directives.end() ; ++d ) for( ; d != item.directives.end() ; ++d )
{ {
if( Call(d->name, info1) && info1.result ) Info info(*output_stream, empty);
if( Call(d->name, info) && info.res )
{ {
// there is no sense to go through all functions // there is no sense to go through all functions
++how_many_true; ++how_many_true;
@@ -1141,7 +1220,9 @@ void Generator::MakeTextIfone(Pattern::Item & item)
for( ; d != item.directives.end() ; ++d ) for( ; d != item.directives.end() ; ++d )
{ {
if( Call(d->name, info1) && info1.result ) Info info(*output_stream, empty);
if( Call(d->name, info) && info.res )
{ {
// there is no sense to go through all functions // there is no sense to go through all functions
++how_many_true; ++how_many_true;
@@ -1163,8 +1244,10 @@ Functions::Function * function;
if( function->type == Functions::function ) if( function->type == Functions::function )
{ {
Call(function, info1, &text); Info info(*output_stream, text);
res = info1.result;
Call(function, info);
res = info.res;
} }
else else
{ {
@@ -1190,21 +1273,28 @@ Functions::Function * function1, * function2;
if( function1->type == Functions::function && function2->type == Functions::function ) if( function1->type == Functions::function && function2->type == Functions::function )
{ {
Info info1(*output_stream, empty);
Info info2(*output_stream, empty);
Call(function1, info1); Call(function1, info1);
Call(function2, info2); Call(function2, info2);
res = (info1.result == info2.result); res = (info1.res == info2.res);
} }
else else
if( function1->type == Functions::function ) if( function1->type == Functions::function )
{ {
Call(function1, info1, &fun_name2); // only the former is a function Info info(*output_stream, fun_name2);
res = info1.result;
Call(function1, info); // only the former is a function
res = info.res;
} }
else else
if( function2->type == Functions::function ) if( function2->type == Functions::function )
{ {
Call(function2, info2, &fun_name1); // only the latter is a function Info info(*output_stream, fun_name1);
res = info2.result;
Call(function2, info); // only the latter is a function
res = info.res;
} }
else else
res = (function1->variable == function2->variable); // both are variables res = (function1->variable == function2->variable); // both are variables
@@ -1268,14 +1358,11 @@ bool Generator::MakeTextIfindexnumber(Pattern::Item & item, Functions::Function
if( *last_char == '\0' ) if( *last_char == '\0' )
{ {
if( function->iter == number ) result = (function->iter == number);
result = true;
// we don't have to set result as false (false is default)
} }
else else
{ {
CreateMsg(output_stream, "if-index: syntax error"); CreateMsg(*output_stream, "if-index: syntax error");
return false; return false;
} }
@@ -1328,11 +1415,43 @@ void Generator::MakeTextIfindex(Pattern::Item & item)
void Generator::MakeTextForLoop(Pattern::Item & item, Functions::Function * function)
{
for( ; current_item != -1 ; ++function->iter )
{
if( function->iter >= max_for_items )
{
CreateMsg(*output_stream, item.directives[0].name.c_str(), "function exceeded a limit for a [for] statement");
break;
}
if( item.directives.size() == 2 )
{
Info info(*output_stream, item.directives[1].name);
Call(function, info);
if( !info.res )
break;
}
else
{
Info info(*output_stream, empty);
Call(function, info);
if( !info.res )
break;
}
if( !item.item_table.empty() )
MakeText( *item.item_table[0] );
}
}
void Generator::MakeTextFor(Pattern::Item & item) void Generator::MakeTextFor(Pattern::Item & item)
{ {
const int max_loop = 5000; if( item.directives.empty() )
if( item.directives.size() != 1 )
return; return;
Functions::Function * function; Functions::Function * function;
@@ -1342,26 +1461,14 @@ void Generator::MakeTextFor(Pattern::Item & item)
if( function->is_for ) if( function->is_for )
{ {
CreateMsg(output_stream, item.directives[0].name.c_str(), "this function is already used in a [for] statement"); CreateMsg(*output_stream, item.directives[0].name.c_str(), "this function is already used in a [for] statement");
return; return;
} }
for( function->is_for = true, function->iter=0 ; loop != -1 ; ++function->iter )
{
if( function->iter >= max_loop )
{
CreateMsg(output_stream, item.directives[0].name.c_str(), "function exceeded a limit for a [for] statement");
break;
}
Call(function, info1);
if( !info1.result ) function->is_for = true;
break; function->iter = 0;
if( item.item_table.size() > 0 ) MakeTextForLoop(item, function);
MakeText( *item.item_table[0] );
}
function->is_for = false; function->is_for = false;
function->iter = 0; function->iter = 0;
@@ -1376,7 +1483,7 @@ void Generator::MakeTextDefine(Pattern::Item & item)
if( item.directives[1].is_text ) if( item.directives[1].is_text )
{ {
functions.Insert(item.directives[0].name, item.directives[1].name); functions->Insert(item.directives[0].name, item.directives[1].name);
} }
else else
{ {
@@ -1385,9 +1492,9 @@ void Generator::MakeTextDefine(Pattern::Item & item)
if( Find(item.directives[1].name, &function) ) if( Find(item.directives[1].name, &function) )
{ {
if( function->type == Functions::function ) if( function->type == Functions::function )
functions.Insert(item.directives[0].name, function->user_function); functions->Insert(item.directives[0].name, function->user_function);
else else
functions.Insert(item.directives[0].name, function->variable); functions->Insert(item.directives[0].name, function->variable);
} }
} }
} }
@@ -1397,22 +1504,20 @@ void Generator::MakeTextDefine(Pattern::Item & item)
void Generator::MakeText(Pattern::Item & item) void Generator::MakeText(Pattern::Item & item)
{ {
const int max_loop = 50000; if( current_item == -1 )
if( loop == -1 )
return; return;
if( ++loop > max_loop ) if( ++current_item > max_items )
{ {
loop = -1; current_item = -1;
CreateMsg(output_stream, "Generator exceeded allowed number of elements"); CreateMsg(*output_stream, "Generator exceeded allowed number of elements");
return; return;
} }
switch( item.type ) switch( item.type )
{ {
case Pattern::Item::item_text: case Pattern::Item::item_text:
output_stream << item.text; *output_stream << item.text;
break; break;
case Pattern::Item::item_container: case Pattern::Item::item_container:
MakeTextContainer(item); MakeTextContainer(item);
@@ -1445,7 +1550,7 @@ void Generator::MakeText(Pattern::Item & item)
MakeTextDefine(item); MakeTextDefine(item);
break; break;
case Pattern::Item::item_err: case Pattern::Item::item_err:
CreateMsg(output_stream, "a wrong directive"); CreateMsg(*output_stream, "a wrong directive");
break; break;
default: default:
break; break;
+33 -18
View File
@@ -164,6 +164,7 @@ private:
void ReadDirectiveComment(Item & item); void ReadDirectiveComment(Item & item);
void ReadDirectiveInclude(Item & item); void ReadDirectiveInclude(Item & item);
void ReadDirectiveDef(Item & item); void ReadDirectiveDef(Item & item);
void ReadDirectiveNormal(Item::Directive & directive, Item & item);
void CreateTreeReadItemDirective(Item & item); void CreateTreeReadItemDirective(Item & item);
@@ -185,22 +186,25 @@ private:
struct Info struct Info
{ {
// this variables you can set in your function // output stream
std::ostringstream & out; std::ostringstream & out;
//std::string out_string;
bool result;
// in a [is function "text"] statement this is the pointer to "text" object // an optional string parameter in a normal statement [user_function "parameter"]
// otherwise this is null pointer // or in "is" statement [is user_function "parameter"]
const std::string * is; // or in "for" statement [for user_function "parameter"]
const std::string & par;
// this is set by Generator // this is set by Generator
// normally is 0 // normally is 0
// in a [for] statement it indicates the number of the current iteration (the first is 0) // in a [for] statement it indicates the number of the current iteration (the first is 0)
int iter; int iter;
// return value from a user function (default false if not set directly by the user function)
// for a variable it is set to true if the variable is not empty
bool res;
Info(std::ostringstream & o); // arguments: output_stream, string_parameter
Info(std::ostringstream & o, const std::string & p);
void Clear(); void Clear();
}; };
@@ -250,26 +254,36 @@ private:
class Generator class Generator
{ {
public: public:
Generator(std::ostringstream &, Pattern & data, Functions & functions); Generator();
Generator(std::ostringstream & o, Pattern & p, Functions & f);
void SetOutStream(std::ostringstream & o);
void SetPattern(Pattern & p);
void SetFunctions(Functions & f);
void SetMax(int max_items_, int max_for_items_);
void Generate(); void Generate();
private: private:
std::ostringstream & output_stream; std::ostringstream * output_stream;
Pattern & pattern; Pattern * pattern;
Functions & functions; Functions * functions;
Info info1, info2;
int loop;
int current_item;
int max_items;
int max_for_items;
// an empty string for info objects
const std::string empty;
bool Find(const std::string & key, Functions::Function ** function); bool Find(const std::string & key, Functions::Function ** function);
void Call(Functions::Function * function, Info & info, const std::string * is = 0); void Call(Functions::Function * function, Info & info);
bool Call(const std::string & name, Info & info, Functions::Function ** pfun = 0, const std::string * is = 0); bool Call(const std::string & name, Info & info, Functions::Function ** pfun = 0);
void CallUserFunction(Functions::Function * function, Info & info); void CallUserFunction(Functions::Function * function, Info & info);
void CallVariable(Functions::Function * function, Info & info); void CallVariable(Functions::Function * function, Info & info);
@@ -280,6 +294,7 @@ private:
void MakeTextIfno(Pattern::Item & item); void MakeTextIfno(Pattern::Item & item);
void MakeTextIfone(Pattern::Item & item); void MakeTextIfone(Pattern::Item & item);
void MakeTextIfindex(Pattern::Item & item); void MakeTextIfindex(Pattern::Item & item);
void MakeTextForLoop(Pattern::Item & item, Functions::Function * function);
void MakeTextFor(Pattern::Item & item); void MakeTextFor(Pattern::Item & item);
void MakeTextContainer(Pattern::Item & item); void MakeTextContainer(Pattern::Item & item);
void MakeTextNormal(Pattern::Item & item); void MakeTextNormal(Pattern::Item & item);