added: possibility to define a block
changed: in Functions Functions are only for user-defined functions now (before they could remember a string variable too) added: class Vars for variables a variable can be a string or an alias to an other function or block added: now we can have nested functions calls e.g.: [function1 [function2]] in the above example an output (stream) from function2 will be passed as the first argument to funcion1 (will be passed as a string) removed: UTF8() method from PatternParser now it is treated that when we have only std::string (or char*) that this is an UTF-8 string git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@970 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
parent
b5faf171e3
commit
71c5bd11d5
|
@ -1,8 +1,9 @@
|
||||||
# DO NOT DELETE
|
# DO NOT DELETE
|
||||||
|
|
||||||
item.o: item.h funinfo.h
|
blocks.o: blocks.h item.h funinfo.h functions.h ../../pikotools/utf8/utf8.h
|
||||||
pattern.o: pattern.h item.h funinfo.h functions.h stringconv.h
|
item.o: item.h funinfo.h functions.h ../../pikotools/utf8/utf8.h
|
||||||
pattern.o: ../../pikotools/utf8/utf8.h
|
pattern.o: pattern.h item.h funinfo.h functions.h ../../pikotools/utf8/utf8.h
|
||||||
patternparser.o: patternparser.h pattern.h item.h funinfo.h functions.h
|
patternparser.o: patternparser.h blocks.h item.h funinfo.h functions.h
|
||||||
patternparser.o: stringconv.h ../../pikotools/utf8/utf8.h
|
patternparser.o: ../../pikotools/utf8/utf8.h pattern.h
|
||||||
stringconv.o: stringconv.h
|
stringconv.o: stringconv.h
|
||||||
|
vars.o: vars.h
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
o = item.o pattern.o patternparser.o stringconv.o
|
o = blocks.o item.o pattern.o patternparser.o stringconv.o vars.o
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
#include "blocks.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Ezc
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
void Blocks::Insert(const std::wstring & name, const Item & item)
|
||||||
|
{
|
||||||
|
blocks_tab[name] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Blocks::Iterator Blocks::Find(const std::wstring & name)
|
||||||
|
{
|
||||||
|
return blocks_tab.find(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Blocks::Iterator Blocks::Begin()
|
||||||
|
{
|
||||||
|
return blocks_tab.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Blocks::Iterator Blocks::End()
|
||||||
|
{
|
||||||
|
return blocks_tab.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t Blocks::Size()
|
||||||
|
{
|
||||||
|
return blocks_tab.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* This file is a part of EZC -- Easy templating in C++
|
||||||
|
* and is distributed under the (new) BSD licence.
|
||||||
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Tomasz Sowa
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||||
|
* project may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef headerfile_ezc_blocks
|
||||||
|
#define headerfile_ezc_blocks
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include "item.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Ezc
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Blocks
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::map<std::wstring, Item> BlocksTable;
|
||||||
|
typedef BlocksTable::iterator Iterator;
|
||||||
|
|
||||||
|
void Insert(const std::wstring & name, const Item & item);
|
||||||
|
|
||||||
|
Iterator Find(const std::wstring & name);
|
||||||
|
|
||||||
|
Iterator Begin();
|
||||||
|
Iterator End();
|
||||||
|
size_t Size();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
BlocksTable blocks_tab;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
#endif
|
142
src/functions.h
142
src/functions.h
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007-2012, Tomasz Sowa
|
* Copyright (c) 2007-2014, 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
|
||||||
|
@ -39,8 +39,9 @@
|
||||||
#define headerfile_ezc_functions
|
#define headerfile_ezc_functions
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include "utf8/utf8.h"
|
||||||
#include "funinfo.h"
|
#include "funinfo.h"
|
||||||
#include "stringconv.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Ezc
|
namespace Ezc
|
||||||
|
@ -55,95 +56,43 @@ class Functions
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef void (*UserFunction)(FunInfo<StreamType> &);
|
typedef void (*UserFunction)(FunInfo<StreamType> &);
|
||||||
enum Type { function, variable };
|
typedef std::map<std::wstring, UserFunction> FunctionsTable;
|
||||||
|
|
||||||
struct Function
|
|
||||||
{
|
|
||||||
Function();
|
|
||||||
|
|
||||||
Type type;
|
|
||||||
UserFunction user_function; // used when type is 'function'
|
|
||||||
std::wstring variable; // used when type is 'variable'
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::map<std::wstring, Function> FunctionsTable;
|
|
||||||
typedef typename FunctionsTable::iterator Iterator;
|
typedef typename FunctionsTable::iterator Iterator;
|
||||||
|
|
||||||
|
void Insert(const char * key, UserFunction ufunction);
|
||||||
void Insert(const char * key, UserFunction ufunction); // inserting a function
|
void Insert(const std::string & key, UserFunction ufunction);
|
||||||
void Insert(const char * key, const char * var); // inserting a variable
|
void Insert(const wchar_t * key, UserFunction ufunction);
|
||||||
void Insert(const char * key, const std::string & var); // inserting a variable
|
|
||||||
void Insert(const std::string & key, UserFunction ufunction); // inserting a function
|
|
||||||
void Insert(const std::string & key, const char * var); // inserting a variable
|
|
||||||
void Insert(const std::string & key, const std::string & var); // inserting a variable
|
|
||||||
void Insert(const std::wstring & key, UserFunction ufunction);
|
void Insert(const std::wstring & key, UserFunction ufunction);
|
||||||
void Insert(const std::wstring & key, const wchar_t * var);
|
|
||||||
void Insert(const std::wstring & key, const std::wstring & var);
|
|
||||||
|
|
||||||
bool Find(const std::string & key, Function ** fun);
|
typename Iterator Find(const std::wstring & key);
|
||||||
bool Find(const std::wstring & key, Function ** fun);
|
|
||||||
|
|
||||||
Iterator Begin();
|
Iterator Begin();
|
||||||
Iterator End();
|
Iterator End();
|
||||||
size_t Size() const;
|
size_t Size() const;
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
FunctionsTable functions_tab;
|
FunctionsTable functions_tab;
|
||||||
std::wstring temp_key;
|
std::wstring temp_key;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
|
||||||
Functions<StreamType>::Function::Function()
|
|
||||||
{
|
|
||||||
type = Functions::variable;
|
|
||||||
user_function = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Functions<StreamType>::Insert(const char * key, UserFunction ufunction)
|
void Functions<StreamType>::Insert(const char * key, UserFunction ufunction)
|
||||||
{
|
{
|
||||||
Function f;
|
PT::UTF8ToWide(key, temp_key);
|
||||||
f.type = function;
|
functions_tab[temp_key] = ufunction;
|
||||||
f.user_function = ufunction;
|
temp_key.clear();
|
||||||
|
|
||||||
AssignString(key, temp_key);
|
|
||||||
functions_tab[temp_key] = f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
|
||||||
void Functions<StreamType>::Insert(const char * key, const char * var)
|
|
||||||
{
|
|
||||||
Function f;
|
|
||||||
f.type = variable;
|
|
||||||
AssignString(var, f.variable);
|
|
||||||
|
|
||||||
AssignString(key, temp_key);
|
|
||||||
functions_tab[temp_key] = f;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
|
||||||
void Functions<StreamType>::Insert(const char * key, const std::string & var)
|
|
||||||
{
|
|
||||||
Function f;
|
|
||||||
f.type = variable;
|
|
||||||
AssignString(var, f.variable);
|
|
||||||
|
|
||||||
AssignString(key, temp_key);
|
|
||||||
functions_tab[temp_key] = f;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Functions<StreamType>::Insert(const std::string & key, UserFunction ufunction)
|
void Functions<StreamType>::Insert(const std::string & key, UserFunction ufunction)
|
||||||
{
|
{
|
||||||
|
@ -152,54 +101,18 @@ void Functions<StreamType>::Insert(const std::string & key, UserFunction ufuncti
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Functions<StreamType>::Insert(const std::string & key, const char * var)
|
void Functions<StreamType>::Insert(const wchar_t * key, UserFunction ufunction)
|
||||||
{
|
{
|
||||||
Insert(key.c_str(), var);
|
temp_key = key;
|
||||||
|
functions_tab[temp_key] = ufunction;
|
||||||
|
temp_key.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
|
||||||
void Functions<StreamType>::Insert(const std::string & key, const std::string & var)
|
|
||||||
{
|
|
||||||
Insert(key.c_str(), var);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Functions<StreamType>::Insert(const std::wstring & key, UserFunction ufunction)
|
void Functions<StreamType>::Insert(const std::wstring & key, UserFunction ufunction)
|
||||||
{
|
{
|
||||||
Function f;
|
functions_tab[key] = ufunction;
|
||||||
f.type = function;
|
|
||||||
f.user_function = ufunction;
|
|
||||||
|
|
||||||
functions_tab[key] = f;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
|
||||||
void Functions<StreamType>::Insert(const std::wstring & key, const wchar_t * var)
|
|
||||||
{
|
|
||||||
Function f;
|
|
||||||
f.type = variable;
|
|
||||||
f.variable = var;
|
|
||||||
|
|
||||||
functions_tab[key] = f;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
|
||||||
void Functions<StreamType>::Insert(const std::wstring & key, const std::wstring & var)
|
|
||||||
{
|
|
||||||
Function f;
|
|
||||||
f.type = variable;
|
|
||||||
f.variable = var;
|
|
||||||
|
|
||||||
functions_tab[key] = f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -207,25 +120,12 @@ void Functions<StreamType>::Insert(const std::wstring & key, const std::wstring
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
|
||||||
bool Functions<StreamType>::Find(const std::string & key, Function ** fun)
|
|
||||||
{
|
|
||||||
AssignString(key, temp_key);
|
|
||||||
return Find(temp_key, fun);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
bool Functions<StreamType>::Find(const std::wstring & key, Function ** fun)
|
typename Functions<StreamType>::Iterator Functions<StreamType>::Find(const std::wstring & key)
|
||||||
{
|
{
|
||||||
typename FunctionsTable::iterator i = functions_tab.find( key );
|
return functions_tab.find(key);
|
||||||
|
|
||||||
if( i == functions_tab.end() )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
*fun = &(i->second);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,15 @@ struct Stack
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~Stack()
|
||||||
|
{
|
||||||
|
if( fun_data && remove )
|
||||||
|
{
|
||||||
|
delete fun_data;
|
||||||
|
fun_data = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Clear()
|
void Clear()
|
||||||
{
|
{
|
||||||
iter = 0;
|
iter = 0;
|
||||||
|
@ -107,17 +116,12 @@ struct FunInfo
|
||||||
// output stream
|
// output stream
|
||||||
StreamType & out;
|
StreamType & out;
|
||||||
|
|
||||||
// the out stream is treated in case sensitive
|
|
||||||
// used only in [is...] statements
|
|
||||||
// default: true
|
|
||||||
bool case_sensitive;
|
|
||||||
|
|
||||||
// table of parameters
|
// table of parameters
|
||||||
// the table can be empty
|
// the table can be empty
|
||||||
std::vector<std::wstring> & params;
|
std::vector<std::wstring> & params;
|
||||||
|
|
||||||
// the first parameter
|
// the first parameter
|
||||||
// you can always use it even if there is not any parameters (params is empty)
|
// you can always use it even if there are not any parameters (params is empty)
|
||||||
// in such a way the reference points to an empty string
|
// in such a way the reference points to an empty string
|
||||||
const std::wstring & par;
|
const std::wstring & par;
|
||||||
|
|
||||||
|
@ -129,7 +133,7 @@ struct FunInfo
|
||||||
bool is_for;
|
bool is_for;
|
||||||
|
|
||||||
// indicates that this function is from [if ...] statement
|
// indicates that this function is from [if ...] statement
|
||||||
// is true for all kind of if's: if-one, if-any, if-no....
|
// it is true for all kind of if's: if-one, if-any, if-no....
|
||||||
bool is_if;
|
bool is_if;
|
||||||
|
|
||||||
// indicates that this function is from [is ...] or [is-no ...] statements
|
// indicates that this function is from [is ...] or [is-no ...] statements
|
||||||
|
@ -141,28 +145,26 @@ struct FunInfo
|
||||||
// indicates that this function is from a filter statement [filter ...]
|
// indicates that this function is from a filter statement [filter ...]
|
||||||
bool is_filter;
|
bool is_filter;
|
||||||
|
|
||||||
// a pointer to a stack's item from generator's stack
|
// a stack's item from generator's stack
|
||||||
// it is never null
|
|
||||||
// each function has a new stack item
|
// each function has a new stack item
|
||||||
// on this stack you have iter (description below) and fun_data pointer
|
// on this stack you have iter (description below) and fun_data pointer
|
||||||
// you can assign to it your own object derived from FunData
|
// you can assign to it your own object derived from FunData
|
||||||
Stack * stack;
|
Stack & stack;
|
||||||
|
|
||||||
// the same as stack->iter (this is mainly for backward compatibility)
|
// the same as stack.iter (this is mainly for backward compatibility)
|
||||||
// it indicates the number of a current iteration for the [for] statement (the first iteration is 0)
|
// it indicates the number of a current iteration for the [for] statement (the first iteration is 0)
|
||||||
// for other statements than [for] this is always zero
|
// for other statements than [for] this is always zero
|
||||||
size_t iter;
|
size_t iter;
|
||||||
|
|
||||||
// return value from a user's function (default false if not set directly by the function)
|
// return value from a user's function (default false if not set directly by the function)
|
||||||
// for a variable it is set to true if the variable is not empty
|
|
||||||
bool res;
|
bool res;
|
||||||
|
|
||||||
|
|
||||||
// arguments: output_stream, table_of_parameters, the_first_parameter
|
// arguments: output_stream, table_of_parameters, the_first_parameter
|
||||||
FunInfo(StreamType & o,
|
FunInfo(StreamType & o,
|
||||||
std::vector<std::wstring> & pars,
|
std::vector<std::wstring> & pars,
|
||||||
const std::wstring & first_par,
|
const std::wstring & first_par,
|
||||||
const StreamType & i) : out(o), params(pars), par(first_par), in(i)
|
const StreamType & input_stream,
|
||||||
|
Stack & s) : out(o), params(pars), par(first_par), in(input_stream), stack(s)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
|
@ -176,9 +178,7 @@ struct FunInfo
|
||||||
is_is = false;
|
is_is = false;
|
||||||
is_normal = false;
|
is_normal = false;
|
||||||
is_filter = false;
|
is_filter = false;
|
||||||
stack = 0;
|
|
||||||
iter = 0;
|
iter = 0;
|
||||||
case_sensitive = true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
636
src/generator.h
636
src/generator.h
|
@ -39,6 +39,8 @@
|
||||||
#ifndef headerfile_ezc_generator
|
#ifndef headerfile_ezc_generator
|
||||||
#define headerfile_ezc_generator
|
#define headerfile_ezc_generator
|
||||||
|
|
||||||
|
#include "vars.h"
|
||||||
|
#include "blocks.h"
|
||||||
#include "pattern.h"
|
#include "pattern.h"
|
||||||
#include "functions.h"
|
#include "functions.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -65,6 +67,10 @@ public:
|
||||||
Generator & operator=(const Generator & n);
|
Generator & operator=(const Generator & n);
|
||||||
~Generator();
|
~Generator();
|
||||||
|
|
||||||
|
void SetPattern(Pattern & pattern);
|
||||||
|
void SetVars(Vars & vars);
|
||||||
|
void SetBlocks(Blocks & blocks);
|
||||||
|
void SetFunctions(Functions<StreamType> & functions);
|
||||||
|
|
||||||
void SetMax(size_t max_items_, size_t max_for_items_);
|
void SetMax(size_t max_items_, size_t max_for_items_);
|
||||||
|
|
||||||
|
@ -102,34 +108,52 @@ public:
|
||||||
void SkipStream(int stream_index);
|
void SkipStream(int stream_index);
|
||||||
|
|
||||||
// the main methods for generating
|
// the main methods for generating
|
||||||
void Generate(StreamType & o, Pattern & p, Functions<StreamType> & f);
|
void Generate(StreamType & o);
|
||||||
void Generate(std::vector<StreamType> & o, Pattern & p, Functions<StreamType> & f);
|
void Generate(std::vector<StreamType> & o);
|
||||||
void Generate(std::vector<StreamType*> & o, Pattern & p, Functions<StreamType> & f);
|
void Generate(std::vector<StreamType*> & o);
|
||||||
// this method is used only if the pattern has cached functions
|
|
||||||
void Generate(StreamType & o, Pattern & p);
|
|
||||||
void Generate(std::vector<StreamType> & o, Pattern & p);
|
|
||||||
void Generate(std::vector<StreamType*> & o, Pattern & p);
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
struct BlockStack
|
||||||
|
{
|
||||||
|
std::vector<std::wstring> args;
|
||||||
|
StreamType * out_stream;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<BlockStack> block_stack_tab;
|
||||||
|
size_t block_stack_index;
|
||||||
|
size_t block_stack_size;
|
||||||
|
|
||||||
// current output stream
|
// current output stream
|
||||||
// if we are printing only to one stream e.g. [put stream "3"]
|
// if we are printing only to one stream e.g. [ezc output "3"]
|
||||||
// then output_stream is pointing directly to that stream
|
// then output_stream is pointing directly to that stream
|
||||||
// but if we are printing to more than one stream e.g. [put stream "0" "2" "5"]
|
// but if we are printing to more than one stream e.g. [ezc output "0" "2" "5"]
|
||||||
// then output_stream is pointing to output_tmp_stream and at the end
|
// then output_stream is pointing to output_tmp_stream and at the end
|
||||||
// output_tmp_stream is copied to the correct streams
|
// output_tmp_stream is copied to the correct streams
|
||||||
// output_stream can be null e.g. [put stream] without arguments
|
// output_stream can be null e.g. [ezc output] without arguments
|
||||||
// in such a case we do not print anything
|
// in such a case we do not print anything (but any functions are evaluated)
|
||||||
StreamType * output_stream;
|
StreamType * output_stream;
|
||||||
Pattern * pattern;
|
|
||||||
Functions<StreamType> * functions;
|
Pattern * ppattern;
|
||||||
|
Vars * pvars;
|
||||||
|
Blocks * pblocks;
|
||||||
|
Functions<StreamType> * pfunctions;
|
||||||
|
|
||||||
// output_tmp_stream is used when outputting to more than one stream
|
// output_tmp_stream is used when outputting to more than one stream
|
||||||
// (first we output to output_tmp_stream and then the content is copied
|
// (first we output to output_tmp_stream and then the content is copied
|
||||||
// to the correct streams)
|
// to the correct streams)
|
||||||
StreamType output_tmp_stream;
|
StreamType output_tmp_stream;
|
||||||
|
|
||||||
|
// local_temp_stream is used when there are nested function calls
|
||||||
|
// e.g.: [function1 [function2]]
|
||||||
|
// function2 will be redirected to local_temp_stream and the string
|
||||||
|
// will be copied to Item::function.par std::wstring object
|
||||||
|
StreamType local_temp_stream;
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::wstring> parameters;
|
||||||
|
|
||||||
// pointers to the output streams
|
// pointers to the output streams
|
||||||
std::vector<StreamType*> output_stream_tab;
|
std::vector<StreamType*> output_stream_tab;
|
||||||
|
|
||||||
|
@ -164,12 +188,12 @@ private:
|
||||||
std::vector<StreamType*> filter_tab;
|
std::vector<StreamType*> filter_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..] [is...] or [for...]
|
// temporary streams used in [if..] [is...] or [for...]
|
||||||
// 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_temp2;
|
StreamType stream_temp1, stream_temp2, stream_temp_define;
|
||||||
|
|
||||||
// whether last function has put its content in case_sensitive (set FunInfo::case_sensitive)
|
|
||||||
bool last_case_sensitive;
|
|
||||||
|
|
||||||
// last result from a user function (FunInfo::res)
|
// last result from a user function (FunInfo::res)
|
||||||
bool last_res;
|
bool last_res;
|
||||||
|
@ -194,29 +218,56 @@ private:
|
||||||
|
|
||||||
void ResizeFilterTab();
|
void ResizeFilterTab();
|
||||||
void ResizeStack();
|
void ResizeStack();
|
||||||
|
void ResizeBlockStack();
|
||||||
|
|
||||||
void ClearFilterTab();
|
void ClearFilterTab();
|
||||||
void ClearForStack(bool resize_stack = true);
|
void ClearForStack();
|
||||||
void ClearStream(StreamType & str);
|
void ClearStream(StreamType & str);
|
||||||
void RemoveStackFunData(Stack & sitem);
|
void RemoveStackFunData(Stack & sitem);
|
||||||
|
|
||||||
template<class CharType>
|
template<class CharType>
|
||||||
CharType ToLower(CharType c);
|
CharType ToLower(CharType c);
|
||||||
|
|
||||||
template<class CharType>
|
bool AreStreamsEqual(StreamType & str1, StreamType & str2);
|
||||||
bool StrCmpNc(CharType * str1, CharType * str2);
|
const std::wstring & GetStringFromStream(StreamType & str);
|
||||||
|
|
||||||
bool AreStreamsEqual(StreamType & str1, StreamType & str2, bool case_sensitive);
|
bool FindInCache(const Item::Function & item_fun,
|
||||||
|
typename Functions<StreamType>::UserFunction ** function,
|
||||||
|
Item ** item_block,
|
||||||
|
std::wstring ** variable);
|
||||||
|
|
||||||
|
bool FindInFunctionsAndBlocks(const std::wstring & name,
|
||||||
|
typename Functions<StreamType>::UserFunction ** function,
|
||||||
|
Item ** item_block);
|
||||||
|
|
||||||
bool Find(const Item::Function & item_fun, typename Functions<StreamType>::Function ** function);
|
bool FindInVariables(const std::wstring & name,
|
||||||
|
typename Functions<StreamType>::UserFunction ** function,
|
||||||
|
Item ** item_block,
|
||||||
|
std::wstring ** variable);
|
||||||
|
|
||||||
void Call(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info);
|
bool Find(const Item::Function & item_fun,
|
||||||
void Call(typename Functions<StreamType>::Function * function, std::vector<std::wstring> & params,
|
typename Functions<StreamType>::UserFunction ** function,
|
||||||
StreamType & out_stream, bool clear_out_stream, const StreamType & in_stream);
|
Item ** item_block,
|
||||||
|
std::wstring ** variable);
|
||||||
|
|
||||||
bool Call(Item::Function & item_fun, StreamType & out_stream, bool clear_out_stream);
|
void CallFunction(typename Functions<StreamType>::UserFunction * function,
|
||||||
bool Call(Item::Function & function);
|
FunInfo<StreamType> & info);
|
||||||
|
|
||||||
|
void CallFunction(typename Functions<StreamType>::UserFunction * function,
|
||||||
|
std::vector<std::wstring> & params,
|
||||||
|
StreamType & out_stream,
|
||||||
|
const StreamType & in_stream);
|
||||||
|
|
||||||
|
bool CallBlock(Item & item_block,
|
||||||
|
std::vector<std::wstring> & params,
|
||||||
|
StreamType & out_stream);
|
||||||
|
|
||||||
|
bool Call(Item::Function & item_fun,
|
||||||
|
StreamType & out_stream,
|
||||||
|
bool clear_out_stream,
|
||||||
|
const StreamType & in_stream);
|
||||||
|
|
||||||
|
bool Call(Item::Function & item_fun);
|
||||||
|
|
||||||
wchar_t CreateSpecialChar(wchar_t c);
|
wchar_t CreateSpecialChar(wchar_t c);
|
||||||
const wchar_t * PrintSpecialChar(const wchar_t * start, const wchar_t * end);
|
const wchar_t * PrintSpecialChar(const wchar_t * start, const wchar_t * end);
|
||||||
|
@ -245,7 +296,6 @@ private:
|
||||||
void MakeTextIfanyno(Item & item);
|
void MakeTextIfanyno(Item & item);
|
||||||
void MakeTextIfoneno(Item & item);
|
void MakeTextIfoneno(Item & item);
|
||||||
void MakeTextIfindex(Item & item);
|
void MakeTextIfindex(Item & item);
|
||||||
void MakeTextForLoop(Item & item, typename Functions<StreamType>::Function * function);
|
|
||||||
void MakeTextFor(Item & item);
|
void MakeTextFor(Item & item);
|
||||||
void MakeItemText(Item & item);
|
void MakeItemText(Item & item);
|
||||||
void MakeTextContainer(Item & item);
|
void MakeTextContainer(Item & item);
|
||||||
|
@ -260,7 +310,7 @@ private:
|
||||||
|
|
||||||
void MakeEzcStream(Item::Function & fun);
|
void MakeEzcStream(Item::Function & fun);
|
||||||
|
|
||||||
void Generate(Pattern * p, Functions<StreamType> * f);
|
void Generate();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -275,8 +325,10 @@ template<class StreamType>
|
||||||
Generator<StreamType>::Generator() : empty_stream()
|
Generator<StreamType>::Generator() : empty_stream()
|
||||||
{
|
{
|
||||||
output_stream = 0;
|
output_stream = 0;
|
||||||
pattern = 0;
|
ppattern = 0;
|
||||||
functions = 0;
|
pvars = 0;
|
||||||
|
pblocks = 0;
|
||||||
|
pfunctions = 0;
|
||||||
|
|
||||||
max_items = 50000;
|
max_items = 50000;
|
||||||
max_for_items = 5000;
|
max_for_items = 5000;
|
||||||
|
@ -286,6 +338,7 @@ Generator<StreamType>::Generator() : empty_stream()
|
||||||
skip_new_line = false;
|
skip_new_line = false;
|
||||||
is_generator_working = false;
|
is_generator_working = false;
|
||||||
stack_size = 300;
|
stack_size = 300;
|
||||||
|
block_stack_size = 64;
|
||||||
has_skip_stream_index = false;
|
has_skip_stream_index = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,8 +360,11 @@ Generator<StreamType> & Generator<StreamType>::operator=(const Generator<StreamT
|
||||||
output_tmp_stream = n.output_tmp_stream;
|
output_tmp_stream = n.output_tmp_stream;
|
||||||
output_stream = n.output_stream;
|
output_stream = n.output_stream;
|
||||||
|
|
||||||
pattern = n.pattern;
|
ppattern = n.ppattern;
|
||||||
functions = n.functions;
|
pvars = n.pvars;
|
||||||
|
pblocks = n.pblocks;
|
||||||
|
pfunctions = n.pfunctions;
|
||||||
|
|
||||||
max_items = n.max_items;
|
max_items = n.max_items;
|
||||||
max_for_items = n.max_for_items;
|
max_for_items = n.max_for_items;
|
||||||
special_chars = n.special_chars;
|
special_chars = n.special_chars;
|
||||||
|
@ -316,9 +372,11 @@ Generator<StreamType> & Generator<StreamType>::operator=(const Generator<StreamT
|
||||||
skip_new_line = n.skip_new_line;
|
skip_new_line = n.skip_new_line;
|
||||||
has_skip_stream_index = n.has_skip_stream_index;
|
has_skip_stream_index = n.has_skip_stream_index;
|
||||||
|
|
||||||
// filter and stack will be auto resized after next call to Generate() method
|
// filter, stack and block_stack will be auto resized when calling Generate() method
|
||||||
filter_size = n.filter_size;
|
filter_size = n.filter_size;
|
||||||
stack_size = n.stack_size;
|
stack_size = n.stack_size;
|
||||||
|
block_stack_size = n.block_stack_size;
|
||||||
|
|
||||||
|
|
||||||
// don't copy filter tab
|
// don't copy filter tab
|
||||||
// don't copy stack
|
// don't copy stack
|
||||||
|
@ -341,6 +399,35 @@ Generator<StreamType>::~Generator()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
void Generator<StreamType>::SetPattern(Pattern & pattern)
|
||||||
|
{
|
||||||
|
ppattern = &pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
void Generator<StreamType>::SetVars(Vars & vars)
|
||||||
|
{
|
||||||
|
pvars = &vars;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
void Generator<StreamType>::SetBlocks(Blocks & blocks)
|
||||||
|
{
|
||||||
|
pblocks = &blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
void Generator<StreamType>::SetFunctions(Functions<StreamType> & functions)
|
||||||
|
{
|
||||||
|
pfunctions = &functions;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::ResizeFilterTab()
|
void Generator<StreamType>::ResizeFilterTab()
|
||||||
{
|
{
|
||||||
|
@ -378,6 +465,30 @@ void Generator<StreamType>::ResizeStack()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
void Generator<StreamType>::ResizeBlockStack()
|
||||||
|
{
|
||||||
|
if( block_stack_tab.size() != block_stack_size )
|
||||||
|
{
|
||||||
|
if( block_stack_tab.size() < block_stack_size )
|
||||||
|
{
|
||||||
|
size_t i = block_stack_tab.size();
|
||||||
|
block_stack_tab.resize(block_stack_size);
|
||||||
|
|
||||||
|
for( ; i<block_stack_tab.size() ; ++i)
|
||||||
|
block_stack_tab[i].out_stream = new StreamType();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(size_t i=block_stack_size ; i<block_stack_tab.size() ; ++i)
|
||||||
|
delete block_stack_tab[i].out_stream;
|
||||||
|
|
||||||
|
block_stack_tab.resize(block_stack_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::ClearFilterTab()
|
void Generator<StreamType>::ClearFilterTab()
|
||||||
{
|
{
|
||||||
|
@ -389,13 +500,10 @@ void Generator<StreamType>::ClearFilterTab()
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::ClearForStack(bool resize_stack)
|
void Generator<StreamType>::ClearForStack()
|
||||||
{
|
{
|
||||||
for(size_t i=0 ; i<stack_tab.size() ; ++i)
|
for(size_t i=0 ; i<stack_tab.size() ; ++i)
|
||||||
RemoveStackFunData(stack_tab[i]);
|
RemoveStackFunData(stack_tab[i]);
|
||||||
|
|
||||||
if( resize_stack )
|
|
||||||
stack_tab.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -448,22 +556,9 @@ return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
|
||||||
template<class CharType>
|
|
||||||
bool Generator<StreamType>::StrCmpNc(CharType * str1, CharType * str2)
|
|
||||||
{
|
|
||||||
for( ; ToLower(*str1) == ToLower(*str2) ; ++str1, ++str2)
|
|
||||||
if( *str1 == 0 )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
bool Generator<StreamType>::AreStreamsEqual(StreamType & str1, StreamType & str2, bool case_sensitive)
|
bool Generator<StreamType>::AreStreamsEqual(StreamType & str1, StreamType & str2)
|
||||||
{
|
|
||||||
if( case_sensitive )
|
|
||||||
{
|
{
|
||||||
#ifdef EZC_HAS_SPECIAL_STREAM
|
#ifdef EZC_HAS_SPECIAL_STREAM
|
||||||
return str1.Str() == str2.Str();
|
return str1.Str() == str2.Str();
|
||||||
|
@ -471,14 +566,18 @@ bool Generator<StreamType>::AreStreamsEqual(StreamType & str1, StreamType & str2
|
||||||
return str1.str() == str2.str();
|
return str1.str() == str2.str();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
const std::wstring & Generator<StreamType>::GetStringFromStream(StreamType & stream)
|
||||||
{
|
{
|
||||||
#ifdef EZC_HAS_SPECIAL_STREAM
|
#ifdef EZC_HAS_SPECIAL_STREAM
|
||||||
return StrCmpNc(str1.CStr(), str2.CStr());
|
const std::wstring & str = stream.Str();
|
||||||
#else
|
#else
|
||||||
return StrCmpNc(str1.str().c_str(), str2.str().c_str());
|
const std::wstring & str = stream.str();
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -529,7 +628,7 @@ void Generator<StreamType>::SetStackSize(size_t new_stack_size)
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::Generate(Pattern * p, Functions<StreamType> * f)
|
void Generator<StreamType>::Generate()
|
||||||
{
|
{
|
||||||
if( is_generator_working )
|
if( is_generator_working )
|
||||||
{
|
{
|
||||||
|
@ -550,27 +649,27 @@ void Generator<StreamType>::Generate(Pattern * p, Functions<StreamType> * f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pattern = p;
|
|
||||||
functions = f;
|
|
||||||
break_generating = false;
|
break_generating = false;
|
||||||
current_item = 0;
|
current_item = 0;
|
||||||
|
|
||||||
// in the case that there something has left on the stack
|
// in the case that there something has left on the stack
|
||||||
// from previous call to Generate()
|
// from previous call to Generate()
|
||||||
// (an exception could have been thrown)
|
// (an exception could have been thrown)
|
||||||
ClearForStack(false);
|
ClearForStack();
|
||||||
|
|
||||||
ResizeFilterTab();
|
ResizeFilterTab();
|
||||||
ResizeStack();
|
ResizeStack();
|
||||||
|
ResizeBlockStack();
|
||||||
filter_index = 0;
|
filter_index = 0;
|
||||||
stack_index = 0;
|
stack_index = 0;
|
||||||
|
block_stack_index = 0;
|
||||||
|
|
||||||
if( pattern )
|
if( ppattern )
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
is_generator_working = true;
|
is_generator_working = true;
|
||||||
MakeText( pattern->item_root );
|
MakeText( ppattern->item_root );
|
||||||
|
|
||||||
if( output_stream_index.size() > 1 )
|
if( output_stream_index.size() > 1 )
|
||||||
WriteTmpStreamToStreams();
|
WriteTmpStreamToStreams();
|
||||||
|
@ -587,109 +686,170 @@ void Generator<StreamType>::Generate(Pattern * p, Functions<StreamType> * f)
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::Generate(StreamType & o, Pattern & p, Functions<StreamType> & f)
|
void Generator<StreamType>::Generate(StreamType & o)
|
||||||
{
|
{
|
||||||
output_stream_tab.resize(1);
|
output_stream_tab.resize(1);
|
||||||
output_stream_tab[0] = &o;
|
output_stream_tab[0] = &o;
|
||||||
|
|
||||||
Generate(&p, &f);
|
Generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::Generate(std::vector<StreamType> & o, Pattern & p, Functions<StreamType> & f)
|
void Generator<StreamType>::Generate(std::vector<StreamType> & o)
|
||||||
{
|
{
|
||||||
output_stream_tab.resize(o.size());
|
output_stream_tab.resize(o.size());
|
||||||
|
|
||||||
for(size_t i=0 ; i<o.size() ; ++i)
|
for(size_t i=0 ; i<o.size() ; ++i)
|
||||||
output_stream_tab[i] = &o[i];
|
output_stream_tab[i] = &o[i];
|
||||||
|
|
||||||
Generate(&p, &f);
|
Generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::Generate(std::vector<StreamType*> & o, Pattern & p, Functions<StreamType> & f)
|
void Generator<StreamType>::Generate(std::vector<StreamType*> & o)
|
||||||
{
|
{
|
||||||
output_stream_tab.resize(o.size());
|
output_stream_tab.resize(o.size());
|
||||||
|
|
||||||
for(size_t i=0 ; i<o.size() ; ++i)
|
for(size_t i=0 ; i<o.size() ; ++i)
|
||||||
output_stream_tab[i] = o[i];
|
output_stream_tab[i] = o[i];
|
||||||
|
|
||||||
Generate(&p, &f);
|
Generate();
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
|
||||||
void Generator<StreamType>::Generate(StreamType & o, Pattern & p)
|
|
||||||
{
|
|
||||||
output_stream_tab.resize(1);
|
|
||||||
output_stream_tab[0] = &o;
|
|
||||||
|
|
||||||
Generate(&p, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
|
||||||
void Generator<StreamType>::Generate(std::vector<StreamType> & o, Pattern & p)
|
|
||||||
{
|
|
||||||
output_stream_tab.resize(o.size());
|
|
||||||
|
|
||||||
for(size_t i=0 ; i<o.size() ; ++i)
|
|
||||||
output_stream_tab[i] = &o[i];
|
|
||||||
|
|
||||||
Generate(&p, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::Generate(std::vector<StreamType*> & o, Pattern & p)
|
bool Generator<StreamType>::FindInCache(const Item::Function & item_fun,
|
||||||
|
typename Functions<StreamType>::UserFunction ** function,
|
||||||
|
Item ** item_block,
|
||||||
|
std::wstring ** variable)
|
||||||
{
|
{
|
||||||
output_stream_tab.resize(o.size());
|
if( item_fun.arg >=0 )
|
||||||
|
{
|
||||||
|
empty_argument.clear();
|
||||||
|
*variable = &empty_argument;
|
||||||
|
|
||||||
for(size_t i=0 ; i<o.size() ; ++i)
|
// it's a numeric function -- an argument to a block e.g.: [1]
|
||||||
output_stream_tab[i] = o[i];
|
if( block_stack_index > 0 )
|
||||||
|
{
|
||||||
|
BlockStack & block_stack = block_stack_tab[block_stack_index-1];
|
||||||
|
|
||||||
Generate(&p, 0);
|
if( size_t(item_fun.arg) < block_stack.args.size() )
|
||||||
|
*variable = &block_stack.args[item_fun.arg];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
|
||||||
bool Generator<StreamType>::Find(const Item::Function & item_fun, typename Functions<StreamType>::Function ** function)
|
|
||||||
{
|
|
||||||
if( !functions )
|
|
||||||
{
|
|
||||||
if( item_fun.fun_cache )
|
if( item_fun.fun_cache )
|
||||||
{
|
{
|
||||||
*function = reinterpret_cast<typename Functions<StreamType>::Function*>(item_fun.fun_cache);
|
*function = reinterpret_cast<typename Functions<StreamType>::UserFunction*>(item_fun.fun_cache);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( item_fun.item_block )
|
||||||
|
{
|
||||||
|
*item_block = item_fun.item_block;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
bool Generator<StreamType>::FindInFunctionsAndBlocks(const std::wstring & name,
|
||||||
|
typename Functions<StreamType>::UserFunction ** function,
|
||||||
|
Item ** item_block)
|
||||||
|
{
|
||||||
|
if( pfunctions )
|
||||||
|
{
|
||||||
|
Functions<StreamType>::Iterator i = pfunctions->Find(name);
|
||||||
|
|
||||||
|
if( i != pfunctions->End() )
|
||||||
|
{
|
||||||
|
*function = &i->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pblocks )
|
||||||
|
{
|
||||||
|
Blocks::Iterator i = pblocks->Find(name);
|
||||||
|
|
||||||
|
if( i != pblocks->End() )
|
||||||
|
{
|
||||||
|
*item_block = &i->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
bool Generator<StreamType>::FindInVariables(const std::wstring & name,
|
||||||
|
typename Functions<StreamType>::UserFunction ** function,
|
||||||
|
Item ** item_block,
|
||||||
|
std::wstring ** variable)
|
||||||
|
{
|
||||||
|
if( pvars )
|
||||||
|
{
|
||||||
|
Vars::Iterator i = pvars->Find(name);
|
||||||
|
|
||||||
|
if( i != pvars->End() )
|
||||||
|
{
|
||||||
|
Vars::Variable & var = i->second;
|
||||||
|
|
||||||
|
if( var.type == Vars::variable_string )
|
||||||
|
{
|
||||||
|
*variable = &var.val;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CreateUnknownMsg(item_fun.name);
|
// this is an alias to a function or to a block
|
||||||
return false;
|
return FindInFunctionsAndBlocks(var.val, function, item_block);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !functions->Find(item_fun.name, function) )
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
bool Generator<StreamType>::Find(const Item::Function & item_fun,
|
||||||
|
typename Functions<StreamType>::UserFunction ** function,
|
||||||
|
Item ** item_block,
|
||||||
|
std::wstring ** variable)
|
||||||
{
|
{
|
||||||
CreateUnknownMsg(item_fun.name);
|
*function = 0;
|
||||||
return false;
|
*item_block = 0;
|
||||||
}
|
*variable = 0;
|
||||||
|
|
||||||
|
if( FindInCache(item_fun, function, item_block, variable) )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if( FindInFunctionsAndBlocks(item_fun.name, function, item_block) )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if( FindInVariables(item_fun.name, function, item_block, variable) )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
CreateUnknownMsg(item_fun.name);
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::Call(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info)
|
void Generator<StreamType>::CallFunction(typename Functions<StreamType>::UserFunction * function, FunInfo<StreamType> & info)
|
||||||
{
|
{
|
||||||
info.Clear();
|
info.Clear();
|
||||||
|
|
||||||
|
@ -698,61 +858,130 @@ void Generator<StreamType>::Call(typename Functions<StreamType>::Function * func
|
||||||
info.is_is = is_generating_is;
|
info.is_is = is_generating_is;
|
||||||
info.is_normal = is_generating_normal;
|
info.is_normal = is_generating_normal;
|
||||||
info.is_filter = is_generating_filter;
|
info.is_filter = is_generating_filter;
|
||||||
|
info.iter = info.stack.iter;
|
||||||
|
|
||||||
info.stack = &stack_tab[stack_index-1];
|
(*function)(info);
|
||||||
info.iter = stack_tab[stack_index-1].iter;
|
|
||||||
|
|
||||||
if( function->type == Functions<StreamType>::function )
|
|
||||||
{
|
|
||||||
(function->user_function)(info);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
info.out << function->variable;
|
|
||||||
info.res = !function->variable.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
last_res = info.res;
|
last_res = info.res;
|
||||||
last_case_sensitive = info.case_sensitive;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::Call(typename Functions<StreamType>::Function * function,
|
void Generator<StreamType>::CallFunction(typename Functions<StreamType>::UserFunction * function,
|
||||||
std::vector<std::wstring> & params,
|
std::vector<std::wstring> & params,
|
||||||
StreamType & out_stream,
|
StreamType & out_stream,
|
||||||
bool clear_out_stream,
|
|
||||||
const StreamType & in_stream)
|
const StreamType & in_stream)
|
||||||
{
|
{
|
||||||
if( clear_out_stream )
|
|
||||||
ClearStream(out_stream);
|
|
||||||
|
|
||||||
if( params.empty() )
|
if( params.empty() )
|
||||||
{
|
{
|
||||||
FunInfo<StreamType> info(out_stream, params, empty, in_stream);
|
FunInfo<StreamType> info(out_stream, params, empty, in_stream, stack_tab[stack_index-1]);
|
||||||
Call(function, info);
|
CallFunction(function, info);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FunInfo<StreamType> info(out_stream, params, params[0], in_stream);
|
FunInfo<StreamType> info(out_stream, params, params[0], in_stream, stack_tab[stack_index-1]);
|
||||||
Call(function, info);
|
CallFunction(function, info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
bool Generator<StreamType>::CallBlock(Item & item_block,
|
||||||
|
std::vector<std::wstring> & params,
|
||||||
|
StreamType & out_stream)
|
||||||
|
{
|
||||||
|
if( block_stack_index >= block_stack_tab.size() )
|
||||||
|
{
|
||||||
|
CreateMsg(L"Generator exceeded allowed number of blocks");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamType * old_stream = output_stream;
|
||||||
|
BlockStack & block_stack = block_stack_tab[block_stack_index];
|
||||||
|
|
||||||
|
block_stack.args.resize(params.size());
|
||||||
|
|
||||||
|
for(size_t i=0 ; i<params.size() ; ++i)
|
||||||
|
block_stack.args[i] = params[i]; // or may std::move in the future? (params will not be used anymore)
|
||||||
|
|
||||||
|
output_stream = block_stack.out_stream;
|
||||||
|
ClearStream(*output_stream);
|
||||||
|
block_stack_index += 1;
|
||||||
|
|
||||||
|
MakeText(item_block);
|
||||||
|
|
||||||
|
const std::wstring & str = GetStringFromStream(*output_stream);
|
||||||
|
out_stream << str;
|
||||||
|
last_res = !str.empty();
|
||||||
|
|
||||||
|
ClearStream(*output_stream);
|
||||||
|
output_stream = old_stream;
|
||||||
|
block_stack_index -= 1;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// return: true if a function or variable was found and called
|
// return: true if a function or variable was found and called
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
bool Generator<StreamType>::Call(Item::Function & item_fun, StreamType & out_stream, bool clear_out_stream)
|
bool Generator<StreamType>::Call(Item::Function & item_fun,
|
||||||
|
StreamType & out_stream,
|
||||||
|
bool clear_out_stream,
|
||||||
|
const StreamType & in_stream)
|
||||||
{
|
{
|
||||||
typename Functions<StreamType>::Function * fun;
|
typename Functions<StreamType>::UserFunction * fun;
|
||||||
|
Item * item_block;
|
||||||
|
std::wstring * variable;
|
||||||
|
|
||||||
if( !Find(item_fun, &fun) )
|
if( clear_out_stream )
|
||||||
|
ClearStream(out_stream);
|
||||||
|
|
||||||
|
if( !Find(item_fun, &fun, &item_block, &variable) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Call(fun, item_fun.params, out_stream, clear_out_stream, empty_stream);
|
for(size_t i=0 ; i<item_fun.parameters.size() ; ++i)
|
||||||
|
{
|
||||||
|
Item::Function & fun_child = *item_fun.parameters[i];
|
||||||
|
|
||||||
|
if( !fun_child.name.empty() )
|
||||||
|
{
|
||||||
|
Call(fun_child, local_temp_stream, true, empty_stream);
|
||||||
|
|
||||||
|
if( fun || item_block )
|
||||||
|
fun_child.par = GetStringFromStream(local_temp_stream);
|
||||||
|
|
||||||
|
// the stream has to be cleared when we finished
|
||||||
|
ClearStream(local_temp_stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( fun || item_block )
|
||||||
|
{
|
||||||
|
parameters.resize(item_fun.parameters.size());
|
||||||
|
|
||||||
|
for(size_t i=0 ; i<item_fun.parameters.size() ; ++i)
|
||||||
|
{
|
||||||
|
// in c++11 we can use std::move here
|
||||||
|
parameters[i] = item_fun.parameters[i]->par;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( fun )
|
||||||
|
{
|
||||||
|
CallFunction(fun, parameters, out_stream, in_stream);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( item_block )
|
||||||
|
{
|
||||||
|
return CallBlock(*item_block, parameters, out_stream);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( variable )
|
||||||
|
{
|
||||||
|
out_stream << *variable;
|
||||||
|
last_res = !variable->empty();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -763,7 +992,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);
|
return Call(item_fun, stream_temp1, true, empty_stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -949,11 +1178,7 @@ return res;
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::WriteTmpStreamToStreams()
|
void Generator<StreamType>::WriteTmpStreamToStreams()
|
||||||
{
|
{
|
||||||
#ifdef EZC_HAS_SPECIAL_STREAM
|
const std::wstring & str = GetStringFromStream(output_tmp_stream);
|
||||||
const std::wstring & str = output_tmp_stream.Str();
|
|
||||||
#else
|
|
||||||
const std::wstring & str = output_tmp_stream.str();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if( !str.empty() )
|
if( !str.empty() )
|
||||||
{
|
{
|
||||||
|
@ -977,7 +1202,7 @@ void Generator<StreamType>::CreateMsg(const wchar_t * type, const wchar_t * arg)
|
||||||
{
|
{
|
||||||
if( output_stream )
|
if( output_stream )
|
||||||
{
|
{
|
||||||
pattern->CreateMsg(temp_msg, type, arg);
|
ppattern->CreateMsg(temp_msg, type, arg);
|
||||||
output_stream->write(temp_msg.c_str(), temp_msg.size());
|
output_stream->write(temp_msg.c_str(), temp_msg.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1045,11 +1270,11 @@ void Generator<StreamType>::MakeTextNormal(Item & item)
|
||||||
|
|
||||||
if( output_stream )
|
if( output_stream )
|
||||||
{
|
{
|
||||||
Call(item.functions[0], *output_stream, false);
|
Call(item.functions[0], *output_stream, false, empty_stream);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Call(item.functions[0], stream_temp1, false);
|
Call(item.functions[0], stream_temp1, false, empty_stream);
|
||||||
ClearStream(stream_temp1);
|
ClearStream(stream_temp1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1203,23 +1428,13 @@ void Generator<StreamType>::MakeTextIs(Item & item, bool equal)
|
||||||
|
|
||||||
is_generating_is = true;
|
is_generating_is = true;
|
||||||
|
|
||||||
// if one of these two functions has set case_sensitive to false
|
if( !Call(item.functions[0], stream_temp1, true, empty_stream) )
|
||||||
// then we compare in case insensitive mode
|
|
||||||
bool case_sensitive = true;
|
|
||||||
|
|
||||||
if( !Call(item.functions[0], stream_temp1, true) )
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( !last_case_sensitive )
|
if( !Call(item.functions[1], stream_temp2, true, empty_stream) )
|
||||||
case_sensitive = false;
|
|
||||||
|
|
||||||
if( !Call(item.functions[1], stream_temp2, true) )
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( !last_case_sensitive )
|
bool res = AreStreamsEqual(stream_temp1, stream_temp2);
|
||||||
case_sensitive = false;
|
|
||||||
|
|
||||||
bool res = AreStreamsEqual(stream_temp1, stream_temp2, case_sensitive);
|
|
||||||
|
|
||||||
if( !equal )
|
if( !equal )
|
||||||
res = !res;
|
res = !res;
|
||||||
|
@ -1321,8 +1536,11 @@ size_t for_index;
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::MakeTextForLoop(Item & item, typename Functions<StreamType>::Function * function)
|
void Generator<StreamType>::MakeTextFor(Item & item)
|
||||||
{
|
{
|
||||||
|
if( item.functions.size() != 1 )
|
||||||
|
return;
|
||||||
|
|
||||||
stack_tab[stack_index-1].is_for = true;
|
stack_tab[stack_index-1].is_for = true;
|
||||||
|
|
||||||
for( ; !break_generating ; stack_tab[stack_index-1].iter += 1 )
|
for( ; !break_generating ; stack_tab[stack_index-1].iter += 1 )
|
||||||
|
@ -1337,7 +1555,8 @@ void Generator<StreamType>::MakeTextForLoop(Item & item, typename Functions<Stre
|
||||||
// is_generating_for will be changed by next call to MakeText()
|
// is_generating_for will be changed by next call to MakeText()
|
||||||
// so we should set it in each iterations
|
// so we should set it in each iterations
|
||||||
is_generating_for = true;
|
is_generating_for = true;
|
||||||
Call(function, item.functions[0].params, stream_temp1, true, empty_stream);
|
//Call(function, item.functions[0].params, stream_temp1, true, empty_stream);
|
||||||
|
Call(item.functions[0], stream_temp1, true, empty_stream);
|
||||||
|
|
||||||
if( !last_res )
|
if( !last_res )
|
||||||
break;
|
break;
|
||||||
|
@ -1348,55 +1567,64 @@ void Generator<StreamType>::MakeTextForLoop(Item & item, typename Functions<Stre
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
|
||||||
void Generator<StreamType>::MakeTextFor(Item & item)
|
|
||||||
{
|
|
||||||
if( item.functions.size() != 1 )
|
|
||||||
return;
|
|
||||||
|
|
||||||
typename Functions<StreamType>::Function * function;
|
|
||||||
|
|
||||||
if( !Find(item.functions[0], &function) )
|
|
||||||
return;
|
|
||||||
|
|
||||||
MakeTextForLoop(item, function);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::MakeTextDefine(Item & item)
|
void Generator<StreamType>::MakeTextDefine(Item & item)
|
||||||
{
|
{
|
||||||
if( !functions )
|
if( !pvars )
|
||||||
{
|
{
|
||||||
CreateMsg(L"[def] statement is not available when used without functions set");
|
CreateMsg(L"[def] statement not available");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( item.functions.size() == 1 )
|
if( item.functions.size() == 1 &&
|
||||||
|
item.functions[0].parameters.size() == 1 )
|
||||||
{
|
{
|
||||||
// inserting a new variable
|
if( item.functions[0].parameters[0]->name.empty() )
|
||||||
if( item.functions[0].params.size() == 1 )
|
{
|
||||||
functions->Insert(item.functions[0].name, item.functions[0].params[0]);
|
// it is [def name "string"]
|
||||||
|
pvars->Insert(item.functions[0].name, Vars::variable_string, item.functions[0].parameters[0]->par);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if( item.functions.size() == 2 )
|
|
||||||
{
|
{
|
||||||
typename Functions<StreamType>::Function * function;
|
// it is [def name [function]]
|
||||||
|
if( Call(*item.functions[0].parameters[0], stream_temp_define, true, empty_stream) )
|
||||||
|
{
|
||||||
|
const std::wstring & str = GetStringFromStream(stream_temp_define);
|
||||||
|
pvars->Insert(item.functions[0].name, Vars::variable_string, str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( item.functions.size() == 2 &&
|
||||||
|
item.functions[0].parameters.empty() &&
|
||||||
|
item.functions[1].parameters.empty() )
|
||||||
|
{
|
||||||
|
typename Functions<StreamType>::UserFunction * function;
|
||||||
|
Item * item_block;
|
||||||
|
std::wstring * variable;
|
||||||
|
|
||||||
if( Find(item.functions[1], &function) )
|
if( Find(item.functions[1], &function, &item_block, &variable) )
|
||||||
{
|
{
|
||||||
if( function->type == Functions<StreamType>::function )
|
if( variable )
|
||||||
{
|
{
|
||||||
// inserting a new function
|
Vars::Iterator i = pvars->Find(*variable);
|
||||||
functions->Insert(item.functions[0].name, function->user_function);
|
|
||||||
|
if( i != pvars->End() )
|
||||||
|
{
|
||||||
|
Vars::Variable & var = i->second;
|
||||||
|
pvars->Insert(*variable, var.type, var.val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// inserting a new variable (the value is copied)
|
pvars->Insert(item.functions[0].name, Vars::variable_alias, item.functions[1].name);
|
||||||
functions->Insert(item.functions[0].name, function->variable);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CreateMsg(L"[def] unknown function/block/variable", item.functions[1].name.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1409,9 +1637,18 @@ void Generator<StreamType>::MakeTextFilter(Item & item)
|
||||||
if( item.functions.size() != 1 )
|
if( item.functions.size() != 1 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
typename Functions<StreamType>::Function * function;
|
typename Functions<StreamType>::UserFunction * function;
|
||||||
|
Item * item_block;
|
||||||
|
std::wstring * variable;
|
||||||
|
|
||||||
if( !Find(item.functions[0], &function) )
|
if( !Find(item.functions[0], &function, &item_block, &variable) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// IMPROVE ME
|
||||||
|
// what about blocks and variables?
|
||||||
|
// may when there is a block we can get the whole content from filter
|
||||||
|
// and put it as the first argument to the block?
|
||||||
|
if( !function )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( filter_index >= filter_tab.size() )
|
if( filter_index >= filter_tab.size() )
|
||||||
|
@ -1434,11 +1671,13 @@ void Generator<StreamType>::MakeTextFilter(Item & item)
|
||||||
|
|
||||||
if( old_stream )
|
if( old_stream )
|
||||||
{
|
{
|
||||||
Call(function, item.functions[0].params, *old_stream, false, *output_stream);
|
//Call(function, item.functions[0].params, *old_stream, false, *output_stream);
|
||||||
|
Call(item.functions[0], *old_stream, false, *output_stream);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Call(function, item.functions[0].params, stream_temp1, true, *output_stream);
|
//Call(function, item.functions[0].params, stream_temp1, true, *output_stream);
|
||||||
|
Call(item.functions[0], stream_temp1, true, *output_stream);
|
||||||
ClearStream(stream_temp1);
|
ClearStream(stream_temp1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1457,9 +1696,9 @@ void Generator<StreamType>::MakeEzcStream(Item::Function & fun)
|
||||||
|
|
||||||
output_stream_index.clear();
|
output_stream_index.clear();
|
||||||
|
|
||||||
for(size_t i=0 ; i<fun.params.size() ; ++i)
|
for(size_t i=0 ; i<fun.parameters.size() ; ++i)
|
||||||
{
|
{
|
||||||
size_t index = StrToSize(fun.params[i].c_str());
|
size_t index = StrToSize(fun.parameters[i]->par.c_str()); // !! CHECK ME or ->name ?
|
||||||
|
|
||||||
if( index < output_stream_tab.size() )
|
if( index < output_stream_tab.size() )
|
||||||
{
|
{
|
||||||
|
@ -1505,6 +1744,7 @@ void Generator<StreamType>::MakeTextEzc(Item & item)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
bool Generator<StreamType>::LimitAchieved()
|
bool Generator<StreamType>::LimitAchieved()
|
||||||
{
|
{
|
||||||
|
|
14
src/item.cpp
14
src/item.cpp
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007-2011, Tomasz Sowa
|
* Copyright (c) 2007-2014, 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
|
||||||
|
@ -161,5 +161,17 @@ Item::~Item()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Item::ClearCache()
|
||||||
|
{
|
||||||
|
for(size_t f = 0; f < functions.size() ; ++f)
|
||||||
|
functions[f].fun_cache = 0;
|
||||||
|
|
||||||
|
for(size_t i = 0; i < item_tab.size() ; ++i)
|
||||||
|
item_tab[i]->ClearCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Ezc
|
} // namespace Ezc
|
||||||
|
|
||||||
|
|
99
src/item.h
99
src/item.h
|
@ -42,6 +42,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "funinfo.h"
|
#include "funinfo.h"
|
||||||
|
#include "functions.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Ezc
|
namespace Ezc
|
||||||
|
@ -56,21 +57,75 @@ struct Item
|
||||||
item_none, item_container, item_text, item_normal, item_is, item_isno,
|
item_none, item_container, item_text, item_normal, item_is, item_isno,
|
||||||
item_if, item_ifno, item_ifany, item_ifone, item_ifanyno, item_ifoneno, item_ifindex,
|
item_if, item_ifno, item_ifany, item_ifone, item_ifanyno, item_ifoneno, item_ifindex,
|
||||||
item_for, item_else, item_end, item_err, item_include, item_comment, item_def, item_filter,
|
item_for, item_else, item_end, item_err, item_include, item_comment, item_def, item_filter,
|
||||||
item_ezc
|
item_ezc, item_block
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct Function
|
struct Function
|
||||||
{
|
{
|
||||||
std::wstring name; // function name
|
std::wstring name; // function name (can be empty, means there is no any function -- only a text parameter)
|
||||||
std::vector<std::wstring> params; // function parameters
|
std::wstring par; // parameter
|
||||||
void * fun_cache;
|
std::vector<Function*> parameters;
|
||||||
|
void * fun_cache; // only valid if name is not empty
|
||||||
|
Item * item_block;
|
||||||
|
int arg; // used if name is numeric (if no then is equal -1)
|
||||||
|
|
||||||
|
|
||||||
Function()
|
Function()
|
||||||
{
|
{
|
||||||
fun_cache = 0;
|
fun_cache = 0;
|
||||||
|
item_block = 0;
|
||||||
|
arg = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~Function()
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
Function(const Function & f)
|
||||||
|
{
|
||||||
|
operator=(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
Function & operator=(const Function & f)
|
||||||
|
{
|
||||||
|
name = f.name;
|
||||||
|
par = f.par;
|
||||||
|
fun_cache = f.fun_cache;
|
||||||
|
item_block = f.item_block;
|
||||||
|
arg = f.arg;
|
||||||
|
|
||||||
|
for(size_t i=0 ; i<f.parameters.size() ; ++i)
|
||||||
|
parameters.push_back(new Function(*f.parameters[i]));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Function & AddNewParam()
|
||||||
|
{
|
||||||
|
parameters.push_back(new Function());
|
||||||
|
|
||||||
|
return *parameters.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
for(size_t i=0 ; i<parameters.size() ; ++i)
|
||||||
|
delete parameters[i];
|
||||||
|
|
||||||
|
parameters.clear();
|
||||||
|
name.clear();
|
||||||
|
par.clear();
|
||||||
|
fun_cache = 0;
|
||||||
|
item_block = 0;
|
||||||
|
arg = -1;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
std::wstring text; // used in: item_text
|
std::wstring text; // used in: item_text
|
||||||
std::wstring file_name; // used in: item_include (as a file name)
|
std::wstring file_name; // used in: item_include (as a file name)
|
||||||
|
@ -89,9 +144,45 @@ struct Item
|
||||||
Type LastItemType();
|
Type LastItemType();
|
||||||
void DeleteLastItem();
|
void DeleteLastItem();
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
void CacheFunctions(Functions<StreamType> & fun);
|
||||||
|
|
||||||
|
void ClearCache();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
void Item::CacheFunctions(Functions<StreamType> & fun)
|
||||||
|
{
|
||||||
|
// one exception (if_index is putting its argument on the functions stack)
|
||||||
|
if( type != Item::item_ifindex )
|
||||||
|
{
|
||||||
|
for(size_t f=0; f < functions.size() ; ++f)
|
||||||
|
{
|
||||||
|
Functions<StreamType>::Iterator i = fun.Find(functions[f].name);
|
||||||
|
|
||||||
|
if( i != fun.End() )
|
||||||
|
{
|
||||||
|
functions[f].fun_cache = i->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
functions[f].fun_cache = 0;
|
||||||
|
// teraz chyba nie trzeba tego logowac
|
||||||
|
// bo mamy zmienne i identyfikator moze byc znaleziony w runtime
|
||||||
|
// #ifdef EZC_USE_WINIX_LOGGER
|
||||||
|
// Winix::log << Winix::log1 << "Ezc: unknown function: " << item.functions[f].name << Winix::logend;
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i=0; i < item_tab.size() ; ++i)
|
||||||
|
item_tab[i]->CacheFunctions(fun);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace Ezc
|
} // namespace Ezc
|
||||||
|
|
||||||
|
|
|
@ -60,22 +60,6 @@ void Pattern::Clear()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Pattern::ClearCache()
|
|
||||||
{
|
|
||||||
ClearCache(item_root);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Pattern::ClearCache(Item & item)
|
|
||||||
{
|
|
||||||
for(size_t f = 0; f < item.functions.size() ; ++f)
|
|
||||||
item.functions[f].fun_cache = 0;
|
|
||||||
|
|
||||||
for(size_t i = 0; i < item.item_tab.size() ; ++i)
|
|
||||||
ClearCache(*item.item_tab[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -132,6 +116,8 @@ void Pattern::CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Ezc
|
} // namespace Ezc
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -80,37 +80,7 @@ private:
|
||||||
std::wstring commentary_start, commentary_stop;
|
std::wstring commentary_start, commentary_stop;
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
|
||||||
void CacheFunctions(Item & item, Functions<StreamType> & fun)
|
|
||||||
{
|
|
||||||
typename Functions<StreamType>::Function * ezc_fun;
|
|
||||||
|
|
||||||
// one exception (if_index is putting its argument on the functions stack)
|
|
||||||
if( item.type != Item::item_ifindex )
|
|
||||||
{
|
|
||||||
for(size_t f=0; f < item.functions.size() ; ++f)
|
|
||||||
{
|
|
||||||
if( fun.Find(item.functions[f].name, &ezc_fun) )
|
|
||||||
{
|
|
||||||
item.functions[f].fun_cache = ezc_fun;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
item.functions[f].fun_cache = 0;
|
|
||||||
|
|
||||||
#ifdef EZC_USE_WINIX_LOGGER
|
|
||||||
Winix::log << Winix::log1 << "Ezc: unknown function: " << item.functions[f].name << Winix::logend;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(size_t i=0; i < item.item_tab.size() ; ++i)
|
|
||||||
CacheFunctions(*item.item_tab[i], fun);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ClearCache(Item & item);
|
|
||||||
|
|
||||||
}; // class Pattern
|
}; // class Pattern
|
||||||
|
|
||||||
|
|
|
@ -48,10 +48,9 @@ namespace Ezc
|
||||||
PatternParser::PatternParser()
|
PatternParser::PatternParser()
|
||||||
{
|
{
|
||||||
allow_include = true;
|
allow_include = true;
|
||||||
input_as_utf8 = true;
|
pblocks = 0;
|
||||||
delete_white_text_items = false;
|
|
||||||
|
|
||||||
include_level_max = 100;
|
include_level_max = 100;
|
||||||
|
delete_white_text_items = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -116,6 +115,12 @@ void PatternParser::Directory(const std::wstring & dir, const std::wstring & dir
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void PatternParser::SetBlocks(Blocks & blocks)
|
||||||
|
{
|
||||||
|
pblocks = &blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PatternParser::ParseFile(const std::string & file_name, Pattern & pattern)
|
void PatternParser::ParseFile(const std::string & file_name, Pattern & pattern)
|
||||||
{
|
{
|
||||||
ParseFile(file_name.c_str(), pattern);
|
ParseFile(file_name.c_str(), pattern);
|
||||||
|
@ -156,11 +161,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)
|
||||||
{
|
{
|
||||||
if( input_as_utf8 )
|
|
||||||
PT::UTF8ToWide(str, string_content);
|
PT::UTF8ToWide(str, string_content);
|
||||||
else
|
|
||||||
AssignString(str, string_content);
|
|
||||||
|
|
||||||
ParseString(string_content.c_str(), pattern);
|
ParseString(string_content.c_str(), pattern);
|
||||||
string_content.clear();
|
string_content.clear();
|
||||||
}
|
}
|
||||||
|
@ -218,16 +219,6 @@ void PatternParser::SetIncludeMax(int include_max)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void PatternParser::UTF8(bool utf8)
|
|
||||||
{
|
|
||||||
input_as_utf8 = utf8;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -343,35 +334,10 @@ return true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void PatternParser::ReadFile(std::ifstream & file, std::wstring & result)
|
void PatternParser::ReadFile(std::ifstream & file, std::wstring & result)
|
||||||
{
|
|
||||||
if( input_as_utf8 )
|
|
||||||
{
|
{
|
||||||
PT::UTF8ToWide(file, result);
|
PT::UTF8ToWide(file, result);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
ReadFileContent(file, result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void PatternParser::ReadFileContent(std::ifstream & file, std::wstring & result)
|
|
||||||
{
|
|
||||||
while( true )
|
|
||||||
{
|
|
||||||
int c = file.get();
|
|
||||||
|
|
||||||
if( !file )
|
|
||||||
break;
|
|
||||||
|
|
||||||
result += static_cast<wchar_t>(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -519,14 +485,38 @@ return true;
|
||||||
|
|
||||||
bool PatternParser::ReadParams(Item::Function & function)
|
bool PatternParser::ReadParams(Item::Function & function)
|
||||||
{
|
{
|
||||||
function.params.clear();
|
while( true )
|
||||||
|
{
|
||||||
|
SkipWhite();
|
||||||
|
|
||||||
while( ReadString(temp_param) )
|
if( *itext == '[' )
|
||||||
function.params.push_back(temp_param);
|
{
|
||||||
|
++itext; // skipping '['
|
||||||
|
ReadFunction(function.AddNewParam());
|
||||||
|
|
||||||
|
SkipWhite();
|
||||||
|
if( *itext == ']' )
|
||||||
|
++itext;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if( *itext == '\"' )
|
||||||
|
{
|
||||||
|
if( ReadString(temp_param) )
|
||||||
|
{
|
||||||
|
Item::Function & fun = function.AddNewParam();
|
||||||
|
fun.par = temp_param;
|
||||||
|
// fun.name is empty so it is treated as a text parameter
|
||||||
|
}
|
||||||
|
|
||||||
temp_param.clear();
|
temp_param.clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return !function.params.empty();
|
return !function.parameters.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -534,13 +524,14 @@ return !function.params.empty();
|
||||||
bool PatternParser::ReadFunction(Item::Function & function)
|
bool PatternParser::ReadFunction(Item::Function & function)
|
||||||
{
|
{
|
||||||
SkipWhite();
|
SkipWhite();
|
||||||
|
function.Clear();
|
||||||
function.name.clear();
|
|
||||||
function.params.clear();
|
|
||||||
|
|
||||||
if( !ReadName(function.name) )
|
if( !ReadName(function.name) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if( IsPositiveNumber(function.name) )
|
||||||
|
function.arg = wcstol(function.name.c_str(), 0, 10);
|
||||||
|
|
||||||
ReadParams(function);
|
ReadParams(function);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -556,8 +547,7 @@ bool PatternParser::ReadFunctions(Item & item)
|
||||||
while( ReadFunction(temp_function) )
|
while( ReadFunction(temp_function) )
|
||||||
item.functions.push_back(temp_function);
|
item.functions.push_back(temp_function);
|
||||||
|
|
||||||
temp_function.name.clear();
|
temp_function.Clear();
|
||||||
temp_function.params.clear();
|
|
||||||
|
|
||||||
return !item.functions.empty();
|
return !item.functions.empty();
|
||||||
}
|
}
|
||||||
|
@ -667,11 +657,25 @@ void PatternParser::ReadDirectiveIsno(Item & item)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void PatternParser::ReadDirectiveEnd(Item & item)
|
||||||
|
{
|
||||||
|
item.type = Item::item_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void PatternParser::ReadDirectiveElse(Item & item)
|
||||||
|
{
|
||||||
|
item.type = Item::item_else;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void PatternParser::ReadDirectiveIfindex(Item & item)
|
void PatternParser::ReadDirectiveIfindex(Item & item)
|
||||||
{
|
{
|
||||||
item.type = Item::item_err;
|
item.type = Item::item_err;
|
||||||
item.functions.clear();
|
item.functions.clear();
|
||||||
temp_function.params.clear();
|
temp_function.Clear();
|
||||||
|
|
||||||
// reading: odd, even, first or a number (without quotes)
|
// reading: odd, even, first or a number (without quotes)
|
||||||
if( !ReadName(temp_function.name) )
|
if( !ReadName(temp_function.name) )
|
||||||
|
@ -724,26 +728,25 @@ void PatternParser::ReadDirectiveDef(Item & item)
|
||||||
item.type = Item::item_err;
|
item.type = Item::item_err;
|
||||||
ReadFunctions(item);
|
ReadFunctions(item);
|
||||||
|
|
||||||
if( item.functions.size() == 1 )
|
if( item.functions.size() == 1 && item.functions[0].parameters.size() == 1 )
|
||||||
{
|
{
|
||||||
if( item.functions[0].params.size() == 1 )
|
// it is [def name "value"]
|
||||||
{
|
// or [def name [otherfunction]]
|
||||||
// this is: [def variable "value"]
|
// or [def name [otherfunction "argument"]] etc.
|
||||||
|
|
||||||
item.type = Item::item_def;
|
item.type = Item::item_def;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
if( item.functions.size() == 2 )
|
if( item.functions.size() == 2 &&
|
||||||
|
item.functions[0].parameters.empty() && item.functions[1].parameters.empty() )
|
||||||
{
|
{
|
||||||
if( item.functions[0].params.empty() && item.functions[1].params.empty())
|
// it is an alias:
|
||||||
{
|
// [def name function]
|
||||||
// this is:
|
// (name is an alias to a function, to a block or to an other variable)
|
||||||
// [def variable2 variable1], or
|
|
||||||
// [def function2 function1]
|
|
||||||
item.type = Item::item_def;
|
item.type = Item::item_def;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PatternParser::ReadDirectiveFilter(Item & item)
|
void PatternParser::ReadDirectiveFilter(Item & item)
|
||||||
|
@ -762,14 +765,30 @@ void PatternParser::ReadDirectiveEzc(Item & item)
|
||||||
ReadFunctions(item);
|
ReadFunctions(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PatternParser::ReadDirectiveBlock(Item & item)
|
||||||
|
{
|
||||||
|
item.type = Item::item_block;
|
||||||
|
ReadFunctions(item);
|
||||||
|
|
||||||
|
// only one function without arguments
|
||||||
|
if( item.functions.size() != 1 || !item.functions[0].parameters.empty() )
|
||||||
|
item.type = Item::item_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// user defined directive
|
// user defined directive
|
||||||
void PatternParser::ReadDirectiveNormal(const std::wstring & name, Item & item)
|
void PatternParser::ReadDirectiveNormal(const std::wstring & name, Item & item)
|
||||||
{
|
{
|
||||||
temp_function.name = name;
|
temp_function.Clear();
|
||||||
ReadParams(temp_function);
|
ReadParams(temp_function);
|
||||||
|
temp_function.name = name;
|
||||||
|
|
||||||
|
if( IsPositiveNumber(name) )
|
||||||
|
temp_function.arg = wcstol(name.c_str(), 0, 10);
|
||||||
|
|
||||||
item.functions.clear();
|
item.functions.clear();
|
||||||
|
|
||||||
item.functions.push_back(temp_function);
|
item.functions.push_back(temp_function);
|
||||||
item.type = Item::item_normal;
|
item.type = Item::item_normal;
|
||||||
}
|
}
|
||||||
|
@ -792,13 +811,14 @@ std::wstring name;
|
||||||
else if( name == L"if-index" ) ReadDirectiveIfindex(item);
|
else if( name == L"if-index" ) ReadDirectiveIfindex(item);
|
||||||
else if( name == L"is" ) ReadDirectiveIs(item);
|
else if( name == L"is" ) ReadDirectiveIs(item);
|
||||||
else if( name == L"is-no" ) ReadDirectiveIsno(item);
|
else if( name == L"is-no" ) ReadDirectiveIsno(item);
|
||||||
else if( name == L"end" ) item.type = Item::item_end;
|
else if( name == L"end" ) ReadDirectiveEnd(item);
|
||||||
else if( name == L"else" ) item.type = Item::item_else;
|
else if( name == L"else" ) ReadDirectiveElse(item);
|
||||||
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"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"block" ) ReadDirectiveBlock(item);
|
||||||
else if( name == L"#" ) ReadDirectiveComment(item);
|
else if( name == L"#" ) ReadDirectiveComment(item);
|
||||||
else
|
else
|
||||||
ReadDirectiveNormal(name, item);
|
ReadDirectiveNormal(name, item);
|
||||||
|
@ -904,6 +924,21 @@ void PatternParser::CreateTreeReadIf(Item & item)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void PatternParser::CreateTreeReadBlock(Item & item)
|
||||||
|
{
|
||||||
|
Item item_block;
|
||||||
|
|
||||||
|
CreateTree(item_block);
|
||||||
|
|
||||||
|
if( item_block.LastItemType() == Item::item_end )
|
||||||
|
item_block.DeleteLastItem();
|
||||||
|
|
||||||
|
if( pblocks && item.functions.size()==1 )
|
||||||
|
pblocks->Insert(item.functions[0].name, item_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void PatternParser::CreateTreeReadFor(Item & item)
|
void PatternParser::CreateTreeReadFor(Item & item)
|
||||||
{
|
{
|
||||||
Item * pitem = item.AddItem();
|
Item * pitem = item.AddItem();
|
||||||
|
@ -931,8 +966,12 @@ void PatternParser::CreateTree(Item & item)
|
||||||
item.DeleteLastItem();
|
item.DeleteLastItem();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( pitem->type == Item::item_block )
|
||||||
|
CreateTreeReadBlock(*pitem);
|
||||||
}
|
}
|
||||||
while( pitem->type == Item::item_comment );
|
while( pitem->type == Item::item_comment ||
|
||||||
|
pitem->type == Item::item_block );
|
||||||
|
|
||||||
if( pitem->type == Item::item_end || pitem->type == Item::item_else )
|
if( pitem->type == Item::item_end || pitem->type == Item::item_else )
|
||||||
return;
|
return;
|
||||||
|
@ -954,6 +993,8 @@ void PatternParser::CreateTree(Item & item)
|
||||||
|
|
||||||
if( pitem->type == Item::item_include )
|
if( pitem->type == Item::item_include )
|
||||||
CreateTreeReadInclude(*pitem);
|
CreateTreeReadInclude(*pitem);
|
||||||
|
|
||||||
|
// item_def is ignored here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,8 @@
|
||||||
#ifndef headerfile_ezc_patternparser
|
#ifndef headerfile_ezc_patternparser
|
||||||
#define headerfile_ezc_patternparser
|
#define headerfile_ezc_patternparser
|
||||||
|
|
||||||
|
#include "blocks.h"
|
||||||
#include "pattern.h"
|
#include "pattern.h"
|
||||||
#include "stringconv.h"
|
|
||||||
#include "utf8/utf8.h"
|
#include "utf8/utf8.h"
|
||||||
|
|
||||||
#ifdef EZC_USE_WINIX_LOGGER
|
#ifdef EZC_USE_WINIX_LOGGER
|
||||||
|
@ -83,11 +83,7 @@ public:
|
||||||
void DeleteWhiteTextItems(bool del);
|
void DeleteWhiteTextItems(bool del);
|
||||||
void SetIncludeMax(int include_max);
|
void SetIncludeMax(int include_max);
|
||||||
|
|
||||||
// files and strings (only char* and std::string) are treated
|
void SetBlocks(Blocks & blocks);
|
||||||
// as UTF-8
|
|
||||||
void UTF8(bool utf8);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -115,7 +111,6 @@ private:
|
||||||
std::wstring directory, directory2;
|
std::wstring directory, directory2;
|
||||||
|
|
||||||
|
|
||||||
bool input_as_utf8;
|
|
||||||
|
|
||||||
int include_level, include_level_max;
|
int include_level, include_level_max;
|
||||||
|
|
||||||
|
@ -135,6 +130,7 @@ private:
|
||||||
// temporary object for a EZC function
|
// temporary object for a EZC function
|
||||||
Item::Function temp_function;
|
Item::Function temp_function;
|
||||||
|
|
||||||
|
Blocks * pblocks;
|
||||||
|
|
||||||
|
|
||||||
void ReadFile(const std::wstring & name, std::wstring & result);
|
void ReadFile(const std::wstring & name, std::wstring & result);
|
||||||
|
@ -143,7 +139,6 @@ private:
|
||||||
bool IsFileCorrect(const wchar_t * name);
|
bool IsFileCorrect(const wchar_t * name);
|
||||||
bool ReadFileFromDir(const std::wstring & dir, const wchar_t * name, std::wstring & result);
|
bool ReadFileFromDir(const std::wstring & dir, const wchar_t * name, std::wstring & result);
|
||||||
void ReadFile(std::ifstream & file, std::wstring & result);
|
void ReadFile(std::ifstream & file, std::wstring & result);
|
||||||
void ReadFileContent(std::ifstream & file, std::wstring & result);
|
|
||||||
|
|
||||||
int ReadCharInText();
|
int ReadCharInText();
|
||||||
bool IsWhite(wchar_t c);
|
bool IsWhite(wchar_t c);
|
||||||
|
@ -168,6 +163,8 @@ private:
|
||||||
void ReadDirectiveIfoneno(Item & item);
|
void ReadDirectiveIfoneno(Item & item);
|
||||||
void ReadDirectiveIs(Item & item);
|
void ReadDirectiveIs(Item & item);
|
||||||
void ReadDirectiveIsno(Item & item);
|
void ReadDirectiveIsno(Item & item);
|
||||||
|
void ReadDirectiveEnd(Item & item);
|
||||||
|
void ReadDirectiveElse(Item & item);
|
||||||
void ReadDirectiveIfindex(Item & item);
|
void ReadDirectiveIfindex(Item & item);
|
||||||
void ReadDirectiveFor(Item & item);
|
void ReadDirectiveFor(Item & item);
|
||||||
void ReadDirectiveComment(Item & item);
|
void ReadDirectiveComment(Item & item);
|
||||||
|
@ -175,6 +172,7 @@ private:
|
||||||
void ReadDirectiveDef(Item & item);
|
void ReadDirectiveDef(Item & item);
|
||||||
void ReadDirectiveFilter(Item & item);
|
void ReadDirectiveFilter(Item & item);
|
||||||
void ReadDirectiveEzc(Item & item);
|
void ReadDirectiveEzc(Item & item);
|
||||||
|
void ReadDirectiveBlock(Item & item);
|
||||||
void ReadDirectiveNormal(const std::wstring & name, Item & item);
|
void ReadDirectiveNormal(const std::wstring & name, Item & item);
|
||||||
|
|
||||||
void CreateTreeReadItemDirectiveCheckEnding(Item & item);
|
void CreateTreeReadItemDirectiveCheckEnding(Item & item);
|
||||||
|
@ -182,6 +180,7 @@ private:
|
||||||
void CreateTreeReadItemText(Item & item);
|
void CreateTreeReadItemText(Item & item);
|
||||||
bool CreateTreeReadItem(Item & item);
|
bool CreateTreeReadItem(Item & item);
|
||||||
void CreateTreeReadIf(Item & item);
|
void CreateTreeReadIf(Item & item);
|
||||||
|
void CreateTreeReadBlock(Item & item);
|
||||||
void CreateTreeReadFor(Item & item);
|
void CreateTreeReadFor(Item & item);
|
||||||
void CreateTree(Item & item);
|
void CreateTree(Item & item);
|
||||||
void CreateTreeReadInclude(Item & item);
|
void CreateTreeReadInclude(Item & item);
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
#include "vars.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Ezc
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
void Vars::Insert(const std::wstring & name, VariableType type, const std::wstring & value)
|
||||||
|
{
|
||||||
|
Variable variable;
|
||||||
|
|
||||||
|
variable.type = type;
|
||||||
|
variable.val = value;
|
||||||
|
|
||||||
|
vars_tab[name] = variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Vars::Iterator Vars::Find(const std::wstring & name)
|
||||||
|
{
|
||||||
|
return vars_tab.find(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Vars::Iterator Vars::Begin()
|
||||||
|
{
|
||||||
|
return vars_tab.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Vars::Iterator Vars::End()
|
||||||
|
{
|
||||||
|
return vars_tab.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t Vars::Size()
|
||||||
|
{
|
||||||
|
return vars_tab.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* This file is a part of EZC -- Easy templating in C++
|
||||||
|
* and is distributed under the (new) BSD licence.
|
||||||
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Tomasz Sowa
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||||
|
* project may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef headerfile_ezc_vars
|
||||||
|
#define headerfile_ezc_vars
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace Ezc
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Vars
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum VariableType
|
||||||
|
{
|
||||||
|
variable_string,
|
||||||
|
variable_alias
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Variable
|
||||||
|
{
|
||||||
|
VariableType type;
|
||||||
|
std::wstring val;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::map<std::wstring, Variable> VariablesTable;
|
||||||
|
typedef VariablesTable::iterator Iterator;
|
||||||
|
|
||||||
|
void Insert(const std::wstring & name, VariableType type, const std::wstring & value);
|
||||||
|
|
||||||
|
Iterator Find(const std::wstring & name);
|
||||||
|
|
||||||
|
Iterator Begin();
|
||||||
|
Iterator End();
|
||||||
|
size_t Size();
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
VariablesTable vars_tab;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue