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:
Tomasz Sowa 2010-05-30 21:07:15 +00:00
parent f65178dd0e
commit b89c6daa7d
4 changed files with 231 additions and 111 deletions

View File

@ -1,4 +1,4 @@
Copyright (c) 2007, Tomasz Sowa
Copyright (c) 2007-2010, Tomasz Sowa
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@ -1,3 +1,3 @@
# DO NOT DELETE
edanticezc.o: ezc.h /home/tomek/roboczy/winix/core/log.h
ezc.o: ezc.h

View File

@ -523,10 +523,18 @@ void Pattern::ReadDirectiveFor(Item & item)
Item::Directive directive = ReadDirective();
if( !directive.name.empty() )
{
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)
{
@ -614,11 +636,7 @@ void Pattern::CreateTreeReadItemDirective(Item & item)
if( directive.name == "#" )
ReadDirectiveComment(item);
else
{
// user defined
item.directives.push_back(directive);
item.type = Item::item_normal;
}
ReadDirectiveNormal(directive, item);
CreateTreeReadItemDirectiveCheckEnding(item);
}
@ -865,6 +883,9 @@ Pattern::Item::~Item()
}
/*
*
* Info
@ -874,14 +895,12 @@ Pattern::Item::~Item()
void Info::Clear()
{
// default settings indicate 'false'
result = false;
is = 0;
iter = 0;
res = false; // false by default
iter = 0;
}
Info::Info(std::ostringstream & o) : out(o)
Info::Info(std::ostringstream & o, const std::string & p) : out(o), par(p)
{
Clear();
}
@ -889,6 +908,7 @@ Info::Info(std::ostringstream & o) : out(o)
/*
*
* 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)
{
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;
}
@ -986,7 +1066,7 @@ void Generator::CallUserFunction(Functions::Function * function, Info & info)
if( function->is_running )
{
// recurrences are not allowed
CreateMsg(output_stream, "the function is currently running" );
CreateMsg(*output_stream, "the function is being executed" );
return;
}
@ -996,21 +1076,18 @@ void Generator::CallUserFunction(Functions::Function * function, Info & info)
}
void Generator::CallVariable(Functions::Function * function, Info & info)
{
if( info.is || function->is_for )
return;
info.out << function->variable;
info.res = !function->variable.empty();
}
void Generator::Call(Functions::Function * function, Info & info, const std::string * is)
void Generator::Call(Functions::Function * function, Info & info)
{
info.Clear();
info.iter = function->iter;
info.is = is;
if( function->type == Functions::function )
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
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) )
{
Call(function, info, is);
Call(function, info);
if( pfun )
*pfun = function;
@ -1034,24 +1111,12 @@ bool Generator::Call(const std::string & name, Info & info, Functions::Function
return true;
}
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();
for( ; i != item.item_table.end() ; ++i )
{
for( ; i != item.item_table.end() && current_item != -1 ; ++i )
MakeText(**i);
if( loop < 0 )
break;
}
}
void Generator::MakeTextNormal(Pattern::Item & item)
{
if( item.directives.size() != 1 )
if( item.directives.empty() )
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)
{
if( result )
@ -1102,11 +1178,12 @@ void Generator::MakeTextIfany(Pattern::Item & item)
for( ; d != item.directives.end() ; ++d )
{
if( !Call(d->name, info1) )
// maybe it should only be treated as a false? (when there is no such a function/variable)
Info info(*output_stream, empty);
if( !Call(d->name, info) )
return;
if( info1.result )
if( info.res )
++how_many_true;
}
@ -1121,7 +1198,9 @@ void Generator::MakeTextIfno(Pattern::Item & item)
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
++how_many_true;
@ -1141,7 +1220,9 @@ void Generator::MakeTextIfone(Pattern::Item & item)
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
++how_many_true;
@ -1163,8 +1244,10 @@ Functions::Function * function;
if( function->type == Functions::function )
{
Call(function, info1, &text);
res = info1.result;
Info info(*output_stream, text);
Call(function, info);
res = info.res;
}
else
{
@ -1190,21 +1273,28 @@ Functions::Function * function1, * function2;
if( function1->type == Functions::function && function2->type == Functions::function )
{
Info info1(*output_stream, empty);
Info info2(*output_stream, empty);
Call(function1, info1);
Call(function2, info2);
res = (info1.result == info2.result);
res = (info1.res == info2.res);
}
else
if( function1->type == Functions::function )
{
Call(function1, info1, &fun_name2); // only the former is a function
res = info1.result;
Info info(*output_stream, fun_name2);
Call(function1, info); // only the former is a function
res = info.res;
}
else
if( function2->type == Functions::function )
{
Call(function2, info2, &fun_name1); // only the latter is a function
res = info2.result;
Info info(*output_stream, fun_name1);
Call(function2, info); // only the latter is a function
res = info.res;
}
else
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( function->iter == number )
result = true;
// we don't have to set result as false (false is default)
result = (function->iter == number);
}
else
{
CreateMsg(output_stream, "if-index: syntax error");
CreateMsg(*output_stream, "if-index: syntax error");
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)
{
const int max_loop = 5000;
if( item.directives.size() != 1 )
if( item.directives.empty() )
return;
Functions::Function * function;
@ -1342,26 +1461,14 @@ void Generator::MakeTextFor(Pattern::Item & item)
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;
}
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 )
break;
function->is_for = true;
function->iter = 0;
if( item.item_table.size() > 0 )
MakeText( *item.item_table[0] );
}
MakeTextForLoop(item, function);
function->is_for = false;
function->iter = 0;
@ -1376,7 +1483,7 @@ void Generator::MakeTextDefine(Pattern::Item & item)
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
{
@ -1385,9 +1492,9 @@ void Generator::MakeTextDefine(Pattern::Item & item)
if( Find(item.directives[1].name, &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
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)
{
const int max_loop = 50000;
if( loop == -1 )
if( current_item == -1 )
return;
if( ++loop > max_loop )
if( ++current_item > max_items )
{
loop = -1;
CreateMsg(output_stream, "Generator exceeded allowed number of elements");
current_item = -1;
CreateMsg(*output_stream, "Generator exceeded allowed number of elements");
return;
}
switch( item.type )
{
case Pattern::Item::item_text:
output_stream << item.text;
*output_stream << item.text;
break;
case Pattern::Item::item_container:
MakeTextContainer(item);
@ -1445,7 +1550,7 @@ void Generator::MakeText(Pattern::Item & item)
MakeTextDefine(item);
break;
case Pattern::Item::item_err:
CreateMsg(output_stream, "a wrong directive");
CreateMsg(*output_stream, "a wrong directive");
break;
default:
break;

View File

@ -164,6 +164,7 @@ private:
void ReadDirectiveComment(Item & item);
void ReadDirectiveInclude(Item & item);
void ReadDirectiveDef(Item & item);
void ReadDirectiveNormal(Item::Directive & directive, Item & item);
void CreateTreeReadItemDirective(Item & item);
@ -185,22 +186,25 @@ private:
struct Info
{
// this variables you can set in your function
// output stream
std::ostringstream & out;
//std::string out_string;
bool result;
// in a [is function "text"] statement this is the pointer to "text" object
// otherwise this is null pointer
const std::string * is;
// an optional string parameter in a normal statement [user_function "parameter"]
// or in "is" statement [is user_function "parameter"]
// or in "for" statement [for user_function "parameter"]
const std::string & par;
// this is set by Generator
// normally is 0
// in a [for] statement it indicates the number of the current iteration (the first is 0)
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();
};
@ -250,26 +254,36 @@ private:
class Generator
{
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();
private:
std::ostringstream & output_stream;
Pattern & pattern;
Functions & functions;
Info info1, info2;
int loop;
std::ostringstream * output_stream;
Pattern * pattern;
Functions * functions;
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);
void Call(Functions::Function * function, Info & info, const std::string * is = 0);
bool Call(const std::string & name, Info & info, Functions::Function ** pfun = 0, const std::string * is = 0);
void Call(Functions::Function * function, Info & info);
bool Call(const std::string & name, Info & info, Functions::Function ** pfun = 0);
void CallUserFunction(Functions::Function * function, Info & info);
void CallVariable(Functions::Function * function, Info & info);
@ -280,6 +294,7 @@ private:
void MakeTextIfno(Pattern::Item & item);
void MakeTextIfone(Pattern::Item & item);
void MakeTextIfindex(Pattern::Item & item);
void MakeTextForLoop(Pattern::Item & item, Functions::Function * function);
void MakeTextFor(Pattern::Item & item);
void MakeTextContainer(Pattern::Item & item);
void MakeTextNormal(Pattern::Item & item);