From b89c6daa7dbc87f880847701163958c41908ebb5 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Sun, 30 May 2010 21:07:15 +0000 Subject: [PATCH] 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 --- COPYRIGHT | 2 +- src/Makefile.dep | 2 +- src/ezc.cpp | 287 ++++++++++++++++++++++++++++++++--------------- src/ezc.h | 51 ++++++--- 4 files changed, 231 insertions(+), 111 deletions(-) diff --git a/COPYRIGHT b/COPYRIGHT index cb07a6e..99a378c 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -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 diff --git a/src/Makefile.dep b/src/Makefile.dep index 1782db6..3fda4df 100755 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -1,3 +1,3 @@ # DO NOT DELETE -edanticezc.o: ezc.h /home/tomek/roboczy/winix/core/log.h +ezc.o: ezc.h diff --git a/src/ezc.cpp b/src/ezc.cpp index e7342fd..f7c555b 100644 --- a/src/ezc.cpp +++ b/src/ezc.cpp @@ -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::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; diff --git a/src/ezc.h b/src/ezc.h index 61eb85e..517042d 100644 --- a/src/ezc.h +++ b/src/ezc.h @@ -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);