Merge pull request 'api2021 part I' (#5) from api2021 into master

Reviewed-on: #5
This commit is contained in:
Tomasz Sowa 2021-05-27 10:41:16 +02:00
commit 0bcaca4770
9 changed files with 392 additions and 175 deletions

View File

@ -20,13 +20,13 @@ $(libname): $(o)
%.o: %.cpp %.o: %.cpp
$(CXX) -c $(CXXFLAGS) -I$(GLOBAL_WORKING_DIR)/pikotools $< $(CXX) -c $(CXXFLAGS) -I$(GLOBAL_WORKING_DIR)/pikotools/src $<
depend: depend:
# !! IMPROVE ME # !! IMPROVE ME
# as Ezc is a different project we rather shoudn't use '-I$(global_relative_working_dir)/pikotools' here? # as Ezc is a different project we rather shoudn't use '-I$(global_relative_working_dir)/pikotools' here?
makedepend -Y. -I$(global_relative_working_dir)/pikotools -f- *.cpp > Makefile.dep makedepend -Y. -I$(global_relative_working_dir)/pikotools/src -f- *.cpp > Makefile.dep
echo -n "o = " > Makefile.o.dep echo -n "o = " > Makefile.o.dep
ls -1 *.cpp | xargs -I foo echo -n foo " " | sed -E "s/([^\.]*)\.cpp[ ]/\1\.o/g" >> Makefile.o.dep ls -1 *.cpp | xargs -I foo echo -n foo " " | sed -E "s/([^\.]*)\.cpp[ ]/\1\.o/g" >> Makefile.o.dep

View File

@ -1,38 +1,8 @@
# DO NOT DELETE # DO NOT DELETE
blocks.o: blocks.h item.h cache.h functions.h ../../pikotools/utf8/utf8.h blocks.o: blocks.h item.h cache.h functions.h funinfo.h objects.h
blocks.o: ../../pikotools/textstream/textstream.h cache.o: cache.h item.h functions.h funinfo.h objects.h blocks.h
blocks.o: ../../pikotools/space/space.h ../../pikotools/textstream/types.h
blocks.o: ../../pikotools/date/date.h ../../pikotools/convert/inttostr.h
blocks.o: ../../pikotools/membuffer/membuffer.h
blocks.o: ../../pikotools/textstream/types.h funinfo.h objects.h
cache.o: cache.h item.h functions.h ../../pikotools/utf8/utf8.h
cache.o: ../../pikotools/textstream/textstream.h
cache.o: ../../pikotools/space/space.h ../../pikotools/textstream/types.h
cache.o: ../../pikotools/date/date.h ../../pikotools/convert/inttostr.h
cache.o: ../../pikotools/membuffer/membuffer.h
cache.o: ../../pikotools/textstream/types.h funinfo.h objects.h blocks.h
item.o: item.h item.o: item.h
pattern.o: pattern.h item.h cache.h functions.h ../../pikotools/utf8/utf8.h pattern.o: pattern.h item.h cache.h functions.h funinfo.h objects.h blocks.h
pattern.o: ../../pikotools/textstream/textstream.h
pattern.o: ../../pikotools/space/space.h ../../pikotools/textstream/types.h
pattern.o: ../../pikotools/date/date.h ../../pikotools/convert/inttostr.h
pattern.o: ../../pikotools/membuffer/membuffer.h
pattern.o: ../../pikotools/textstream/types.h funinfo.h objects.h blocks.h
patternparser.o: patternparser.h blocks.h item.h cache.h functions.h patternparser.o: patternparser.h blocks.h item.h cache.h functions.h
patternparser.o: ../../pikotools/utf8/utf8.h patternparser.o: funinfo.h objects.h pattern.h
patternparser.o: ../../pikotools/textstream/textstream.h
patternparser.o: ../../pikotools/space/space.h
patternparser.o: ../../pikotools/textstream/types.h
patternparser.o: ../../pikotools/date/date.h
patternparser.o: ../../pikotools/convert/inttostr.h
patternparser.o: ../../pikotools/membuffer/membuffer.h
patternparser.o: ../../pikotools/textstream/types.h funinfo.h objects.h
patternparser.o: pattern.h ../../pikotools/log/log.h
patternparser.o: ../../pikotools/log/filelog.h
patternparser.o: ../../pikotools/convert/convert.h
patternparser.o: ../../pikotools/convert/inttostr.h
patternparser.o: ../../pikotools/convert/patternreplacer.h
patternparser.o: ../../pikotools/convert/strtoint.h
patternparser.o: ../../pikotools/convert/text.h
patternparser.o: ../../pikotools/convert/misc.h

View File

@ -88,7 +88,7 @@ private:
template<class StreamType> template<class StreamType>
void Functions<StreamType>::Insert(const char * key, UserFunction ufunction) void Functions<StreamType>::Insert(const char * key, UserFunction ufunction)
{ {
PT::UTF8ToWide(key, temp_key); pt::utf8_to_wide(key, temp_key);
functions_tab[temp_key] = ufunction; functions_tab[temp_key] = ufunction;
temp_key.clear(); temp_key.clear();
} }

View File

@ -40,6 +40,7 @@
#define headerfile_ezc_funinfo #define headerfile_ezc_funinfo
#include <vector> #include <vector>
#include <map>
#include "item.h" #include "item.h"
@ -52,11 +53,27 @@ namespace Ezc
*/ */
struct Var struct Var
{ {
/*
* if true then means 'str' is a function name and should be called (res is ignored)
*
* if false then means 'str' is a string value and res is a boolean value
*/
bool is_function;
std::wstring str; // a string value std::wstring str; // a string value
bool res; // a boolean value bool res; // a boolean value
Var()
{
res = false;
is_function = false;
}
}; };
typedef std::map<std::wstring, Var> Vars;
/* /*
a base class for your own function data class a base class for your own function data class

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2007-2018, Tomasz Sowa * Copyright (c) 2007-2021, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -73,6 +73,7 @@ public:
void SetBlocks(Blocks & blocks); void SetBlocks(Blocks & blocks);
void SetFunctions(Functions<StreamType> & functions); void SetFunctions(Functions<StreamType> & functions);
void SetObjects(Objects<StreamType> & objects); void SetObjects(Objects<StreamType> & objects);
void SetVariables(Vars & variables); // [def] and [let]
void SetMax(size_t max_items_, size_t max_for_items_); void SetMax(size_t max_items_, size_t max_for_items_);
@ -131,11 +132,6 @@ public:
private: private:
// variables set
typedef std::map<std::wstring, Var> Vars;
Vars vars;
struct BlockStack struct BlockStack
{ {
std::vector<Var> args; std::vector<Var> args;
@ -155,6 +151,7 @@ private:
Blocks * pblocks; Blocks * pblocks;
Functions<StreamType> * pfunctions; Functions<StreamType> * pfunctions;
Objects<StreamType> * pobjects; Objects<StreamType> * pobjects;
Vars * pvars;
// pointer to the output streams map (can be null) // pointer to the output streams map (can be null)
// output stream will be created when [ezc out "stream_name"] statement is found // output stream will be created when [ezc out "stream_name"] statement is found
@ -185,9 +182,6 @@ private:
std::vector<StreamType*> ezc_out_stack_tab; std::vector<StreamType*> ezc_out_stack_tab;
const StreamType empty_stream; const StreamType empty_stream;
// used in [0] [1] [2] when there is no such argument defined
std::wstring empty_argument;
// temporary streams used in [if..] [for...] or [def ...] // temporary streams used in [if..] [for...] or [def ...]
// or if output_stream is null and an ezc function should be called // or if output_stream is null and an ezc function should be called
StreamType stream_temp1, stream_temp_define; StreamType stream_temp1, stream_temp_define;
@ -242,7 +236,7 @@ private:
CharType ToLower(CharType c); CharType ToLower(CharType c);
bool CheckBlockArgument(Item::Function & item_fun, std::wstring ** variable); bool CheckBlockArgument(int arg_index, Var ** variable);
bool FindInCache(Item::Function & item_fun, bool FindInCache(Item::Function & item_fun,
BaseObj<StreamType> ** base_obj, BaseObj<StreamType> ** base_obj,
@ -257,15 +251,16 @@ private:
Item ** item_block); Item ** item_block);
bool FindInVariables(const std::wstring & name, bool FindInVariables(const std::wstring & name,
std::wstring ** variable); Var ** variable);
bool Find(Item::Function & item_fun, bool Find(Item::Function & item_fun,
std::wstring * fun_name,
BaseObj<StreamType> ** base_obj, BaseObj<StreamType> ** base_obj,
int * method_index, int * method_index,
typename Functions<StreamType>::UserFunction ** function, typename Functions<StreamType>::UserFunction ** function,
Item ** item_block, Item ** item_block,
std::wstring ** variable); Var ** variable);
void CallFunction(typename Functions<StreamType>::UserFunction * function, void CallFunction(typename Functions<StreamType>::UserFunction * function,
FunInfo<StreamType> & info); FunInfo<StreamType> & info);
@ -289,8 +284,14 @@ private:
StreamType & out_stream, StreamType & out_stream,
const StreamType & in_stream); const StreamType & in_stream);
bool CallVariable(Item::Function & item_fun,
Var * variable,
std::vector<Var> & parameters,
StreamType & out_stream,
const StreamType & in_stream);
bool Call(Item::Function & item_fun, bool Call(Item::Function & item_fun,
std::wstring * fun_name,
StreamType & out_stream, StreamType & out_stream,
bool clear_out_stream, bool clear_out_stream,
const StreamType & in_stream); const StreamType & in_stream);
@ -324,7 +325,12 @@ private:
void MakeItemText(Item & item); void MakeItemText(Item & item);
void MakeTextContainer(Item & item); void MakeTextContainer(Item & item);
void MakeTextNormal(Item & item); void MakeTextNormal(Item & item);
void MakeTextDefine(Item & item, Var & var);
void MakeTextDefine(Item & item); void MakeTextDefine(Item & item);
void MakeTextDefineIfNotSet(Item & item);
void MakeTextLet(Item & item, Var & var);
void MakeTextLet(Item & item);
void MakeTextLetIfNotSet(Item & item);
void MakeTextFilter(Item & item); void MakeTextFilter(Item & item);
void MakeTextEzc(Item & item); void MakeTextEzc(Item & item);
void MakeTextReturn(Item & item); void MakeTextReturn(Item & item);
@ -349,6 +355,7 @@ Generator<StreamType>::Generator() : empty_stream()
pblocks = 0; pblocks = 0;
pfunctions = 0; pfunctions = 0;
pobjects = 0; pobjects = 0;
pvars = 0;
max_items = 50000; max_items = 50000;
max_for_items = 5000; max_for_items = 5000;
@ -382,6 +389,7 @@ Generator<StreamType> & Generator<StreamType>::operator=(const Generator<StreamT
pblocks = n.pblocks; pblocks = n.pblocks;
pfunctions = n.pfunctions; pfunctions = n.pfunctions;
pobjects = n.pobjects; pobjects = n.pobjects;
pvars = n.pvars;
max_items = n.max_items; max_items = n.max_items;
max_for_items = n.max_for_items; max_for_items = n.max_for_items;
@ -429,8 +437,8 @@ Generator<StreamType>::~Generator()
template<class StreamType> template<class StreamType>
void Generator<StreamType>::SetCommentary(const char * com_start, const char * com_stop) void Generator<StreamType>::SetCommentary(const char * com_start, const char * com_stop)
{ {
PT::UTF8ToWide(com_start, commentary_start); pt::utf8_to_wide(com_start, commentary_start);
PT::UTF8ToWide(com_stop, commentary_stop); pt::utf8_to_wide(com_stop, commentary_stop);
} }
@ -438,8 +446,8 @@ void Generator<StreamType>::SetCommentary(const char * com_start, const char * c
template<class StreamType> template<class StreamType>
void Generator<StreamType>::SetCommentary(const std::string & com_start, const std::string & com_stop) void Generator<StreamType>::SetCommentary(const std::string & com_start, const std::string & com_stop)
{ {
PT::UTF8ToWide(com_start, commentary_start); pt::utf8_to_wide(com_start, commentary_start);
PT::UTF8ToWide(com_stop, commentary_stop); pt::utf8_to_wide(com_stop, commentary_stop);
} }
@ -491,6 +499,14 @@ void Generator<StreamType>::SetObjects(Objects<StreamType> & objects)
pobjects = &objects; pobjects = &objects;
} }
template<class StreamType>
void Generator<StreamType>::SetVariables(Vars & variables)
{
pvars = &variables;
}
template<class StreamType> template<class StreamType>
void Generator<StreamType>::CanUseCache(bool can_use_cache) void Generator<StreamType>::CanUseCache(bool can_use_cache)
{ {
@ -679,10 +695,7 @@ return c;
template<class StreamType> template<class StreamType>
bool Generator<StreamType>::ConvertToBool(const std::wstring & str) bool Generator<StreamType>::ConvertToBool(const std::wstring & str)
{ {
if( str == L"true" ) return !str.empty();
return true;
return false;
} }
@ -756,7 +769,6 @@ void Generator<StreamType>::Generate()
filter_index = 0; filter_index = 0;
stack_index = 0; stack_index = 0;
block_stack_index = 0; block_stack_index = 0;
vars.clear();
if( ppattern ) if( ppattern )
{ {
@ -766,7 +778,6 @@ void Generator<StreamType>::Generate()
MakeText( ppattern->item_root ); MakeText( ppattern->item_root );
// !! IMPROVE ME we can print an error message if the stacks are not empty // !! IMPROVE ME we can print an error message if the stacks are not empty
// (some [end] statements has been omited) // (some [end] statements has been omited)
vars.clear();
is_generator_working = false; is_generator_working = false;
} }
catch(...) catch(...)
@ -808,28 +819,24 @@ void Generator<StreamType>::Generate(OutStreams<StreamType> & out_streams)
template<class StreamType> template<class StreamType>
bool Generator<StreamType>::CheckBlockArgument(Item::Function & item_fun, std::wstring ** variable) bool Generator<StreamType>::CheckBlockArgument(int arg_index, Var ** variable)
{ {
if( item_fun.arg < 0 ) if( arg_index < 0 )
return false; return false;
empty_argument.clear();
*variable = &empty_argument;
last_res = ConvertToBool(empty_argument);
// it's a numeric function -- an argument to a block e.g.: [1] // it's a numeric function -- an argument to a block e.g.: [1]
if( block_stack_index > 0 ) if( block_stack_index > 0 )
{ {
BlockStack & block_stack = block_stack_tab[block_stack_index-1]; BlockStack & block_stack = block_stack_tab[block_stack_index-1];
if( size_t(item_fun.arg) < block_stack.args.size() ) if( size_t(arg_index) < block_stack.args.size() )
{ {
*variable = &block_stack.args[item_fun.arg].str; *variable = &block_stack.args[arg_index];
last_res = block_stack.args[item_fun.arg].res; return true;
} }
} }
return true; return false;
} }
@ -914,50 +921,58 @@ return false;
template<class StreamType> template<class StreamType>
bool Generator<StreamType>::FindInVariables(const std::wstring & name, bool Generator<StreamType>::FindInVariables(const std::wstring & name,
std::wstring ** variable) Var ** variable)
{ {
Vars::iterator i = vars.find(name); if( pvars )
if( i != vars.end() )
{ {
Var & var = i->second; Vars::iterator i = pvars->find(name);
*variable = &var.str; if( i != pvars->end() )
last_res = var.res; {
return true; *variable = &(i->second);
return true;
}
} }
return false; return false;
} }
/*
* fun_name can be null, it is used only with [let ...] statements
* and if not null then means: as a funcion name we are not using item_fun.name but fun_name
*/
template<class StreamType> template<class StreamType>
bool Generator<StreamType>::Find(Item::Function & item_fun, bool Generator<StreamType>::Find(Item::Function & item_fun,
std::wstring * fun_name,
BaseObj<StreamType> ** base_obj, BaseObj<StreamType> ** base_obj,
int * method_index, int * method_index,
typename Functions<StreamType>::UserFunction ** function, typename Functions<StreamType>::UserFunction ** function,
Item ** item_block, Item ** item_block,
std::wstring ** variable) Var ** variable)
{ {
*base_obj = 0; *base_obj = nullptr;
*method_index = -1; *method_index = -1;
*function = 0; *function = nullptr;
*item_block = 0; *item_block = nullptr;
*variable = 0; *variable = nullptr;
if( CheckBlockArgument(item_fun, variable) ) if( CheckBlockArgument(item_fun.arg, variable) )
return true; return true;
if( FindInCache(item_fun, base_obj, method_index, function, item_block) ) if( FindInCache(item_fun, base_obj, method_index, function, item_block) )
return true; return true;
if( FindInFunctionsAndBlocks(item_fun.name, base_obj, method_index, function, item_block) ) if( !fun_name )
fun_name = &item_fun.name;
if( FindInFunctionsAndBlocks(*fun_name, base_obj, method_index, function, item_block) )
return true; return true;
if( FindInVariables(item_fun.name, variable) ) if( FindInVariables(*fun_name, variable) )
return true; return true;
CreateUnknownMsg(item_fun.name); CreateUnknownMsg(*fun_name);
return false; return false;
} }
@ -1089,9 +1104,32 @@ return true;
} }
// return: true if a function, variable or block was found and called
template<class StreamType>
bool Generator<StreamType>::CallVariable(Item::Function & item_fun, Var * variable, std::vector<Var> & parameters, StreamType & out_stream, const StreamType & in_stream)
{
if( variable->is_function )
{
return Call(item_fun, &variable->str, out_stream, false, in_stream);
}
else
{
out_stream << variable->str;
last_res = variable->res;
return true;
}
}
/*
* fun_name can be null, it is used only with [let ...] statements
* and if not null then means: as a funcion name we are not using item_fun.name but fun_name
*
* return: true if a function, variable or block was found and called (evaluated)
*/
template<class StreamType> template<class StreamType>
bool Generator<StreamType>::Call(Item::Function & item_fun, bool Generator<StreamType>::Call(Item::Function & item_fun,
std::wstring * fun_name,
StreamType & out_stream, StreamType & out_stream,
bool clear_out_stream, bool clear_out_stream,
const StreamType & in_stream) const StreamType & in_stream)
@ -1100,13 +1138,13 @@ BaseObj<StreamType> * base_obj;
int method_index; int method_index;
typename Functions<StreamType>::UserFunction * fun; typename Functions<StreamType>::UserFunction * fun;
Item * item_block; Item * item_block;
std::wstring * variable; Var * variable;
std::vector<Var> parameters; std::vector<Var> parameters;
if( clear_out_stream ) if( clear_out_stream )
ClearStream(out_stream); ClearStream(out_stream);
if( !Find(item_fun, &base_obj, &method_index, &fun, &item_block, &variable) ) if( !Find(item_fun, fun_name, &base_obj, &method_index, &fun, &item_block, &variable) )
return false; return false;
parameters.resize(item_fun.parameters.size()); parameters.resize(item_fun.parameters.size());
@ -1118,7 +1156,7 @@ std::vector<Var> parameters;
if( fun_child.is_function ) if( fun_child.is_function )
{ {
StreamType local_temp_stream; StreamType local_temp_stream;
Call(fun_child, local_temp_stream, true, empty_stream); Call(fun_child, nullptr, local_temp_stream, true, empty_stream);
#ifdef EZC_HAS_SPECIAL_STREAM #ifdef EZC_HAS_SPECIAL_STREAM
parameters[i].str = local_temp_stream.Str(); parameters[i].str = local_temp_stream.Str();
@ -1145,9 +1183,9 @@ std::vector<Var> parameters;
return CallBlock(*item_block, parameters, out_stream); return CallBlock(*item_block, parameters, out_stream);
else else
if( variable ) if( variable )
out_stream.write(variable->c_str(), variable->size()); return CallVariable(item_fun, variable, parameters, out_stream, in_stream);
return true; return true;
} }
@ -1156,7 +1194,7 @@ return true;
template<class StreamType> template<class StreamType>
bool Generator<StreamType>::Call(Item::Function & item_fun) bool Generator<StreamType>::Call(Item::Function & item_fun)
{ {
return Call(item_fun, stream_temp1, true, empty_stream); return Call(item_fun, nullptr, stream_temp1, true, empty_stream);
} }
@ -1529,11 +1567,11 @@ void Generator<StreamType>::MakeTextNormal(Item & item)
{ {
if( output_stream ) if( output_stream )
{ {
Call(item.function, *output_stream, false, empty_stream); Call(item.function, nullptr, *output_stream, false, empty_stream);
} }
else else
{ {
Call(item.function, stream_temp1, false, empty_stream); Call(item.function, nullptr, stream_temp1, false, empty_stream);
ClearStream(stream_temp1); ClearStream(stream_temp1);
} }
} }
@ -1604,7 +1642,7 @@ void Generator<StreamType>::MakeTextFor(Item & item)
} }
else else
{ {
Call(item.function, stream_temp1, true, empty_stream); Call(item.function, nullptr, stream_temp1, true, empty_stream);
} }
if( !last_res ) if( !last_res )
@ -1616,51 +1654,151 @@ void Generator<StreamType>::MakeTextFor(Item & item)
} }
template<class StreamType>
void Generator<StreamType>::MakeTextDefine(Item & item, Var & var)
{
var.str.clear();
var.res = ConvertToBool(var.str);
var.is_function = false;
if( item.function.parameters.empty() )
{
return;
}
if( item.function.parameters.size() > 1 )
{
CreateMsg(L"[def] can have only one parameter");
return;
}
Item::Function & fun = *item.function.parameters[0];
if( fun.is_function )
{
// call function
if( Call(fun, nullptr, stream_temp_define, true, empty_stream) )
{
#ifdef EZC_HAS_SPECIAL_STREAM
var.str += stream_temp_define.Str();
#else
var.str += stream_temp_define.str();
#endif
var.res = last_res;
}
else
{
CreateMsg(L"[def] unknown function/block/variable", item.function.name);
}
}
else
{
var.str = fun.name;
var.res = ConvertToBool(fun.name);
}
}
template<class StreamType> template<class StreamType>
void Generator<StreamType>::MakeTextDefine(Item & item) void Generator<StreamType>::MakeTextDefine(Item & item)
{ {
if( !can_use_vars ) if( !can_use_vars || !pvars )
{ {
CreateMsg(L"[def] statement not available"); CreateMsg(L"[def] statement not available");
return; return;
} }
Var & var = vars[item.function.name]; Var & var = (*pvars)[item.function.name];
var.str.clear(); MakeTextDefine(item, var);
var.res = false; }
for(size_t i=0 ; i < item.function.parameters.size() ; ++i)
{
if( !item.function.parameters[i]->is_function )
{
var.str += item.function.parameters[i]->name;
var.res = ConvertToBool(item.function.parameters[i]->name);
}
else
{
// it is a function parameter
if( Call(*item.function.parameters[i], stream_temp_define, true, empty_stream) )
{
#ifdef EZC_HAS_SPECIAL_STREAM
var.str += stream_temp_define.Str();
#else
var.str += stream_temp_define.str();
#endif
var.res = last_res;
} template<class StreamType>
else void Generator<StreamType>::MakeTextDefineIfNotSet(Item & item)
{ {
CreateMsg(L"[def] unknown function/block/variable", item.function.name); if( !can_use_vars || !pvars )
} {
} CreateMsg(L"[def?] statement not available");
return;
}
Vars::iterator vi = pvars->find(item.function.name);
if( vi == pvars->end() )
{
Var & var = (*pvars)[item.function.name];
MakeTextDefine(item, var);
} }
} }
template<class StreamType>
void Generator<StreamType>::MakeTextLet(Item & item, Var & var)
{
var.str.clear();
var.res = ConvertToBool(var.str);
var.is_function = true;
if( item.function.parameters.empty() )
{
var.is_function = false;
return;
}
if( item.function.parameters.size() > 1 )
{
CreateMsg(L"[let] can have only one parameter");
return;
}
Item::Function & fun = *item.function.parameters[0];
var.str = fun.name;
var.is_function = fun.is_function;
if( !fun.is_function )
{
var.res = ConvertToBool(var.str);
}
}
template<class StreamType>
void Generator<StreamType>::MakeTextLet(Item & item)
{
if( !can_use_vars || !pvars )
{
CreateMsg(L"[let] statement not available");
return;
}
Var & var = (*pvars)[item.function.name];
MakeTextLet(item, var);
}
template<class StreamType>
void Generator<StreamType>::MakeTextLetIfNotSet(Item & item)
{
if( !can_use_vars || !pvars )
{
CreateMsg(L"[let?] statement not available");
return;
}
Vars::iterator vi = pvars->find(item.function.name);
if( vi == pvars->end() )
{
Var & var = (*pvars)[item.function.name];
MakeTextLet(item, var);
}
}
template<class StreamType> template<class StreamType>
void Generator<StreamType>::MakeTextFilter(Item & item) void Generator<StreamType>::MakeTextFilter(Item & item)
{ {
@ -1683,11 +1821,11 @@ void Generator<StreamType>::MakeTextFilter(Item & item)
if( old_stream ) if( old_stream )
{ {
Call(item.function, *old_stream, false, *output_stream); Call(item.function, nullptr, *old_stream, false, *output_stream);
} }
else else
{ {
Call(item.function, stream_temp1, true, *output_stream); Call(item.function, nullptr, stream_temp1, true, *output_stream);
ClearStream(stream_temp1); ClearStream(stream_temp1);
} }
@ -1703,7 +1841,7 @@ void Generator<StreamType>::MakeTextFilter(Item & item)
/* /*
although we are using a stack for [etc out] there is no need for the stack now although we are using a stack for [etc out] there is no need for the stack now
because the output is only a one-level map (not nested structure) because the output is only a one-level map (not nested structure)
but in the future we can use more complicated class like PT::Space but in the future we can use more complicated class like pt::Space
and then nested [ezc out] statements can product a better output and then nested [ezc out] statements can product a better output
*/ */
template<class StreamType> template<class StreamType>
@ -1777,12 +1915,14 @@ void Generator<StreamType>::MakeTextReturn(Item & item)
{ {
// output stream in [return] statement is ignored (we use only the stream produced by the whole block) // output stream in [return] statement is ignored (we use only the stream produced by the whole block)
// this Call() sets last_res which is used later when we return to CallBlock() // this Call() sets last_res which is used later when we return to CallBlock()
Call(item.function, stream_temp1, false, empty_stream); Call(item.function, nullptr, stream_temp1, false, empty_stream);
ClearStream(stream_temp1); ClearStream(stream_temp1);
} }
} }
template<class StreamType> template<class StreamType>
bool Generator<StreamType>::LimitAchieved() bool Generator<StreamType>::LimitAchieved()
{ {
@ -1831,15 +1971,18 @@ void Generator<StreamType>::MakeText(Item & item)
stack_tab[stack_index-1].Clear(); stack_tab[stack_index-1].Clear();
stack_tab[stack_index-1].item = &item; stack_tab[stack_index-1].item = &item;
if ( item.type == Item::item_text ) MakeItemText(item); if ( item.type == Item::item_text ) MakeItemText(item);
else if( item.type == Item::item_container )MakeTextContainer(item); else if( item.type == Item::item_container ) MakeTextContainer(item);
else if( item.type == Item::item_function ) MakeTextNormal(item); else if( item.type == Item::item_function ) MakeTextNormal(item);
else if( item.type == Item::item_if ) MakeTextIf(item); else if( item.type == Item::item_if ) MakeTextIf(item);
else if( item.type == Item::item_def ) MakeTextDefine(item); else if( item.type == Item::item_def ) MakeTextDefine(item);
else if( item.type == Item::item_for ) MakeTextFor(item); else if( item.type == Item::item_def_if_not_set ) MakeTextDefineIfNotSet(item);
else if( item.type == Item::item_filter ) MakeTextFilter(item); else if( item.type == Item::item_let ) MakeTextLet(item);
else if( item.type == Item::item_ezc ) MakeTextEzc(item); else if( item.type == Item::item_let_if_not_set ) MakeTextLetIfNotSet(item);
else if( item.type == Item::item_return ) MakeTextReturn(item); else if( item.type == Item::item_for ) MakeTextFor(item);
else if( item.type == Item::item_filter ) MakeTextFilter(item);
else if( item.type == Item::item_ezc ) MakeTextEzc(item);
else if( item.type == Item::item_return ) MakeTextReturn(item);
else if( item.type == Item::item_err ) else if( item.type == Item::item_err )
CreateMsg(L"a wrong directive"); CreateMsg(L"a wrong directive");

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2007-2018, Tomasz Sowa * Copyright (c) 2007-2021, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -55,7 +55,8 @@ struct Item
{ {
item_none, item_container, item_text, item_function, item_if, item_none, item_container, item_text, item_function, item_if,
item_for, item_else, item_end, item_err, item_include, item_comment, item_for, item_else, item_end, item_err, item_include, item_comment,
item_def, item_filter, item_ezc, item_block, item_return item_def, item_def_if_not_set, item_let, item_let_if_not_set,
item_filter, item_ezc, item_block, item_return
}; };

View File

@ -155,7 +155,7 @@ protected: \
{ \ { \
EzcTemplateMethod item; \ EzcTemplateMethod item; \
\ \
PT::UTF8ToWide(name, item.fun_name); \ pt::utf8_to_wide(name, item.fun_name); \
item.fun = fun; \ item.fun = fun; \
\ \
ezc_template_method_tab.push_back(item); \ ezc_template_method_tab.push_back(item); \
@ -165,7 +165,7 @@ protected: \
{ \ { \
EzcTemplateMethod item; \ EzcTemplateMethod item; \
\ \
PT::UTF8ToWide(name, item.fun_name); \ pt::utf8_to_wide(name, item.fun_name); \
item.fun = fun; \ item.fun = fun; \
\ \
ezc_template_method_tab.push_back(item); \ ezc_template_method_tab.push_back(item); \
@ -294,7 +294,7 @@ size_t Objects<StreamType>::Size() const
template<class StreamType> template<class StreamType>
void Objects<StreamType>::Clear() void Objects<StreamType>::Clear()
{ {
return obj_tab.clear(); obj_tab.clear();
} }

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2007-2018, Tomasz Sowa * Copyright (c) 2007-2021, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -64,17 +64,17 @@ void PatternParser::Directory(const char * dir, const char * dir2)
directory2.clear(); directory2.clear();
if( dir ) if( dir )
PT::UTF8ToWide(dir, directory); pt::utf8_to_wide(dir, directory);
if( dir2 ) if( dir2 )
PT::UTF8ToWide(dir2, directory2); pt::utf8_to_wide(dir2, directory2);
} }
void PatternParser::Directory(const std::string & dir) void PatternParser::Directory(const std::string & dir)
{ {
PT::UTF8ToWide(dir, directory); pt::utf8_to_wide(dir, directory);
directory2.clear(); directory2.clear();
} }
@ -82,8 +82,8 @@ void PatternParser::Directory(const std::string & dir)
void PatternParser::Directory(const std::string & dir, const std::string & dir2) void PatternParser::Directory(const std::string & dir, const std::string & dir2)
{ {
PT::UTF8ToWide(dir, directory); pt::utf8_to_wide(dir, directory);
PT::UTF8ToWide(dir2, directory2); pt::utf8_to_wide(dir2, directory2);
} }
@ -126,16 +126,16 @@ void PatternParser::SetBlocks(Blocks & blocks)
void PatternParser::SetCommentary(const char * com_start, const char * com_stop) void PatternParser::SetCommentary(const char * com_start, const char * com_stop)
{ {
PT::UTF8ToWide(com_start, commentary_start); pt::utf8_to_wide(com_start, commentary_start);
PT::UTF8ToWide(com_stop, commentary_stop); pt::utf8_to_wide(com_stop, commentary_stop);
} }
void PatternParser::SetCommentary(const std::string & com_start, const std::string & com_stop) void PatternParser::SetCommentary(const std::string & com_start, const std::string & com_stop)
{ {
PT::UTF8ToWide(com_start, commentary_start); pt::utf8_to_wide(com_start, commentary_start);
PT::UTF8ToWide(com_stop, commentary_stop); pt::utf8_to_wide(com_stop, commentary_stop);
} }
@ -161,7 +161,7 @@ void PatternParser::SetProgramMode(bool program_mode)
} }
void PatternParser::SetLogger(PT::Log * log) void PatternParser::SetLogger(pt::Log * log)
{ {
this->log = log; this->log = log;
} }
@ -195,7 +195,7 @@ void PatternParser::ParseFile(const std::string & file_name, Pattern & pattern)
void PatternParser::ParseFile(const char * file_name, Pattern & pattern) void PatternParser::ParseFile(const char * file_name, Pattern & pattern)
{ {
pat = &pattern; pat = &pattern;
PT::UTF8ToWide(file_name, pat->item_root.file_name); pt::utf8_to_wide(file_name, pat->item_root.file_name);
include_level = 0; include_level = 0;
CreateTreeReadIncludeSkipAllowFlag(pat->item_root); CreateTreeReadIncludeSkipAllowFlag(pat->item_root);
@ -225,7 +225,7 @@ void PatternParser::ParseFile(const wchar_t * file_name, Pattern & pattern)
void PatternParser::ParseString(const char * str, Pattern & pattern) void PatternParser::ParseString(const char * str, Pattern & pattern)
{ {
PT::UTF8ToWide(str, string_content); pt::utf8_to_wide(str, string_content);
ParseString(string_content.c_str(), pattern); ParseString(string_content.c_str(), pattern);
string_content.clear(); string_content.clear();
} }
@ -372,7 +372,7 @@ bool PatternParser::ReadFileFromDir(const std::wstring & dir, const wchar_t * na
file_name = dir; file_name = dir;
file_name += '/'; file_name += '/';
file_name += name; file_name += name;
PT::WideToUTF8(file_name, afile_name); pt::wide_to_utf8(file_name, afile_name);
std::ifstream file(afile_name.c_str()); std::ifstream file(afile_name.c_str());
@ -386,9 +386,9 @@ bool PatternParser::ReadFileFromDir(const std::wstring & dir, const wchar_t * na
if( log ) if( log )
{ {
if( include_level <= 1 ) if( include_level <= 1 )
(*log) << PT::Log::log4 << "Ezc: reading pattern: " << afile_name << PT::Log::logend; (*log) << pt::Log::log4 << "Ezc: reading pattern: " << afile_name << pt::Log::logend;
else else
(*log) << PT::Log::log4 << " including pattern: " << afile_name << PT::Log::logend; (*log) << pt::Log::log4 << " including pattern: " << afile_name << pt::Log::logend;
} }
ReadFile(file, result); ReadFile(file, result);
@ -403,7 +403,7 @@ return true;
void PatternParser::ReadFile(std::ifstream & file, std::wstring & result) void PatternParser::ReadFile(std::ifstream & file, std::wstring & result)
{ {
PT::UTF8ToWide(file, result); pt::utf8_to_wide(file, result);
} }
@ -486,7 +486,7 @@ bool PatternParser::IsNameChar(wchar_t c)
return ((c>='a' && c<='z') || return ((c>='a' && c<='z') ||
(c>='A' && c<='Z') || (c>='A' && c<='Z') ||
(c>='0' && c<='9') || (c>='0' && c<='9') ||
c=='_' || c=='-' || c=='.' || c=='#'); c=='_' || c=='-' || c=='.' || c=='#' || c=='?');
} }
@ -784,10 +784,85 @@ void PatternParser::ReadDirectiveInclude(Item & item)
void PatternParser::ReadDirectiveDef(Item & item) void PatternParser::ReadDirectiveDef(Item & item)
{ {
item.type = Item::item_def; item.type = Item::item_def;
ReadFunction(item);
if( ReadFunction(item) )
{
if( item.function.parameters.size() > 1 )
item.type = Item::item_err;
}
} }
void PatternParser::ReadDirectiveDefIfNotSet(Item & item)
{
item.type = Item::item_def_if_not_set;
if( ReadFunction(item) )
{
if( item.function.parameters.size() > 1 )
item.type = Item::item_err;
}
}
void PatternParser::ReadDirectiveLet(Item & item)
{
item.type = Item::item_let;
if( ReadFunction(item) )
{
std::vector<Item::Function*> & parameters = item.function.parameters;
if( parameters.size() > 1 )
{
item.type = Item::item_err;
item.function.Clear();
}
else
if( parameters.size() == 1 && parameters[0]->is_function && !parameters[0]->parameters.empty() )
{
/*
* if the first parameter in [let] is a function e.g. [let variable function_name] (here the first parameter is function_name)
* then the function cannot have parameters itselt (because it is not evaluated here)
* this is only an alias
*/
item.type = Item::item_err;
item.function.Clear();
}
}
}
void PatternParser::ReadDirectiveLetIfNotSet(Item & item)
{
item.type = Item::item_let_if_not_set;
if( ReadFunction(item) )
{
std::vector<Item::Function*> & parameters = item.function.parameters;
if( parameters.size() > 1 )
{
item.type = Item::item_err;
item.function.Clear();
}
else
if( parameters.size() == 1 && parameters[0]->is_function && !parameters[0]->parameters.empty() )
{
/*
* if the first parameter in [let] is a function e.g. [let variable function_name] (here the first parameter is function_name)
* then the function cannot have parameters itselt (because it is not evaluated here)
* this is only an alias
*/
item.type = Item::item_err;
item.function.Clear();
}
}
}
void PatternParser::ReadDirectiveFilter(Item & item) void PatternParser::ReadDirectiveFilter(Item & item)
{ {
item.type = Item::item_filter; item.type = Item::item_filter;
@ -825,11 +900,16 @@ void PatternParser::ReadDirectiveOut(Item & item)
void PatternParser::ReadDirectiveBlock(Item & item) void PatternParser::ReadDirectiveBlock(Item & item)
{ {
item.type = Item::item_block; item.type = Item::item_block;
ReadFunction(item);
// only one function without arguments if( ReadFunction(item) )
if( !item.function.parameters.empty() ) {
item.type = Item::item_err; // only one function without arguments
if( !item.function.parameters.empty() )
{
item.type = Item::item_err;
item.function.Clear();
}
}
} }
@ -859,6 +939,9 @@ std::wstring name;
else if( name == L"for" ) ReadDirectiveFor(item); else if( name == L"for" ) ReadDirectiveFor(item);
else if( name == L"include" ) ReadDirectiveInclude(item); else if( name == L"include" ) ReadDirectiveInclude(item);
else if( name == L"def" ) ReadDirectiveDef(item); else if( name == L"def" ) ReadDirectiveDef(item);
else if( name == L"def?" ) ReadDirectiveDefIfNotSet(item);
else if( name == L"let" ) ReadDirectiveLet(item);
else if( name == L"let?" ) ReadDirectiveLetIfNotSet(item);
else if( name == L"filter" ) ReadDirectiveFilter(item); else if( name == L"filter" ) ReadDirectiveFilter(item);
else if( name == L"ezc" ) ReadDirectiveEzc(item); else if( name == L"ezc" ) ReadDirectiveEzc(item);
else if( name == L"out" ) ReadDirectiveOut(item); else if( name == L"out" ) ReadDirectiveOut(item);
@ -935,7 +1018,7 @@ bool PatternParser::CreateTreeCheckProgramDirective(Item & item)
{ {
const wchar_t * old_itext = itext; const wchar_t * old_itext = itext;
if( PT::IsSubStringNoCasep(L"if", itext) ) if( pt::is_substr_nc(L"if", itext) )
{ {
itext += 2; itext += 2;
SkipWhite(); SkipWhite();
@ -948,7 +1031,7 @@ bool PatternParser::CreateTreeCheckProgramDirective(Item & item)
} }
} }
if( PT::IsSubStringNoCasep(L"while", itext) ) if( pt::is_substr_nc(L"while", itext) )
{ {
itext += 5; itext += 5;
SkipWhite(); SkipWhite();
@ -1042,7 +1125,7 @@ void PatternParser::CreateTreeReadInclude(Item & item)
{ {
if( log ) if( log )
{ {
(*log) << PT::Log::log2 << "Ezc: \"include\" directive is not allowed" << PT::Log::logend; (*log) << pt::Log::log2 << "Ezc: \"include\" directive is not allowed" << pt::Log::logend;
} }
} }
} }
@ -1059,7 +1142,7 @@ void PatternParser::CreateTreeReadIncludeSkipAllowFlag(Item & item)
{ {
if( log ) if( log )
{ {
(*log) << PT::Log::log1 << "Ezc: \"include\" directive has reached the maximum level" << PT::Log::logend; (*log) << pt::Log::log1 << "Ezc: \"include\" directive has reached the maximum level" << pt::Log::logend;
} }
return; return;
@ -1095,7 +1178,7 @@ void PatternParser::CreateTreeReadIf(Item & item)
{ {
SkipWhite(); SkipWhite();
if( PT::IsSubStringNoCasep(L"else", itext) ) if( pt::is_substr_nc(L"else", itext) )
{ {
itext += 4; itext += 4;
pitem = item.AddItem(); pitem = item.AddItem();

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2007-2018, Tomasz Sowa * Copyright (c) 2007-2021, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -89,7 +89,7 @@ public:
void SetProgramMode(bool program_mode); void SetProgramMode(bool program_mode);
void SetLogger(PT::Log * log); void SetLogger(pt::Log * log);
private: private:
@ -138,7 +138,7 @@ private:
bool program_mode; bool program_mode;
PT::Log * log; pt::Log * log;
void CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t * arg = 0); void CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t * arg = 0);
@ -175,6 +175,9 @@ private:
void ReadDirectiveComment(Item & item); void ReadDirectiveComment(Item & item);
void ReadDirectiveInclude(Item & item); void ReadDirectiveInclude(Item & item);
void ReadDirectiveDef(Item & item); void ReadDirectiveDef(Item & item);
void ReadDirectiveDefIfNotSet(Item & item);
void ReadDirectiveLet(Item & item);
void ReadDirectiveLetIfNotSet(Item & item);
void ReadDirectiveFilter(Item & item); void ReadDirectiveFilter(Item & item);
void ReadDirectiveEzc(Item & item); void ReadDirectiveEzc(Item & item);
void ReadDirectiveOut(Item & item); void ReadDirectiveOut(Item & item);