From b2aacc2da3f9bb06674dd2d040243c64cc262c7a Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Mon, 25 Jan 2010 05:19:54 +0000 Subject: [PATCH] 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 --- src/ezc.cpp | 307 ++++++++++++++++++++++++++++++++-------------------- src/ezc.h | 37 ++++--- 2 files changed, 211 insertions(+), 133 deletions(-) diff --git a/src/ezc.cpp b/src/ezc.cpp index 6011c10..fe1e121 100644 --- a/src/ezc.cpp +++ b/src/ezc.cpp @@ -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(); + // the second quotation mark (") is missing + 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,9 +789,8 @@ void Info::Clear() { // default settings indicate 'false' result = false; - out_string.clear(); - - iter = 0; + is = 0; + iter = 0; } @@ -776,20 +799,6 @@ Info::Info(std::ostringstream & o) : out(o) 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) { - // przetestowac to jeszcze !!!! (wczesniej sprawdzenie bylo w Find) !! if( function->is_running ) { // recurrences are not allowed @@ -903,16 +911,20 @@ 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); else @@ -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::iterator d = item.directives.begin(); + std::vector::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::iterator d = item.directives.begin(); + std::vector::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::iterator d = item.directives.begin(); + std::vector::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); } } } diff --git a/src/ezc.h b/src/ezc.h index d425e08..41de9f9 100644 --- a/src/ezc.h +++ b/src/ezc.h @@ -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_table; - std::vector directives; + std::vector 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,8 +172,12 @@ 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 @@ -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);