changed: [is ...] command

struct Info doesn't have out_string now



git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@281 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Tomasz Sowa 2010-01-25 05:19:54 +00:00
parent dbe91a6d91
commit b2aacc2da3
2 changed files with 211 additions and 133 deletions

View File

@ -134,14 +134,14 @@ void Pattern::ParseFile(const std::string & file_name)
void Pattern::ParseFile(const char * file_name)
{
std::string file;
Item::Directive file;
file.is_text = true;
if( directory.empty() )
SplitUnixDirectory(file_name, directory, file);
SplitUnixDirectory(file_name, directory, file.name);
else
file = file_name;
file.insert(file.begin(), '\"');
file.name = file_name;
item_root.directives.clear();
item_root.directives.push_back( file );
@ -191,6 +191,15 @@ return true;
}
/*
'name' must be a relative path
*/
std::string Pattern::ReadFile(const std::string & name)
{
return ReadFile(name.c_str());
}
/*
'name' must be a relative path
*/
@ -272,10 +281,11 @@ std::string::size_type i;
std::string Pattern::ReadDirective()
Pattern::Item::Directive Pattern::ReadDirective()
{
std::string directive;
Item::Directive directive;
directive.is_text = false;
SkipWhiteCharacters();
while( (*itext>='a' && *itext<='z') ||
@ -283,8 +293,7 @@ std::string directive;
(*itext>='0' && *itext<='9') ||
*itext=='_' || *itext=='-' || *itext=='.' || *itext=='#' )
{
directive += *itext;
directive.name += *itext;
++itext;
}
@ -294,36 +303,52 @@ return directive;
std::string Pattern::ReadString(bool skip_first_quote)
// string can have a quote character (escaped with a backslash) e.g. "sample text \"with quotes\""
// use \\ to insert one backslash
Pattern::Item::Directive Pattern::ReadString()
{
std::string directive;
Item::Directive directive;
directive.is_text = true;
SkipWhiteCharacters();
// string is signed by its first character equal (")
if( *itext != '\"' )
return directive;
// string is signed by its first character equal (")
if( !skip_first_quote )
directive += '\"';
// skipping the first quote character
++itext;
for( ++itext ; *itext && *itext!='\"' && *itext!='\n' ; ++itext )
directive += *itext;
for( ; *itext && *itext!='\"' && *itext!='\n' ; ++itext )
{
if( itext[0]=='\\' && itext[1]=='\"' )
{
directive.name += '\"';
++itext;
}
else
if( itext[0]=='\\' && itext[1]=='\\' )
{
directive.name += '\\';
++itext;
}
else
{
directive.name += *itext;
}
}
if( *itext != '\"' )
// the second quotation mark (") is missing
directive.clear();
directive.name.clear();
else
++itext;
// the second quotation mark (") we don't add into the 'directive'
return directive;
}
std::string Pattern::ReadDirectiveOrString()
Pattern::Item::Directive Pattern::ReadDirectiveOrString()
{
SkipWhiteCharacters();
@ -362,9 +387,9 @@ void Pattern::ReadDirectiveIfany(Item & item)
while( true )
{
std::string directive = ReadDirective();
Item::Directive directive = ReadDirective();
if( directive.empty() )
if( directive.name.empty() )
break;
item.directives.push_back(directive);
@ -397,15 +422,15 @@ void Pattern::ReadDirectiveIfone(Item & item)
void Pattern::ReadDirectiveIs(Item & item)
{
item.type = Item::item_is;
std::string directive = ReadDirective();
Item::Directive directive = ReadDirectiveOrString();
if( !directive.empty() )
if( directive.is_text || !directive.name.empty() )
{
item.directives.push_back(directive);
directive = ReadDirectiveOrString();
if( !directive.empty() )
if( directive.is_text || !directive.name.empty() )
item.directives.push_back(directive);
}
@ -417,15 +442,15 @@ void Pattern::ReadDirectiveIs(Item & item)
void Pattern::ReadDirectiveIfindex(Item & item)
{
item.type = Item::item_ifindex;
std::string directive = ReadDirective();
Item::Directive directive = ReadDirective();
if( !directive.empty() )
if( !directive.name.empty() )
{
item.directives.push_back(directive);
directive = ReadDirective();
if( !directive.empty() )
if( !directive.name.empty() )
item.directives.push_back(directive);
}
@ -437,9 +462,9 @@ void Pattern::ReadDirectiveIfindex(Item & item)
void Pattern::ReadDirectiveFor(Item & item)
{
item.type = Item::item_for;
std::string directive = ReadDirective();
Item::Directive directive = ReadDirective();
if( !directive.empty() )
if( !directive.name.empty() )
item.directives.push_back(directive);
else
item.type = Item::item_err;
@ -459,28 +484,27 @@ void Pattern::ReadDirectiveComment(Item & item)
void Pattern::ReadDirectiveInclude(Item & item)
{
item.type = Item::item_include;
std::string directive = ReadString();
Item::Directive directive = ReadString();
if( !directive.empty() )
if( !directive.name.empty() )
item.directives.push_back(directive);
else
item.type = Item::item_err;
}
void Pattern::ReadDirectiveDef(Item & item)
{
item.type = Item::item_def;
std::string directive = ReadDirective();
Item::Directive directive = ReadDirective();
if( !directive.empty() )
if( !directive.name.empty() )
{
item.directives.push_back(directive);
directive = ReadDirectiveOrString();
if( !directive.empty() )
if( directive.is_text || !directive.name.empty() )
item.directives.push_back(directive);
}
@ -494,39 +518,39 @@ void Pattern::CreateTreeReadItemDirective(Item & item)
{
++itext;
std::string directive = ReadDirective();
Item::Directive directive = ReadDirective();
if( directive == "if-any" )
if( directive.name == "if-any" )
ReadDirectiveIfany(item);
else
if( directive == "if-no" )
if( directive.name == "if-no" )
ReadDirectiveIfno(item);
else
if( directive == "if-one" )
if( directive.name == "if-one" )
ReadDirectiveIfone(item);
else
if( directive == "is" )
if( directive.name == "is" )
ReadDirectiveIs(item);
else
if( directive == "if-index" )
if( directive.name == "if-index" )
ReadDirectiveIfindex(item);
else
if( directive == "end" )
if( directive.name == "end" )
item.type = Item::item_end;
else
if( directive == "else" )
if( directive.name == "else" )
item.type = Item::item_else;
else
if( directive == "for" )
if( directive.name == "for" )
ReadDirectiveFor(item);
else
if( directive == "include" )
if( directive.name == "include" )
ReadDirectiveInclude(item);
else
if( directive == "def" )
if( directive.name == "def" )
ReadDirectiveDef(item);
else
if( directive == "#" )
if( directive.name == "#" )
ReadDirectiveComment(item);
else
{
@ -578,15 +602,15 @@ return false;
void Pattern::CreateTreeReadInclude(Item & item)
{
if( !allow_include || item.directives.empty() || item.directives[0].empty() || item.directives[0][0]!='\"' )
if( !allow_include || item.directives.empty() || !item.directives[0].is_text || item.directives[0].name.empty() )
return;
std::string file_text = ReadFile( item.directives[0].c_str()+1 );
std::string file_text = ReadFile( item.directives[0].name );
const char * itext_copy = itext;
const char * itext_old = itext;
itext = file_text.c_str();
CreateTree(item);
itext = itext_copy;
itext = itext_old;
}
@ -765,8 +789,7 @@ void Info::Clear()
{
// default settings indicate 'false'
result = false;
out_string.clear();
is = 0;
iter = 0;
}
@ -777,20 +800,6 @@ Info::Info(std::ostringstream & o) : out(o)
}
bool Info::IsTrue() const
{
if( result || !out_string.empty() )
return true;
return false;
}
bool Info::IsFalse() const
{
return !IsTrue();
}
/*
@ -887,7 +896,6 @@ return true;
void Generator::CallUserFunction(Functions::Function * function, Info & info)
{
// przetestowac to jeszcze !!!! (wczesniej sprawdzenie bylo w Find) !!
if( function->is_running )
{
// recurrences are not allowed
@ -903,15 +911,19 @@ void Generator::CallUserFunction(Functions::Function * function, Info & info)
void Generator::CallVariable(Functions::Function * function, Info & info)
{
info.out_string = function->variable;
if( info.is || function->is_for )
return;
info.out << function->variable;
}
void Generator::Call(Functions::Function * function, Info & info)
void Generator::Call(Functions::Function * function, Info & info, const std::string * is)
{
info.Clear();
info.iter = function->iter;
info.is = is;
if( function->type == Functions::function )
CallUserFunction(function, info);
@ -921,13 +933,13 @@ void Generator::Call(Functions::Function * function, Info & info)
// return: true if a function or variable was found and called
bool Generator::Call(const std::string & name, Info & info, Functions::Function ** pfun)
bool Generator::Call(const std::string & name, Info & info, Functions::Function ** pfun, const std::string * is)
{
Functions::Function * function;
if( Find(name, &function) )
{
Call(function, info);
Call(function, info, is);
if( pfun )
*pfun = function;
@ -976,10 +988,7 @@ void Generator::MakeTextNormal(Pattern::Item & item)
if( item.directives.size() != 1 )
return;
Call(item.directives[0], info1);
if( !info1.out_string.empty() )
output_stream << info1.out_string;
Call(item.directives[0].name, info1);
}
@ -1001,16 +1010,16 @@ void Generator::MakeTextIf_go(Pattern::Item & item, bool result)
void Generator::MakeTextIfany(Pattern::Item & item)
{
std::vector<std::string>::iterator d = item.directives.begin();
std::vector<Pattern::Item::Directive>::iterator d = item.directives.begin();
unsigned how_many_true = 0;
for( ; d != item.directives.end() ; ++d )
{
if( !Call(*d, info1) )
if( !Call(d->name, info1) )
// maybe it should only be treated as a false? (when there is no such a function/variable)
return;
if( info1.IsTrue() )
if( info1.result )
++how_many_true;
}
@ -1020,12 +1029,12 @@ void Generator::MakeTextIfany(Pattern::Item & item)
void Generator::MakeTextIfno(Pattern::Item & item)
{
std::vector<std::string>::iterator d = item.directives.begin();
std::vector<Pattern::Item::Directive>::iterator d = item.directives.begin();
unsigned how_many_true = 0;
for( ; d != item.directives.end() ; ++d )
{
if( Call(*d, info1) && info1.IsTrue() )
if( Call(d->name, info1) && info1.result )
{
// there is no sense to go through all functions
++how_many_true;
@ -1040,12 +1049,12 @@ void Generator::MakeTextIfno(Pattern::Item & item)
void Generator::MakeTextIfone(Pattern::Item & item)
{
std::vector<std::string>::iterator d = item.directives.begin();
std::vector<Pattern::Item::Directive>::iterator d = item.directives.begin();
int how_many_true = 0;
for( ; d != item.directives.end() ; ++d )
{
if( Call(*d, info1) && info1.IsTrue() )
if( Call(d->name, info1) && info1.result )
{
// there is no sense to go through all functions
++how_many_true;
@ -1057,30 +1066,97 @@ void Generator::MakeTextIfone(Pattern::Item & item)
}
bool Generator::MakeTextIsFunText(const std::string & fun_name, const std::string & text, bool & res)
{
Functions::Function * function;
if( !Find(fun_name, &function) )
return false;
if( function->type == Functions::function )
{
Call(function, info1, &text);
res = info1.result;
}
else
{
// this is a variable
res = (function->variable == text);
}
return true;
}
bool Generator::MakeTextIsFunFun(const std::string & fun_name1, const std::string & fun_name2, bool & res)
{
Functions::Function * function1, * function2;
if( !Find(fun_name1, &function1) )
return false;
if( !Find(fun_name2, &function2) )
return false;
if( function1->type == Functions::function && function2->type == Functions::function )
{
Call(function1, info1);
Call(function2, info2);
res = (info1.result == info2.result);
}
else
if( function1->type == Functions::function )
{
Call(function1, info1, &fun_name2); // only the former is a function
res = info1.result;
}
else
if( function2->type == Functions::function )
{
Call(function2, info2, &fun_name1); // only the latter is a function
res = info2.result;
}
else
res = (function1->variable == function2->variable); // both are variables
return false;
}
void Generator::MakeTextIs(Pattern::Item & item)
{
if( item.directives.size() != 2 )
return;
if( !Call(item.directives[0], info1) )
return;
bool result = false;
if( !item.directives[1].empty() && item.directives[1][0]=='\"' )
if( item.directives[0].is_text && item.directives[1].is_text )
{
// second directive is a string
if( std::strcmp(info1.out_string.c_str(), item.directives[1].c_str()+1) == 0 )
result = true;
// both directives are text
result = (item.directives[0].name == item.directives[1].name);
}
else
if( item.directives[0].is_text )
{
// first directive is text, second not
if( !MakeTextIsFunText(item.directives[1].name, item.directives[0].name, result) )
return;
}
else
if( item.directives[1].is_text )
{
// second directive is text, first not
if( !MakeTextIsFunText(item.directives[0].name, item.directives[1].name, result) )
return;
}
else
{
if( Call(item.directives[1], info2) )
{
if( info1.result==info2.result && info1.out_string==info2.out_string )
result = true;
}
// both directive are not text
MakeTextIsFunFun(item.directives[0].name, item.directives[1].name, result);
}
MakeTextIf_go(item, result);
@ -1092,7 +1168,7 @@ bool Generator::MakeTextIfindexnumber(Pattern::Item & item, Functions::Function
if( item.directives.size() != 2 )
return false;
const char * number_text = item.directives[1].c_str();
const char * number_text = item.directives[1].name.c_str();
char * last_char;
int number = (int)strtol(number_text, &last_char, 10);
@ -1125,25 +1201,25 @@ void Generator::MakeTextIfindex(Pattern::Item & item)
Functions::Function * function;
if( !Find(item.directives[0], &function) )
if( !Find(item.directives[0].name, &function) )
return;
bool result = false;
if( item.directives[1] == "odd" )
if( item.directives[1].name == "odd" )
{
if( (function->iter & 1) == 1 )
result = true;
}
else
if( item.directives[1] == "even" )
if( item.directives[1].name == "even" )
{
if( (function->iter & 1) == 0 )
result = true;
}
else
if( item.directives[1] == "first" )
if( item.directives[1].name == "first" )
{
if( function->iter == 0 )
result = true;
@ -1168,12 +1244,12 @@ void Generator::MakeTextFor(Pattern::Item & item)
Functions::Function * function;
if( !Find(item.directives[0], &function) )
if( !Find(item.directives[0].name, &function) )
return;
if( function->is_for )
{
CreateMsg(output_stream, item.directives[0].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;
}
@ -1181,13 +1257,13 @@ void Generator::MakeTextFor(Pattern::Item & item)
{
if( function->iter >= max_loop )
{
CreateMsg(output_stream, item.directives[0].c_str(), "function exceeded a limit for a [for] statement");
CreateMsg(output_stream, item.directives[0].name.c_str(), "function exceeded a limit for a [for] statement");
break;
}
Call(function, info1);
if( info1.IsFalse() )
if( !info1.result )
break;
if( item.item_table.size() > 0 )
@ -1205,21 +1281,20 @@ void Generator::MakeTextDefine(Pattern::Item & item)
if( item.directives.size() != 2 )
return;
if( !item.directives[1].empty() && item.directives[1][0]=='\"' )
if( item.directives[1].is_text )
{
// second directive is a string
functions.Insert(item.directives[0], item.directives[1].c_str() + 1);
functions.Insert(item.directives[0].name, item.directives[1].name);
}
else
{
Functions::Function * function;
if( Find(item.directives[1], &function) )
if( Find(item.directives[1].name, &function) )
{
if( function->type == Functions::function )
functions.Insert(item.directives[0], function->user_function);
functions.Insert(item.directives[0].name, function->user_function);
else
functions.Insert(item.directives[0], function->variable);
functions.Insert(item.directives[0].name, function->variable);
}
}
}

View File

@ -35,11 +35,6 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* version 0.9.2
*
*/
#ifndef headerfileezc
#define headerfileezc
@ -87,13 +82,17 @@ public:
item_include, item_is, item_ifone, item_comment, item_def
};
struct Directive
{
bool is_text; // if true that means a directive in quotes "static text"
std::string name;
};
ItemType type;
std::string text;
std::vector<Item*> item_table;
std::vector<std::string> directives;
std::vector<Directive> directives;
Item();
Item(const Item & i);
@ -128,6 +127,7 @@ private:
bool CheckFileName(const char * name);
std::string ReadFile(const std::string & name);
std::string ReadFile(const char * name);
int ReadCharInText();
@ -135,9 +135,9 @@ private:
void SkipWhiteCharacters();
void CheckWhiteAndDelete(std::string & s);
std::string ReadDirective();
std::string ReadString(bool skip_first_quote = false);
std::string ReadDirectiveOrString();
Item::Directive ReadDirective();
Item::Directive ReadString();
Item::Directive ReadDirectiveOrString();
void CreateTreeReadItemDirectiveCheckEnding(Item & item);
@ -172,9 +172,13 @@ struct Info
{
// this variables you can set in your function
std::ostringstream & out;
std::string out_string;
//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;
// this is set by Generator
// normally is 0
// in a [for] statement it indicates the number of the current iteration (the first is 0)
@ -183,15 +187,12 @@ struct Info
Info(std::ostringstream & o);
void Clear();
bool IsTrue() const;
bool IsFalse() const;
};
// functions or variables
class Functions
{
public:
@ -252,8 +253,8 @@ private:
bool Find(const std::string & key, Functions::Function ** function);
bool Call(const std::string & name, Info & info, Functions::Function ** pfun = 0);
void Call(Functions::Function * function, Info & info);
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 CallUserFunction(Functions::Function * function, Info & info);
void CallVariable(Functions::Function * function, Info & info);
@ -267,6 +268,8 @@ private:
void MakeTextFor(Pattern::Item & item);
void MakeTextContainer(Pattern::Item & item);
void MakeTextNormal(Pattern::Item & item);
bool MakeTextIsFunText(const std::string & fun_name, const std::string & text, bool & res);
bool MakeTextIsFunFun(const std::string & fun_name1, const std::string & fun_name2, bool & res);
void MakeTextIs(Pattern::Item & item);
void MakeTextDefine(Pattern::Item & item);
void MakeText(Pattern::Item & item);