From acb42f453c22728a128a10bd6a2eed2c61c75ba1 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Tue, 29 Jun 2021 23:38:38 +0200 Subject: [PATCH] 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 --- src/generator.h | 8 +++ src/patternparser.cpp | 125 +++++++++++++++++++++++++++++++++++++----- src/patternparser.h | 22 +++++++- 3 files changed, 139 insertions(+), 16 deletions(-) diff --git a/src/generator.h b/src/generator.h index fc5b61a..cecbad6 100644 --- a/src/generator.h +++ b/src/generator.h @@ -2441,7 +2441,15 @@ template void Generator::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 } diff --git a/src/patternparser.cpp b/src/patternparser.cpp index d82b623..7402133 100644 --- a/src/patternparser.cpp +++ b/src/patternparser.cpp @@ -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(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; } diff --git a/src/patternparser.h b/src/patternparser.h index bab52f3..421d1ad 100644 --- a/src/patternparser.h +++ b/src/patternparser.h @@ -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_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);