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) void Pattern::ParseFile(const char * file_name)
{ {
std::string file; Item::Directive file;
file.is_text = true;
if( directory.empty() ) if( directory.empty() )
SplitUnixDirectory(file_name, directory, file); SplitUnixDirectory(file_name, directory, file.name);
else else
file = file_name; file.name = file_name;
file.insert(file.begin(), '\"');
item_root.directives.clear(); item_root.directives.clear();
item_root.directives.push_back( file ); 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 '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(); SkipWhiteCharacters();
while( (*itext>='a' && *itext<='z') || while( (*itext>='a' && *itext<='z') ||
@ -283,8 +293,7 @@ std::string directive;
(*itext>='0' && *itext<='9') || (*itext>='0' && *itext<='9') ||
*itext=='_' || *itext=='-' || *itext=='.' || *itext=='#' ) *itext=='_' || *itext=='-' || *itext=='.' || *itext=='#' )
{ {
directive += *itext; directive.name += *itext;
++itext; ++itext;
} }
@ -294,36 +303,52 @@ return directive;
// string can have a quote character (escaped with a backslash) e.g. "sample text \"with quotes\""
std::string Pattern::ReadString(bool skip_first_quote) // use \\ to insert one backslash
Pattern::Item::Directive Pattern::ReadString()
{ {
std::string directive; Item::Directive directive;
directive.is_text = true;
SkipWhiteCharacters(); SkipWhiteCharacters();
// string is signed by its first character equal (")
if( *itext != '\"' ) if( *itext != '\"' )
return directive; return directive;
// string is signed by its first character equal (") // skipping the first quote character
if( !skip_first_quote ) ++itext;
directive += '\"';
for( ++itext ; *itext && *itext!='\"' && *itext!='\n' ; ++itext ) for( ; *itext && *itext!='\"' && *itext!='\n' ; ++itext )
directive += *itext; {
if( itext[0]=='\\' && itext[1]=='\"' )
{
directive.name += '\"';
++itext;
}
else
if( itext[0]=='\\' && itext[1]=='\\' )
{
directive.name += '\\';
++itext;
}
else
{
directive.name += *itext;
}
}
if( *itext != '\"' ) if( *itext != '\"' )
// the second quotation mark (") is missing // the second quotation mark (") is missing
directive.clear(); directive.name.clear();
else else
++itext; ++itext;
// the second quotation mark (") we don't add into the 'directive'
return directive; return directive;
} }
std::string Pattern::ReadDirectiveOrString() Pattern::Item::Directive Pattern::ReadDirectiveOrString()
{ {
SkipWhiteCharacters(); SkipWhiteCharacters();
@ -362,9 +387,9 @@ void Pattern::ReadDirectiveIfany(Item & item)
while( true ) while( true )
{ {
std::string directive = ReadDirective(); Item::Directive directive = ReadDirective();
if( directive.empty() ) if( directive.name.empty() )
break; break;
item.directives.push_back(directive); item.directives.push_back(directive);
@ -397,15 +422,15 @@ void Pattern::ReadDirectiveIfone(Item & item)
void Pattern::ReadDirectiveIs(Item & item) void Pattern::ReadDirectiveIs(Item & item)
{ {
item.type = Item::item_is; 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); item.directives.push_back(directive);
directive = ReadDirectiveOrString(); directive = ReadDirectiveOrString();
if( !directive.empty() ) if( directive.is_text || !directive.name.empty() )
item.directives.push_back(directive); item.directives.push_back(directive);
} }
@ -417,15 +442,15 @@ void Pattern::ReadDirectiveIs(Item & item)
void Pattern::ReadDirectiveIfindex(Item & item) void Pattern::ReadDirectiveIfindex(Item & item)
{ {
item.type = Item::item_ifindex; 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); item.directives.push_back(directive);
directive = ReadDirective(); directive = ReadDirective();
if( !directive.empty() ) if( !directive.name.empty() )
item.directives.push_back(directive); item.directives.push_back(directive);
} }
@ -437,9 +462,9 @@ void Pattern::ReadDirectiveIfindex(Item & item)
void Pattern::ReadDirectiveFor(Item & item) void Pattern::ReadDirectiveFor(Item & item)
{ {
item.type = Item::item_for; 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); item.directives.push_back(directive);
else else
item.type = Item::item_err; item.type = Item::item_err;
@ -459,28 +484,27 @@ void Pattern::ReadDirectiveComment(Item & item)
void Pattern::ReadDirectiveInclude(Item & item) void Pattern::ReadDirectiveInclude(Item & item)
{ {
item.type = Item::item_include; 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); item.directives.push_back(directive);
else else
item.type = Item::item_err; item.type = Item::item_err;
} }
void Pattern::ReadDirectiveDef(Item & item) void Pattern::ReadDirectiveDef(Item & item)
{ {
item.type = Item::item_def; 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); item.directives.push_back(directive);
directive = ReadDirectiveOrString(); directive = ReadDirectiveOrString();
if( !directive.empty() ) if( directive.is_text || !directive.name.empty() )
item.directives.push_back(directive); item.directives.push_back(directive);
} }
@ -494,39 +518,39 @@ void Pattern::CreateTreeReadItemDirective(Item & item)
{ {
++itext; ++itext;
std::string directive = ReadDirective(); Item::Directive directive = ReadDirective();
if( directive == "if-any" ) if( directive.name == "if-any" )
ReadDirectiveIfany(item); ReadDirectiveIfany(item);
else else
if( directive == "if-no" ) if( directive.name == "if-no" )
ReadDirectiveIfno(item); ReadDirectiveIfno(item);
else else
if( directive == "if-one" ) if( directive.name == "if-one" )
ReadDirectiveIfone(item); ReadDirectiveIfone(item);
else else
if( directive == "is" ) if( directive.name == "is" )
ReadDirectiveIs(item); ReadDirectiveIs(item);
else else
if( directive == "if-index" ) if( directive.name == "if-index" )
ReadDirectiveIfindex(item); ReadDirectiveIfindex(item);
else else
if( directive == "end" ) if( directive.name == "end" )
item.type = Item::item_end; item.type = Item::item_end;
else else
if( directive == "else" ) if( directive.name == "else" )
item.type = Item::item_else; item.type = Item::item_else;
else else
if( directive == "for" ) if( directive.name == "for" )
ReadDirectiveFor(item); ReadDirectiveFor(item);
else else
if( directive == "include" ) if( directive.name == "include" )
ReadDirectiveInclude(item); ReadDirectiveInclude(item);
else else
if( directive == "def" ) if( directive.name == "def" )
ReadDirectiveDef(item); ReadDirectiveDef(item);
else else
if( directive == "#" ) if( directive.name == "#" )
ReadDirectiveComment(item); ReadDirectiveComment(item);
else else
{ {
@ -578,15 +602,15 @@ return false;
void Pattern::CreateTreeReadInclude(Item & item) 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; 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(); itext = file_text.c_str();
CreateTree(item); CreateTree(item);
itext = itext_copy; itext = itext_old;
} }
@ -765,9 +789,8 @@ void Info::Clear()
{ {
// default settings indicate 'false' // default settings indicate 'false'
result = false; result = false;
out_string.clear(); is = 0;
iter = 0;
iter = 0;
} }
@ -776,20 +799,6 @@ Info::Info(std::ostringstream & o) : out(o)
Clear(); Clear();
} }
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) void Generator::CallUserFunction(Functions::Function * function, Info & info)
{ {
// przetestowac to jeszcze !!!! (wczesniej sprawdzenie bylo w Find) !!
if( function->is_running ) if( function->is_running )
{ {
// recurrences are not allowed // recurrences are not allowed
@ -903,16 +911,20 @@ void Generator::CallUserFunction(Functions::Function * function, Info & info)
void Generator::CallVariable(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.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);
else else
@ -921,13 +933,13 @@ void Generator::Call(Functions::Function * function, Info & info)
// 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) bool Generator::Call(const std::string & name, Info & info, Functions::Function ** pfun, const std::string * is)
{ {
Functions::Function * function; Functions::Function * function;
if( Find(name, &function) ) if( Find(name, &function) )
{ {
Call(function, info); Call(function, info, is);
if( pfun ) if( pfun )
*pfun = function; *pfun = function;
@ -976,10 +988,7 @@ void Generator::MakeTextNormal(Pattern::Item & item)
if( item.directives.size() != 1 ) if( item.directives.size() != 1 )
return; return;
Call(item.directives[0], info1); Call(item.directives[0].name, info1);
if( !info1.out_string.empty() )
output_stream << info1.out_string;
} }
@ -1001,16 +1010,16 @@ void Generator::MakeTextIf_go(Pattern::Item & item, bool result)
void Generator::MakeTextIfany(Pattern::Item & item) 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; unsigned how_many_true = 0;
for( ; d != item.directives.end() ; ++d ) 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) // maybe it should only be treated as a false? (when there is no such a function/variable)
return; return;
if( info1.IsTrue() ) if( info1.result )
++how_many_true; ++how_many_true;
} }
@ -1020,12 +1029,12 @@ void Generator::MakeTextIfany(Pattern::Item & item)
void Generator::MakeTextIfno(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; unsigned how_many_true = 0;
for( ; d != item.directives.end() ; ++d ) 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 // there is no sense to go through all functions
++how_many_true; ++how_many_true;
@ -1040,12 +1049,12 @@ void Generator::MakeTextIfno(Pattern::Item & item)
void Generator::MakeTextIfone(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; int how_many_true = 0;
for( ; d != item.directives.end() ; ++d ) 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 // there is no sense to go through all functions
++how_many_true; ++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) void Generator::MakeTextIs(Pattern::Item & item)
{ {
if( item.directives.size() != 2 ) if( item.directives.size() != 2 )
return; return;
if( !Call(item.directives[0], info1) )
return;
bool result = false; 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 // both directives are text
if( std::strcmp(info1.out_string.c_str(), item.directives[1].c_str()+1) == 0 ) result = (item.directives[0].name == item.directives[1].name);
result = true; }
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 else
{ {
if( Call(item.directives[1], info2) ) // both directive are not text
{ MakeTextIsFunFun(item.directives[0].name, item.directives[1].name, result);
if( info1.result==info2.result && info1.out_string==info2.out_string )
result = true;
}
} }
MakeTextIf_go(item, result); MakeTextIf_go(item, result);
@ -1092,7 +1168,7 @@ bool Generator::MakeTextIfindexnumber(Pattern::Item & item, Functions::Function
if( item.directives.size() != 2 ) if( item.directives.size() != 2 )
return false; return false;
const char * number_text = item.directives[1].c_str(); const char * number_text = item.directives[1].name.c_str();
char * last_char; char * last_char;
int number = (int)strtol(number_text, &last_char, 10); int number = (int)strtol(number_text, &last_char, 10);
@ -1125,25 +1201,25 @@ void Generator::MakeTextIfindex(Pattern::Item & item)
Functions::Function * function; Functions::Function * function;
if( !Find(item.directives[0], &function) ) if( !Find(item.directives[0].name, &function) )
return; return;
bool result = false; bool result = false;
if( item.directives[1] == "odd" ) if( item.directives[1].name == "odd" )
{ {
if( (function->iter & 1) == 1 ) if( (function->iter & 1) == 1 )
result = true; result = true;
} }
else else
if( item.directives[1] == "even" ) if( item.directives[1].name == "even" )
{ {
if( (function->iter & 1) == 0 ) if( (function->iter & 1) == 0 )
result = true; result = true;
} }
else else
if( item.directives[1] == "first" ) if( item.directives[1].name == "first" )
{ {
if( function->iter == 0 ) if( function->iter == 0 )
result = true; result = true;
@ -1168,12 +1244,12 @@ void Generator::MakeTextFor(Pattern::Item & item)
Functions::Function * function; Functions::Function * function;
if( !Find(item.directives[0], &function) ) if( !Find(item.directives[0].name, &function) )
return; return;
if( function->is_for ) 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; return;
} }
@ -1181,13 +1257,13 @@ void Generator::MakeTextFor(Pattern::Item & item)
{ {
if( function->iter >= max_loop ) 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; break;
} }
Call(function, info1); Call(function, info1);
if( info1.IsFalse() ) if( !info1.result )
break; break;
if( item.item_table.size() > 0 ) if( item.item_table.size() > 0 )
@ -1205,21 +1281,20 @@ void Generator::MakeTextDefine(Pattern::Item & item)
if( item.directives.size() != 2 ) if( item.directives.size() != 2 )
return; 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].name, item.directives[1].name);
functions.Insert(item.directives[0], item.directives[1].c_str() + 1);
} }
else else
{ {
Functions::Function * function; Functions::Function * function;
if( Find(item.directives[1], &function) ) if( Find(item.directives[1].name, &function) )
{ {
if( function->type == Functions::function ) if( function->type == Functions::function )
functions.Insert(item.directives[0], function->user_function); functions.Insert(item.directives[0].name, function->user_function);
else 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. * THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* version 0.9.2
*
*/
#ifndef headerfileezc #ifndef headerfileezc
#define headerfileezc #define headerfileezc
@ -87,13 +82,17 @@ public:
item_include, item_is, item_ifone, item_comment, item_def 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; ItemType type;
std::string text; std::string text;
std::vector<Item*> item_table; std::vector<Item*> item_table;
std::vector<std::string> directives; std::vector<Directive> directives;
Item(); Item();
Item(const Item & i); Item(const Item & i);
@ -128,6 +127,7 @@ private:
bool CheckFileName(const char * name); bool CheckFileName(const char * name);
std::string ReadFile(const std::string & name);
std::string ReadFile(const char * name); std::string ReadFile(const char * name);
int ReadCharInText(); int ReadCharInText();
@ -135,9 +135,9 @@ private:
void SkipWhiteCharacters(); void SkipWhiteCharacters();
void CheckWhiteAndDelete(std::string & s); void CheckWhiteAndDelete(std::string & s);
std::string ReadDirective(); Item::Directive ReadDirective();
std::string ReadString(bool skip_first_quote = false); Item::Directive ReadString();
std::string ReadDirectiveOrString(); Item::Directive ReadDirectiveOrString();
void CreateTreeReadItemDirectiveCheckEnding(Item & item); void CreateTreeReadItemDirectiveCheckEnding(Item & item);
@ -172,8 +172,12 @@ struct Info
{ {
// this variables you can set in your function // this variables you can set in your function
std::ostringstream & out; std::ostringstream & out;
std::string out_string; //std::string out_string;
bool result; 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 // this is set by Generator
// normally is 0 // normally is 0
@ -183,15 +187,12 @@ struct Info
Info(std::ostringstream & o); Info(std::ostringstream & o);
void Clear(); void Clear();
bool IsTrue() const;
bool IsFalse() const;
}; };
// functions or variables
class Functions class Functions
{ {
public: public:
@ -252,8 +253,8 @@ private:
bool Find(const std::string & key, Functions::Function ** function); 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, 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);
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);
@ -267,6 +268,8 @@ private:
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);
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 MakeTextIs(Pattern::Item & item);
void MakeTextDefine(Pattern::Item & item); void MakeTextDefine(Pattern::Item & item);
void MakeText(Pattern::Item & item); void MakeText(Pattern::Item & item);