changed: Pattern class has been split into two classes: Pattern and PatternParser
in Pattern we have only the tree in PatternParser there is the whole logic used to parse a file git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@969 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
parent
fd75a1f119
commit
b5faf171e3
|
@ -21,6 +21,8 @@ endif
|
|||
depend:
|
||||
# we do not use $(additionalinclude) here because the dependencies would be added to the repository
|
||||
# and messes other projects
|
||||
# !! IMPROVE ME
|
||||
# as Ezc is a different project we rather shoudn't use '-I../../pikotools' here?
|
||||
makedepend -Y. -I../../pikotools -f- *.cpp > Makefile.dep
|
||||
echo -n "o = " > Makefile.o.dep
|
||||
ls -1 *.cpp | xargs -I foo echo -n foo " " | sed -E "s/([^\.]*)\.cpp[ ]/\1\.o/g" >> Makefile.o.dep
|
||||
|
|
|
@ -3,4 +3,6 @@
|
|||
item.o: item.h funinfo.h
|
||||
pattern.o: pattern.h item.h funinfo.h functions.h stringconv.h
|
||||
pattern.o: ../../pikotools/utf8/utf8.h
|
||||
patternparser.o: patternparser.h pattern.h item.h funinfo.h functions.h
|
||||
patternparser.o: stringconv.h ../../pikotools/utf8/utf8.h
|
||||
stringconv.o: stringconv.h
|
||||
|
|
|
@ -1 +1 @@
|
|||
o = item.o pattern.o stringconv.o
|
||||
o = item.o pattern.o patternparser.o stringconv.o
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007-2012, Tomasz Sowa
|
||||
* Copyright (c) 2007-2014, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -40,5 +40,6 @@
|
|||
#define headerfile_ezc_ezc
|
||||
|
||||
#include "generator.h"
|
||||
#include "patternparser.h"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007-2013, Tomasz Sowa
|
||||
* Copyright (c) 2007-2014, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -222,6 +222,7 @@ private:
|
|||
const wchar_t * PrintSpecialChar(const wchar_t * start, const wchar_t * end);
|
||||
void PrintSpecialText(const wchar_t * start, const wchar_t * end);
|
||||
void PrintNormalText(const wchar_t * start, const wchar_t * end);
|
||||
bool IsWhite(wchar_t c);
|
||||
void TrimWhite(const wchar_t *& start, const wchar_t *& end);
|
||||
void SkipWhite(const wchar_t *& str);
|
||||
size_t StrToSize(const wchar_t * str, const wchar_t ** str_end = 0);
|
||||
|
@ -886,13 +887,26 @@ void Generator<StreamType>::PrintNormalText(const wchar_t * start, const wchar_t
|
|||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::TrimWhite(const wchar_t *& start, const wchar_t *& end)
|
||||
{
|
||||
while( start != end && pattern->IsWhite(*start) )
|
||||
while( start != end && IsWhite(*start) )
|
||||
++start;
|
||||
|
||||
while( start != end && pattern->IsWhite(*(end-1)) )
|
||||
while( start != end && IsWhite(*(end-1)) )
|
||||
--end;
|
||||
}
|
||||
|
||||
|
@ -900,7 +914,7 @@ void Generator<StreamType>::TrimWhite(const wchar_t *& start, const wchar_t *& e
|
|||
template<class StreamType>
|
||||
void Generator<StreamType>::SkipWhite(const wchar_t *& str)
|
||||
{
|
||||
while( pattern->IsWhite(*str) )
|
||||
while( IsWhite(*str) )
|
||||
str += 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007-2013, Tomasz Sowa
|
||||
* Copyright (c) 2007-2014, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -74,7 +74,7 @@ struct Item
|
|||
Type type;
|
||||
std::wstring text; // used in: item_text
|
||||
std::wstring file_name; // used in: item_include (as a file name)
|
||||
std::vector<Item*> item_tab; // childs
|
||||
std::vector<Item*> item_tab; // childs
|
||||
std::vector<Function> functions;
|
||||
|
||||
Item();
|
||||
|
|
921
src/pattern.cpp
921
src/pattern.cpp
|
@ -35,28 +35,20 @@
|
|||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "pattern.h"
|
||||
|
||||
#include "utf8/utf8.h"
|
||||
|
||||
|
||||
namespace Ezc
|
||||
{
|
||||
|
||||
|
||||
|
||||
Pattern::Pattern()
|
||||
{
|
||||
Clear();
|
||||
|
||||
// !!!!! IMPROVE ME as default there can be empty strings
|
||||
commentary_start = L"<!-- ";
|
||||
commentary_stop = L" -->";
|
||||
|
||||
allow_include = true;
|
||||
input_as_utf8 = true;
|
||||
delete_white_text_items = false;
|
||||
|
||||
include_level_max = 100;
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
|
@ -67,12 +59,14 @@ void Pattern::Clear()
|
|||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ClearCache()
|
||||
{
|
||||
ClearCache(item_root);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ClearCache(Item & item)
|
||||
{
|
||||
for(size_t f = 0; f < item.functions.size() ; ++f)
|
||||
|
@ -84,179 +78,6 @@ void Pattern::ClearCache(Item & item)
|
|||
|
||||
|
||||
|
||||
void Pattern::Directory(const char * dir, const char * dir2)
|
||||
{
|
||||
directory.clear();
|
||||
directory2.clear();
|
||||
|
||||
if( dir )
|
||||
PT::UTF8ToWide(dir, directory);
|
||||
|
||||
if( dir2 )
|
||||
PT::UTF8ToWide(dir2, directory2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::Directory(const std::string & dir)
|
||||
{
|
||||
PT::UTF8ToWide(dir, directory);
|
||||
directory2.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::Directory(const std::string & dir, const std::string & dir2)
|
||||
{
|
||||
PT::UTF8ToWide(dir, directory);
|
||||
PT::UTF8ToWide(dir2, directory2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::Directory(const wchar_t * dir, const wchar_t * dir2)
|
||||
{
|
||||
directory.clear();
|
||||
directory2.clear();
|
||||
|
||||
if( dir )
|
||||
directory = dir;
|
||||
|
||||
if( dir2 )
|
||||
directory2 = dir2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::Directory(const std::wstring & dir)
|
||||
{
|
||||
directory = dir;
|
||||
directory2.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::Directory(const std::wstring & dir, const std::wstring & dir2)
|
||||
{
|
||||
directory = dir;
|
||||
directory2 = dir2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ParseFile(const std::string & file_name)
|
||||
{
|
||||
ParseFile( file_name.c_str() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Pattern::ParseFile(const char * file_name)
|
||||
{
|
||||
PT::UTF8ToWide(file_name, item_root.file_name);
|
||||
include_level = 0;
|
||||
CreateTreeReadIncludeSkipAllowFlag(item_root);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Pattern::ParseFile(const std::wstring & file_name)
|
||||
{
|
||||
ParseFile( file_name.c_str() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Pattern::ParseFile(const wchar_t * file_name)
|
||||
{
|
||||
item_root.file_name = file_name;
|
||||
include_level = 0;
|
||||
CreateTreeReadIncludeSkipAllowFlag(item_root);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Pattern::ParseString(const char * str)
|
||||
{
|
||||
if( input_as_utf8 )
|
||||
PT::UTF8ToWide(str, string_content);
|
||||
else
|
||||
AssignString(str, string_content);
|
||||
|
||||
ParseString(string_content.c_str());
|
||||
string_content.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ParseString(const std::string & str)
|
||||
{
|
||||
ParseString(str.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Pattern::ParseString(const wchar_t * str)
|
||||
{
|
||||
itext = str;
|
||||
include_level = 0;
|
||||
CreateTree(item_root);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ParseString(const std::wstring & str)
|
||||
{
|
||||
ParseString(str.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Pattern::AllowInclude(bool allow)
|
||||
{
|
||||
allow_include = allow;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::DeleteWhiteTextItems(bool del)
|
||||
{
|
||||
delete_white_text_items = del;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::SetIncludeMax(int include_max)
|
||||
{
|
||||
include_level_max = include_max;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::UTF8(bool utf8)
|
||||
{
|
||||
input_as_utf8 = utf8;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Pattern::SetCommentary(const char * com_start, const char * com_stop)
|
||||
{
|
||||
|
@ -311,738 +132,6 @@ void Pattern::CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
bool Pattern::HasFileAtBeginning(const wchar_t * path, const wchar_t * file)
|
||||
{
|
||||
for(; *path && *file; ++path, ++file)
|
||||
{
|
||||
if( *path != *file )
|
||||
return false;
|
||||
}
|
||||
|
||||
if( *file != 0 )
|
||||
return false;
|
||||
|
||||
// "\" is from a dos path syntax
|
||||
if( *path==0 || *path=='\\' || *path=='/' )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
".." is not allowed in the file path
|
||||
you cannot go up from your template directory
|
||||
*/
|
||||
bool Pattern::IsFileCorrect(const wchar_t * name)
|
||||
{
|
||||
while( *name )
|
||||
{
|
||||
if( HasFileAtBeginning(name, L"..") )
|
||||
return false;
|
||||
|
||||
// looking for the next slash of backslash
|
||||
while( *name && *name!='\\' && *name!='/' )
|
||||
name += 1;
|
||||
|
||||
// skipping the slash (or backslash)
|
||||
if( *name )
|
||||
name += 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
'name' must be a relative path - without a slash or backslash
|
||||
*/
|
||||
void Pattern::ReadFile(const std::wstring & name, std::wstring & result)
|
||||
{
|
||||
ReadFile(name.c_str(), result);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
'name' must be a relative path - without a slash or backslash
|
||||
*/
|
||||
void Pattern::ReadFile(const wchar_t * name, std::wstring & result)
|
||||
{
|
||||
if( !IsFileCorrect(name) )
|
||||
{
|
||||
CreateMsg(result, L"incorrect file name: ", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.clear();
|
||||
|
||||
if( !ReadFileFromDir(directory, name, result) )
|
||||
if( !ReadFileFromDir(directory2, name, result) )
|
||||
CreateMsg(result, L"can't open: ", name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Pattern::ReadFileFromDir(const std::wstring & dir, const wchar_t * name, std::wstring & result)
|
||||
{
|
||||
if( dir.empty() )
|
||||
return false;
|
||||
|
||||
file_name = dir;
|
||||
file_name += '/';
|
||||
file_name += name;
|
||||
PT::WideToUTF8(file_name, afile_name);
|
||||
|
||||
std::ifstream file(afile_name.c_str());
|
||||
|
||||
if( !file )
|
||||
{
|
||||
file_name.clear();
|
||||
afile_name.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef EZC_USE_WINIX_LOGGER
|
||||
if( include_level <= 1 )
|
||||
Winix::log << Winix::log3 << "Ezc: reading pattern: " << afile_name << Winix::logend;
|
||||
else
|
||||
Winix::log << Winix::log3 << " including pattern: " << afile_name << Winix::logend;
|
||||
#endif
|
||||
|
||||
ReadFile(file, result);
|
||||
|
||||
file_name.clear();
|
||||
afile_name.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Pattern::ReadFile(std::ifstream & file, std::wstring & result)
|
||||
{
|
||||
if( input_as_utf8 )
|
||||
{
|
||||
PT::UTF8ToWide(file, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadFileContent(file, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Pattern::ReadFileContent(std::ifstream & file, std::wstring & result)
|
||||
{
|
||||
while( true )
|
||||
{
|
||||
int c = file.get();
|
||||
|
||||
if( !file )
|
||||
break;
|
||||
|
||||
result += static_cast<wchar_t>(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int Pattern::ReadCharInText()
|
||||
{
|
||||
if( *itext==0 || *itext=='[' )
|
||||
return -1;
|
||||
|
||||
if( *itext == '\\' )
|
||||
{
|
||||
if( *(itext+1)=='\\' || *(itext+1)=='[' || *(itext+1)==']' )
|
||||
++itext;
|
||||
}
|
||||
|
||||
return *(itext++);
|
||||
}
|
||||
|
||||
|
||||
bool Pattern::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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::SkipWhite()
|
||||
{
|
||||
while( IsWhite(*itext) )
|
||||
++itext;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::CheckWhiteAndDelete(std::wstring & s)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if( s.empty() )
|
||||
return;
|
||||
|
||||
for(i=0 ; i<s.size() && IsWhite(s[i]) ; ++i);
|
||||
|
||||
if( i == s.size() )
|
||||
s.clear(); // the whole string consists of white characters
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Pattern::IsNameChar(wchar_t c)
|
||||
{
|
||||
return ((c>='a' && c<='z') ||
|
||||
(c>='A' && c<='Z') ||
|
||||
(c>='0' && c<='9') ||
|
||||
c=='_' || c=='-' || c=='.' || c=='#');
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Pattern::IsDigit(wchar_t c)
|
||||
{
|
||||
return (c>='0' && c<='9');
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Pattern::IsPositiveNumber(const std::wstring & str)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for(i=0 ; i<str.size() ; ++i)
|
||||
if( !IsDigit(str[i]) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// reading an expression name or a function name
|
||||
bool Pattern::ReadName(std::wstring & name)
|
||||
{
|
||||
name.clear();
|
||||
SkipWhite();
|
||||
|
||||
while( IsNameChar(*itext) )
|
||||
{
|
||||
name += *itext;
|
||||
++itext;
|
||||
}
|
||||
|
||||
return !name.empty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// string can have a quote character (escaped with a backslash) e.g. "sample text \"with quotes\""
|
||||
// use \\ to insert one backslash
|
||||
bool Pattern::ReadString(std::wstring & str)
|
||||
{
|
||||
str.clear();
|
||||
SkipWhite();
|
||||
|
||||
// string is signed by its first quote character (")
|
||||
if( *itext != '\"' )
|
||||
return false;
|
||||
|
||||
++itext;
|
||||
|
||||
while( *itext && *itext!='\"' )
|
||||
{
|
||||
if( itext[0]=='\\' && itext[1]=='\"' )
|
||||
{
|
||||
str += '\"';
|
||||
itext += 2;
|
||||
}
|
||||
else
|
||||
if( itext[0]=='\\' && itext[1]=='\\' )
|
||||
{
|
||||
str += '\\';
|
||||
itext += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
str += *itext;
|
||||
itext += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if( *itext == '\"' )
|
||||
++itext;
|
||||
|
||||
// if there was not a quote at the end we do not report an error
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool Pattern::ReadParams(Item::Function & function)
|
||||
{
|
||||
function.params.clear();
|
||||
|
||||
while( ReadString(temp_param) )
|
||||
function.params.push_back(temp_param);
|
||||
|
||||
temp_param.clear();
|
||||
|
||||
return !function.params.empty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Pattern::ReadFunction(Item::Function & function)
|
||||
{
|
||||
SkipWhite();
|
||||
|
||||
function.name.clear();
|
||||
function.params.clear();
|
||||
|
||||
if( !ReadName(function.name) )
|
||||
return false;
|
||||
|
||||
ReadParams(function);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool Pattern::ReadFunctions(Item & item)
|
||||
{
|
||||
item.functions.clear();
|
||||
|
||||
while( ReadFunction(temp_function) )
|
||||
item.functions.push_back(temp_function);
|
||||
|
||||
temp_function.name.clear();
|
||||
temp_function.params.clear();
|
||||
|
||||
return !item.functions.empty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Pattern::CreateTreeReadItemDirectiveCheckEnding(Item & item)
|
||||
{
|
||||
SkipWhite();
|
||||
|
||||
if( *itext != ']' )
|
||||
{
|
||||
item.type = Item::item_err;
|
||||
|
||||
while( *itext!=0 && *itext!=']' )
|
||||
++itext;
|
||||
}
|
||||
|
||||
if( *itext == ']' )
|
||||
++itext;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveIf(Item & item)
|
||||
{
|
||||
item.type = Item::item_if;
|
||||
ReadFunctions(item);
|
||||
|
||||
if( item.functions.size() != 1 )
|
||||
item.type = Item::item_err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveIfno(Item & item)
|
||||
{
|
||||
item.type = Item::item_ifno;
|
||||
ReadFunctions(item);
|
||||
|
||||
if( item.functions.size() != 1 )
|
||||
item.type = Item::item_err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveIfany(Item & item)
|
||||
{
|
||||
item.type = Item::item_ifany;
|
||||
|
||||
if( !ReadFunctions(item) )
|
||||
item.type = Item::item_err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveIfone(Item & item)
|
||||
{
|
||||
item.type = Item::item_ifone;
|
||||
|
||||
if( !ReadFunctions(item) )
|
||||
item.type = Item::item_err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveIfanyno(Item & item)
|
||||
{
|
||||
item.type = Item::item_ifanyno;
|
||||
|
||||
if( !ReadFunctions(item) )
|
||||
item.type = Item::item_err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveIfoneno(Item & item)
|
||||
{
|
||||
item.type = Item::item_ifoneno;
|
||||
|
||||
if( !ReadFunctions(item) )
|
||||
item.type = Item::item_err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveIs(Item & item)
|
||||
{
|
||||
item.type = Item::item_is;
|
||||
ReadFunctions(item);
|
||||
|
||||
if( item.functions.size() != 2 )
|
||||
item.type = Item::item_err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveIsno(Item & item)
|
||||
{
|
||||
item.type = Item::item_isno;
|
||||
ReadFunctions(item);
|
||||
|
||||
if( item.functions.size() != 2 )
|
||||
item.type = Item::item_err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveIfindex(Item & item)
|
||||
{
|
||||
item.type = Item::item_err;
|
||||
item.functions.clear();
|
||||
temp_function.params.clear();
|
||||
|
||||
// reading: odd, even, first or a number (without quotes)
|
||||
if( !ReadName(temp_function.name) )
|
||||
return;
|
||||
|
||||
if( temp_function.name != L"odd" && temp_function.name != L"even" &&
|
||||
temp_function.name != L"first" && !IsPositiveNumber(temp_function.name) )
|
||||
return;
|
||||
|
||||
item.functions.push_back(temp_function);
|
||||
item.type = Item::item_ifindex;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveFor(Item & item)
|
||||
{
|
||||
item.type = Item::item_for;
|
||||
ReadFunctions(item);
|
||||
|
||||
if( item.functions.size() != 1 )
|
||||
item.type = Item::item_err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveComment(Item & item)
|
||||
{
|
||||
item.type = Item::item_comment;
|
||||
|
||||
// skipping the comment
|
||||
while( *itext && *itext!=']' )
|
||||
++itext;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveInclude(Item & item)
|
||||
{
|
||||
if( ReadString(item.file_name) )
|
||||
item.type = Item::item_include;
|
||||
else
|
||||
item.type = Item::item_err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveDef(Item & item)
|
||||
{
|
||||
item.type = Item::item_err;
|
||||
ReadFunctions(item);
|
||||
|
||||
if( item.functions.size() == 1 )
|
||||
{
|
||||
if( item.functions[0].params.size() == 1 )
|
||||
{
|
||||
// this is: [def variable "value"]
|
||||
item.type = Item::item_def;
|
||||
}
|
||||
}
|
||||
else
|
||||
if( item.functions.size() == 2 )
|
||||
{
|
||||
if( item.functions[0].params.empty() && item.functions[1].params.empty())
|
||||
{
|
||||
// this is:
|
||||
// [def variable2 variable1], or
|
||||
// [def function2 function1]
|
||||
item.type = Item::item_def;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveFilter(Item & item)
|
||||
{
|
||||
item.type = Item::item_filter;
|
||||
ReadFunctions(item);
|
||||
|
||||
if( item.functions.size() != 1 )
|
||||
item.type = Item::item_err;
|
||||
}
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveEzc(Item & item)
|
||||
{
|
||||
item.type = Item::item_ezc;
|
||||
ReadFunctions(item);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// user defined directive
|
||||
void Pattern::ReadDirectiveNormal(const std::wstring & name, Item & item)
|
||||
{
|
||||
temp_function.name = name;
|
||||
ReadParams(temp_function);
|
||||
item.functions.clear();
|
||||
item.functions.push_back(temp_function);
|
||||
item.type = Item::item_normal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::CreateTreeReadItemDirective(Item & item)
|
||||
{
|
||||
std::wstring name;
|
||||
|
||||
++itext;
|
||||
ReadName(name);
|
||||
|
||||
if ( name == L"if" ) ReadDirectiveIf(item);
|
||||
else if( name == L"if-no" ) ReadDirectiveIfno(item);
|
||||
else if( name == L"if-any" ) ReadDirectiveIfany(item);
|
||||
else if( name == L"if-one" ) ReadDirectiveIfone(item);
|
||||
else if( name == L"if-any-no" ) ReadDirectiveIfanyno(item);
|
||||
else if( name == L"if-one-no" ) ReadDirectiveIfoneno(item);
|
||||
else if( name == L"if-index" ) ReadDirectiveIfindex(item);
|
||||
else if( name == L"is" ) ReadDirectiveIs(item);
|
||||
else if( name == L"is-no" ) ReadDirectiveIsno(item);
|
||||
else if( name == L"end" ) item.type = Item::item_end;
|
||||
else if( name == L"else" ) item.type = Item::item_else;
|
||||
else if( name == L"for" ) ReadDirectiveFor(item);
|
||||
else if( name == L"include" ) ReadDirectiveInclude(item);
|
||||
else if( name == L"def" ) ReadDirectiveDef(item);
|
||||
else if( name == L"filter" ) ReadDirectiveFilter(item);
|
||||
else if( name == L"ezc" ) ReadDirectiveEzc(item);
|
||||
else if( name == L"#" ) ReadDirectiveComment(item);
|
||||
else
|
||||
ReadDirectiveNormal(name, item);
|
||||
|
||||
CreateTreeReadItemDirectiveCheckEnding(item);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::CreateTreeReadItemText(Item & item)
|
||||
{
|
||||
int c;
|
||||
|
||||
while( (c = ReadCharInText()) != -1 )
|
||||
item.text += static_cast<wchar_t>(c);
|
||||
|
||||
if( delete_white_text_items )
|
||||
CheckWhiteAndDelete(item.text);
|
||||
|
||||
item.type = Item::item_text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Pattern::CreateTreeReadItem(Item & item)
|
||||
{
|
||||
item.Clear();
|
||||
|
||||
if( *itext == '[' )
|
||||
{
|
||||
CreateTreeReadItemDirective(item);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if( *itext )
|
||||
{
|
||||
CreateTreeReadItemText(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
// the end of the string
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Pattern::CreateTreeReadInclude(Item & item)
|
||||
{
|
||||
if( !allow_include )
|
||||
return;
|
||||
|
||||
CreateTreeReadIncludeSkipAllowFlag(item);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Pattern::CreateTreeReadIncludeSkipAllowFlag(Item & item)
|
||||
{
|
||||
if( item.file_name.empty() )
|
||||
return;
|
||||
|
||||
if( include_level > include_level_max )
|
||||
{
|
||||
#ifdef EZC_USE_WINIX_LOGGER
|
||||
Winix::log << Winix::log1 << "Ezc: \"include\" directive has reached the maximum level" << Winix::logend;
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
++include_level;
|
||||
std::wstring file_text; // this temporary object must not be global (includes can be nested)
|
||||
ReadFile(item.file_name, file_text);
|
||||
|
||||
const wchar_t * itext_old = itext;
|
||||
itext = file_text.c_str();
|
||||
CreateTree(item);
|
||||
itext = itext_old;
|
||||
--include_level;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::CreateTreeReadIf(Item & item)
|
||||
{
|
||||
Item * pitem = item.AddItem();
|
||||
CreateTree(*pitem);
|
||||
|
||||
if( pitem->LastItemType() == Item::item_else )
|
||||
{
|
||||
pitem->DeleteLastItem();
|
||||
|
||||
pitem = item.AddItem();
|
||||
CreateTree(*pitem);
|
||||
}
|
||||
|
||||
if( pitem->LastItemType() == Item::item_end )
|
||||
pitem->DeleteLastItem();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::CreateTreeReadFor(Item & item)
|
||||
{
|
||||
Item * pitem = item.AddItem();
|
||||
CreateTree(*pitem);
|
||||
|
||||
if( pitem->LastItemType() == Item::item_end )
|
||||
pitem->DeleteLastItem();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::CreateTree(Item & item)
|
||||
{
|
||||
item.Clear();
|
||||
item.type = Item::item_container;
|
||||
|
||||
while( true )
|
||||
{
|
||||
Item * pitem = item.AddItem();
|
||||
|
||||
do
|
||||
{
|
||||
if( !CreateTreeReadItem(*pitem) )
|
||||
{
|
||||
item.DeleteLastItem();
|
||||
return;
|
||||
}
|
||||
}
|
||||
while( pitem->type == Item::item_comment );
|
||||
|
||||
if( pitem->type == Item::item_end || pitem->type == Item::item_else )
|
||||
return;
|
||||
|
||||
if( pitem->type == Item::item_if ||
|
||||
pitem->type == Item::item_ifno ||
|
||||
pitem->type == Item::item_ifany ||
|
||||
pitem->type == Item::item_ifone ||
|
||||
pitem->type == Item::item_ifanyno ||
|
||||
pitem->type == Item::item_ifoneno ||
|
||||
pitem->type == Item::item_ifindex ||
|
||||
pitem->type == Item::item_is ||
|
||||
pitem->type == Item::item_isno )
|
||||
CreateTreeReadIf(*pitem);
|
||||
|
||||
if( pitem->type == Item::item_for ||
|
||||
pitem->type == Item::item_filter )
|
||||
CreateTreeReadFor(*pitem);
|
||||
|
||||
if( pitem->type == Item::item_include )
|
||||
CreateTreeReadInclude(*pitem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace Ezc
|
||||
|
||||
|
||||
|
|
156
src/pattern.h
156
src/pattern.h
|
@ -42,12 +42,6 @@
|
|||
#include <string>
|
||||
#include "item.h"
|
||||
#include "functions.h"
|
||||
#include "stringconv.h"
|
||||
#include "utf8/utf8.h"
|
||||
|
||||
#ifdef EZC_USE_WINIX_LOGGER
|
||||
#include "core/log.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace Ezc
|
||||
|
@ -60,52 +54,8 @@ public:
|
|||
|
||||
Pattern();
|
||||
|
||||
/*!
|
||||
clearing only the tree
|
||||
*/
|
||||
void Clear();
|
||||
|
||||
|
||||
// first we're trying to read a file from directory dir
|
||||
// if there is no such a file there then we try read from dir2
|
||||
// (the second dir2 can be empty - it will not be used)
|
||||
void Directory(const char * dir, const char * dir2 = 0);
|
||||
void Directory(const std::string & dir);
|
||||
void Directory(const std::string & dir, const std::string & dir2);
|
||||
|
||||
void Directory(const wchar_t * dir, const wchar_t * dir2 = 0);
|
||||
void Directory(const std::wstring & dir);
|
||||
void Directory(const std::wstring & dir, const std::wstring & dir2);
|
||||
|
||||
void ParseFile(const char * file_name);
|
||||
void ParseFile(const std::string & file_name);
|
||||
|
||||
void ParseFile(const wchar_t * file_name);
|
||||
void ParseFile(const std::wstring & file_name);
|
||||
|
||||
|
||||
void ParseString(const char * str);
|
||||
void ParseString(const std::string & str);
|
||||
void ParseString(const wchar_t * str);
|
||||
void ParseString(const std::wstring & str);
|
||||
|
||||
void AllowInclude(bool allow);
|
||||
void DeleteWhiteTextItems(bool del);
|
||||
void SetIncludeMax(int include_max);
|
||||
|
||||
// files and strings (only char* and std::string) are treated
|
||||
// as UTF-8
|
||||
void UTF8(bool utf8);
|
||||
|
||||
void SetCommentary(const char * com_start, const char * com_stop);
|
||||
void SetCommentary(const std::string & com_start, const std::string & com_stop);
|
||||
void SetCommentary(const wchar_t * com_start, const wchar_t * com_stop);
|
||||
void SetCommentary(const std::wstring & com_start, const std::wstring & com_stop);
|
||||
|
||||
void CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t * arg = 0);
|
||||
static bool IsWhite(wchar_t c);
|
||||
|
||||
Item item_root;
|
||||
void ClearCache();
|
||||
|
||||
template<class StreamType>
|
||||
void CacheFunctions(Functions<StreamType> & fun)
|
||||
|
@ -113,107 +63,23 @@ public:
|
|||
CacheFunctions(item_root, fun);
|
||||
}
|
||||
|
||||
void ClearCache();
|
||||
void SetCommentary(const char * com_start, const char * com_stop);
|
||||
void SetCommentary(const std::string & com_start, const std::string & com_stop);
|
||||
void SetCommentary(const wchar_t * com_start, const wchar_t * com_stop);
|
||||
void SetCommentary(const std::wstring & com_start, const std::wstring & com_stop);
|
||||
|
||||
void CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t * arg = 0);
|
||||
|
||||
|
||||
Item item_root;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// the main pointer to the parsed text
|
||||
const wchar_t * itext;
|
||||
|
||||
|
||||
// allowing include tag
|
||||
// default: true
|
||||
bool allow_include;
|
||||
|
||||
// if true all text-items which have only white characters (with new lines as well)
|
||||
// will be deleted - useful in *.txt templates
|
||||
// this not actually delete the whole item but only the string
|
||||
// the item will be present with an empty string
|
||||
// default: false
|
||||
bool delete_white_text_items;
|
||||
|
||||
// first we're trying to read a file from 'directory'
|
||||
// if there is no such a file there then we try read from 'directory2'
|
||||
// we read from these directories only if they are not empty
|
||||
std::wstring directory, directory2;
|
||||
|
||||
|
||||
bool input_as_utf8;
|
||||
|
||||
int include_level, include_level_max;
|
||||
|
||||
|
||||
|
||||
std::wstring commentary_start, commentary_stop;
|
||||
|
||||
|
||||
// temporary content for ParseString(const char*) method
|
||||
std::wstring string_content;
|
||||
|
||||
// temporary object for a file name
|
||||
std::wstring file_name;
|
||||
|
||||
// temporary object for a file name
|
||||
std::string afile_name;
|
||||
|
||||
// temporary object for a EZC function's parameter
|
||||
std::wstring temp_param;
|
||||
|
||||
// temporary object for a EZC function
|
||||
Item::Function temp_function;
|
||||
|
||||
|
||||
|
||||
void ReadFile(const std::wstring & name, std::wstring & result);
|
||||
void ReadFile(const wchar_t * name, std::wstring & result);
|
||||
bool HasFileAtBeginning(const wchar_t * path, const wchar_t * file);
|
||||
bool IsFileCorrect(const wchar_t * name);
|
||||
bool ReadFileFromDir(const std::wstring & dir, const wchar_t * name, std::wstring & result);
|
||||
void ReadFile(std::ifstream & file, std::wstring & result);
|
||||
void ReadFileContent(std::ifstream & file, std::wstring & result);
|
||||
|
||||
int ReadCharInText();
|
||||
void SkipWhite();
|
||||
void CheckWhiteAndDelete(std::wstring & s);
|
||||
|
||||
bool IsNameChar(wchar_t c);
|
||||
bool IsDigit(wchar_t c);
|
||||
bool IsPositiveNumber(const std::wstring & str);
|
||||
|
||||
bool ReadName(std::wstring & name);
|
||||
bool ReadString(std::wstring & str);
|
||||
bool ReadParams(Item::Function & function);
|
||||
bool ReadFunction(Item::Function & function);
|
||||
bool ReadFunctions(Item & item);
|
||||
|
||||
void ReadDirectiveIf(Item & item);
|
||||
void ReadDirectiveIfno(Item & item);
|
||||
void ReadDirectiveIfany(Item & item);
|
||||
void ReadDirectiveIfone(Item & item);
|
||||
void ReadDirectiveIfanyno(Item & item);
|
||||
void ReadDirectiveIfoneno(Item & item);
|
||||
void ReadDirectiveIs(Item & item);
|
||||
void ReadDirectiveIsno(Item & item);
|
||||
void ReadDirectiveIfindex(Item & item);
|
||||
void ReadDirectiveFor(Item & item);
|
||||
void ReadDirectiveComment(Item & item);
|
||||
void ReadDirectiveInclude(Item & item);
|
||||
void ReadDirectiveDef(Item & item);
|
||||
void ReadDirectiveFilter(Item & item);
|
||||
void ReadDirectiveEzc(Item & item);
|
||||
void ReadDirectiveNormal(const std::wstring & name, Item & item);
|
||||
|
||||
void CreateTreeReadItemDirectiveCheckEnding(Item & item);
|
||||
void CreateTreeReadItemDirective(Item & item);
|
||||
void CreateTreeReadItemText(Item & item);
|
||||
bool CreateTreeReadItem(Item & item);
|
||||
void CreateTreeReadIf(Item & item);
|
||||
void CreateTreeReadFor(Item & item);
|
||||
void CreateTree(Item & item);
|
||||
void CreateTreeReadInclude(Item & item);
|
||||
void CreateTreeReadIncludeSkipAllowFlag(Item & item);
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void CacheFunctions(Item & item, Functions<StreamType> & fun)
|
||||
{
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
*/
|
||||
|
||||
|
||||
#include "pattern.h"
|
||||
#include "patternparser.h"
|
||||
|
||||
|
||||
|
||||
|
@ -45,13 +45,8 @@ namespace Ezc
|
|||
|
||||
|
||||
|
||||
Pattern::Pattern()
|
||||
PatternParser::PatternParser()
|
||||
{
|
||||
Clear();
|
||||
|
||||
commentary_start = L"<!-- ";
|
||||
commentary_stop = L" -->";
|
||||
|
||||
allow_include = true;
|
||||
input_as_utf8 = true;
|
||||
delete_white_text_items = false;
|
||||
|
@ -61,30 +56,7 @@ Pattern::Pattern()
|
|||
|
||||
|
||||
|
||||
void Pattern::Clear()
|
||||
{
|
||||
item_root.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]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::Directory(const char * dir, const char * dir2)
|
||||
void PatternParser::Directory(const char * dir, const char * dir2)
|
||||
{
|
||||
directory.clear();
|
||||
directory2.clear();
|
||||
|
@ -98,7 +70,7 @@ void Pattern::Directory(const char * dir, const char * dir2)
|
|||
|
||||
|
||||
|
||||
void Pattern::Directory(const std::string & dir)
|
||||
void PatternParser::Directory(const std::string & dir)
|
||||
{
|
||||
PT::UTF8ToWide(dir, directory);
|
||||
directory2.clear();
|
||||
|
@ -106,7 +78,7 @@ void Pattern::Directory(const std::string & dir)
|
|||
|
||||
|
||||
|
||||
void Pattern::Directory(const std::string & dir, const std::string & dir2)
|
||||
void PatternParser::Directory(const std::string & dir, const std::string & dir2)
|
||||
{
|
||||
PT::UTF8ToWide(dir, directory);
|
||||
PT::UTF8ToWide(dir2, directory2);
|
||||
|
@ -114,7 +86,7 @@ void Pattern::Directory(const std::string & dir, const std::string & dir2)
|
|||
|
||||
|
||||
|
||||
void Pattern::Directory(const wchar_t * dir, const wchar_t * dir2)
|
||||
void PatternParser::Directory(const wchar_t * dir, const wchar_t * dir2)
|
||||
{
|
||||
directory.clear();
|
||||
directory2.clear();
|
||||
|
@ -128,7 +100,7 @@ void Pattern::Directory(const wchar_t * dir, const wchar_t * dir2)
|
|||
|
||||
|
||||
|
||||
void Pattern::Directory(const std::wstring & dir)
|
||||
void PatternParser::Directory(const std::wstring & dir)
|
||||
{
|
||||
directory = dir;
|
||||
directory2.clear();
|
||||
|
@ -136,7 +108,7 @@ void Pattern::Directory(const std::wstring & dir)
|
|||
|
||||
|
||||
|
||||
void Pattern::Directory(const std::wstring & dir, const std::wstring & dir2)
|
||||
void PatternParser::Directory(const std::wstring & dir, const std::wstring & dir2)
|
||||
{
|
||||
directory = dir;
|
||||
directory2 = dir2;
|
||||
|
@ -144,79 +116,77 @@ void Pattern::Directory(const std::wstring & dir, const std::wstring & dir2)
|
|||
|
||||
|
||||
|
||||
void Pattern::ParseFile(const std::string & file_name)
|
||||
void PatternParser::ParseFile(const std::string & file_name, Pattern & pattern)
|
||||
{
|
||||
ParseFile( file_name.c_str() );
|
||||
ParseFile(file_name.c_str(), pattern);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Pattern::ParseFile(const char * file_name)
|
||||
void PatternParser::ParseFile(const char * file_name, Pattern & pattern)
|
||||
{
|
||||
PT::UTF8ToWide(file_name, item_root.file_name);
|
||||
pat = &pattern;
|
||||
PT::UTF8ToWide(file_name, pat->item_root.file_name);
|
||||
include_level = 0;
|
||||
CreateTreeReadIncludeSkipAllowFlag(item_root);
|
||||
CreateTreeReadIncludeSkipAllowFlag(pat->item_root);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Pattern::ParseFile(const std::wstring & file_name)
|
||||
void PatternParser::ParseFile(const std::wstring & file_name, Pattern & pattern)
|
||||
{
|
||||
ParseFile( file_name.c_str() );
|
||||
ParseFile(file_name.c_str(), pattern);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Pattern::ParseFile(const wchar_t * file_name)
|
||||
void PatternParser::ParseFile(const wchar_t * file_name, Pattern & pattern)
|
||||
{
|
||||
item_root.file_name = file_name;
|
||||
pat = &pattern;
|
||||
pat->item_root.file_name = file_name;
|
||||
include_level = 0;
|
||||
CreateTreeReadIncludeSkipAllowFlag(item_root);
|
||||
CreateTreeReadIncludeSkipAllowFlag(pat->item_root);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Pattern::ParseString(const char * str)
|
||||
void PatternParser::ParseString(const char * str, Pattern & pattern)
|
||||
{
|
||||
if( input_as_utf8 )
|
||||
PT::UTF8ToWide(str, string_content);
|
||||
else
|
||||
AssignString(str, string_content);
|
||||
|
||||
ParseString(string_content.c_str());
|
||||
ParseString(string_content.c_str(), pattern);
|
||||
string_content.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ParseString(const std::string & str)
|
||||
void PatternParser::ParseString(const std::string & str, Pattern & pattern)
|
||||
{
|
||||
ParseString(str.c_str());
|
||||
ParseString(str.c_str(), pattern);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Pattern::ParseString(const wchar_t * str)
|
||||
void PatternParser::ParseString(const wchar_t * str, Pattern & pattern)
|
||||
{
|
||||
pat = &pattern;
|
||||
itext = str;
|
||||
include_level = 0;
|
||||
CreateTree(item_root);
|
||||
CreateTree(pat->item_root);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::ParseString(const std::wstring & str)
|
||||
void PatternParser::ParseString(const std::wstring & str, Pattern & pattern)
|
||||
{
|
||||
ParseString(str.c_str());
|
||||
ParseString(str.c_str(), pattern);
|
||||
}
|
||||
|
||||
|
||||
|
@ -227,28 +197,28 @@ void Pattern::ParseString(const std::wstring & str)
|
|||
|
||||
|
||||
|
||||
void Pattern::AllowInclude(bool allow)
|
||||
void PatternParser::AllowInclude(bool allow)
|
||||
{
|
||||
allow_include = allow;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::DeleteWhiteTextItems(bool del)
|
||||
void PatternParser::DeleteWhiteTextItems(bool del)
|
||||
{
|
||||
delete_white_text_items = del;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::SetIncludeMax(int include_max)
|
||||
void PatternParser::SetIncludeMax(int include_max)
|
||||
{
|
||||
include_level_max = include_max;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::UTF8(bool utf8)
|
||||
void PatternParser::UTF8(bool utf8)
|
||||
{
|
||||
input_as_utf8 = utf8;
|
||||
}
|
||||
|
@ -258,62 +228,11 @@ void Pattern::UTF8(bool utf8)
|
|||
|
||||
|
||||
|
||||
void Pattern::SetCommentary(const char * com_start, const char * com_stop)
|
||||
{
|
||||
PT::UTF8ToWide(com_start, commentary_start);
|
||||
PT::UTF8ToWide(com_stop, commentary_stop);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::SetCommentary(const std::string & com_start, const std::string & com_stop)
|
||||
{
|
||||
PT::UTF8ToWide(com_start, commentary_start);
|
||||
PT::UTF8ToWide(com_stop, commentary_stop);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::SetCommentary(const wchar_t * com_start, const wchar_t * com_stop)
|
||||
{
|
||||
commentary_start = com_start;
|
||||
commentary_stop = com_stop;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Pattern::SetCommentary(const std::wstring & com_start, const std::wstring & com_stop)
|
||||
{
|
||||
commentary_start = com_start;
|
||||
commentary_stop = com_stop;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Pattern::CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t * arg)
|
||||
{
|
||||
out = commentary_start;
|
||||
out += L"Ezc: ";
|
||||
out += type;
|
||||
|
||||
if( arg )
|
||||
{
|
||||
out += ' ';
|
||||
out += arg;
|
||||
}
|
||||
|
||||
out += commentary_stop;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool Pattern::HasFileAtBeginning(const wchar_t * path, const wchar_t * file)
|
||||
bool PatternParser::HasFileAtBeginning(const wchar_t * path, const wchar_t * file)
|
||||
{
|
||||
for(; *path && *file; ++path, ++file)
|
||||
{
|
||||
|
@ -336,7 +255,7 @@ return false;
|
|||
".." is not allowed in the file path
|
||||
you cannot go up from your template directory
|
||||
*/
|
||||
bool Pattern::IsFileCorrect(const wchar_t * name)
|
||||
bool PatternParser::IsFileCorrect(const wchar_t * name)
|
||||
{
|
||||
while( *name )
|
||||
{
|
||||
|
@ -361,7 +280,7 @@ return true;
|
|||
/*
|
||||
'name' must be a relative path - without a slash or backslash
|
||||
*/
|
||||
void Pattern::ReadFile(const std::wstring & name, std::wstring & result)
|
||||
void PatternParser::ReadFile(const std::wstring & name, std::wstring & result)
|
||||
{
|
||||
ReadFile(name.c_str(), result);
|
||||
}
|
||||
|
@ -370,11 +289,11 @@ void Pattern::ReadFile(const std::wstring & name, std::wstring & result)
|
|||
/*
|
||||
'name' must be a relative path - without a slash or backslash
|
||||
*/
|
||||
void Pattern::ReadFile(const wchar_t * name, std::wstring & result)
|
||||
void PatternParser::ReadFile(const wchar_t * name, std::wstring & result)
|
||||
{
|
||||
if( !IsFileCorrect(name) )
|
||||
{
|
||||
CreateMsg(result, L"incorrect file name: ", name);
|
||||
pat->CreateMsg(result, L"incorrect file name: ", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -382,13 +301,13 @@ void Pattern::ReadFile(const wchar_t * name, std::wstring & result)
|
|||
|
||||
if( !ReadFileFromDir(directory, name, result) )
|
||||
if( !ReadFileFromDir(directory2, name, result) )
|
||||
CreateMsg(result, L"can't open: ", name);
|
||||
pat->CreateMsg(result, L"can't open: ", name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Pattern::ReadFileFromDir(const std::wstring & dir, const wchar_t * name, std::wstring & result)
|
||||
bool PatternParser::ReadFileFromDir(const std::wstring & dir, const wchar_t * name, std::wstring & result)
|
||||
{
|
||||
if( dir.empty() )
|
||||
return false;
|
||||
|
@ -425,7 +344,7 @@ return true;
|
|||
|
||||
|
||||
|
||||
void Pattern::ReadFile(std::ifstream & file, std::wstring & result)
|
||||
void PatternParser::ReadFile(std::ifstream & file, std::wstring & result)
|
||||
{
|
||||
if( input_as_utf8 )
|
||||
{
|
||||
|
@ -440,7 +359,7 @@ void Pattern::ReadFile(std::ifstream & file, std::wstring & result)
|
|||
|
||||
|
||||
|
||||
void Pattern::ReadFileContent(std::ifstream & file, std::wstring & result)
|
||||
void PatternParser::ReadFileContent(std::ifstream & file, std::wstring & result)
|
||||
{
|
||||
while( true )
|
||||
{
|
||||
|
@ -456,7 +375,7 @@ void Pattern::ReadFileContent(std::ifstream & file, std::wstring & result)
|
|||
|
||||
|
||||
|
||||
int Pattern::ReadCharInText()
|
||||
int PatternParser::ReadCharInText()
|
||||
{
|
||||
if( *itext==0 || *itext=='[' )
|
||||
return -1;
|
||||
|
@ -471,7 +390,7 @@ return *(itext++);
|
|||
}
|
||||
|
||||
|
||||
bool Pattern::IsWhite(wchar_t c)
|
||||
bool PatternParser::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
|
||||
|
@ -484,7 +403,7 @@ return false;
|
|||
|
||||
|
||||
|
||||
void Pattern::SkipWhite()
|
||||
void PatternParser::SkipWhite()
|
||||
{
|
||||
while( IsWhite(*itext) )
|
||||
++itext;
|
||||
|
@ -492,7 +411,7 @@ void Pattern::SkipWhite()
|
|||
|
||||
|
||||
|
||||
void Pattern::CheckWhiteAndDelete(std::wstring & s)
|
||||
void PatternParser::CheckWhiteAndDelete(std::wstring & s)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
|
@ -507,7 +426,7 @@ size_t i;
|
|||
|
||||
|
||||
|
||||
bool Pattern::IsNameChar(wchar_t c)
|
||||
bool PatternParser::IsNameChar(wchar_t c)
|
||||
{
|
||||
return ((c>='a' && c<='z') ||
|
||||
(c>='A' && c<='Z') ||
|
||||
|
@ -517,14 +436,14 @@ bool Pattern::IsNameChar(wchar_t c)
|
|||
|
||||
|
||||
|
||||
bool Pattern::IsDigit(wchar_t c)
|
||||
bool PatternParser::IsDigit(wchar_t c)
|
||||
{
|
||||
return (c>='0' && c<='9');
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Pattern::IsPositiveNumber(const std::wstring & str)
|
||||
bool PatternParser::IsPositiveNumber(const std::wstring & str)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
|
@ -537,7 +456,7 @@ return true;
|
|||
|
||||
|
||||
// reading an expression name or a function name
|
||||
bool Pattern::ReadName(std::wstring & name)
|
||||
bool PatternParser::ReadName(std::wstring & name)
|
||||
{
|
||||
name.clear();
|
||||
SkipWhite();
|
||||
|
@ -556,7 +475,7 @@ return !name.empty();
|
|||
|
||||
// string can have a quote character (escaped with a backslash) e.g. "sample text \"with quotes\""
|
||||
// use \\ to insert one backslash
|
||||
bool Pattern::ReadString(std::wstring & str)
|
||||
bool PatternParser::ReadString(std::wstring & str)
|
||||
{
|
||||
str.clear();
|
||||
SkipWhite();
|
||||
|
@ -598,7 +517,7 @@ return true;
|
|||
|
||||
|
||||
|
||||
bool Pattern::ReadParams(Item::Function & function)
|
||||
bool PatternParser::ReadParams(Item::Function & function)
|
||||
{
|
||||
function.params.clear();
|
||||
|
||||
|
@ -612,7 +531,7 @@ return !function.params.empty();
|
|||
|
||||
|
||||
|
||||
bool Pattern::ReadFunction(Item::Function & function)
|
||||
bool PatternParser::ReadFunction(Item::Function & function)
|
||||
{
|
||||
SkipWhite();
|
||||
|
||||
|
@ -630,7 +549,7 @@ return true;
|
|||
|
||||
|
||||
|
||||
bool Pattern::ReadFunctions(Item & item)
|
||||
bool PatternParser::ReadFunctions(Item & item)
|
||||
{
|
||||
item.functions.clear();
|
||||
|
||||
|
@ -646,7 +565,7 @@ return !item.functions.empty();
|
|||
|
||||
|
||||
|
||||
void Pattern::CreateTreeReadItemDirectiveCheckEnding(Item & item)
|
||||
void PatternParser::CreateTreeReadItemDirectiveCheckEnding(Item & item)
|
||||
{
|
||||
SkipWhite();
|
||||
|
||||
|
@ -664,7 +583,7 @@ void Pattern::CreateTreeReadItemDirectiveCheckEnding(Item & item)
|
|||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveIf(Item & item)
|
||||
void PatternParser::ReadDirectiveIf(Item & item)
|
||||
{
|
||||
item.type = Item::item_if;
|
||||
ReadFunctions(item);
|
||||
|
@ -675,7 +594,7 @@ void Pattern::ReadDirectiveIf(Item & item)
|
|||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveIfno(Item & item)
|
||||
void PatternParser::ReadDirectiveIfno(Item & item)
|
||||
{
|
||||
item.type = Item::item_ifno;
|
||||
ReadFunctions(item);
|
||||
|
@ -686,7 +605,7 @@ void Pattern::ReadDirectiveIfno(Item & item)
|
|||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveIfany(Item & item)
|
||||
void PatternParser::ReadDirectiveIfany(Item & item)
|
||||
{
|
||||
item.type = Item::item_ifany;
|
||||
|
||||
|
@ -696,7 +615,7 @@ void Pattern::ReadDirectiveIfany(Item & item)
|
|||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveIfone(Item & item)
|
||||
void PatternParser::ReadDirectiveIfone(Item & item)
|
||||
{
|
||||
item.type = Item::item_ifone;
|
||||
|
||||
|
@ -706,7 +625,7 @@ void Pattern::ReadDirectiveIfone(Item & item)
|
|||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveIfanyno(Item & item)
|
||||
void PatternParser::ReadDirectiveIfanyno(Item & item)
|
||||
{
|
||||
item.type = Item::item_ifanyno;
|
||||
|
||||
|
@ -716,7 +635,7 @@ void Pattern::ReadDirectiveIfanyno(Item & item)
|
|||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveIfoneno(Item & item)
|
||||
void PatternParser::ReadDirectiveIfoneno(Item & item)
|
||||
{
|
||||
item.type = Item::item_ifoneno;
|
||||
|
||||
|
@ -726,7 +645,7 @@ void Pattern::ReadDirectiveIfoneno(Item & item)
|
|||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveIs(Item & item)
|
||||
void PatternParser::ReadDirectiveIs(Item & item)
|
||||
{
|
||||
item.type = Item::item_is;
|
||||
ReadFunctions(item);
|
||||
|
@ -737,7 +656,7 @@ void Pattern::ReadDirectiveIs(Item & item)
|
|||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveIsno(Item & item)
|
||||
void PatternParser::ReadDirectiveIsno(Item & item)
|
||||
{
|
||||
item.type = Item::item_isno;
|
||||
ReadFunctions(item);
|
||||
|
@ -748,7 +667,7 @@ void Pattern::ReadDirectiveIsno(Item & item)
|
|||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveIfindex(Item & item)
|
||||
void PatternParser::ReadDirectiveIfindex(Item & item)
|
||||
{
|
||||
item.type = Item::item_err;
|
||||
item.functions.clear();
|
||||
|
@ -768,7 +687,7 @@ void Pattern::ReadDirectiveIfindex(Item & item)
|
|||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveFor(Item & item)
|
||||
void PatternParser::ReadDirectiveFor(Item & item)
|
||||
{
|
||||
item.type = Item::item_for;
|
||||
ReadFunctions(item);
|
||||
|
@ -779,7 +698,7 @@ void Pattern::ReadDirectiveFor(Item & item)
|
|||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveComment(Item & item)
|
||||
void PatternParser::ReadDirectiveComment(Item & item)
|
||||
{
|
||||
item.type = Item::item_comment;
|
||||
|
||||
|
@ -790,7 +709,7 @@ void Pattern::ReadDirectiveComment(Item & item)
|
|||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveInclude(Item & item)
|
||||
void PatternParser::ReadDirectiveInclude(Item & item)
|
||||
{
|
||||
if( ReadString(item.file_name) )
|
||||
item.type = Item::item_include;
|
||||
|
@ -800,7 +719,7 @@ void Pattern::ReadDirectiveInclude(Item & item)
|
|||
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveDef(Item & item)
|
||||
void PatternParser::ReadDirectiveDef(Item & item)
|
||||
{
|
||||
item.type = Item::item_err;
|
||||
ReadFunctions(item);
|
||||
|
@ -827,7 +746,7 @@ void Pattern::ReadDirectiveDef(Item & item)
|
|||
}
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveFilter(Item & item)
|
||||
void PatternParser::ReadDirectiveFilter(Item & item)
|
||||
{
|
||||
item.type = Item::item_filter;
|
||||
ReadFunctions(item);
|
||||
|
@ -837,7 +756,7 @@ void Pattern::ReadDirectiveFilter(Item & item)
|
|||
}
|
||||
|
||||
|
||||
void Pattern::ReadDirectiveEzc(Item & item)
|
||||
void PatternParser::ReadDirectiveEzc(Item & item)
|
||||
{
|
||||
item.type = Item::item_ezc;
|
||||
ReadFunctions(item);
|
||||
|
@ -846,7 +765,7 @@ void Pattern::ReadDirectiveEzc(Item & item)
|
|||
|
||||
|
||||
// user defined directive
|
||||
void Pattern::ReadDirectiveNormal(const std::wstring & name, Item & item)
|
||||
void PatternParser::ReadDirectiveNormal(const std::wstring & name, Item & item)
|
||||
{
|
||||
temp_function.name = name;
|
||||
ReadParams(temp_function);
|
||||
|
@ -857,7 +776,7 @@ void Pattern::ReadDirectiveNormal(const std::wstring & name, Item & item)
|
|||
|
||||
|
||||
|
||||
void Pattern::CreateTreeReadItemDirective(Item & item)
|
||||
void PatternParser::CreateTreeReadItemDirective(Item & item)
|
||||
{
|
||||
std::wstring name;
|
||||
|
||||
|
@ -889,7 +808,7 @@ std::wstring name;
|
|||
|
||||
|
||||
|
||||
void Pattern::CreateTreeReadItemText(Item & item)
|
||||
void PatternParser::CreateTreeReadItemText(Item & item)
|
||||
{
|
||||
int c;
|
||||
|
||||
|
@ -904,7 +823,7 @@ int c;
|
|||
|
||||
|
||||
|
||||
bool Pattern::CreateTreeReadItem(Item & item)
|
||||
bool PatternParser::CreateTreeReadItem(Item & item)
|
||||
{
|
||||
item.Clear();
|
||||
|
||||
|
@ -928,7 +847,7 @@ return false;
|
|||
|
||||
|
||||
|
||||
void Pattern::CreateTreeReadInclude(Item & item)
|
||||
void PatternParser::CreateTreeReadInclude(Item & item)
|
||||
{
|
||||
if( !allow_include )
|
||||
return;
|
||||
|
@ -939,7 +858,7 @@ void Pattern::CreateTreeReadInclude(Item & item)
|
|||
|
||||
|
||||
|
||||
void Pattern::CreateTreeReadIncludeSkipAllowFlag(Item & item)
|
||||
void PatternParser::CreateTreeReadIncludeSkipAllowFlag(Item & item)
|
||||
{
|
||||
if( item.file_name.empty() )
|
||||
return;
|
||||
|
@ -966,7 +885,7 @@ void Pattern::CreateTreeReadIncludeSkipAllowFlag(Item & item)
|
|||
|
||||
|
||||
|
||||
void Pattern::CreateTreeReadIf(Item & item)
|
||||
void PatternParser::CreateTreeReadIf(Item & item)
|
||||
{
|
||||
Item * pitem = item.AddItem();
|
||||
CreateTree(*pitem);
|
||||
|
@ -985,7 +904,7 @@ void Pattern::CreateTreeReadIf(Item & item)
|
|||
|
||||
|
||||
|
||||
void Pattern::CreateTreeReadFor(Item & item)
|
||||
void PatternParser::CreateTreeReadFor(Item & item)
|
||||
{
|
||||
Item * pitem = item.AddItem();
|
||||
CreateTree(*pitem);
|
||||
|
@ -996,7 +915,7 @@ void Pattern::CreateTreeReadFor(Item & item)
|
|||
|
||||
|
||||
|
||||
void Pattern::CreateTree(Item & item)
|
||||
void PatternParser::CreateTree(Item & item)
|
||||
{
|
||||
item.Clear();
|
||||
item.type = Item::item_container;
|
||||
|
|
|
@ -36,12 +36,10 @@
|
|||
*/
|
||||
|
||||
|
||||
#ifndef headerfile_ezc_pattern
|
||||
#define headerfile_ezc_pattern
|
||||
#ifndef headerfile_ezc_patternparser
|
||||
#define headerfile_ezc_patternparser
|
||||
|
||||
#include <string>
|
||||
#include "item.h"
|
||||
#include "functions.h"
|
||||
#include "pattern.h"
|
||||
#include "stringconv.h"
|
||||
#include "utf8/utf8.h"
|
||||
|
||||
|
@ -54,17 +52,11 @@ namespace Ezc
|
|||
{
|
||||
|
||||
|
||||
class Pattern
|
||||
class PatternParser
|
||||
{
|
||||
public:
|
||||
|
||||
Pattern();
|
||||
|
||||
/*!
|
||||
clearing only the tree
|
||||
*/
|
||||
void Clear();
|
||||
|
||||
PatternParser();
|
||||
|
||||
// first we're trying to read a file from directory dir
|
||||
// if there is no such a file there then we try read from dir2
|
||||
|
@ -77,17 +69,15 @@ public:
|
|||
void Directory(const std::wstring & dir);
|
||||
void Directory(const std::wstring & dir, const std::wstring & dir2);
|
||||
|
||||
void ParseFile(const char * file_name);
|
||||
void ParseFile(const std::string & file_name);
|
||||
void ParseFile(const char * file_name, Pattern & pattern);
|
||||
void ParseFile(const std::string & file_name, Pattern & pattern);
|
||||
void ParseFile(const wchar_t * file_name, Pattern & pattern);
|
||||
void ParseFile(const std::wstring & file_name, Pattern & pattern);
|
||||
|
||||
void ParseFile(const wchar_t * file_name);
|
||||
void ParseFile(const std::wstring & file_name);
|
||||
|
||||
|
||||
void ParseString(const char * str);
|
||||
void ParseString(const std::string & str);
|
||||
void ParseString(const wchar_t * str);
|
||||
void ParseString(const std::wstring & str);
|
||||
void ParseString(const char * str, Pattern & pattern);
|
||||
void ParseString(const std::string & str, Pattern & pattern);
|
||||
void ParseString(const wchar_t * str, Pattern & pattern);
|
||||
void ParseString(const std::wstring & str, Pattern & pattern);
|
||||
|
||||
void AllowInclude(bool allow);
|
||||
void DeleteWhiteTextItems(bool del);
|
||||
|
@ -97,26 +87,13 @@ public:
|
|||
// as UTF-8
|
||||
void UTF8(bool utf8);
|
||||
|
||||
void SetCommentary(const char * com_start, const char * com_stop);
|
||||
void SetCommentary(const std::string & com_start, const std::string & com_stop);
|
||||
void SetCommentary(const wchar_t * com_start, const wchar_t * com_stop);
|
||||
void SetCommentary(const std::wstring & com_start, const std::wstring & com_stop);
|
||||
|
||||
void CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t * arg = 0);
|
||||
static bool IsWhite(wchar_t c);
|
||||
|
||||
Item item_root;
|
||||
|
||||
template<class StreamType>
|
||||
void CacheFunctions(Functions<StreamType> & fun)
|
||||
{
|
||||
CacheFunctions(item_root, fun);
|
||||
}
|
||||
|
||||
void ClearCache();
|
||||
|
||||
private:
|
||||
|
||||
// the output object
|
||||
Pattern * pat;
|
||||
|
||||
// the main pointer to the parsed text
|
||||
const wchar_t * itext;
|
||||
|
||||
|
@ -143,10 +120,6 @@ private:
|
|||
int include_level, include_level_max;
|
||||
|
||||
|
||||
|
||||
std::wstring commentary_start, commentary_stop;
|
||||
|
||||
|
||||
// temporary content for ParseString(const char*) method
|
||||
std::wstring string_content;
|
||||
|
||||
|
@ -173,6 +146,7 @@ private:
|
|||
void ReadFileContent(std::ifstream & file, std::wstring & result);
|
||||
|
||||
int ReadCharInText();
|
||||
bool IsWhite(wchar_t c);
|
||||
void SkipWhite();
|
||||
void CheckWhiteAndDelete(std::wstring & s);
|
||||
|
||||
|
@ -214,39 +188,7 @@ private:
|
|||
void CreateTreeReadIncludeSkipAllowFlag(Item & item);
|
||||
|
||||
|
||||
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 PatternParser
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue