added support for two new ezc statements for clearing/trimming text nodes

[ezc clear_all_white_nodes "yes"]...[end] - will clear a text node if the text consists of only white characters
[ezc trim_text_nodes "yes"]...[end] - will trim text nodes (removes white characters at the beginning and at the end)

"yes" is assumed by default if not present, also "no" can be specified to change the behavior
This commit is contained in:
Tomasz Sowa 2021-06-29 23:38:38 +02:00
parent c2283f70d4
commit acb42f453c
3 changed files with 139 additions and 16 deletions

View File

@ -2441,7 +2441,15 @@ template<class StreamType>
void Generator<StreamType>::MakeTextEzc(Item & item)
{
if( item.function.name == L"frame" )
{
MakeEzcFrame(item);
}
else
if( item.function.name == L"clear_all_white_nodes" || item.function.name == L"trim_text_nodes" )
{
// text nodes are already cleared/trimmed by PatternParser
MakeTextContainer(item);
}
// in the future we can use more builtin functions
}

View File

@ -136,6 +136,30 @@ void PatternParser::SetLogger(pt::Log * log)
}
void PatternParser::InitializeEnvTab()
{
env_tab.clear();
Env env;
env.clear_all_white_nodes = delete_white_text_items;
env_tab.push_back(env);
}
void PatternParser::IncreaseEnvTab()
{
if( env_tab.empty() )
{
InitializeEnvTab();
}
else
{
env_tab.push_back(env_tab.back());
}
}
void PatternParser::ParseFile(const std::string & file_name, Pattern & pattern)
{
ParseFile(file_name.c_str(), pattern);
@ -147,10 +171,13 @@ void PatternParser::ParseFile(const std::string & file_name, Pattern & pattern)
void PatternParser::ParseFile(const char * file_name, Pattern & pattern)
{
pat = &pattern;
pat->Clear();
pt::utf8_to_wide(file_name, pat->item_root.file_name);
include_level = 0;
InitializeEnvTab();
CreateTreeReadIncludeSkipAllowFlag(pat->item_root);
env_tab.clear();
}
@ -167,9 +194,13 @@ void PatternParser::ParseFile(const std::wstring & file_name, Pattern & pattern)
void PatternParser::ParseFile(const wchar_t * file_name, Pattern & pattern)
{
pat = &pattern;
pat->Clear();
pat->item_root.file_name = file_name;
include_level = 0;
InitializeEnvTab();
CreateTreeReadIncludeSkipAllowFlag(pat->item_root);
env_tab.clear();
}
@ -194,11 +225,13 @@ void PatternParser::ParseString(const std::string & str, Pattern & pattern)
void PatternParser::ParseString(const wchar_t * str, Pattern & pattern)
{
pat = &pattern;
pat->Clear();
itext = str;
include_level = 0;
InitializeEnvTab();
pat->item_root.Clear();
CreateTreeContainer(pat->item_root);
env_tab.clear();
}
@ -387,13 +420,7 @@ return *(itext++);
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
if( c==' ' || c=='\t' || c==13 || c==160 || c==10 )
return true;
return false;
return pt::is_white(c, true, true);
}
@ -425,7 +452,7 @@ size_t count = 1;
void PatternParser::CheckWhiteAndDelete(std::wstring & s)
{
size_t i;
if( s.empty() )
return;
@ -851,6 +878,9 @@ void PatternParser::ReadDirectiveFilter(Item & item)
}
void PatternParser::ReadDirectiveEzc(Item & item)
{
item.type = Item::item_ezc;
@ -901,7 +931,53 @@ void PatternParser::ReadDirectiveReturn(Item & item)
}
/*
* returns true if an Env struct has been added to env_tab
*/
bool PatternParser::CheckEnv(Item & item)
{
if( item.function.name == L"clear_all_white_nodes" )
{
IncreaseEnvTab();
env_tab.back().clear_all_white_nodes = CheckEnvIsYesParameter(item);
return true;
}
if( item.function.name == L"trim_text_nodes" )
{
IncreaseEnvTab();
env_tab.back().trim_text_nodes = CheckEnvIsYesParameter(item);
return true;
}
return false;
}
/*
*
* if no parameters are present then we assume the "yes" is by default
*
*/
bool PatternParser::CheckEnvIsYesParameter(Item & item)
{
if( item.function.parameters.size() > 0 && !item.function.parameters[0]->is_function )
{
std::wstring & name = item.function.parameters[0]->name;
if( name == L"yes" || name == L"true" )
{
return true;
}
else
if( name == L"no" || name == L"false" )
{
return false;
}
}
return true;
}
void PatternParser::CreateTreeReadItemDirective(Item & item)
@ -947,8 +1023,20 @@ int c;
while( (c = ReadCharInText()) != -1 )
item.text += static_cast<wchar_t>(c);
if( delete_white_text_items )
CheckWhiteAndDelete(item.text);
if( !env_tab.empty() )
{
Env & env = env_tab.back();
if( env.clear_all_white_nodes )
{
CheckWhiteAndDelete(item.text);
}
if( env.trim_text_nodes )
{
pt::trim_white(item.text, true, true);
}
}
item.type = Item::item_text;
}
@ -1199,7 +1287,7 @@ void PatternParser::CreateTreeReadBlock(Item & item)
void PatternParser::CreateTreeReadFor(Item & item)
void PatternParser::CreateTreeReadOneChild(Item & item)
{
Item * pitem = item.AddItem();
@ -1228,22 +1316,29 @@ bool PatternParser::CreateTree(Item & item)
}
while( item.type == Item::item_comment || item.type == Item::item_block );
bool reduce_env_tab = false;
if(item.type == Item::item_ezc)
reduce_env_tab = CheckEnv(item);
// such container can be read in program mode
if( item.type == Item::item_container )
CreateTreeContainer(item);
if( item.type == Item::item_if )
CreateTreeReadIf(item);
CreateTreeReadIf(item); // reads one child or two if [else] statement is present
// CHECK ME is it correct to check item_filter and item_ezc here and call CreateTreeReadFor?
if( item.type == Item::item_for ||
item.type == Item::item_filter ||
item.type == Item::item_ezc )
CreateTreeReadFor(item);
CreateTreeReadOneChild(item);
if( item.type == Item::item_include )
CreateTreeReadInclude(item);
if( reduce_env_tab && !env_tab.empty() )
env_tab.resize(env_tab.size() - 1);
return true;
}

