2010-11-22 02:23:32 +01:00
|
|
|
/*
|
2014-10-17 23:48:11 +02:00
|
|
|
* This file is a part of EZC -- Easy templating in C++ library
|
|
|
|
* and is distributed under the BSD 3-Clause licence.
|
2010-11-22 02:23:32 +01:00
|
|
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2021-05-23 10:02:51 +02:00
|
|
|
* Copyright (c) 2007-2021, Tomasz Sowa
|
2010-11-22 02:23:32 +01:00
|
|
|
* 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_generator
|
|
|
|
#define headerfile_ezc_generator
|
|
|
|
|
2021-05-31 18:37:09 +02:00
|
|
|
#include <sstream>
|
|
|
|
#include <fstream>
|
|
|
|
#include <vector>
|
2014-10-17 23:36:55 +02:00
|
|
|
#include "blocks.h"
|
2010-11-22 02:23:32 +01:00
|
|
|
#include "pattern.h"
|
|
|
|
#include "functions.h"
|
2015-06-14 20:20:00 +02:00
|
|
|
#include "objects.h"
|
2015-11-12 10:53:20 +01:00
|
|
|
#include "outstreams.h"
|
2018-10-30 00:50:10 +01:00
|
|
|
#include "expressionparser.h"
|
2021-05-31 18:37:09 +02:00
|
|
|
#include "models.h"
|
2021-06-19 20:18:30 +02:00
|
|
|
#include "log/log.h"
|
2011-01-26 13:42:49 +01:00
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
#ifdef EZC_HAS_MORM_LIBRARY
|
|
|
|
#include "model.h"
|
|
|
|
#endif
|
2010-11-22 02:23:32 +01:00
|
|
|
|
|
|
|
namespace Ezc
|
|
|
|
{
|
2012-02-27 18:39:46 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
2010-11-25 02:55:32 +01:00
|
|
|
/*
|
|
|
|
StreamType
|
2010-11-25 23:39:58 +01:00
|
|
|
we use only method write(const wchar_t * str, size_t len) from the stream
|
2010-11-25 02:55:32 +01:00
|
|
|
*/
|
2010-11-22 02:23:32 +01:00
|
|
|
template<class StreamType>
|
|
|
|
class Generator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
Generator();
|
2011-01-26 13:42:49 +01:00
|
|
|
Generator(const Generator & n);
|
|
|
|
Generator & operator=(const Generator & n);
|
|
|
|
~Generator();
|
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
void SetPattern(Pattern & pattern);
|
|
|
|
void SetBlocks(Blocks & blocks);
|
|
|
|
void SetFunctions(Functions<StreamType> & functions);
|
2015-06-14 20:20:00 +02:00
|
|
|
void SetObjects(Objects<StreamType> & objects);
|
2021-05-23 10:02:51 +02:00
|
|
|
void SetVariables(Vars & variables); // [def] and [let]
|
2021-06-16 14:16:49 +02:00
|
|
|
|
2021-06-19 20:18:30 +02:00
|
|
|
void SetLogger(pt::Log & logger);
|
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
#ifdef EZC_HAS_MORM_LIBRARY
|
2021-05-31 18:37:09 +02:00
|
|
|
void SetModels(Models & models);
|
2021-06-16 14:16:49 +02:00
|
|
|
#endif
|
2010-11-22 02:23:32 +01:00
|
|
|
|
2012-02-24 13:04:36 +01:00
|
|
|
void SetMax(size_t max_items_, size_t max_for_items_);
|
2010-11-22 02:23:32 +01:00
|
|
|
|
|
|
|
// recognizing some special characters in text patterns (item_text in Patterns)
|
|
|
|
// \r will be a carriage return (13)
|
|
|
|
// \n will be a new line (10)
|
|
|
|
// \t will be a tabulator (9)
|
|
|
|
// \s will be a space
|
|
|
|
// \\ will be one '\'
|
2010-11-25 02:55:32 +01:00
|
|
|
// if the second character is different from those shown above the first slash will be printed
|
|
|
|
// so "\x" gives "\x"
|
2010-11-22 02:23:32 +01:00
|
|
|
// default: false
|
|
|
|
void RecognizeSpecialChars(bool spec);
|
|
|
|
|
|
|
|
// trimming white characters (at the beginning and at the end of an item_text)
|
|
|
|
// (special char \s if enabled is not treated as a white character here)
|
|
|
|
// default: false
|
|
|
|
void TrimWhite(bool trim);
|
|
|
|
|
|
|
|
// skipping new line characters (from the whole string in an item_text)
|
|
|
|
// but you can use a new line character written as "\n" (if special chars are turn on)
|
|
|
|
// default: false
|
|
|
|
void SkipNewLine(bool skip);
|
|
|
|
|
2011-01-26 13:42:49 +01:00
|
|
|
// default: 20
|
|
|
|
void SetMaxFilters(size_t new_len);
|
|
|
|
|
2012-02-27 18:39:46 +01:00
|
|
|
// default stack size: 300
|
|
|
|
void SetStackSize(size_t new_stack_size);
|
|
|
|
|
2014-10-19 23:09:34 +02:00
|
|
|
// set whether or not we can use cache for functions or blocks
|
|
|
|
// true by default
|
|
|
|
void CanUseCache(bool can_use_cache);
|
|
|
|
|
|
|
|
// set whether or not we can use variables: [def ...] statement
|
|
|
|
// true by default
|
|
|
|
void CanUseVars(bool can_use_variables);
|
|
|
|
|
2018-10-30 00:50:10 +01:00
|
|
|
void SetProgramMode(bool program_mode);
|
|
|
|
|
|
|
|
void SetExpressionParser(ExpressionParser * expression_parser);
|
|
|
|
|
|
|
|
|
2010-11-25 23:39:58 +01:00
|
|
|
// the main methods for generating
|
2015-11-12 10:53:20 +01:00
|
|
|
void Generate(StreamType & out);
|
|
|
|
void Generate(StreamType & out, OutStreams<StreamType> & out_streams);
|
|
|
|
void Generate(OutStreams<StreamType> & out_streams);
|
|
|
|
|
2010-11-25 23:39:58 +01:00
|
|
|
|
2010-11-22 02:23:32 +01:00
|
|
|
|
|
|
|
private:
|
|
|
|
|
2014-10-28 18:46:24 +01:00
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
struct FindHelper
|
|
|
|
{
|
2021-06-19 20:18:30 +02:00
|
|
|
std::wstring * fun_name;
|
2021-06-16 14:16:49 +02:00
|
|
|
|
|
|
|
BaseObj<StreamType> * base_obj;
|
|
|
|
int method_index;
|
|
|
|
typename Functions<StreamType>::UserFunction * function;
|
|
|
|
Item * item_block;
|
|
|
|
Var * variable;
|
|
|
|
|
2021-06-19 20:18:30 +02:00
|
|
|
#ifdef EZC_HAS_MORM_LIBRARY
|
|
|
|
morm::ModelWrapper * model_wrapper;
|
|
|
|
#endif
|
2021-06-16 14:16:49 +02:00
|
|
|
|
|
|
|
FindHelper()
|
|
|
|
{
|
2021-06-19 20:18:30 +02:00
|
|
|
fun_name = nullptr;
|
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
base_obj = nullptr;
|
|
|
|
method_index = -1;
|
|
|
|
function = nullptr;
|
|
|
|
item_block = nullptr;
|
|
|
|
variable = nullptr;
|
2021-06-19 20:18:30 +02:00
|
|
|
|
|
|
|
#ifdef EZC_HAS_MORM_LIBRARY
|
|
|
|
model_wrapper = nullptr;
|
|
|
|
#endif
|
2021-06-16 14:16:49 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef EZC_HAS_MORM_LIBRARY
|
|
|
|
|
|
|
|
struct CallModelHelper
|
|
|
|
{
|
|
|
|
size_t field_index;
|
|
|
|
morm::ModelWrapper * model_wrapper;
|
|
|
|
morm::Model * model;
|
|
|
|
|
|
|
|
|
|
|
|
CallModelHelper()
|
|
|
|
{
|
|
|
|
field_index = 0;
|
|
|
|
model_wrapper = nullptr;
|
|
|
|
model = nullptr;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
struct BlockStack
|
|
|
|
{
|
2014-10-28 18:46:24 +01:00
|
|
|
std::vector<Var> args;
|
2014-10-17 23:36:55 +02:00
|
|
|
StreamType * out_stream;
|
2014-10-28 18:46:24 +01:00
|
|
|
bool was_return;
|
2014-10-17 23:36:55 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
std::vector<BlockStack> block_stack_tab;
|
|
|
|
size_t block_stack_index;
|
|
|
|
size_t block_stack_size;
|
|
|
|
|
2015-11-12 10:53:20 +01:00
|
|
|
// current output stream (can be null)
|
|
|
|
// at the beginning it is pointing to the main stream (to the StreamType argument passsed to Generate method)
|
2010-11-22 02:23:32 +01:00
|
|
|
StreamType * output_stream;
|
2014-10-17 23:36:55 +02:00
|
|
|
|
|
|
|
Pattern * ppattern;
|
|
|
|
Blocks * pblocks;
|
|
|
|
Functions<StreamType> * pfunctions;
|
2015-06-14 20:20:00 +02:00
|
|
|
Objects<StreamType> * pobjects;
|
2021-06-16 14:16:49 +02:00
|
|
|
#ifdef EZC_HAS_MORM_LIBRARY
|
2021-05-31 18:37:09 +02:00
|
|
|
Models * pmodels;
|
2021-06-16 14:16:49 +02:00
|
|
|
#endif
|
2021-06-19 20:18:30 +02:00
|
|
|
Vars * pvars;
|
|
|
|
|
|
|
|
pt::Log * plog;
|
2013-11-07 11:16:10 +01:00
|
|
|
|
2015-11-12 10:53:20 +01:00
|
|
|
// pointer to the output streams map (can be null)
|
2021-05-28 16:10:16 +02:00
|
|
|
// output stream will be created when [ezc frame "stream_name"] statement is found
|
|
|
|
OutStreams<StreamType> * output_frames_streams;
|
2013-11-07 11:16:10 +01:00
|
|
|
|
2010-11-22 02:23:32 +01:00
|
|
|
// temporary error messages
|
|
|
|
std::wstring temp_msg;
|
|
|
|
|
|
|
|
bool break_generating;
|
2012-02-24 13:04:36 +01:00
|
|
|
size_t current_item;
|
|
|
|
size_t max_items;
|
|
|
|
size_t max_for_items;
|
2010-11-22 02:23:32 +01:00
|
|
|
bool special_chars;
|
|
|
|
bool trim_white;
|
|
|
|
bool skip_new_line;
|
2012-02-27 18:39:46 +01:00
|
|
|
|
2021-05-28 16:10:16 +02:00
|
|
|
size_t ezc_frames_stack_index;
|
|
|
|
size_t ezc_frames_stack_size;
|
2015-11-12 10:53:20 +01:00
|
|
|
|
2012-02-27 18:39:46 +01:00
|
|
|
size_t stack_index;
|
|
|
|
size_t stack_size;
|
|
|
|
|
2011-01-26 13:42:49 +01:00
|
|
|
size_t filter_index;
|
|
|
|
size_t filter_size;
|
|
|
|
// we have to use a pointers table because standard streams such
|
|
|
|
// as std::wostringstream are not copyable
|
|
|
|
std::vector<StreamType*> filter_tab;
|
2021-05-28 16:10:16 +02:00
|
|
|
std::vector<StreamType*> ezc_frame_stack_tab;
|
2011-01-26 13:42:49 +01:00
|
|
|
const StreamType empty_stream;
|
|
|
|
|
2014-11-02 18:26:56 +01:00
|
|
|
// temporary streams used in [if..] [for...] or [def ...]
|
2013-11-07 11:16:10 +01:00
|
|
|
// or if output_stream is null and an ezc function should be called
|
2014-11-02 18:26:56 +01:00
|
|
|
StreamType stream_temp1, stream_temp_define;
|
2011-01-26 13:42:49 +01:00
|
|
|
|
2011-04-26 19:17:06 +02:00
|
|
|
// last result from a user function (FunInfo::res)
|
|
|
|
bool last_res;
|
2010-11-22 02:23:32 +01:00
|
|
|
|
2011-04-26 19:17:06 +02:00
|
|
|
// true if this Generator is working now
|
|
|
|
bool is_generator_working;
|
|
|
|
|
2012-02-24 13:04:36 +01:00
|
|
|
// true if the Generator is working with [for ...], [if ...] etc.
|
2012-01-17 23:57:06 +01:00
|
|
|
bool is_generating_for;
|
2012-02-24 13:04:36 +01:00
|
|
|
bool is_generating_if;
|
|
|
|
bool is_generating_normal;
|
|
|
|
bool is_generating_filter;
|
2012-01-17 23:57:06 +01:00
|
|
|
|
2011-04-26 19:17:06 +02:00
|
|
|
// an empty string for FunInfo objects
|
2010-11-22 02:23:32 +01:00
|
|
|
// when there is no any parameters
|
|
|
|
const std::wstring empty;
|
|
|
|
|
2011-04-26 19:17:06 +02:00
|
|
|
// a stack for [for] statements
|
2012-02-27 18:39:46 +01:00
|
|
|
std::vector<Stack> stack_tab;
|
2011-01-15 00:59:30 +01:00
|
|
|
|
2014-10-19 23:09:34 +02:00
|
|
|
bool can_use_vars;
|
|
|
|
bool can_find_in_cache;
|
2018-10-30 00:50:10 +01:00
|
|
|
bool program_mode;
|
|
|
|
|
|
|
|
ExpressionParser * expression_parser;
|
|
|
|
|
|
|
|
|
2011-04-26 19:17:06 +02:00
|
|
|
|
2015-11-12 10:53:20 +01:00
|
|
|
void ResizeStreamStack(std::vector<StreamType*> & stream_tab, size_t stream_tab_max_size);
|
2011-01-26 13:42:49 +01:00
|
|
|
void ResizeFilterTab();
|
2012-02-27 18:39:46 +01:00
|
|
|
void ResizeStack();
|
2014-10-17 23:36:55 +02:00
|
|
|
void ResizeBlockStack();
|
2021-05-28 16:10:16 +02:00
|
|
|
void ResizeEzcFrameStack();
|
2014-10-17 23:36:55 +02:00
|
|
|
|
2015-11-12 10:53:20 +01:00
|
|
|
void ClearStreamStack(std::vector<StreamType*> & stream_tab);
|
2011-01-26 13:42:49 +01:00
|
|
|
void ClearFilterTab();
|
2014-10-17 23:36:55 +02:00
|
|
|
void ClearForStack();
|
2014-10-21 09:21:20 +02:00
|
|
|
void ClearBlockStack();
|
2021-05-28 16:10:16 +02:00
|
|
|
void ClearEzcFrameTab();
|
2014-10-21 09:21:20 +02:00
|
|
|
|
2011-01-26 13:42:49 +01:00
|
|
|
void ClearStream(StreamType & str);
|
2012-02-27 18:39:46 +01:00
|
|
|
void RemoveStackFunData(Stack & sitem);
|
2011-01-26 13:42:49 +01:00
|
|
|
|
2015-03-08 03:31:21 +01:00
|
|
|
bool ConvertToBool(const std::wstring & str);
|
|
|
|
|
2011-04-26 19:17:06 +02:00
|
|
|
template<class CharType>
|
|
|
|
CharType ToLower(CharType c);
|
|
|
|
|
2015-06-14 20:20:00 +02:00
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
bool CheckBlockArgument(int arg_index, FindHelper & find_helper);
|
2015-06-14 20:20:00 +02:00
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
bool FindInCache(Item::Function & item_fun, FindHelper & find_helper);
|
2011-04-26 19:17:06 +02:00
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
#ifdef EZC_HAS_MORM_LIBRARY
|
2021-06-19 20:18:30 +02:00
|
|
|
bool FindInModels(FindHelper & find_helper);
|
2021-06-16 14:16:49 +02:00
|
|
|
#endif
|
2021-05-31 18:37:09 +02:00
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
bool FindInFunctionsAndBlocks(const std::wstring & name, FindHelper & find_helper);
|
2014-10-17 23:36:55 +02:00
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
bool FindInVariables(const std::wstring & name, FindHelper & find_helper);
|
2015-06-14 20:20:00 +02:00
|
|
|
|
2021-06-19 20:18:30 +02:00
|
|
|
bool Find(Item::Function & item_fun, FindHelper & find_helper);
|
2011-01-26 13:42:49 +01:00
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
void CallFunction(typename Functions<StreamType>::UserFunction & function, FunInfo<StreamType> & info);
|
2014-10-17 23:36:55 +02:00
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
void CallFunction(typename Functions<StreamType>::UserFunction & function,
|
2014-10-28 18:46:24 +01:00
|
|
|
std::vector<Var> & parameters,
|
|
|
|
StreamType & out_stream,
|
|
|
|
const StreamType & in_stream);
|
2014-10-17 23:36:55 +02:00
|
|
|
|
|
|
|
bool CallBlock(Item & item_block,
|
2014-10-28 18:46:24 +01:00
|
|
|
std::vector<Var> & parameters,
|
2014-10-17 23:36:55 +02:00
|
|
|
StreamType & out_stream);
|
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
void CallObject(BaseObj<StreamType> & base_obj, int method_index, FunInfo<StreamType> & info);
|
2015-06-14 20:20:00 +02:00
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
#ifdef EZC_HAS_MORM_LIBRARY
|
2021-06-19 20:18:30 +02:00
|
|
|
bool CallModel(morm::Model & model, const std::wstring & field, std::vector<Var> parameters, StreamType & out_stream, const StreamType & in_stream);
|
2021-06-16 14:16:49 +02:00
|
|
|
CallModelHelper FindLastModelWrapper(morm::ModelWrapper & models_base, std::vector<std::wstring> & fields);
|
2021-06-19 20:18:30 +02:00
|
|
|
void CallModelWrapper(FindHelper & find_helper, std::vector<std::wstring> & fields, std::vector<Var> parameters, StreamType & out_stream, const StreamType & in_stream);
|
2021-06-16 14:16:49 +02:00
|
|
|
#endif
|
2015-06-14 20:20:00 +02:00
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
void CallObject(BaseObj<StreamType> & base_obj,
|
2015-06-14 20:20:00 +02:00
|
|
|
int method_index,
|
|
|
|
std::vector<Var> & parameters,
|
|
|
|
StreamType & out_stream,
|
|
|
|
const StreamType & in_stream);
|
|
|
|
|
2021-05-23 10:02:51 +02:00
|
|
|
bool CallVariable(Item::Function & item_fun,
|
2021-06-16 14:16:49 +02:00
|
|
|
Var & variable,
|
2021-05-23 10:02:51 +02:00
|
|
|
std::vector<Var> & parameters,
|
|
|
|
StreamType & out_stream,
|
|
|
|
const StreamType & in_stream);
|
2015-06-14 20:20:00 +02:00
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
bool Call(Item::Function & item_fun,
|
2021-05-23 10:02:51 +02:00
|
|
|
std::wstring * fun_name,
|
2014-10-17 23:36:55 +02:00
|
|
|
StreamType & out_stream,
|
|
|
|
bool clear_out_stream,
|
|
|
|
const StreamType & in_stream);
|
|
|
|
|
|
|
|
bool Call(Item::Function & item_fun);
|
2011-01-26 13:42:49 +01:00
|
|
|
|
2010-11-22 02:23:32 +01:00
|
|
|
wchar_t CreateSpecialChar(wchar_t c);
|
2010-11-25 02:55:32 +01:00
|
|
|
const wchar_t * PrintSpecialChar(const wchar_t * start, const wchar_t * end);
|
2010-11-22 02:23:32 +01:00
|
|
|
void PrintSpecialText(const wchar_t * start, const wchar_t * end);
|
|
|
|
void PrintNormalText(const wchar_t * start, const wchar_t * end);
|
2014-10-11 21:56:48 +02:00
|
|
|
bool IsWhite(wchar_t c);
|
2010-11-22 02:23:32 +01:00
|
|
|
void TrimWhite(const wchar_t *& start, const wchar_t *& end);
|
|
|
|
void SkipWhite(const wchar_t *& str);
|
2013-11-07 11:16:10 +01:00
|
|
|
size_t StrToSize(const wchar_t * str, const wchar_t ** str_end = 0);
|
2021-05-31 18:37:09 +02:00
|
|
|
void CopyStream(pt::TextStream src_stream, StreamType & dst_stream, bool should_escape);
|
|
|
|
bool ShouldEscapeValue(std::vector<Var> parameters);
|
2010-11-22 02:23:32 +01:00
|
|
|
|
2013-11-07 11:16:10 +01:00
|
|
|
|
2015-11-12 10:53:20 +01:00
|
|
|
void CopyTmpStreamToOutputStreams(Item::Function & fun, StreamType & ezc_out_tmp_stream, StreamType & previous_stream);
|
2021-06-19 20:18:30 +02:00
|
|
|
|
|
|
|
void CreateMsg(const wchar_t * type, const std::wstring & model_name, std::vector<std::wstring> & fields,
|
|
|
|
const wchar_t * arg = nullptr, const wchar_t * arg2 = nullptr, const wchar_t * arg3 = nullptr);
|
|
|
|
|
|
|
|
void CreateMsg(const wchar_t * type, const wchar_t * arg = nullptr);
|
2010-11-25 23:39:58 +01:00
|
|
|
void CreateMsg(const std::wstring & type, const std::wstring & arg);
|
|
|
|
void CreateMsg(const std::wstring & type);
|
2021-06-19 20:18:30 +02:00
|
|
|
|
2012-02-27 18:39:46 +01:00
|
|
|
bool LimitAchieved();
|
2010-11-22 02:23:32 +01:00
|
|
|
|
2018-10-30 00:50:10 +01:00
|
|
|
void EvaluateProgramNode(Item & item);
|
|
|
|
|
2010-11-22 02:23:32 +01:00
|
|
|
void MakeTextIf_go(Item & item, bool result);
|
|
|
|
void MakeTextIf(Item & item);
|
|
|
|
void MakeTextFor(Item & item);
|
|
|
|
void MakeItemText(Item & item);
|
|
|
|
void MakeTextContainer(Item & item);
|
|
|
|
void MakeTextNormal(Item & item);
|
2021-05-23 10:02:51 +02:00
|
|
|
void MakeTextDefine(Item & item, Var & var);
|
2010-11-22 02:23:32 +01:00
|
|
|
void MakeTextDefine(Item & item);
|
2021-05-23 10:02:51 +02:00
|
|
|
void MakeTextDefineIfNotSet(Item & item);
|
|
|
|
void MakeTextLet(Item & item, Var & var);
|
|
|
|
void MakeTextLet(Item & item);
|
|
|
|
void MakeTextLetIfNotSet(Item & item);
|
2011-01-26 13:42:49 +01:00
|
|
|
void MakeTextFilter(Item & item);
|
2013-11-07 11:16:10 +01:00
|
|
|
void MakeTextEzc(Item & item);
|
2014-10-28 18:46:24 +01:00
|
|
|
void MakeTextReturn(Item & item);
|
2010-11-22 02:23:32 +01:00
|
|
|
void MakeText(Item & item);
|
2021-05-28 16:10:16 +02:00
|
|
|
void MakeEzcFrame(Item & item);
|
2013-11-07 11:16:10 +01:00
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
void Generate();
|
2013-11-07 11:16:10 +01:00
|
|
|
|
|
|
|
|
2011-01-26 13:42:49 +01:00
|
|
|
|
2010-11-22 02:23:32 +01:00
|
|
|
}; // class Generator
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
2012-07-01 01:24:09 +02:00
|
|
|
Generator<StreamType>::Generator() : empty_stream()
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
2021-05-31 18:37:09 +02:00
|
|
|
ppattern = nullptr;
|
|
|
|
pblocks = nullptr;
|
|
|
|
pfunctions = nullptr;
|
|
|
|
pobjects = nullptr;
|
|
|
|
pvars = nullptr;
|
2021-06-19 20:18:30 +02:00
|
|
|
plog = nullptr;
|
2021-06-16 14:16:49 +02:00
|
|
|
|
|
|
|
#ifdef EZC_HAS_MORM_LIBRARY
|
2021-05-31 18:37:09 +02:00
|
|
|
pmodels = nullptr;
|
2021-06-16 14:16:49 +02:00
|
|
|
#endif
|
2010-11-22 02:23:32 +01:00
|
|
|
|
|
|
|
max_items = 50000;
|
|
|
|
max_for_items = 5000;
|
2011-01-26 13:42:49 +01:00
|
|
|
filter_size = 20;
|
2010-11-22 02:23:32 +01:00
|
|
|
special_chars = false;
|
|
|
|
trim_white = false;
|
|
|
|
skip_new_line = false;
|
2011-04-26 19:17:06 +02:00
|
|
|
is_generator_working = false;
|
2012-02-27 18:39:46 +01:00
|
|
|
stack_size = 300;
|
2014-10-17 23:36:55 +02:00
|
|
|
block_stack_size = 64;
|
2021-05-28 16:10:16 +02:00
|
|
|
ezc_frames_stack_size = 16;
|
2014-10-19 23:09:34 +02:00
|
|
|
can_find_in_cache = true;
|
|
|
|
can_use_vars = true;
|
2018-10-30 00:50:10 +01:00
|
|
|
expression_parser = nullptr;
|
2018-11-01 22:52:33 +01:00
|
|
|
program_mode = false;
|
2010-11-22 02:23:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-26 13:42:49 +01:00
|
|
|
template<class StreamType>
|
|
|
|
Generator<StreamType>::Generator(const Generator<StreamType> & n)
|
|
|
|
{
|
|
|
|
operator=(n);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
Generator<StreamType> & Generator<StreamType>::operator=(const Generator<StreamType> & n)
|
|
|
|
{
|
2014-10-17 23:36:55 +02:00
|
|
|
ppattern = n.ppattern;
|
|
|
|
pblocks = n.pblocks;
|
|
|
|
pfunctions = n.pfunctions;
|
2015-06-14 20:20:00 +02:00
|
|
|
pobjects = n.pobjects;
|
2021-05-23 10:02:51 +02:00
|
|
|
pvars = n.pvars;
|
2021-06-19 20:18:30 +02:00
|
|
|
plog = n.plog;
|
2021-06-16 14:16:49 +02:00
|
|
|
|
|
|
|
#ifdef EZC_HAS_MORM_LIBRARY
|
2021-05-31 18:37:09 +02:00
|
|
|
pmodels = n.pmodels;
|
2021-06-16 14:16:49 +02:00
|
|
|
#endif
|
2014-10-17 23:36:55 +02:00
|
|
|
|
2012-02-27 18:39:46 +01:00
|
|
|
max_items = n.max_items;
|
|
|
|
max_for_items = n.max_for_items;
|
|
|
|
special_chars = n.special_chars;
|
|
|
|
trim_white = n.trim_white;
|
|
|
|
skip_new_line = n.skip_new_line;
|
2014-10-19 23:09:34 +02:00
|
|
|
can_find_in_cache = n.can_find_in_cache;
|
|
|
|
can_use_vars = n.can_use_vars;
|
2012-02-27 18:39:46 +01:00
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
// filter, stack and block_stack will be auto resized when calling Generate() method
|
|
|
|
filter_size = n.filter_size;
|
|
|
|
stack_size = n.stack_size;
|
|
|
|
block_stack_size = n.block_stack_size;
|
2021-05-28 16:10:16 +02:00
|
|
|
ezc_frames_stack_size = n.ezc_frames_stack_size;
|
2018-10-30 00:50:10 +01:00
|
|
|
expression_parser = n.expression_parser;
|
2018-11-01 22:52:33 +01:00
|
|
|
program_mode = n.program_mode;
|
2014-10-17 23:36:55 +02:00
|
|
|
|
2014-10-19 23:09:34 +02:00
|
|
|
// vars doesn't have to be copied
|
2012-02-27 18:39:46 +01:00
|
|
|
|
2011-01-26 13:42:49 +01:00
|
|
|
// don't copy filter tab
|
2012-02-27 18:39:46 +01:00
|
|
|
// don't copy stack
|
2021-05-28 16:10:16 +02:00
|
|
|
// don't copy ezc_frame_stack_tab
|
|
|
|
// don't copy output_stream and output_frames_streams
|
2011-01-26 13:42:49 +01:00
|
|
|
|
2012-02-25 04:29:44 +01:00
|
|
|
// !! CHECK ME
|
|
|
|
// may copying should be denied when generator is working?
|
2011-04-26 19:17:06 +02:00
|
|
|
// don't copy 'is_generator_working' flag
|
|
|
|
is_generator_working = false;
|
2011-01-26 13:42:49 +01:00
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
Generator<StreamType>::~Generator()
|
|
|
|
{
|
|
|
|
ClearFilterTab();
|
2012-02-24 13:04:36 +01:00
|
|
|
ClearForStack();
|
2014-10-21 09:21:20 +02:00
|
|
|
ClearBlockStack();
|
2021-05-28 16:10:16 +02:00
|
|
|
ClearEzcFrameTab();
|
2011-01-26 13:42:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-19 07:42:25 +02:00
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::SetPattern(Pattern & pattern)
|
|
|
|
{
|
|
|
|
ppattern = &pattern;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::SetBlocks(Blocks & blocks)
|
|
|
|
{
|
|
|
|
pblocks = &blocks;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::SetFunctions(Functions<StreamType> & functions)
|
|
|
|
{
|
|
|
|
pfunctions = &functions;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-06-14 20:20:00 +02:00
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::SetObjects(Objects<StreamType> & objects)
|
|
|
|
{
|
|
|
|
pobjects = &objects;
|
|
|
|
}
|
|
|
|
|
2021-05-23 10:02:51 +02:00
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::SetVariables(Vars & variables)
|
|
|
|
{
|
|
|
|
pvars = &variables;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-19 20:18:30 +02:00
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::SetLogger(pt::Log & logger)
|
|
|
|
{
|
|
|
|
plog = &logger;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
#ifdef EZC_HAS_MORM_LIBRARY
|
2021-05-31 18:37:09 +02:00
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::SetModels(Models & models)
|
|
|
|
{
|
|
|
|
pmodels = ⊧
|
|
|
|
}
|
2021-06-16 14:16:49 +02:00
|
|
|
#endif
|
2021-05-31 18:37:09 +02:00
|
|
|
|
2014-10-19 23:09:34 +02:00
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::CanUseCache(bool can_use_cache)
|
|
|
|
{
|
|
|
|
can_find_in_cache = can_use_cache;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::CanUseVars(bool can_use_variables)
|
|
|
|
{
|
|
|
|
can_use_vars = can_use_variables;
|
|
|
|
}
|
|
|
|
|
2018-10-30 00:50:10 +01:00
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::SetProgramMode(bool set_program_mode)
|
|
|
|
{
|
|
|
|
this->program_mode = set_program_mode;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::SetExpressionParser(ExpressionParser * expression_parser)
|
|
|
|
{
|
|
|
|
this->expression_parser = expression_parser;
|
|
|
|
}
|
|
|
|
|
2014-10-19 23:09:34 +02:00
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
|
2015-11-12 10:53:20 +01:00
|
|
|
|
2011-01-26 13:42:49 +01:00
|
|
|
template<class StreamType>
|
2015-11-12 10:53:20 +01:00
|
|
|
void Generator<StreamType>::ResizeStack()
|
2011-01-26 13:42:49 +01:00
|
|
|
{
|
2015-11-12 10:53:20 +01:00
|
|
|
if( stack_tab.size() != stack_size )
|
2011-01-26 13:42:49 +01:00
|
|
|
{
|
2015-11-12 10:53:20 +01:00
|
|
|
if( stack_tab.size() > stack_size )
|
2011-01-26 13:42:49 +01:00
|
|
|
{
|
2015-11-12 10:53:20 +01:00
|
|
|
for(size_t i=stack_size ; i<stack_tab.size() ; ++i)
|
|
|
|
RemoveStackFunData(stack_tab[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
stack_tab.resize(stack_size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::ResizeStreamStack(std::vector<StreamType*> & stream_tab, size_t stream_tab_max_size)
|
|
|
|
{
|
|
|
|
if( stream_tab.size() != stream_tab_max_size )
|
|
|
|
{
|
|
|
|
if( stream_tab.size() < stream_tab_max_size )
|
|
|
|
{
|
|
|
|
size_t i = stream_tab.size();
|
|
|
|
stream_tab.resize(stream_tab_max_size);
|
|
|
|
|
|
|
|
for( ; i<stream_tab.size() ; ++i)
|
|
|
|
stream_tab[i] = new StreamType();
|
2011-01-26 13:42:49 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-11-12 10:53:20 +01:00
|
|
|
for(size_t i=stream_tab_max_size ; i<stream_tab.size() ; ++i)
|
|
|
|
delete stream_tab[i];
|
2011-01-26 13:42:49 +01:00
|
|
|
|
2015-11-12 10:53:20 +01:00
|
|
|
stream_tab.resize(stream_tab_max_size);
|
2011-01-26 13:42:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-27 18:39:46 +01:00
|
|
|
template<class StreamType>
|
2015-11-12 10:53:20 +01:00
|
|
|
void Generator<StreamType>::ResizeFilterTab()
|
2012-02-27 18:39:46 +01:00
|
|
|
{
|
2015-11-12 10:53:20 +01:00
|
|
|
ResizeStreamStack(filter_tab, filter_size);
|
|
|
|
}
|
2012-02-27 18:39:46 +01:00
|
|
|
|
2015-11-12 10:53:20 +01:00
|
|
|
|
|
|
|
template<class StreamType>
|
2021-05-28 16:10:16 +02:00
|
|
|
void Generator<StreamType>::ResizeEzcFrameStack()
|
2015-11-12 10:53:20 +01:00
|
|
|
{
|
2021-05-28 16:10:16 +02:00
|
|
|
ResizeStreamStack(ezc_frame_stack_tab, ezc_frames_stack_size);
|
2012-02-27 18:39:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-12 10:53:20 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::ClearStreamStack(std::vector<StreamType*> & stream_tab)
|
|
|
|
{
|
|
|
|
for(size_t i=0 ; i<stream_tab.size() ; ++i)
|
|
|
|
delete stream_tab[i];
|
|
|
|
|
|
|
|
stream_tab.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-26 13:42:49 +01:00
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::ClearFilterTab()
|
|
|
|
{
|
2015-11-12 10:53:20 +01:00
|
|
|
ClearStreamStack(filter_tab);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
2021-05-28 16:10:16 +02:00
|
|
|
void Generator<StreamType>::ClearEzcFrameTab()
|
2015-11-12 10:53:20 +01:00
|
|
|
{
|
2021-05-28 16:10:16 +02:00
|
|
|
ClearStreamStack(ezc_frame_stack_tab);
|
2011-01-26 13:42:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-21 09:21:20 +02:00
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::ClearBlockStack()
|
|
|
|
{
|
|
|
|
for(size_t i=0 ; i<block_stack_tab.size() ; ++i)
|
|
|
|
delete block_stack_tab[i].out_stream;
|
|
|
|
|
|
|
|
block_stack_tab.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-24 13:04:36 +01:00
|
|
|
template<class StreamType>
|
2014-10-17 23:36:55 +02:00
|
|
|
void Generator<StreamType>::ClearForStack()
|
2012-02-24 13:04:36 +01:00
|
|
|
{
|
|
|
|
for(size_t i=0 ; i<stack_tab.size() ; ++i)
|
2012-02-25 04:29:44 +01:00
|
|
|
RemoveStackFunData(stack_tab[i]);
|
2012-02-24 13:04:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-26 13:42:49 +01:00
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::ClearStream(StreamType & str)
|
|
|
|
{
|
|
|
|
#ifdef EZC_HAS_SPECIAL_STREAM
|
|
|
|
str.Clear();
|
|
|
|
#else
|
|
|
|
str.str(L"");
|
|
|
|
#endif
|
|
|
|
}
|
2010-11-22 02:23:32 +01:00
|
|
|
|
|
|
|
|
2012-02-25 04:29:44 +01:00
|
|
|
template<class StreamType>
|
2012-02-27 18:39:46 +01:00
|
|
|
void Generator<StreamType>::RemoveStackFunData(Stack & s)
|
2012-02-25 04:29:44 +01:00
|
|
|
{
|
2014-10-19 07:42:25 +02:00
|
|
|
if( s.fun_data && s.auto_remove )
|
2012-02-25 04:29:44 +01:00
|
|
|
{
|
2012-02-27 18:39:46 +01:00
|
|
|
delete s.fun_data;
|
|
|
|
s.fun_data = 0;
|
2012-02-25 04:29:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-04-26 19:17:06 +02:00
|
|
|
template<class StreamType>
|
|
|
|
template<class CharType>
|
|
|
|
CharType Generator<StreamType>::ToLower(CharType c)
|
|
|
|
{
|
|
|
|
if( c>='A' && c<='Z' )
|
|
|
|
return c - 'A' + 'a';
|
|
|
|
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-08 03:31:21 +01:00
|
|
|
template<class StreamType>
|
|
|
|
bool Generator<StreamType>::ConvertToBool(const std::wstring & str)
|
|
|
|
{
|
2021-05-23 10:02:51 +02:00
|
|
|
return !str.empty();
|
2015-03-08 03:31:21 +01:00
|
|
|
}
|
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
|
2010-11-22 02:23:32 +01:00
|
|
|
template<class StreamType>
|
2012-02-24 13:04:36 +01:00
|
|
|
void Generator<StreamType>::SetMax(size_t max_items_, size_t max_for_items_)
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
|
|
|
max_items = max_items_;
|
|
|
|
max_for_items = max_for_items_;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::RecognizeSpecialChars(bool spec)
|
|
|
|
{
|
|
|
|
special_chars = spec;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::TrimWhite(bool trim)
|
|
|
|
{
|
|
|
|
trim_white = trim;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::SkipNewLine(bool skip)
|
|
|
|
{
|
|
|
|
skip_new_line = skip;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
2011-01-26 13:42:49 +01:00
|
|
|
void Generator<StreamType>::SetMaxFilters(size_t new_len)
|
|
|
|
{
|
|
|
|
// the table will be resized when Generate() method is called
|
|
|
|
filter_size = new_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-27 18:39:46 +01:00
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::SetStackSize(size_t new_stack_size)
|
|
|
|
{
|
|
|
|
// the stack will be resized when Generate() method is called
|
|
|
|
stack_size = new_stack_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-11-07 11:16:10 +01:00
|
|
|
|
2011-01-26 13:42:49 +01:00
|
|
|
template<class StreamType>
|
2014-10-17 23:36:55 +02:00
|
|
|
void Generator<StreamType>::Generate()
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
2011-04-26 19:17:06 +02:00
|
|
|
if( is_generator_working )
|
2011-01-26 13:42:49 +01:00
|
|
|
{
|
2013-11-07 11:16:10 +01:00
|
|
|
CreateMsg(L"generator busy");
|
2011-01-26 13:42:49 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-11-25 23:39:58 +01:00
|
|
|
break_generating = false;
|
|
|
|
current_item = 0;
|
2012-02-27 18:39:46 +01:00
|
|
|
|
|
|
|
// in the case that there something has left on the stack
|
|
|
|
// from previous call to Generate()
|
|
|
|
// (an exception could have been thrown)
|
2014-10-17 23:36:55 +02:00
|
|
|
ClearForStack();
|
2012-02-27 18:39:46 +01:00
|
|
|
|
2011-01-26 13:42:49 +01:00
|
|
|
ResizeFilterTab();
|
2012-02-27 18:39:46 +01:00
|
|
|
ResizeStack();
|
2014-10-17 23:36:55 +02:00
|
|
|
ResizeBlockStack();
|
2021-05-28 16:10:16 +02:00
|
|
|
ResizeEzcFrameStack();
|
2011-01-26 13:42:49 +01:00
|
|
|
filter_index = 0;
|
2012-02-27 18:39:46 +01:00
|
|
|
stack_index = 0;
|
2014-10-17 23:36:55 +02:00
|
|
|
block_stack_index = 0;
|
2010-11-25 23:39:58 +01:00
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
if( ppattern )
|
2011-01-26 13:42:49 +01:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2011-04-26 19:17:06 +02:00
|
|
|
is_generator_working = true;
|
2014-10-17 23:36:55 +02:00
|
|
|
MakeText( ppattern->item_root );
|
2015-11-12 10:53:20 +01:00
|
|
|
// !! IMPROVE ME we can print an error message if the stacks are not empty
|
|
|
|
// (some [end] statements has been omited)
|
2011-04-26 19:17:06 +02:00
|
|
|
is_generator_working = false;
|
2011-01-26 13:42:49 +01:00
|
|
|
}
|
|
|
|
catch(...)
|
|
|
|
{
|
2011-04-26 19:17:06 +02:00
|
|
|
is_generator_working = false;
|
2011-01-26 13:42:49 +01:00
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
2010-11-25 23:39:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
2015-11-12 10:53:20 +01:00
|
|
|
void Generator<StreamType>::Generate(StreamType & out)
|
2010-11-25 23:39:58 +01:00
|
|
|
{
|
2015-11-12 10:53:20 +01:00
|
|
|
output_stream = &out;
|
2021-05-28 16:10:16 +02:00
|
|
|
output_frames_streams = 0;
|
2014-10-17 23:36:55 +02:00
|
|
|
Generate();
|
2011-01-26 13:42:49 +01:00
|
|
|
}
|
|
|
|
|
2010-11-22 02:23:32 +01:00
|
|
|
|
|
|
|
|
2013-11-07 11:16:10 +01:00
|
|
|
template<class StreamType>
|
2015-11-12 10:53:20 +01:00
|
|
|
void Generator<StreamType>::Generate(StreamType & out, OutStreams<StreamType> & out_streams)
|
2013-11-07 11:16:10 +01:00
|
|
|
{
|
2015-11-12 10:53:20 +01:00
|
|
|
output_stream = &out;
|
2021-05-28 16:10:16 +02:00
|
|
|
output_frames_streams = &out_streams;
|
2014-10-17 23:36:55 +02:00
|
|
|
Generate();
|
2013-11-07 11:16:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
2015-11-12 10:53:20 +01:00
|
|
|
void Generator<StreamType>::Generate(OutStreams<StreamType> & out_streams)
|
2013-11-07 11:16:10 +01:00
|
|
|
{
|
2015-11-12 10:53:20 +01:00
|
|
|
output_stream = 0;
|
2021-05-28 16:10:16 +02:00
|
|
|
output_frames_streams = &out_streams;
|
2014-10-17 23:36:55 +02:00
|
|
|
Generate();
|
2013-11-07 11:16:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-06-14 20:20:00 +02:00
|
|
|
|
2011-01-26 13:42:49 +01:00
|
|
|
template<class StreamType>
|
2021-06-16 14:16:49 +02:00
|
|
|
bool Generator<StreamType>::CheckBlockArgument(int arg_index, FindHelper & find_helper)
|
2011-01-26 13:42:49 +01:00
|
|
|
{
|
2021-05-23 10:02:51 +02:00
|
|
|
if( arg_index < 0 )
|
2015-06-14 20:20:00 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// it's a numeric function -- an argument to a block e.g.: [1]
|
|
|
|
if( block_stack_index > 0 )
|
2014-10-17 23:36:55 +02:00
|
|
|
{
|
2015-06-14 20:20:00 +02:00
|
|
|
BlockStack & block_stack = block_stack_tab[block_stack_index-1];
|
2013-11-07 11:16:10 +01:00
|
|
|
|
2021-05-23 10:02:51 +02:00
|
|
|
if( size_t(arg_index) < block_stack.args.size() )
|
2014-10-17 23:36:55 +02:00
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
find_helper.variable = &block_stack.args[arg_index];
|
2021-05-23 10:02:51 +02:00
|
|
|
return true;
|
2014-10-17 23:36:55 +02:00
|
|
|
}
|
|
|
|
}
|
2013-11-07 11:16:10 +01:00
|
|
|
|
2021-05-23 10:02:51 +02:00
|
|
|
return false;
|
2015-06-14 20:20:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
2021-06-16 14:16:49 +02:00
|
|
|
bool Generator<StreamType>::FindInCache(Item::Function & item_fun, FindHelper & find_helper)
|
2015-06-14 20:20:00 +02:00
|
|
|
{
|
2014-10-19 23:09:34 +02:00
|
|
|
if( can_find_in_cache )
|
2014-10-17 23:36:55 +02:00
|
|
|
{
|
2015-06-14 20:20:00 +02:00
|
|
|
if( item_fun.base_obj )
|
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
find_helper.base_obj = reinterpret_cast<BaseObj<StreamType> * >(item_fun.base_obj);
|
|
|
|
find_helper.method_index = item_fun.method_index;
|
2015-06-14 20:20:00 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-10-19 23:09:34 +02:00
|
|
|
if( item_fun.fun_cache )
|
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
find_helper.function = reinterpret_cast<typename Functions<StreamType>::UserFunction*>(item_fun.fun_cache);
|
2014-10-19 23:09:34 +02:00
|
|
|
return true;
|
|
|
|
}
|
2013-11-07 11:16:10 +01:00
|
|
|
|
2014-10-19 23:09:34 +02:00
|
|
|
if( item_fun.item_block )
|
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
find_helper.item_block = item_fun.item_block;
|
2014-10-19 23:09:34 +02:00
|
|
|
return true;
|
|
|
|
}
|
2014-10-17 23:36:55 +02:00
|
|
|
}
|
2013-11-07 11:16:10 +01:00
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
return false;
|
2010-11-22 02:23:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
#ifdef EZC_HAS_MORM_LIBRARY
|
2021-05-31 18:37:09 +02:00
|
|
|
|
|
|
|
template<class StreamType>
|
2021-06-19 20:18:30 +02:00
|
|
|
bool Generator<StreamType>::FindInModels(FindHelper & find_helper)
|
2021-05-31 18:37:09 +02:00
|
|
|
{
|
|
|
|
if( pmodels )
|
|
|
|
{
|
2021-06-19 20:18:30 +02:00
|
|
|
morm::ModelWrapper * m = pmodels->Find(*find_helper.fun_name);
|
2021-05-31 18:37:09 +02:00
|
|
|
|
|
|
|
if( m )
|
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
find_helper.model_wrapper = m;
|
2021-05-31 18:37:09 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
#endif
|
2021-05-31 18:37:09 +02:00
|
|
|
|
|
|
|
|
2013-11-07 11:16:10 +01:00
|
|
|
template<class StreamType>
|
2021-06-16 14:16:49 +02:00
|
|
|
bool Generator<StreamType>::FindInFunctionsAndBlocks(const std::wstring & name, FindHelper & find_helper)
|
2013-11-07 11:16:10 +01:00
|
|
|
{
|
2015-06-14 20:20:00 +02:00
|
|
|
if( pobjects )
|
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
typename Objects<StreamType>::Iterator i = pobjects->Find(name, find_helper.method_index);
|
2015-06-14 20:20:00 +02:00
|
|
|
|
|
|
|
if( i != pobjects->End() )
|
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
find_helper.base_obj = *i;
|
2015-06-14 20:20:00 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
if( pfunctions )
|
|
|
|
{
|
2014-10-18 00:14:28 +02:00
|
|
|
typename Functions<StreamType>::Iterator i = pfunctions->Find(name);
|
2013-11-07 11:16:10 +01:00
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
if( i != pfunctions->End() )
|
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
find_helper.function = &i->second;
|
2014-10-17 23:36:55 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2013-11-07 11:16:10 +01:00
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
if( pblocks )
|
|
|
|
{
|
|
|
|
Blocks::Iterator i = pblocks->Find(name);
|
2010-11-22 02:23:32 +01:00
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
if( i != pblocks->End() )
|
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
find_helper.item_block = &i->second;
|
2014-10-17 23:36:55 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2010-11-22 02:23:32 +01:00
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
return false;
|
|
|
|
}
|
2010-11-22 02:23:32 +01:00
|
|
|
|
2010-11-25 23:39:58 +01:00
|
|
|
|
2010-11-22 02:23:32 +01:00
|
|
|
template<class StreamType>
|
2021-06-16 14:16:49 +02:00
|
|
|
bool Generator<StreamType>::FindInVariables(const std::wstring & name, FindHelper & find_helper)
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
2021-05-23 10:02:51 +02:00
|
|
|
if( pvars )
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
2021-05-23 10:02:51 +02:00
|
|
|
Vars::iterator i = pvars->find(name);
|
2014-10-17 23:36:55 +02:00
|
|
|
|
2021-05-23 10:02:51 +02:00
|
|
|
if( i != pvars->end() )
|
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
find_helper.variable = &(i->second);
|
2021-05-23 10:02:51 +02:00
|
|
|
return true;
|
|
|
|
}
|
2010-11-25 23:39:58 +01:00
|
|
|
}
|
|
|
|
|
2021-05-23 10:02:51 +02:00
|
|
|
return false;
|
2014-10-17 23:36:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
|
2021-05-23 10:02:51 +02:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*/
|
2014-10-17 23:36:55 +02:00
|
|
|
template<class StreamType>
|
2021-06-19 20:18:30 +02:00
|
|
|
bool Generator<StreamType>::Find(Item::Function & item_fun, FindHelper & find_helper)
|
2021-06-16 14:16:49 +02:00
|
|
|
{
|
|
|
|
#ifdef EZC_HAS_MORM_LIBRARY
|
2021-06-19 20:18:30 +02:00
|
|
|
if( FindInModels(find_helper) )
|
2021-06-16 14:16:49 +02:00
|
|
|
return true;
|
|
|
|
#endif
|
2015-06-14 20:20:00 +02:00
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
if( CheckBlockArgument(item_fun.arg, find_helper) )
|
2014-10-17 23:36:55 +02:00
|
|
|
return true;
|
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
if( FindInCache(item_fun, find_helper) )
|
2014-10-17 23:36:55 +02:00
|
|
|
return true;
|
|
|
|
|
2021-06-19 20:18:30 +02:00
|
|
|
if( FindInFunctionsAndBlocks(*find_helper.fun_name, find_helper) )
|
2014-10-17 23:36:55 +02:00
|
|
|
return true;
|
|
|
|
|
2021-06-19 20:18:30 +02:00
|
|
|
if( FindInVariables(*find_helper.fun_name, find_helper) )
|
2021-06-16 14:16:49 +02:00
|
|
|
return true;
|
2014-10-17 23:36:55 +02:00
|
|
|
|
2021-06-19 20:18:30 +02:00
|
|
|
CreateMsg(L"unknown function", find_helper.fun_name->c_str());
|
2021-06-16 14:16:49 +02:00
|
|
|
return false;
|
2010-11-22 02:23:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-27 18:39:46 +01:00
|
|
|
|
2010-11-22 02:23:32 +01:00
|
|
|
template<class StreamType>
|
2021-06-16 14:16:49 +02:00
|
|
|
void Generator<StreamType>::CallFunction(typename Functions<StreamType>::UserFunction & function, FunInfo<StreamType> & info)
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
|
|
|
info.Clear();
|
2011-01-15 00:59:30 +01:00
|
|
|
|
2014-11-02 18:26:56 +01:00
|
|
|
info.is_for = is_generating_for;
|
|
|
|
info.is_if = is_generating_if;
|
|
|
|
info.is_normal = is_generating_normal;
|
|
|
|
info.is_filter = is_generating_filter;
|
|
|
|
info.iter = info.stack.iter;
|
2021-06-16 14:16:49 +02:00
|
|
|
info.stack_tab = stack_tab.data();
|
2014-11-02 18:26:56 +01:00
|
|
|
info.stack_index = stack_index-1;
|
2012-02-24 13:04:36 +01:00
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
(function)(info);
|
2011-04-26 19:17:06 +02:00
|
|
|
|
|
|
|
last_res = info.res;
|
2010-11-22 02:23:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
2021-06-16 14:16:49 +02:00
|
|
|
void Generator<StreamType>::CallFunction(typename Functions<StreamType>::UserFunction & function,
|
2014-10-28 18:46:24 +01:00
|
|
|
std::vector<Var> & parameters,
|
2014-10-17 23:36:55 +02:00
|
|
|
StreamType & out_stream,
|
|
|
|
const StreamType & in_stream)
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
2014-10-28 18:46:24 +01:00
|
|
|
if( parameters.empty() )
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
2016-04-04 17:53:11 +02:00
|
|
|
FunInfo<StreamType> info(out_stream, parameters, empty, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item);
|
2014-10-17 23:36:55 +02:00
|
|
|
CallFunction(function, info);
|
2010-11-22 02:23:32 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-04-04 17:53:11 +02:00
|
|
|
FunInfo<StreamType> info(out_stream, parameters, parameters[0].str, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item);
|
2014-10-17 23:36:55 +02:00
|
|
|
CallFunction(function, info);
|
2010-11-22 02:23:32 +01:00
|
|
|
}
|
2011-01-26 13:42:49 +01:00
|
|
|
}
|
2010-11-22 02:23:32 +01:00
|
|
|
|
2011-01-26 13:42:49 +01:00
|
|
|
|
2014-10-28 18:46:24 +01:00
|
|
|
|
2015-06-14 20:20:00 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
2021-06-16 14:16:49 +02:00
|
|
|
void Generator<StreamType>::CallObject(BaseObj<StreamType> & base_obj, int method_index, FunInfo<StreamType> & info)
|
2015-06-14 20:20:00 +02:00
|
|
|
{
|
|
|
|
info.Clear();
|
|
|
|
|
|
|
|
info.is_for = is_generating_for;
|
|
|
|
info.is_if = is_generating_if;
|
|
|
|
info.is_normal = is_generating_normal;
|
|
|
|
info.is_filter = is_generating_filter;
|
|
|
|
info.iter = info.stack.iter;
|
2021-06-16 14:16:49 +02:00
|
|
|
info.stack_tab = stack_tab.data();
|
2015-06-14 20:20:00 +02:00
|
|
|
info.stack_index = stack_index-1;
|
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
base_obj.CallFun(method_index, info);
|
2015-06-14 20:20:00 +02:00
|
|
|
|
|
|
|
last_res = info.res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-05-31 18:37:09 +02:00
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::CopyStream(pt::TextStream src_stream, StreamType & dst_stream, bool should_escape)
|
|
|
|
{
|
|
|
|
pt::TextStream::iterator i = src_stream.begin();
|
|
|
|
|
|
|
|
while( i != src_stream.end() )
|
|
|
|
{
|
|
|
|
if( should_escape )
|
|
|
|
{
|
|
|
|
dst_stream << *i;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
if constexpr(sizeof(pt::TextStream::char_type) == sizeof(typename StreamType::char_type))
|
|
|
|
{
|
|
|
|
dst_stream.write(&(*i), 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
wchar_t buf = static_cast<unsigned char>(*i);
|
|
|
|
dst_stream.write(&buf, 1);
|
|
|
|
}
|
2021-05-31 18:37:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
bool Generator<StreamType>::ShouldEscapeValue(std::vector<Var> parameters)
|
|
|
|
{
|
|
|
|
for(Var & var : parameters)
|
|
|
|
{
|
|
|
|
if( !var.is_function )
|
|
|
|
{
|
|
|
|
if( var.str == L"raw" || var.str == L"noescape" )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
#ifdef EZC_HAS_MORM_LIBRARY
|
2021-05-31 18:37:09 +02:00
|
|
|
|
|
|
|
template<class StreamType>
|
2021-06-19 20:18:30 +02:00
|
|
|
bool Generator<StreamType>::CallModel(morm::Model & model, const std::wstring & field, std::vector<Var> parameters, StreamType & out_stream, const StreamType & in_stream)
|
2021-05-31 18:37:09 +02:00
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
/*
|
|
|
|
* if 'field' is a POD type then 'str' will be used in get_raw_value()
|
|
|
|
* if 'field' is a getter method with pt::TextStream then 'str' will be used too
|
|
|
|
* if 'field' is a getter method which takes FunInfo<> then out_stream will be used and 'str' will be empty
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
pt::TextStream str;
|
2021-06-19 20:18:30 +02:00
|
|
|
bool found = false;
|
2021-05-31 18:37:09 +02:00
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
if( parameters.empty() )
|
2021-05-31 18:37:09 +02:00
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
FunInfo<StreamType> info(out_stream, parameters, empty, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item);
|
2021-06-19 20:18:30 +02:00
|
|
|
found = model.get_raw_value(nullptr, field.c_str(), nullptr, info, str, false);
|
2021-06-16 14:16:49 +02:00
|
|
|
last_res = info.res;
|
2021-05-31 18:37:09 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
FunInfo<StreamType> info(out_stream, parameters, parameters[0].str, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item);
|
2021-06-19 20:18:30 +02:00
|
|
|
found = model.get_raw_value(nullptr, field.c_str(), nullptr, info, str, false);
|
2021-06-16 14:16:49 +02:00
|
|
|
last_res = info.res;
|
|
|
|
}
|
2021-05-31 18:37:09 +02:00
|
|
|
|
2021-06-19 20:18:30 +02:00
|
|
|
if( found )
|
|
|
|
{
|
|
|
|
bool should_escape = ShouldEscapeValue(parameters);
|
|
|
|
CopyStream(str, out_stream, should_escape);
|
|
|
|
}
|
|
|
|
|
|
|
|
return found;
|
2021-06-16 14:16:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
2021-06-18 18:55:39 +02:00
|
|
|
typename Generator<StreamType>::CallModelHelper Generator<StreamType>::FindLastModelWrapper(morm::ModelWrapper & models_base, std::vector<std::wstring> & fields)
|
2021-06-16 14:16:49 +02:00
|
|
|
{
|
|
|
|
CallModelHelper helper;
|
|
|
|
helper.field_index = 0;
|
|
|
|
helper.model_wrapper = &models_base;
|
|
|
|
helper.model = nullptr;
|
|
|
|
|
|
|
|
for(; helper.field_index < fields.size() ; ++helper.field_index)
|
|
|
|
{
|
|
|
|
std::wstring & field = fields[helper.field_index];
|
|
|
|
morm::ModelWrapper * child_models_base = helper.model_wrapper->find_child(field);
|
|
|
|
|
|
|
|
if( !child_models_base )
|
2021-05-31 18:37:09 +02:00
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
helper.model = helper.model_wrapper->get_model();
|
|
|
|
// this can return null for lists/vectors in a case when the iterator is not pointing to a valid item
|
2021-05-31 18:37:09 +02:00
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
if( helper.model )
|
2021-05-31 18:37:09 +02:00
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
child_models_base = helper.model->get_model_wrapper(nullptr, field.c_str(), false);
|
2021-05-31 18:37:09 +02:00
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
if( child_models_base )
|
2021-05-31 18:37:09 +02:00
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
helper.model_wrapper->add_child(field, child_models_base);
|
2021-05-31 18:37:09 +02:00
|
|
|
}
|
|
|
|
}
|
2021-06-16 14:16:49 +02:00
|
|
|
}
|
2021-05-31 18:37:09 +02:00
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
if( !child_models_base )
|
|
|
|
break;
|
2021-05-31 18:37:09 +02:00
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
helper.model_wrapper = child_models_base;
|
|
|
|
helper.model = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return helper;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
2021-06-19 20:18:30 +02:00
|
|
|
void Generator<StreamType>::CallModelWrapper(FindHelper & find_helper, std::vector<std::wstring> & fields,
|
2021-06-16 14:16:49 +02:00
|
|
|
std::vector<Var> parameters, StreamType & out_stream, const StreamType & in_stream)
|
|
|
|
{
|
|
|
|
last_res = false;
|
2021-06-19 20:18:30 +02:00
|
|
|
CallModelHelper helper = FindLastModelWrapper(*find_helper.model_wrapper, fields);
|
2021-06-16 14:16:49 +02:00
|
|
|
|
|
|
|
// if:
|
|
|
|
// helper.field_index == fields.size() - all fields items are models or models containers
|
|
|
|
// helper.field_index == fields.size()-1 - last field is not a model nor a models container
|
|
|
|
// helper.field_index < fields.size()-1 - incorrect
|
|
|
|
|
|
|
|
if( helper.field_index + 1 < fields.size() )
|
|
|
|
{
|
2021-06-19 20:18:30 +02:00
|
|
|
CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", ", fields[helper.field_index].c_str(), L" is not a model nor a model container");
|
2021-06-16 14:16:49 +02:00
|
|
|
last_res = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( helper.field_index + 1 == fields.size() )
|
|
|
|
{
|
|
|
|
// last field is not a model nor a models container
|
|
|
|
|
|
|
|
if( helper.model )
|
|
|
|
{
|
2021-06-19 20:18:30 +02:00
|
|
|
if( !CallModel(*helper.model, fields[helper.field_index], parameters, out_stream, in_stream) )
|
|
|
|
{
|
|
|
|
CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", unknown ", fields[helper.field_index].c_str());
|
|
|
|
}
|
2021-06-16 14:16:49 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
last_res = false;
|
2021-06-19 20:18:30 +02:00
|
|
|
CreateMsg(L"model ", *find_helper.fun_name, fields, L" is not initialized, have you forgotten to use [for ...] statement?");
|
2021-06-16 14:16:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// all fields items are models or models containers
|
|
|
|
// this is usualy in [for...] or [if ...] statements
|
|
|
|
// helper.model_wrapper is always set
|
|
|
|
if( stack_tab[stack_index-1].is_for )
|
|
|
|
{
|
|
|
|
helper.model_wrapper->increment_iterator();
|
|
|
|
helper.model_wrapper->clear_childs();
|
|
|
|
last_res = helper.model_wrapper->is_iterator_correct();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
last_res = !helper.model_wrapper->is_container_empty();
|
2021-05-31 18:37:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-06-16 14:16:49 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2021-05-31 18:37:09 +02:00
|
|
|
|
2015-06-14 20:20:00 +02:00
|
|
|
template<class StreamType>
|
2021-06-16 14:16:49 +02:00
|
|
|
void Generator<StreamType>::CallObject(BaseObj<StreamType> & base_obj,
|
2015-06-14 20:20:00 +02:00
|
|
|
int method_index,
|
|
|
|
std::vector<Var> & parameters,
|
|
|
|
StreamType & out_stream,
|
|
|
|
const StreamType & in_stream)
|
|
|
|
{
|
|
|
|
if( parameters.empty() )
|
|
|
|
{
|
2016-04-04 17:53:11 +02:00
|
|
|
FunInfo<StreamType> info(out_stream, parameters, empty, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item);
|
2015-06-14 20:20:00 +02:00
|
|
|
CallObject(base_obj, method_index, info);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-04-04 17:53:11 +02:00
|
|
|
FunInfo<StreamType> info(out_stream, parameters, parameters[0].str, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item);
|
2015-06-14 20:20:00 +02:00
|
|
|
CallObject(base_obj, method_index, info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
template<class StreamType>
|
|
|
|
bool Generator<StreamType>::CallBlock(Item & item_block,
|
2014-10-28 18:46:24 +01:00
|
|
|
std::vector<Var> & parameters,
|
2014-10-17 23:36:55 +02:00
|
|
|
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];
|
|
|
|
|
2014-10-28 18:46:24 +01:00
|
|
|
block_stack.was_return = false;
|
|
|
|
block_stack.args = parameters;
|
2014-10-17 23:36:55 +02:00
|
|
|
|
|
|
|
output_stream = block_stack.out_stream;
|
|
|
|
ClearStream(*output_stream);
|
|
|
|
block_stack_index += 1;
|
|
|
|
|
|
|
|
MakeText(item_block);
|
|
|
|
|
2014-10-18 00:14:28 +02:00
|
|
|
#ifdef EZC_HAS_SPECIAL_STREAM
|
|
|
|
const std::wstring & str = output_stream->Str();
|
|
|
|
#else
|
|
|
|
const std::wstring & str = output_stream->str();
|
|
|
|
#endif
|
|
|
|
|
2014-10-19 23:09:34 +02:00
|
|
|
out_stream.write(str.c_str(), str.size());
|
2015-03-08 03:31:21 +01:00
|
|
|
// last_res is set by [return ...] statement or other last evaluated function
|
2014-10-17 23:36:55 +02:00
|
|
|
|
|
|
|
ClearStream(*output_stream);
|
|
|
|
output_stream = old_stream;
|
|
|
|
block_stack_index -= 1;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2011-01-26 13:42:49 +01:00
|
|
|
|
2011-04-26 19:17:06 +02:00
|
|
|
|
2021-05-23 10:02:51 +02:00
|
|
|
|
|
|
|
template<class StreamType>
|
2021-06-16 14:16:49 +02:00
|
|
|
bool Generator<StreamType>::CallVariable(Item::Function & item_fun, Var & variable, std::vector<Var> & parameters, StreamType & out_stream, const StreamType & in_stream)
|
2021-05-23 10:02:51 +02:00
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
if( variable.is_function )
|
2021-05-23 10:02:51 +02:00
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
return Call(item_fun, &variable.str, out_stream, false, in_stream);
|
2021-05-23 10:02:51 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
out_stream << variable.str;
|
|
|
|
last_res = variable.res;
|
2021-05-23 10:02:51 +02:00
|
|
|
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)
|
|
|
|
*/
|
2011-01-26 13:42:49 +01:00
|
|
|
template<class StreamType>
|
2014-10-17 23:36:55 +02:00
|
|
|
bool Generator<StreamType>::Call(Item::Function & item_fun,
|
2021-05-23 10:02:51 +02:00
|
|
|
std::wstring * fun_name,
|
2014-10-17 23:36:55 +02:00
|
|
|
StreamType & out_stream,
|
|
|
|
bool clear_out_stream,
|
|
|
|
const StreamType & in_stream)
|
2011-01-26 13:42:49 +01:00
|
|
|
{
|
2021-06-16 14:16:49 +02:00
|
|
|
FindHelper find_helper;
|
2014-10-28 18:46:24 +01:00
|
|
|
std::vector<Var> parameters;
|
2014-10-17 23:36:55 +02:00
|
|
|
|
|
|
|
if( clear_out_stream )
|
|
|
|
ClearStream(out_stream);
|
2011-01-26 13:42:49 +01:00
|
|
|
|
2021-06-19 20:18:30 +02:00
|
|
|
find_helper.fun_name = fun_name;
|
|
|
|
|
|
|
|
if( !find_helper.fun_name )
|
|
|
|
find_helper.fun_name = &item_fun.name;
|
2021-05-31 18:37:09 +02:00
|
|
|
|
2021-06-19 20:18:30 +02:00
|
|
|
if( !Find(item_fun, find_helper) )
|
2021-06-16 14:16:49 +02:00
|
|
|
return false;
|
2011-01-26 13:42:49 +01:00
|
|
|
|
2014-10-28 18:46:24 +01:00
|
|
|
parameters.resize(item_fun.parameters.size());
|
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
for(size_t i=0 ; i<item_fun.parameters.size() ; ++i)
|
|
|
|
{
|
|
|
|
Item::Function & fun_child = *item_fun.parameters[i];
|
|
|
|
|
2015-03-08 03:31:21 +01:00
|
|
|
if( fun_child.is_function )
|
2014-10-17 23:36:55 +02:00
|
|
|
{
|
2014-10-28 18:46:24 +01:00
|
|
|
StreamType local_temp_stream;
|
2021-05-23 10:02:51 +02:00
|
|
|
Call(fun_child, nullptr, local_temp_stream, true, empty_stream);
|
2014-10-17 23:36:55 +02:00
|
|
|
|
2014-10-28 18:46:24 +01:00
|
|
|
#ifdef EZC_HAS_SPECIAL_STREAM
|
|
|
|
parameters[i].str = local_temp_stream.Str();
|
|
|
|
#else
|
|
|
|
parameters[i].str = local_temp_stream.str();
|
|
|
|
#endif
|
2014-10-17 23:36:55 +02:00
|
|
|
|
2014-10-28 18:46:24 +01:00
|
|
|
parameters[i].res = last_res;
|
2014-10-17 23:36:55 +02:00
|
|
|
}
|
2014-10-28 18:46:24 +01:00
|
|
|
else
|
2014-10-17 23:36:55 +02:00
|
|
|
{
|
2015-03-08 03:31:21 +01:00
|
|
|
parameters[i].str = fun_child.name;
|
|
|
|
parameters[i].res = ConvertToBool(fun_child.name);
|
2014-10-17 23:36:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-16 14:16:49 +02:00
|
|
|
#ifdef EZC_HAS_MORM_LIBRARY
|
|
|
|
if( find_helper.model_wrapper )
|
2021-06-19 20:18:30 +02:00
|
|
|
CallModelWrapper(find_helper, item_fun.fields, parameters, out_stream, in_stream);
|
2021-05-31 18:37:09 +02:00
|
|
|
else
|
2021-06-16 14:16:49 +02:00
|
|
|
#endif
|
|
|
|
if( find_helper.base_obj )
|
|
|
|
CallObject(*find_helper.base_obj, find_helper.method_index, parameters, out_stream, in_stream);
|
2015-06-14 20:20:00 +02:00
|
|
|
else
|
2021-06-16 14:16:49 +02:00
|
|
|
if( find_helper.function )
|
|
|
|
CallFunction(*find_helper.function, parameters, out_stream, in_stream);
|
2014-10-17 23:36:55 +02:00
|
|
|
else
|
2021-06-16 14:16:49 +02:00
|
|
|
if( find_helper.item_block )
|
|
|
|
return CallBlock(*find_helper.item_block, parameters, out_stream);
|
2014-10-17 23:36:55 +02:00
|
|
|
else
|
2021-06-16 14:16:49 +02:00
|
|
|
if( find_helper.variable )
|
|
|
|
return CallVariable(item_fun, *find_helper.variable, parameters, out_stream, in_stream);
|
2010-11-25 23:39:58 +01:00
|
|
|
|
2021-05-23 10:02:51 +02:00
|
|
|
return true;
|
2010-11-22 02:23:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-25 23:39:58 +01:00
|
|
|
|
2011-04-26 19:17:06 +02:00
|
|
|
// return: true if a function or variable was found and called
|
2011-01-15 00:59:30 +01:00
|
|
|
template<class StreamType>
|
2011-04-26 19:17:06 +02:00
|
|
|
bool Generator<StreamType>::Call(Item::Function & item_fun)
|
2011-01-15 00:59:30 +01:00
|
|
|
{
|
2021-05-23 10:02:51 +02:00
|
|
|
return Call(item_fun, nullptr, stream_temp1, true, empty_stream);
|
2011-01-15 00:59:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-11-25 23:39:58 +01:00
|
|
|
|
2010-11-22 02:23:32 +01:00
|
|
|
template<class StreamType>
|
|
|
|
wchar_t Generator<StreamType>::CreateSpecialChar(wchar_t c)
|
|
|
|
{
|
|
|
|
wchar_t res = 0;
|
|
|
|
|
|
|
|
if( c == 'r' )
|
|
|
|
res = '\r';
|
|
|
|
else
|
|
|
|
if( c == 'n' )
|
|
|
|
res = '\n';
|
|
|
|
else
|
|
|
|
if( c == 't' )
|
|
|
|
res = '\t';
|
|
|
|
else
|
|
|
|
if( c == 's' )
|
|
|
|
res = ' ';
|
|
|
|
else
|
|
|
|
if( c == '\\' )
|
|
|
|
res = '\\';
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-25 02:55:32 +01:00
|
|
|
|
|
|
|
// a special character is precedeed by a slash '\'
|
|
|
|
// if the special character is unknown the first slash is printing
|
|
|
|
// so "\t" gives one character of code 9
|
|
|
|
// and "\x" gives "\x"
|
2010-11-22 02:23:32 +01:00
|
|
|
template<class StreamType>
|
2010-11-25 02:55:32 +01:00
|
|
|
const wchar_t * Generator<StreamType>::PrintSpecialChar(const wchar_t * start, const wchar_t * end)
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
2010-11-25 02:55:32 +01:00
|
|
|
wchar_t special = 0;
|
2010-11-22 02:23:32 +01:00
|
|
|
|
2010-11-25 02:55:32 +01:00
|
|
|
if( *start == '\\' && (start+1) != end )
|
|
|
|
special = CreateSpecialChar(*(start+1));
|
|
|
|
|
|
|
|
if( special )
|
|
|
|
{
|
|
|
|
output_stream->write(&special, 1);
|
|
|
|
start += 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if( !skip_new_line || *start != 10 )
|
|
|
|
output_stream->write(start, 1);
|
|
|
|
|
|
|
|
start += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return start;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::PrintSpecialText(const wchar_t * start, const wchar_t * end)
|
|
|
|
{
|
2013-11-07 11:16:10 +01:00
|
|
|
if( output_stream )
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
2013-11-07 11:16:10 +01:00
|
|
|
while( start != end )
|
|
|
|
{
|
|
|
|
const wchar_t * end2 = start;
|
2010-11-22 02:23:32 +01:00
|
|
|
|
2013-11-07 11:16:10 +01:00
|
|
|
// looking for a first new line character or a special char
|
|
|
|
// (for new line only if skip_new_line is true)
|
|
|
|
while( end2 != end && *end2 != '\\' && (!skip_new_line || *end2 != 10) )
|
|
|
|
end2 += 1;
|
2010-11-22 02:23:32 +01:00
|
|
|
|
2013-11-07 11:16:10 +01:00
|
|
|
// printing the first part of the text
|
|
|
|
if( start != end2 )
|
|
|
|
output_stream->write(start, end2 - start);
|
2010-11-22 02:23:32 +01:00
|
|
|
|
2013-11-07 11:16:10 +01:00
|
|
|
start = end2;
|
|
|
|
|
|
|
|
// skipping one or more new line characters or special chars
|
|
|
|
// (new lines only if skip_new_line is true)
|
|
|
|
while( start != end && (*start == '\\' || (skip_new_line && *start == 10)) )
|
|
|
|
start = PrintSpecialChar(start, end);
|
|
|
|
}
|
2010-11-22 02:23:32 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::PrintNormalText(const wchar_t * start, const wchar_t * end)
|
|
|
|
{
|
2013-11-07 11:16:10 +01:00
|
|
|
if( output_stream )
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
2013-11-07 11:16:10 +01:00
|
|
|
if( skip_new_line )
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
2013-11-07 11:16:10 +01:00
|
|
|
while( start != end )
|
|
|
|
{
|
|
|
|
const wchar_t * end2 = start;
|
2010-11-25 02:55:32 +01:00
|
|
|
|
2013-11-07 11:16:10 +01:00
|
|
|
// looking for a first new line character
|
|
|
|
while( end2 != end && *end2 != 10 )
|
|
|
|
end2 += 1;
|
2010-11-25 02:55:32 +01:00
|
|
|
|
2013-11-07 11:16:10 +01:00
|
|
|
// printing the first part of the text (until the new line)
|
|
|
|
if( start != end2 )
|
|
|
|
output_stream->write(start, end2 - start);
|
2010-11-25 02:55:32 +01:00
|
|
|
|
2013-11-07 11:16:10 +01:00
|
|
|
start = end2;
|
|
|
|
|
|
|
|
// skipping one or more new line characters
|
|
|
|
while( start != end && *start == 10 )
|
|
|
|
start += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if( start != end )
|
|
|
|
output_stream->write(start, end - start);
|
2010-11-22 02:23:32 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-11 21:56:48 +02:00
|
|
|
template<class StreamType>
|
|
|
|
bool Generator<StreamType>::IsWhite(wchar_t c)
|
|
|
|
{
|
|
|
|
// 13 (\r) is from a dos file at the end of a line (\r\n)
|
|
|
|
// 160 is a non-breaking space
|
|
|
|
|
|
|
|
if( c==' ' || c=='\t' || c==13 || c==160 || c==10 )
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-22 02:23:32 +01:00
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::TrimWhite(const wchar_t *& start, const wchar_t *& end)
|
|
|
|
{
|
2014-10-11 21:56:48 +02:00
|
|
|
while( start != end && IsWhite(*start) )
|
2010-11-22 02:23:32 +01:00
|
|
|
++start;
|
|
|
|
|
2014-10-11 21:56:48 +02:00
|
|
|
while( start != end && IsWhite(*(end-1)) )
|
2010-11-22 02:23:32 +01:00
|
|
|
--end;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::SkipWhite(const wchar_t *& str)
|
|
|
|
{
|
2014-10-11 21:56:48 +02:00
|
|
|
while( IsWhite(*str) )
|
2010-11-22 02:23:32 +01:00
|
|
|
str += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
2012-02-24 13:04:36 +01:00
|
|
|
size_t Generator<StreamType>::StrToSize(const wchar_t * str, const wchar_t ** str_end)
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
2012-02-24 13:04:36 +01:00
|
|
|
size_t res = 0;
|
2010-11-22 02:23:32 +01:00
|
|
|
|
|
|
|
SkipWhite(str);
|
|
|
|
|
2012-02-24 13:04:36 +01:00
|
|
|
// !! IMPROVE ME
|
2010-11-22 02:23:32 +01:00
|
|
|
// overflow is not checked
|
|
|
|
|
|
|
|
while( *str>='0' && *str<='9' )
|
|
|
|
{
|
|
|
|
res *= 10;
|
|
|
|
res += *str - '0';
|
|
|
|
str += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
SkipWhite(str);
|
2013-11-07 11:16:10 +01:00
|
|
|
|
|
|
|
if( str_end )
|
|
|
|
*str_end = str;
|
2010-11-22 02:23:32 +01:00
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-26 13:42:49 +01:00
|
|
|
template<class StreamType>
|
2015-11-12 10:53:20 +01:00
|
|
|
void Generator<StreamType>::CopyTmpStreamToOutputStreams(Item::Function & fun, StreamType & ezc_out_tmp_stream, StreamType & previous_stream)
|
2011-01-26 13:42:49 +01:00
|
|
|
{
|
2021-05-28 16:10:16 +02:00
|
|
|
if( output_frames_streams )
|
2013-11-07 11:16:10 +01:00
|
|
|
{
|
2015-11-12 10:53:20 +01:00
|
|
|
#ifdef EZC_HAS_SPECIAL_STREAM
|
|
|
|
const std::wstring & str = ezc_out_tmp_stream.Str();
|
|
|
|
#else
|
|
|
|
const std::wstring & str = ezc_out_tmp_stream.str();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if( !str.empty() )
|
2013-11-07 11:16:10 +01:00
|
|
|
{
|
2015-11-12 10:53:20 +01:00
|
|
|
previous_stream.write(str.c_str(), str.size());
|
2013-11-07 11:16:10 +01:00
|
|
|
|
2015-11-12 10:53:20 +01:00
|
|
|
for(size_t s=0 ; s < fun.parameters.size() ; ++s)
|
|
|
|
{
|
|
|
|
std::wstring & name = fun.parameters[s]->name;
|
2021-05-28 16:10:16 +02:00
|
|
|
auto imap = output_frames_streams->streams_map.find(name);
|
2015-11-12 10:53:20 +01:00
|
|
|
|
2021-05-28 16:10:16 +02:00
|
|
|
if( imap == output_frames_streams->streams_map.end() )
|
2015-11-12 10:53:20 +01:00
|
|
|
{
|
2021-05-28 16:10:16 +02:00
|
|
|
if( output_frames_streams->streams_map.size() < output_frames_streams->streams_tab.size() )
|
2015-11-12 10:53:20 +01:00
|
|
|
{
|
2015-11-16 13:09:34 +01:00
|
|
|
/* a new stream from the pool (output_stream_tab) is taken */
|
2021-05-28 16:10:16 +02:00
|
|
|
StreamType * stream = output_frames_streams->streams_tab[ output_frames_streams->streams_map.size() ];
|
|
|
|
output_frames_streams->streams_map.insert(std::make_pair(name, stream));
|
2015-11-12 10:53:20 +01:00
|
|
|
ClearStream(*stream);
|
|
|
|
stream->write(str.c_str(), str.size());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-06-19 20:18:30 +02:00
|
|
|
CreateMsg(L"limit of output streams in OutStreams<> has been reached");
|
2015-11-12 10:53:20 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-11-16 13:09:34 +01:00
|
|
|
StreamType * stream = imap->second;
|
2015-11-12 10:53:20 +01:00
|
|
|
stream->write(str.c_str(), str.size());
|
|
|
|
}
|
|
|
|
}
|
2013-11-07 11:16:10 +01:00
|
|
|
}
|
|
|
|
}
|
2011-01-26 13:42:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-06-19 20:18:30 +02:00
|
|
|
|
2014-10-19 07:42:25 +02:00
|
|
|
template<class StreamType>
|
2021-06-19 20:18:30 +02:00
|
|
|
void Generator<StreamType>::CreateMsg(const wchar_t * type, const wchar_t * arg)
|
2014-10-19 07:42:25 +02:00
|
|
|
{
|
2021-06-19 20:18:30 +02:00
|
|
|
if( plog )
|
2014-10-19 07:42:25 +02:00
|
|
|
{
|
2021-06-19 20:18:30 +02:00
|
|
|
(*plog) << pt::Log::log2 << L"Ezc: runtime error: " << type;
|
2014-10-19 07:42:25 +02:00
|
|
|
|
2021-06-19 20:18:30 +02:00
|
|
|
if( arg )
|
|
|
|
{
|
|
|
|
(*plog) << arg;
|
|
|
|
}
|
|
|
|
|
|
|
|
(*plog) << pt::Log::logend;
|
|
|
|
}
|
2014-10-19 07:42:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-19 20:18:30 +02:00
|
|
|
|
2015-11-12 10:53:20 +01:00
|
|
|
template<class StreamType>
|
2021-06-19 20:18:30 +02:00
|
|
|
void Generator<StreamType>::CreateMsg(const wchar_t * type, const std::wstring & model_name, std::vector<std::wstring> & fields,
|
|
|
|
const wchar_t * arg, const wchar_t * arg2, const wchar_t * arg3)
|
2015-11-12 10:53:20 +01:00
|
|
|
{
|
2021-06-19 20:18:30 +02:00
|
|
|
if( plog )
|
|
|
|
{
|
|
|
|
(*plog) << pt::Log::log2 << L"Ezc: " << type << model_name;
|
2015-11-12 10:53:20 +01:00
|
|
|
|
2021-06-19 20:18:30 +02:00
|
|
|
for(std::wstring & str : fields)
|
|
|
|
{
|
|
|
|
(*plog) << '.' << str;
|
|
|
|
}
|
2010-11-22 02:23:32 +01:00
|
|
|
|
2021-06-19 20:18:30 +02:00
|
|
|
if( arg )
|
|
|
|
{
|
|
|
|
(*plog) << arg;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( arg2 )
|
|
|
|
{
|
|
|
|
(*plog) << arg2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( arg3 )
|
|
|
|
{
|
|
|
|
(*plog) << arg3;
|
|
|
|
}
|
2010-11-22 02:23:32 +01:00
|
|
|
|
2021-06-19 20:18:30 +02:00
|
|
|
(*plog) << pt::Log::logend;
|
|
|
|
}
|
|
|
|
}
|
2010-11-22 02:23:32 +01:00
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
2010-11-25 23:39:58 +01:00
|
|
|
void Generator<StreamType>::CreateMsg(const std::wstring & type, const std::wstring & arg)
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
2010-11-25 23:39:58 +01:00
|
|
|
CreateMsg(type.c_str(), arg.c_str());
|
2010-11-22 02:23:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
2010-11-25 23:39:58 +01:00
|
|
|
void Generator<StreamType>::CreateMsg(const std::wstring & type)
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
2010-11-25 23:39:58 +01:00
|
|
|
CreateMsg(type.c_str());
|
2010-11-22 02:23:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-10-30 00:50:10 +01:00
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::EvaluateProgramNode(Item & item)
|
|
|
|
{
|
|
|
|
if( output_stream )
|
|
|
|
{
|
|
|
|
if( item.type == Item::item_function )
|
2018-10-30 21:59:17 +01:00
|
|
|
*output_stream << " expression: " << item.text;
|
2018-10-30 00:50:10 +01:00
|
|
|
|
|
|
|
if( item.type == Item::item_if )
|
2018-10-30 21:59:17 +01:00
|
|
|
*output_stream << " if: " << item.text;
|
2018-10-30 00:50:10 +01:00
|
|
|
|
|
|
|
if( item.type == Item::item_for )
|
2018-10-30 21:59:17 +01:00
|
|
|
*output_stream << " for: " << item.text;
|
2018-10-30 00:50:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
last_res = false;
|
|
|
|
|
|
|
|
if( expression_parser )
|
|
|
|
{
|
|
|
|
if( expression_parser->Parse(item.text) )
|
|
|
|
{
|
|
|
|
last_res = expression_parser->LastResultToBool();
|
2018-10-30 21:59:17 +01:00
|
|
|
|
|
|
|
if( output_stream )
|
|
|
|
{
|
|
|
|
*output_stream << " -> " << expression_parser->LastResult();
|
|
|
|
}
|
2018-10-30 00:50:10 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if( output_stream )
|
|
|
|
{
|
2018-10-30 21:59:17 +01:00
|
|
|
*output_stream << " -> syntax error when evaluating expression: error code: " << (int)expression_parser->LastError();
|
2018-10-30 00:50:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-30 21:59:17 +01:00
|
|
|
if( output_stream )
|
|
|
|
{
|
|
|
|
*output_stream << "\n";
|
|
|
|
}
|
2018-10-30 00:50:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-22 02:23:32 +01:00
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::MakeItemText(Item & item)
|
|
|
|
{
|
|
|
|
const wchar_t * start = item.text.c_str();
|
|
|
|
const wchar_t * end = item.text.c_str() + item.text.size();
|
|
|
|
|
|
|
|
if( trim_white )
|
|
|
|
TrimWhite(start, end);
|
|
|
|
|
|
|
|
if( special_chars )
|
|
|
|
PrintSpecialText(start, end);
|
|
|
|
else
|
|
|
|
PrintNormalText(start, end);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::MakeTextContainer(Item & item)
|
|
|
|
{
|
|
|
|
std::vector<Item*>::iterator i = item.item_tab.begin();
|
|
|
|
|
|
|
|
for( ; i != item.item_tab.end() && !break_generating ; ++i )
|
2011-07-15 04:09:40 +02:00
|
|
|
MakeText(**i);
|
2010-11-22 02:23:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::MakeTextNormal(Item & item)
|
|
|
|
{
|
2012-02-24 13:04:36 +01:00
|
|
|
is_generating_normal = true;
|
2013-11-07 11:16:10 +01:00
|
|
|
|
2018-10-30 00:50:10 +01:00
|
|
|
if( program_mode )
|
2013-11-07 11:16:10 +01:00
|
|
|
{
|
2018-10-30 00:50:10 +01:00
|
|
|
EvaluateProgramNode(item);
|
2013-11-07 11:16:10 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-10-30 00:50:10 +01:00
|
|
|
if( output_stream )
|
|
|
|
{
|
2021-05-23 10:02:51 +02:00
|
|
|
Call(item.function, nullptr, *output_stream, false, empty_stream);
|
2018-10-30 00:50:10 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-05-23 10:02:51 +02:00
|
|
|
Call(item.function, nullptr, stream_temp1, false, empty_stream);
|
2018-10-30 00:50:10 +01:00
|
|
|
ClearStream(stream_temp1);
|
|
|
|
}
|
2013-11-07 11:16:10 +01:00
|
|
|
}
|
2010-11-22 02:23:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::MakeTextIf_go(Item & item, bool result)
|
|
|
|
{
|
|
|
|
if( result )
|
|
|
|
{
|
|
|
|
if( item.item_tab.size() > 0 )
|
|
|
|
MakeText( *item.item_tab[0] );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// second element can be (or not -- it's from [else])
|
|
|
|
if( item.item_tab.size() > 1 )
|
|
|
|
MakeText( *item.item_tab[1] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::MakeTextIf(Item & item)
|
|
|
|
{
|
2012-02-24 13:04:36 +01:00
|
|
|
is_generating_if = true;
|
|
|
|
|
2018-10-30 00:50:10 +01:00
|
|
|
if( program_mode )
|
|
|
|
{
|
|
|
|
EvaluateProgramNode(item);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if( !Call(item.function) )
|
|
|
|
return;
|
|
|
|
}
|
2010-11-22 02:23:32 +01:00
|
|
|
|
2011-04-26 19:17:06 +02:00
|
|
|
MakeTextIf_go(item, last_res);
|
2010-11-22 02:23:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
2014-10-17 23:36:55 +02:00
|
|
|
void Generator<StreamType>::MakeTextFor(Item & item)
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
2012-03-03 21:58:55 +01:00
|
|
|
stack_tab[stack_index-1].is_for = true;
|
|
|
|
|
2012-02-27 18:39:46 +01:00
|
|
|
for( ; !break_generating ; stack_tab[stack_index-1].iter += 1 )
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
2012-02-27 18:39:46 +01:00
|
|
|
if( stack_tab[stack_index-1].iter >= max_for_items )
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
2015-03-08 03:31:21 +01:00
|
|
|
CreateMsg(item.function.name.c_str(),
|
2010-11-22 02:23:32 +01:00
|
|
|
L"function exceeded a limit for a [for] statement");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-01-17 23:57:06 +01:00
|
|
|
// is_generating_for will be changed by next call to MakeText()
|
|
|
|
// so we should set it in each iterations
|
|
|
|
is_generating_for = true;
|
2018-10-30 00:50:10 +01:00
|
|
|
|
|
|
|
if( program_mode )
|
|
|
|
{
|
|
|
|
EvaluateProgramNode(item);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-05-23 10:02:51 +02:00
|
|
|
Call(item.function, nullptr, stream_temp1, true, empty_stream);
|
2018-10-30 00:50:10 +01:00
|
|
|
}
|
2010-11-22 02:23:32 +01:00
|
|
|
|
2011-04-26 19:17:06 +02:00
|
|
|
if( !last_res )
|
2010-11-22 02:23:32 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
if( !item.item_tab.empty() )
|
2018-10-30 00:50:10 +01:00
|
|
|
MakeText( *item.item_tab[0] ); // should be only one item
|
2010-11-22 02:23:32 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
2021-05-23 10:02:51 +02:00
|
|
|
void Generator<StreamType>::MakeTextDefine(Item & item, Var & var)
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
2021-05-23 10:02:51 +02:00
|
|
|
var.str.clear();
|
|
|
|
var.res = ConvertToBool(var.str);
|
|
|
|
var.is_function = false;
|
|
|
|
|
|
|
|
if( item.function.parameters.empty() )
|
2010-11-25 23:39:58 +01:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2015-03-08 03:31:21 +01:00
|
|
|
|
2021-05-23 10:02:51 +02:00
|
|
|
if( item.function.parameters.size() > 1 )
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
2021-05-23 10:02:51 +02:00
|
|
|
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) )
|
2014-10-17 23:36:55 +02:00
|
|
|
{
|
2021-05-23 10:02:51 +02:00
|
|
|
#ifdef EZC_HAS_SPECIAL_STREAM
|
|
|
|
var.str += stream_temp_define.Str();
|
|
|
|
#else
|
|
|
|
var.str += stream_temp_define.str();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
var.res = last_res;
|
2014-10-17 23:36:55 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-05-23 10:02:51 +02:00
|
|
|
CreateMsg(L"[def] unknown function/block/variable", item.function.name);
|
2014-10-17 23:36:55 +02:00
|
|
|
}
|
2010-11-22 02:23:32 +01:00
|
|
|
}
|
2021-05-23 10:02:51 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
var.str = fun.name;
|
|
|
|
var.res = ConvertToBool(fun.name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::MakeTextDefine(Item & item)
|
|
|
|
{
|
|
|
|
if( !can_use_vars || !pvars )
|
|
|
|
{
|
|
|
|
CreateMsg(L"[def] statement not available");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Var & var = (*pvars)[item.function.name];
|
|
|
|
MakeTextDefine(item, var);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::MakeTextDefineIfNotSet(Item & item)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
2010-11-22 02:23:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-05-23 10:02:51 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-22 02:23:32 +01:00
|
|
|
|
|
|
|
|
2011-01-26 13:42:49 +01:00
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::MakeTextFilter(Item & item)
|
|
|
|
{
|
|
|
|
if( filter_index >= filter_tab.size() )
|
|
|
|
{
|
|
|
|
CreateMsg(L"Generator exceeded allowed number of filters");
|
|
|
|
return;
|
|
|
|
}
|
2013-11-07 11:16:10 +01:00
|
|
|
|
2011-01-26 13:42:49 +01:00
|
|
|
StreamType * old_stream = output_stream;
|
|
|
|
output_stream = filter_tab[filter_index];
|
|
|
|
ClearStream(*output_stream);
|
|
|
|
|
|
|
|
filter_index += 1;
|
|
|
|
|
|
|
|
if( !item.item_tab.empty() )
|
|
|
|
MakeText( *item.item_tab[0] ); // should be only one item - item_container
|
|
|
|
|
2012-02-24 13:04:36 +01:00
|
|
|
is_generating_filter = true;
|
2011-01-26 13:42:49 +01:00
|
|
|
|
2013-11-07 11:16:10 +01:00
|
|
|
if( old_stream )
|
|
|
|
{
|
2021-05-23 10:02:51 +02:00
|
|
|
Call(item.function, nullptr, *old_stream, false, *output_stream);
|
2013-11-07 11:16:10 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-05-23 10:02:51 +02:00
|
|
|
Call(item.function, nullptr, stream_temp1, true, *output_stream);
|
2013-11-07 11:16:10 +01:00
|
|
|
ClearStream(stream_temp1);
|
|
|
|
}
|
|
|
|
|
|
|
|
ClearStream(*output_stream);
|
2011-01-26 13:42:49 +01:00
|
|
|
output_stream = old_stream;
|
|
|
|
filter_index -= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-11-07 11:16:10 +01:00
|
|
|
|
2015-11-12 10:53:20 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
2021-05-28 16:10:16 +02:00
|
|
|
although we are using a stack for [etc frame] there is no need for the stack now
|
2015-11-12 10:53:20 +01:00
|
|
|
because the output is only a one-level map (not nested structure)
|
2021-05-20 16:12:41 +02:00
|
|
|
but in the future we can use more complicated class like pt::Space
|
2021-05-28 16:10:16 +02:00
|
|
|
and then nested [ezc frame] statements can product a better output
|
2015-11-12 10:53:20 +01:00
|
|
|
*/
|
2013-11-07 11:16:10 +01:00
|
|
|
template<class StreamType>
|
2021-05-28 16:10:16 +02:00
|
|
|
void Generator<StreamType>::MakeEzcFrame(Item & item)
|
2013-11-07 11:16:10 +01:00
|
|
|
{
|
2015-11-12 10:53:20 +01:00
|
|
|
std::vector<std::wstring*> output_stream_names;
|
|
|
|
StreamType * old_stream;
|
|
|
|
bool stream_added = true;
|
2013-11-07 11:16:10 +01:00
|
|
|
|
2021-05-28 16:10:16 +02:00
|
|
|
if( ezc_frames_stack_index >= ezc_frame_stack_tab.size() )
|
2013-11-07 11:16:10 +01:00
|
|
|
{
|
2021-05-28 16:10:16 +02:00
|
|
|
CreateMsg(L"Generator exceeded allowed number of [ezc frame] statements");
|
2015-11-12 10:53:20 +01:00
|
|
|
return;
|
2013-11-07 11:16:10 +01:00
|
|
|
}
|
|
|
|
|
2015-11-12 10:53:20 +01:00
|
|
|
/*
|
2021-05-28 16:10:16 +02:00
|
|
|
if we encounter the first ezc frame statement without arguments e.g. [ezc frame] or just [frame]
|
2015-11-12 10:53:20 +01:00
|
|
|
then we can simply ignore it
|
|
|
|
*/
|
2021-05-28 16:10:16 +02:00
|
|
|
if( item.function.parameters.empty() && ezc_frames_stack_index == 0 )
|
2015-11-12 10:53:20 +01:00
|
|
|
stream_added = false;
|
|
|
|
|
|
|
|
if( stream_added )
|
2013-11-07 11:16:10 +01:00
|
|
|
{
|
2015-11-12 10:53:20 +01:00
|
|
|
old_stream = output_stream;
|
2021-05-28 16:10:16 +02:00
|
|
|
output_stream = ezc_frame_stack_tab[ezc_frames_stack_index];
|
2015-11-12 10:53:20 +01:00
|
|
|
ClearStream(*output_stream);
|
2021-05-28 16:10:16 +02:00
|
|
|
ezc_frames_stack_index += 1;
|
2013-11-07 11:16:10 +01:00
|
|
|
}
|
2015-11-12 10:53:20 +01:00
|
|
|
|
|
|
|
if( !item.item_tab.empty() )
|
|
|
|
MakeText( *item.item_tab[0] ); // should be only one item - item_container
|
|
|
|
|
|
|
|
if( stream_added )
|
2013-11-07 11:16:10 +01:00
|
|
|
{
|
2015-11-12 10:53:20 +01:00
|
|
|
CopyTmpStreamToOutputStreams(item.function, *output_stream, *old_stream);
|
|
|
|
ClearStream(*output_stream);
|
|
|
|
output_stream = old_stream;
|
2021-05-28 16:10:16 +02:00
|
|
|
ezc_frames_stack_index -= 1;
|
2013-11-07 11:16:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-12 10:53:20 +01:00
|
|
|
|
2013-11-07 11:16:10 +01:00
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::MakeTextEzc(Item & item)
|
|
|
|
{
|
2021-05-28 16:10:16 +02:00
|
|
|
if( item.function.name == L"frame" )
|
|
|
|
MakeEzcFrame(item);
|
2013-11-07 11:16:10 +01:00
|
|
|
|
2015-03-08 03:31:21 +01:00
|
|
|
// in the future we can use more builtin functions
|
2013-11-07 11:16:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-28 18:46:24 +01:00
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::MakeTextReturn(Item & item)
|
|
|
|
{
|
|
|
|
last_res = false;
|
|
|
|
|
|
|
|
if( block_stack_index == 0 )
|
|
|
|
{
|
|
|
|
// the [return] statement is not called from a [block]
|
|
|
|
CreateMsg(L"[return] should be called from a [block]");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockStack & block_stack = block_stack_tab[block_stack_index - 1];
|
|
|
|
block_stack.was_return = true;
|
|
|
|
|
2015-03-08 03:31:21 +01:00
|
|
|
if( item.has_function )
|
2014-10-28 18:46:24 +01:00
|
|
|
{
|
2015-03-08 03:31:21 +01:00
|
|
|
// output stream in [return] statement is ignored (we use only the stream produced by the whole block)
|
2014-10-28 18:46:24 +01:00
|
|
|
// this Call() sets last_res which is used later when we return to CallBlock()
|
2021-05-23 10:02:51 +02:00
|
|
|
Call(item.function, nullptr, stream_temp1, false, empty_stream);
|
2014-10-28 18:46:24 +01:00
|
|
|
ClearStream(stream_temp1);
|
|
|
|
}
|
|
|
|
}
|
2013-11-07 11:16:10 +01:00
|
|
|
|
2014-10-17 23:36:55 +02:00
|
|
|
|
2021-05-23 10:02:51 +02:00
|
|
|
|
|
|
|
|
2010-11-22 02:23:32 +01:00
|
|
|
template<class StreamType>
|
2012-02-27 18:39:46 +01:00
|
|
|
bool Generator<StreamType>::LimitAchieved()
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
|
|
|
if( break_generating )
|
2012-02-27 18:39:46 +01:00
|
|
|
return true;
|
2014-10-28 18:46:24 +01:00
|
|
|
|
|
|
|
if( current_item >= max_items )
|
2010-11-22 02:23:32 +01:00
|
|
|
{
|
|
|
|
break_generating = true;
|
2010-11-25 23:39:58 +01:00
|
|
|
CreateMsg(L"Generator exceeded allowed number of elements");
|
2012-02-27 18:39:46 +01:00
|
|
|
return true;
|
2010-11-22 02:23:32 +01:00
|
|
|
}
|
2014-10-28 18:46:24 +01:00
|
|
|
|
|
|
|
if( stack_index >= stack_tab.size() )
|
2012-02-27 18:39:46 +01:00
|
|
|
{
|
|
|
|
break_generating = true;
|
|
|
|
CreateMsg(L"Generator exceeded the stack size");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-10-28 18:46:24 +01:00
|
|
|
if( block_stack_index > 0 )
|
|
|
|
{
|
|
|
|
BlockStack & block_stack = block_stack_tab[block_stack_index - 1];
|
|
|
|
|
|
|
|
if( block_stack.was_return )
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-02-27 18:39:46 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class StreamType>
|
|
|
|
void Generator<StreamType>::MakeText(Item & item)
|
|
|
|
{
|
|
|
|
if( LimitAchieved() )
|
|
|
|
return;
|
|
|
|
|
2014-10-28 18:46:24 +01:00
|
|
|
current_item += 1;
|
|
|
|
stack_index += 1;
|
2012-02-24 13:04:36 +01:00
|
|
|
is_generating_for = false;
|
|
|
|
is_generating_if = false;
|
|
|
|
is_generating_normal = false;
|
|
|
|
is_generating_filter = false;
|
2012-01-17 23:57:06 +01:00
|
|
|
|
2012-02-27 18:39:46 +01:00
|
|
|
stack_tab[stack_index-1].Clear();
|
2016-04-04 17:53:11 +02:00
|
|
|
stack_tab[stack_index-1].item = &item;
|
2012-02-27 18:39:46 +01:00
|
|
|
|
2021-05-23 10:02:51 +02:00
|
|
|
if ( item.type == Item::item_text ) MakeItemText(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_if ) MakeTextIf(item);
|
|
|
|
else if( item.type == Item::item_def ) MakeTextDefine(item);
|
|
|
|
else if( item.type == Item::item_def_if_not_set ) MakeTextDefineIfNotSet(item);
|
|
|
|
else if( item.type == Item::item_let ) MakeTextLet(item);
|
|
|
|
else if( item.type == Item::item_let_if_not_set ) MakeTextLetIfNotSet(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);
|
2010-11-22 02:23:32 +01:00
|
|
|
else if( item.type == Item::item_err )
|
2010-11-25 23:39:58 +01:00
|
|
|
CreateMsg(L"a wrong directive");
|
2012-02-27 18:39:46 +01:00
|
|
|
|
|
|
|
RemoveStackFunData(stack_tab[stack_index-1]);
|
|
|
|
stack_index -=1;
|
2010-11-22 02:23:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace Ezc
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
2014-11-02 18:26:56 +01:00
|
|
|
|
|
|
|
|