View File

@ -85,6 +85,21 @@ public:
private:
struct Env
{
bool clear_all_white_nodes;
bool trim_text_nodes;
Env()
{
clear_all_white_nodes = false;
trim_text_nodes = false;
}
};
std::vector<Env> env_tab;
// the output object
Pattern * pat;
@ -130,6 +145,8 @@ private:
pt::Log * log;
void InitializeEnvTab();
void IncreaseEnvTab();
void ReadFile(const std::wstring & name, std::wstring & result);
void ReadFile(const wchar_t * name, std::wstring & result);
@ -175,6 +192,9 @@ private:
void ReadDirectiveReturn(Item & item);
void ReadNormalStatement(Item & item);
bool CheckEnv(Item & item);
bool CheckEnvIsYesParameter(Item & item);
void CreateTreeReadDirectiveExpression(Item & item, bool is_statement);
bool CreateTreeCheckProgramDirective(Item & item);
bool CreateTreeReadExpression(Item & item);
@ -185,7 +205,7 @@ private:
bool CreateTreeReadItem(Item & item);
void CreateTreeReadIf(Item & item);
void CreateTreeReadBlock(Item & item);
void CreateTreeReadFor(Item & item);
void CreateTreeReadOneChild(Item & item);
bool CreateTree(Item & item);
void CreateTreeContainer(Item & item);
void CreateTreeReadInclude(Item & item);