4#include <gtest/gtest.h>
14class MacroTest :
public ::testing::Test {
19 std::vector<std::string> m_postlex;
21 Logger::FuncCallback *m_log_callback_save;
22 void *m_log_callback_arg_save;
25 static void LoggerCallback(
void *param,
Logger::LogLevelType level,
const char * str,
bool flush) {
26 MacroTest *p =
static_cast<MacroTest *
> (param);
27 fprintf(stdout,
"%s", str);
37 Logger::Instance()->SaveCallback(m_log_callback_save, m_log_callback_arg_save);
38 Logger::Instance()->SetCallback(&LoggerCallback,
this);
42 Logger::Instance()->SetCallback(m_log_callback_save, m_log_callback_arg_save);
47 ast = Parser::ParseString(str, buffer, &m_postlex, diag);
51 int Count(
TermID token_id) {
53 for (
int c = 0; c < ast->size(); c++) {
54 if ((*ast)[c].second->m_id == token_id) {
61 std::string LexOut() {
63 for (
int i = 0; i < m_postlex.size(); i++) {
224TEST_F(MacroTest, Escape) {
226 ASSERT_TRUE(Parse(
"@\\ {+"));
227 ASSERT_EQ(TermID::ESCAPE, ast->getTermID());
228 EXPECT_STREQ(
"{+", ast->m_text.c_str());
231TEST_F(MacroTest, PredefMacro) {
237 TermPtr term = Term::Create(parser::token_type::MACRO, TermID::MACRO,
"@__NLC_VER__");
245 for (
auto &elem : p.m_predef_macro) {
246 ASSERT_FALSE(elem.first.empty());
247 ASSERT_FALSE(elem.second.empty());
249 term->m_text = elem.first;
250 term->m_id = TermID::MACRO;
251 term->m_lexer_type = parser::token_type::MACRO;
258 ASSERT_TRUE(Parse(
"@__NLC_VER__"));
259 ASSERT_STREQ(std::to_string(
VERSION).c_str(), ast->toString().c_str());
260 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
263 ASSERT_NO_THROW(Parse(
"@__COUNTER__"));
264 ASSERT_STREQ(
"0", ast->toString().c_str());
266 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
268 ASSERT_NO_THROW(Parse(
"@__COUNTER__"));
269 ASSERT_STREQ(
"1", ast->toString().c_str());
270 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
272 ASSERT_NO_THROW(Parse(
"@__COUNTER__"));
273 ASSERT_STREQ(
"2", ast->toString().c_str());
274 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
276 ASSERT_NO_THROW(Parse(
"@__COUNTER__"));
277 ASSERT_STREQ(
"3", ast->toString().c_str());
278 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
281 ASSERT_NO_THROW(Parse(
"@__TIME__"));
282 ASSERT_EQ(10, ast->toString().size()) << ast->toString();
283 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
285 ASSERT_NO_THROW(Parse(
"@__DATE__"));
286 ASSERT_EQ(13, ast->toString().size()) << ast->toString();
287 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
289 ASSERT_NO_THROW(Parse(
"@__TIMESTAMP__"));
290 ASSERT_EQ(26, ast->toString().size()) << ast->toString();
291 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
293 ASSERT_NO_THROW(Parse(
"@__TIMESTAMP_ISO__"));
294 ASSERT_EQ(22, ast->toString().size()) << ast->toString();
295 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
298 ASSERT_NO_THROW(Parse(
"@__LINE__"));
299 ASSERT_STREQ(std::to_string(1).c_str(), ast->toString().c_str());
300 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
302 ASSERT_NO_THROW(Parse(
"\n@__LINE__"));
303 ASSERT_STREQ(std::to_string(2).c_str(), ast->toString().c_str());
304 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
306 ASSERT_NO_THROW(Parse(
"\n\n@__FILE_LINE__"));
307 ASSERT_STREQ(std::to_string(3).c_str(), ast->toString().c_str());
308 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
311 ASSERT_NO_THROW(Parse(
"@__FILE__"));
312 ASSERT_STREQ(
"\"File name undefined!!!\"", ast->toString().c_str());
313 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
315 ASSERT_NO_THROW(Parse(
"@__FILE_NAME__"));
316 ASSERT_STREQ(
"\"File name undefined!!!\"", ast->toString().c_str());
317 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
320 ASSERT_NO_THROW(Parse(
"@__FILE_TIMESTAMP__"));
321 ASSERT_EQ(26, ast->toString().size()) << ast->toString();
322 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
324 ASSERT_NO_THROW(Parse(
"@__FILE_MD5__"));
325 ASSERT_TRUE(ast->toString().size() > 30) << ast->toString();
326 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
329 ASSERT_NO_THROW(Parse(
"@__NLC_SOURCE_GIT__"));
331 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
333 ASSERT_NO_THROW(Parse(
"@__NLC_DATE_BUILD__"));
335 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
337 ASSERT_NO_THROW(Parse(
"@__NLC_SOURCE_BUILD__"));
339 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
343 std::filesystem::create_directories(
"temp");
344 ASSERT_TRUE(std::filesystem::is_directory(
"temp"));
346 std::ofstream out(
"temp/file.md5.test");
347 out <<
"@__LINE__; @__FILE__; @__FILE_TIMESTAMP__; @__FILE_MD5__;";
351 ASSERT_TRUE(ast = p.
ParseFile(
"temp/file.md5.test"))
354 ASSERT_EQ(4, ast->m_block.size()) << ast->toString().c_str();
356 ASSERT_STREQ(
"1", ast->m_block[0]->toString().c_str());
357 ASSERT_EQ(TermID::INTEGER, ast->m_block[0]->getTermID());
359 ASSERT_TRUE(ast->m_block[1]->toString().find(
"temp/file.md5.test\"") != std::string::npos);
360 ASSERT_EQ(TermID::STRWIDE, ast->m_block[1]->getTermID());
362 ASSERT_EQ(26, ast->m_block[2]->toString().size()) << ast->m_block[2]->toString();
363 ASSERT_EQ(TermID::STRWIDE, ast->m_block[2]->getTermID());
365 ASSERT_STREQ(
"\"c3b16159b22333f2b0d1abe7f2960ce0\"", ast->m_block[3]->toString().c_str());
366 ASSERT_EQ(TermID::STRWIDE, ast->m_block[3]->getTermID());
368 std::remove(
"temp/file.md5.test");
372 term->m_text =
"@__NOT_FOUND__";
373 term->m_id = TermID::MACRO;
374 term->m_lexer_type = parser::token_type::MACRO;
384TEST_F(MacroTest, ParseTerm) {
391 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME,
"alias"));
393 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
396 ASSERT_FALSE(term->isCall());
397 ASSERT_STREQ(
"alias", term->toString().c_str());
400 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME,
"alias"));
402 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
405 ASSERT_FALSE(term->isCall());
406 ASSERT_STREQ(
"alias", term->toString().c_str());
408 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME,
"second"));
410 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
413 ASSERT_FALSE(term->isCall());
414 ASSERT_STREQ(
"alias", term->toString().c_str());
416 buff.erase(buff.begin(), buff.begin() + 2);
417 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
"("));
419 ASSERT_ANY_THROW(Parser::ParseTerm(term, buff, 0));
421 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
")"));
423 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
426 ASSERT_TRUE(term->isCall());
427 ASSERT_STREQ(
"second()", term->toString().c_str());
429 buff.erase(buff.end());
431 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME,
"name"));
432 ASSERT_ANY_THROW(Parser::ParseTerm(term, buff, 0));
434 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
")"));
436 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
439 ASSERT_TRUE(term->isCall());
440 ASSERT_STREQ(
"second(name)", term->toString().c_str());
443 buff.erase(buff.end());
444 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
"="));
445 ASSERT_ANY_THROW(Parser::ParseTerm(term, buff, 0));
447 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME,
"value"));
448 ASSERT_ANY_THROW(Parser::ParseTerm(term, buff, 0));
450 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
")"));
452 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
455 ASSERT_TRUE(term->isCall());
456 ASSERT_EQ(1, term->size());
457 ASSERT_STREQ(
"name", term->name(0).c_str());
458 ASSERT_STREQ(
"second(name=value)", term->toString().c_str());
461 buff = Scanner::ParseLexem(
"second2 ( 1 , ( 123 , ) );\n\n\n\n;");
463 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
466 ASSERT_TRUE(term->isCall());
467 ASSERT_EQ(2, term->size());
468 ASSERT_STREQ(
"1", term->at(0).second->toString().c_str());
469 ASSERT_STREQ(
"(123,)", term->at(1).second->toString().c_str());
470 ASSERT_STREQ(
"second2(1, (123,))", term->toString().c_str());
474TEST_F(MacroTest, Pragma) {
478 ASSERT_NO_THROW(Parse(
"; 100",
nullptr,
nullptr)) << LexOut().c_str();
479 ASSERT_NO_THROW(Parse(
"; ; ; ; 100; ",
nullptr,
nullptr)) << LexOut().c_str();
480 ASSERT_NO_THROW(Parse(
"@__PRAGMA_LOCATION__(9) @__PRAGMA_LOCATION__(100) @__LINE__",
nullptr,
nullptr)) << LexOut().c_str();
481 ASSERT_NO_THROW(Parse(
"@__PRAGMA_LOCATION__(9); @__PRAGMA_LOCATION__(100); @__LINE__",
nullptr,
nullptr)) << LexOut().c_str();
482 ASSERT_NO_THROW(Parse(
"@__PRAGMA_LOCATION__(9);; @__PRAGMA_LOCATION__(100);; @__LINE__;",
nullptr,
nullptr)) << LexOut().c_str();
483 ASSERT_NO_THROW(Parse(
"@__PRAGMA_LOCATION__(9);;; @__PRAGMA_LOCATION__(100);;; @__LINE__;;",
nullptr,
nullptr)) << LexOut().c_str();
593 ASSERT_NO_THROW(Parse(
"@__PRAGMA_LOCATION__(9) @__PRAGMA_LOCATION__(100) @__LINE__",
nullptr, diag)) << LexOut().c_str();
594 ASSERT_STREQ(
"100", LexOut().c_str());
597 ASSERT_NO_THROW(Parse(
"@__PRAGMA_LOCATION__(99, 'file_name.test') @__LINE__; @__FILE__",
nullptr, diag)) << LexOut().c_str();
598 ASSERT_STREQ(
"99 ; file_name.test", LexOut().c_str());
601 ASSERT_NO_THROW(Parse(
"@__PRAGMA_LOCATION__(push) @__PRAGMA_LOCATION__(42) @__LINE__; @__PRAGMA_LOCATION__(pop) @__LINE__",
nullptr, diag));
602 ASSERT_STREQ(
"42 ; 1", LexOut().c_str());
605 ASSERT_NO_THROW(Parse(
"@__PRAGMA_LOCATION__(push) @__PRAGMA_LOCATION__(44, 'filename') @__LINE__; @__FILE__; @__PRAGMA_LOCATION__(pop) @__LINE__; @__FILE__",
nullptr, diag));
606 ASSERT_STREQ(
"44 ; filename ; 1 ; File name undefined!!!", LexOut().c_str());
610TEST_F(MacroTest, Annotate) {
613 ASSERT_ANY_THROW(Parse(
"@__ANNOTATION_SET__"));
614 ASSERT_STREQ(
"", LexOut().c_str());
615 ASSERT_TRUE(m_output.find(
"Annotation args in '@__ANNOTATION_SET__' not recognized!") != std::string::npos) << m_output;
619 ASSERT_ANY_THROW(Parse(
"@__ANNOTATION_SET__()"));
620 ASSERT_STREQ(
"", LexOut().c_str());
621 ASSERT_TRUE(m_output.find(
"Annotation args in '@__ANNOTATION_SET__()' not recognized!") != std::string::npos) << m_output;
624 ASSERT_NO_THROW(Parse(
"@__ANNOTATION_SET__(name)"));
625 ASSERT_STREQ(
"", LexOut().c_str());
628 ASSERT_NO_THROW(Parse(
"@__ANNOTATION_SET__(name, \"value\")"));
629 ASSERT_STREQ(
"", LexOut().c_str());
632 ASSERT_NO_THROW(Parse(
"@__ANNOTATION_SET__(name, 1)"));
633 ASSERT_STREQ(
"", LexOut().c_str());
638 ASSERT_ANY_THROW(Parse(
"@__ANNOTATION_IIF__"));
639 ASSERT_STREQ(
"", LexOut().c_str());
640 ASSERT_TRUE(m_output.find(
"Annotation IIF must have three arguments!") != std::string::npos) << m_output;
643 ASSERT_ANY_THROW(Parse(
"@__ANNOTATION_IIF__()"));
644 ASSERT_STREQ(
"", LexOut().c_str());
645 ASSERT_TRUE(m_output.find(
"Annotation IIF must have three arguments!") != std::string::npos) << m_output;
648 ASSERT_ANY_THROW(Parse(
"@__ANNOTATION_IIF__(name)"));
649 ASSERT_STREQ(
"", LexOut().c_str());
650 ASSERT_TRUE(m_output.find(
"Annotation IIF must have three arguments!") != std::string::npos) << m_output;
653 ASSERT_ANY_THROW(Parse(
"@__ANNOTATION_IIF__(name, 1)"));
654 ASSERT_STREQ(
"", LexOut().c_str());
655 ASSERT_TRUE(m_output.find(
"Annotation IIF must have three arguments!") != std::string::npos) << m_output;
659 ASSERT_NO_THROW(Parse(
"@__ANNOTATION_SET__(name, 1) @__ANNOTATION_IIF__(name, 1, 2)"));
660 ASSERT_STREQ(
"1", LexOut().c_str());
667 ASSERT_NO_THROW(Parse(
"@__ANNOTATION_SET__(name, 0) @__ANNOTATION_IIF__(name, 1, 2)"));
668 ASSERT_STREQ(
"2", LexOut().c_str());
671TEST_F(MacroTest, Buffer) {
673 ASSERT_STREQ(
"name", Macro::toMacroHashName(
"name").c_str());
674 ASSERT_STREQ(
"$", Macro::toMacroHashName(
"$name").c_str());
675 ASSERT_STREQ(
"name", Macro::toMacroHashName(
"@name").c_str());
679 MacroPtr macro_buf = std::make_shared<Macro>();
681 ASSERT_FALSE(Macro::IdentityMacro(buffer, term));
683#define CREATE_TERM(type, text) Term::Create(parser::token_type:: type, TermID:: type, text)
685 term = Parse(
"@@ macro @@ := @@ name @@", macro_buf);
687 ASSERT_TRUE(term->isMacro());
688 ASSERT_TRUE(term->Left());
690 buffer.push_back(CREATE_TERM(NAME,
"macro"));
691 ASSERT_TRUE(Macro::IdentityMacro(buffer, term));
694 buffer.push_back(CREATE_TERM(NAME,
"macro2"));
695 ASSERT_TRUE(Macro::IdentityMacro(buffer, term));
698 term->m_text =
"macro2";
699 ASSERT_TRUE(term->m_macro_id.size());
700 term->m_macro_id[0]->m_text =
"macro2";
701 term->Left()->m_macro_seq[0]->m_text =
"macro2";
702 term->Left()->m_macro_id[0]->m_text =
"macro2";
703 ASSERT_FALSE(Macro::IdentityMacro(buffer, term));
705 ASSERT_EQ(2, buffer.size());
706 buffer.erase(buffer.begin(), buffer.begin() + 1);
707 ASSERT_EQ(1, buffer.size());
708 ASSERT_TRUE(Macro::IdentityMacro(buffer, term));
714 TermPtr hash = Parse(
"@@ name1 name2 @@ := @@ @@", macro_buf);
716 ASSERT_TRUE(hash->isMacro());
717 ASSERT_TRUE(hash->Left());
718 ASSERT_TRUE(hash->Right());
720 ASSERT_STREQ(
"name1", Macro::toMacroHash(hash).c_str());
725 MacroPtr macro = std::make_shared<Macro>();
726 ASSERT_EQ(0, macro->size());
728 ASSERT_TRUE(term = Parse(
"@@alias@@ := alias_name", macro));
729 ASSERT_STREQ(
"@@ alias @@ := alias_name", LexOut().c_str());
731 ASSERT_STREQ(
"@@ alias @@ := alias_name;", term->toString().c_str());
732 ASSERT_TRUE(term->Left()->m_macro_seq[0]);
733 ASSERT_EQ(1, term->Left()->m_macro_seq.size());
734 ASSERT_TRUE(term->Left()->m_macro_seq[0]);
735 ASSERT_STREQ(
"alias", term->Left()->m_macro_seq[0]->toString().c_str());
737 BlockType id = macro->begin()->second[0]->GetMacroId();
738 ASSERT_EQ(1,
id.size()) << macro->begin()->second[0]->toString().c_str();
739 ASSERT_STREQ(
"alias",
id[0]->m_text.c_str());
742 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
743 ASSERT_TRUE(macro->GetMacro({
"alias"})) << macro->Dump();
746 ASSERT_ANY_THROW(Parse(
"@@alias@@ ::= alias_name2;", macro)) << macro->Dump();
747 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
754 ASSERT_TRUE(term = Parse(
"@@alias2@@ := alias_name", macro));
755 ASSERT_EQ(2, macro->GetCount());
756 ASSERT_STREQ(
"@@ alias2 @@ := alias_name", LexOut().c_str());
758 ASSERT_TRUE(term->Left());
759 ASSERT_EQ(1, term->Left()->m_macro_seq.size());
760 ASSERT_TRUE(term->Left()->m_macro_seq[0]);
761 ASSERT_STREQ(
"alias2", term->Left()->m_macro_seq[0]->toString().c_str());
764 ASSERT_ANY_THROW(Parse(
"@@@@ @@@@", macro));
766 ASSERT_TRUE(Parse(
"@@@@alias@@@@", macro));
767 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
768 ASSERT_STREQ(
"@@@@ alias @@@@", LexOut().c_str());
770 ASSERT_TRUE(Parse(
"@@@@_@@@@;", macro));
771 ASSERT_EQ(0, macro->GetCount()) << macro->Dump();
772 ASSERT_STREQ(
"@@@@ _ @@@@ ;", LexOut().c_str());
775 ASSERT_TRUE(term = Parse(
"@@if(args)@@ := @@ [@$args] --> @@", macro));
776 ASSERT_EQ(1, macro->size()) << macro->Dump();
777 ASSERT_STREQ(
"@@ if ( args ) @@ := @@ [ @$args ] --> @@", LexOut().c_str());
779 ASSERT_TRUE(term->Left());
780 ASSERT_EQ(4, term->Left()->m_macro_seq.size());
781 ASSERT_EQ(1, term->GetMacroId().size());
782 ASSERT_STREQ(
"if(args)", term->GetMacroId()[0]->toString().c_str());
785 id = macro->begin()->second[0]->GetMacroId();
786 ASSERT_EQ(1,
id.size()) << macro->begin()->second[0]->toString().c_str();
787 ASSERT_STREQ(
"if",
id[0]->m_text.c_str());
790 ASSERT_TRUE(macro->GetMacro({
"if"})) << macro->Dump();
791 ASSERT_TRUE(macro->GetMacro({
"if"})->Right());
792 ASSERT_EQ(4, macro->GetMacro({
"if"})->Right()->m_macro_seq.size()) << macro->GetMacro({
"if"})->Right()->toString().c_str();
794 ASSERT_TRUE(term = Parse(
"@@if2(...)@@ := @@@ [ @__LINE__ ] --> @@@", macro));
795 ASSERT_STREQ(
"@@ if2 ( ... ) @@ := [ @__LINE__ ] -->", LexOut().c_str());
797 ASSERT_TRUE(term = Parse(
"@@if2(...)@@ := @@ [ @__LINE__ ] --> @@", macro));
798 ASSERT_STREQ(
"@@ if2 ( ... ) @@ := @@ [ @__LINE__ ] --> @@", LexOut().c_str());
801 ASSERT_TRUE(term->Left());
802 ASSERT_EQ(4, term->Left()->m_macro_seq.size());
803 ASSERT_EQ(1, term->m_macro_id.size());
804 ASSERT_EQ(1, term->Left()->m_macro_id.size());
805 ASSERT_TRUE(term->m_macro_id[0]);
806 ASSERT_STREQ(
"if2(...)", term->m_macro_id[0]->toString().c_str());
809 ASSERT_EQ(2, macro->size());
810 ASSERT_TRUE(macro->GetMacro({
"if2"}));
811 ASSERT_TRUE(macro->GetMacro({
"if2"})->Right());
812 ASSERT_STREQ(
"@@ [ @__LINE__ ] --> @@", macro->GetMacro({
"if2"})->Right()->toString().c_str());
817 ASSERT_TRUE(term = Parse(
"@@ func $name(arg= @__LINE__ , ...) @@ := @@@ [ @__LINE__ ] --> @@@", macro));
818 ASSERT_STREQ(
"@@ func $name ( arg = @__LINE__ , ... ) @@ := [ @__LINE__ ] -->", LexOut().c_str());
820 ASSERT_EQ(2, term->m_macro_id.size());
821 ASSERT_TRUE(term->m_macro_id[0]);
822 ASSERT_STREQ(
"func", term->m_macro_id[0]->toString().c_str());
823 ASSERT_TRUE(term->m_macro_id[1]);
824 ASSERT_STREQ(
"$name(arg=1, ...)", term->m_macro_id[1]->toString().c_str());
827 ASSERT_EQ(3, macro->size());
828 ASSERT_TRUE(macro->GetMacro(std::vector<std::string>({
"func",
"$"})));
829 ASSERT_TRUE(macro->GetMacro(std::vector<std::string>({
"func",
"$"}))->Right());
830 ASSERT_STREQ(
"@@@ [ @__LINE__ ] --> @@@", macro->GetMacro(std::vector<std::string>({
"func",
"$"}))->Right()->toString().c_str());
836TEST_F(MacroTest, MacroMacro) {
837 MacroPtr macro = std::make_shared<Macro>();
838 ASSERT_EQ(0, macro->size());
840 ASSERT_TRUE(Parse(
"@@alias replace@@ := @@replace@@", macro));
841 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
842 ASSERT_TRUE(Parse(
"@@alias second@@ := @@second@@", macro));
843 ASSERT_EQ(2, macro->GetCount()) << macro->Dump();
844 ASSERT_TRUE(Parse(
"@@text@@ := @@@text;\n text@@@", macro));
845 ASSERT_EQ(3, macro->GetCount()) << macro->Dump();
846 ASSERT_TRUE(Parse(
"@@dsl@@ := @@@ @@m1@@ := @@mm@@;\n @@m2@@ := @@mm@@;\n@@@", macro));
848 ASSERT_EQ(4, macro->GetCount()) << macro->Dump();
849 ASSERT_TRUE(macro->GetMacro({
"alias",
"replace"}));
850 TermPtr macro_replace = macro->GetMacro({
"alias",
"replace"});
851 ASSERT_TRUE(macro->GetMacro({
"alias",
"second"}));
852 TermPtr macro_second = macro->GetMacro({
"alias",
"second"});
853 ASSERT_TRUE(macro->GetMacro({
"text"}));
854 TermPtr macro_text = macro->GetMacro({
"text"});
855 ASSERT_TRUE(macro->GetMacro({
"dsl"}));
856 TermPtr macro_dsl = macro->GetMacro({
"dsl"});
859 TermPtr term = Term::Create(parser::token_type::NAME, TermID::NAME,
"alias");
861 ASSERT_TRUE(macro->GetMacro({
"alias",
"replace"}));
862 ASSERT_TRUE(macro->GetMacro({
"alias",
"second"}));
866 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace));
867 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
868 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
869 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
872 buff.push_back(term);
874 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace));
875 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
876 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
877 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
879 buff.push_back(term);
881 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace));
882 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
883 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
884 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
886 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME,
"second"));
888 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace));
889 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
890 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
891 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
893 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
"("));
895 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace));
896 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
897 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
898 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
900 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
")"));
902 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace));
903 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
904 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
905 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
907 buff.erase(buff.begin());
909 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace));
910 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_second));
911 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
912 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
920 ASSERT_TRUE(Parse(
"alias replace", macro));
921 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
922 ASSERT_STREQ(
"replace", ast->m_text.c_str());
924 ASSERT_TRUE(Parse(
"alias second", macro));
925 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
926 ASSERT_STREQ(
"second", ast->m_text.c_str());
930 ASSERT_EQ(4, macro->GetCount());
931 ASSERT_FALSE(macro->GetMacro({
"m1"})) << macro->Dump();
932 ASSERT_FALSE(macro->GetMacro({
"m2"})) << macro->Dump();
942TEST_F(MacroTest, Simple) {
943 MacroPtr macro = std::make_shared<Macro>();
944 ASSERT_EQ(0, macro->size());
946 ASSERT_NO_THROW(Parse(
"@@alias@@ ::= @@replace@@", macro));
947 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
949 ASSERT_NO_THROW(Parse(
"@@alias()@@ := @@replace@@", macro));
950 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
952 ASSERT_ANY_THROW(Parse(
"@@alias(...)@@ ::= @@error@@", macro));
953 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
955 ASSERT_NO_THROW(Parse(
"@@second(...)@@ := @@second2(@$#, @$...)@@", macro));
956 ASSERT_EQ(2, macro->GetCount()) << macro->Dump();
958 ASSERT_NO_THROW(Parse(
"@@second@@ := @@second2(@$#, @$*)@@", macro));
959 ASSERT_EQ(2, macro->GetCount()) << macro->Dump();
961 ASSERT_NO_THROW(Parse(
"@@text(...)@@ := @@text1(@$#, @$*)@@", macro));
962 ASSERT_EQ(3, macro->GetCount()) << macro->Dump();
963 ASSERT_NO_THROW(Parse(
"@@dsl@@ := @@@\n @@m1@@ := @@mm@@;\n @@m2@@ := @@mm@@;\n@@@", macro));
965 ASSERT_EQ(4, macro->GetCount()) << macro->Dump();
966 ASSERT_TRUE(macro->GetMacro({
"alias"}));
967 TermPtr macro_alias = macro->GetMacro({
"alias"});
968 ASSERT_TRUE(macro->GetMacro({
"second"}));
969 TermPtr macro_second = macro->GetMacro({
"second"});
970 ASSERT_TRUE(macro->GetMacro({
"text"}));
971 TermPtr macro_text = macro->GetMacro({
"text"});
972 ASSERT_TRUE(macro->GetMacro({
"dsl"}));
973 TermPtr macro_dsl = macro->GetMacro({
"dsl"});
976 TermPtr term = Term::Create(parser::token_type::NAME, TermID::NAME,
"alias");
978 ASSERT_TRUE(macro->GetMacro({
"alias"}));
979 ASSERT_TRUE(macro->GetMacro({
"second"}));
983 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_alias));
984 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
985 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
986 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
989 buff.push_back(term);
991 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
992 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
993 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
994 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
996 buff.push_back(term);
998 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
999 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
1000 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
1001 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
1003 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME,
"second"));
1005 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
1006 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
1007 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
1008 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
1010 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
"("));
1012 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
1013 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
1014 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
1015 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
1017 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME,
"arg"));
1019 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
1020 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
1021 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
1022 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
1024 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
")"));
1026 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
1027 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
1028 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
1029 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
1031 buff.erase(buff.begin());
1033 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
1034 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
1035 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
1036 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
1038 buff.erase(buff.begin());
1040 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_alias));
1041 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_second));
1042 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
1043 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
1046 ASSERT_NO_THROW(Parse(
"@alias", macro));
1047 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
1048 ASSERT_STREQ(
"replace", ast->toString().c_str());
1050 ASSERT_NO_THROW(Parse(
"alias", macro));
1051 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
1052 ASSERT_STREQ(
"replace", ast->m_text.c_str());
1054 ASSERT_NO_THROW(Parse(
"second()", macro));
1055 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
1056 ASSERT_STREQ(
"second2", ast->m_text.c_str());
1058 ASSERT_NO_THROW(Parse(
"@second()", macro));
1059 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
1060 ASSERT_STREQ(
"second2", ast->m_text.c_str());
1063 ASSERT_NO_THROW(Parse(
"second(123)", macro));
1064 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
1065 ASSERT_EQ(2, ast->size()) << LexOut();
1066 ASSERT_STREQ(
"second2(1, (123,))", ast->toString().c_str());
1068 ASSERT_NO_THROW(Parse(
"@second(123, 456)", macro));
1069 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
1070 ASSERT_STREQ(
"second2(2, (123, 456,))", ast->toString().c_str());
1072 ASSERT_ANY_THROW(Parse(
"second", macro));
1073 ASSERT_ANY_THROW(Parse(
"@second", macro));
1088 ASSERT_EQ(4, macro->GetCount());
1089 ASSERT_FALSE(macro->GetMacro({
"m1"})) << macro->Dump();
1090 ASSERT_FALSE(macro->GetMacro({
"m2"})) << macro->Dump();
1217TEST_F(MacroTest, MacroAlias) {
1218 MacroPtr macro = std::make_shared<Macro>();
1219 ASSERT_EQ(0, macro->size());
1221 ASSERT_ANY_THROW(Parse(
"@@@@ macro @@ @@@@"));
1222 ASSERT_ANY_THROW(Parse(
"@@@@ @@ macro @@@@"));
1223 ASSERT_ANY_THROW(Parse(
"@@ macro @@@@ @@"));
1224 ASSERT_ANY_THROW(Parse(
"@@ @@@@ macro @@"));
1225 ASSERT_ANY_THROW(Parse(
"@@ @macro @@"));
1226 ASSERT_ANY_THROW(Parse(
"@@ @$macro @@"));
1228 ASSERT_TRUE(Parse(
"@@@@ alias @@@@", macro));
1229 ASSERT_EQ(0, macro->size());
1230 ASSERT_TRUE(Parse(
"@@@@ alias $alias2 @@@@", macro));
1231 ASSERT_EQ(0, macro->size());
1233 ASSERT_TRUE(Parse(
"@@alias@@ ::= @@replace@@", macro));
1234 ASSERT_TRUE(Parse(
"@@alias2@@ := @@alias@@", macro));
1235 ASSERT_TRUE(Parse(
"@@fail@@ := @@fail@@", macro));
1237 ASSERT_EQ(3, macro->size()) << macro->Dump();
1238 ASSERT_TRUE(macro->GetMacro({
"alias"}));
1239 TermPtr macro_alias = macro->GetMacro({
"alias"});
1240 ASSERT_TRUE(macro_alias);
1241 ASSERT_EQ(TermID::CREATE_ONCE, macro_alias->getTermID()) <<
toString(macro_alias->getTermID());
1242 ASSERT_TRUE(macro_alias->Left());
1243 ASSERT_EQ(TermID::MACRO_SEQ, macro_alias->Left()->getTermID()) <<
toString(macro_alias->Left()->getTermID());
1244 ASSERT_TRUE(macro_alias->Right());
1245 ASSERT_TRUE(macro_alias->Right()->m_macro_seq.size()) << macro_alias->Right()->toString();
1246 ASSERT_STREQ(
"replace", macro_alias->Right()->m_macro_seq[0]->m_text.c_str());
1248 ASSERT_TRUE(macro->GetMacro({
"alias2"})) << macro->Dump();
1249 TermPtr macro_alias2 = macro->GetMacro({
"alias2"});
1250 ASSERT_TRUE(macro_alias2);
1251 ASSERT_TRUE(macro_alias2->isMacro());
1252 ASSERT_EQ(TermID::CREATE_OVERLAP, macro_alias2->getTermID()) <<
toString(macro_alias2->getTermID());
1253 ASSERT_TRUE(macro_alias2->Left());
1254 ASSERT_EQ(TermID::MACRO_SEQ, macro_alias2->Left()->getTermID()) <<
toString(macro_alias2->Left()->getTermID());
1255 ASSERT_STREQ(
"alias", macro_alias2->Right()->m_macro_seq[0]->m_text.c_str());
1257 ASSERT_TRUE(macro->GetMacro({
"fail"})) << macro->Dump();
1258 TermPtr macro_fail = macro->GetMacro({
"fail"});
1259 ASSERT_TRUE(macro_fail);
1260 ASSERT_TRUE(macro_fail->Left());
1261 ASSERT_EQ(TermID::MACRO_SEQ, macro_fail->Left()->getTermID());
1262 ASSERT_STREQ(
"fail", macro_fail->Right()->m_macro_seq[0]->m_text.c_str());
1266 TermPtr term = Term::Create(parser::token_type::NAME, TermID::NAME,
"alias");
1268 ASSERT_TRUE(macro->map::find(term->m_text) != macro->end());
1270 BlockType vals = macro->map::find(term->m_text)->second;
1271 ASSERT_EQ(1, vals.size());
1274 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_alias));
1275 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_alias2));
1276 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_fail));
1279 buff.push_back(term);
1281 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
1282 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_alias2));
1283 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_fail));
1286 term = Term::Create(parser::token_type::NAME, TermID::NAME,
"alias");
1287 buff.push_back(term);
1290 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
1291 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_alias2));
1292 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_fail));
1297 ASSERT_EQ(1, Macro::ExtractArgs(buff, macro_alias, macro_args));
1298 ASSERT_EQ(3, macro_args.size()) << Macro::Dump(macro_args);
1303 ASSERT_ANY_THROW(Macro::ExpandString(macro_alias, macro_args));
1306 block = Macro::ExpandMacros(macro_alias, macro_args);
1307 ASSERT_EQ(1, block.size());
1308 ASSERT_TRUE(block[0]);
1309 ASSERT_STREQ(
"replace", block[0]->m_text.c_str());
1313 ASSERT_EQ(3, macro->size());
1314 for (
auto &elem : *macro) {
1316 LOG_DEBUG(
"Hash: %s", elem.first.c_str());
1319 ASSERT_TRUE(Parse(
"alias", macro));
1320 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
1321 ASSERT_STREQ(
"replace", ast->toString().c_str());
1323 ASSERT_TRUE(Parse(
"alias2", macro));
1324 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
1325 ASSERT_STREQ(
"replace", ast->toString().c_str());
1330TEST_F(MacroTest, MacroArgs) {
1332 MacroPtr macro = std::make_shared<Macro>();
1336 Macro::iterator iter;
1360 ASSERT_EQ(0, macro->GetCount());
1362 ASSERT_NO_THROW(Parse(
"@@alias@@ := @@ replace1 @@", macro)) << macro->Dump();
1363 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
1365 ASSERT_ANY_THROW(Parse(
"@@alias@@ ::= @@replace2@@", macro)) << macro->Dump();
1366 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
1367 ASSERT_NO_THROW(Parse(
"@@alias@@ = @@replace3@@", macro)) << macro->Dump();
1368 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
1370 ASSERT_ANY_THROW(Parse(
"@@alias(arg)@@ ::= @@ replace2(@$arg) @@", macro)) << macro->Dump();
1373 ASSERT_NO_THROW(Parse(
"@@@@ alias @@@@", macro)) << macro->Dump();
1374 ASSERT_EQ(0, macro->GetCount()) << macro->Dump();
1376 ASSERT_NO_THROW(Parse(
"@@alias(arg, ... )@@ := @@ replace2(@$arg) @@", macro)) << macro->Dump();
1377 ASSERT_TRUE(macro->GetMacro({
"alias"}));
1378 ASSERT_STREQ(
"@@ alias ( arg , ... ) @@ := @@ replace2 ( @$arg ) @@;", macro->GetMacro({
"alias"})->toString().c_str());
1380 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
1381 ASSERT_ANY_THROW(Parse(
"@@alias(arg, ... )@@ ::= @@ replace3(@$arg) @@", macro)) << macro->Dump();
1382 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
1384 ASSERT_NO_THROW(Parse(
"@@alias(arg, ... )@@ = @@ replace4(@$arg) @@", macro)) << macro->Dump();
1385 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
1386 ASSERT_TRUE(macro->GetMacro({
"alias"}));
1387 ASSERT_STREQ(
"@@ alias ( arg , ... ) @@ := @@ replace4 ( @$arg ) @@;", macro->GetMacro({
"alias"})->toString().c_str());
1389 ASSERT_NO_THROW(Parse(
"@@alias3(...)@@ := @@replace3(@$#, @$...)@@", macro)) << macro->Dump();
1390 ASSERT_EQ(2, macro->GetCount()) << macro->Dump();
1392 ASSERT_ANY_THROW(Parse(
"@@alias3(...)@@ ::= @@ error double macros@@", macro)) << macro->Dump();
1393 ASSERT_EQ(2, macro->GetCount()) << macro->Dump();
1407 ASSERT_NO_THROW(Parse(
"@@macro(arg, ... )@@ ::= @@@ 3*@$arg @@@", macro)) << macro->Dump();
1408 ASSERT_EQ(3, macro->GetCount()) << macro->Dump();
1410 iter = macro->map::find(
"alias");
1411 ASSERT_TRUE(iter != macro->end());
1413 vect = iter->second;
1415 ASSERT_EQ(1, vect.size());
1417 macro_alias1 = vect[0];
1418 ASSERT_TRUE(macro_alias1);
1419 ASSERT_STREQ(
"@@ alias ( arg , ... ) @@ := @@ replace4 ( @$arg ) @@;", macro_alias1->toString().c_str());
1420 ASSERT_TRUE(macro_alias1->Right());
1421 ASSERT_EQ(4, macro_alias1->Right()->m_macro_seq.size());
1422 ASSERT_STREQ(
"replace4", macro_alias1->Right()->m_macro_seq[0]->m_text.c_str());
1455 iter = macro->map::find(
"macro");
1456 ASSERT_TRUE(iter != macro->end());
1458 vect = iter->second;
1459 ASSERT_EQ(1, vect.size());
1460 TermPtr macro_macro1 = vect[0];
1461 ASSERT_TRUE(macro_macro1);
1462 ASSERT_STREQ(
"@@ macro ( arg , ... ) @@ ::= @@@ 3*@$arg @@@;", macro_macro1->toString().c_str());
1463 ASSERT_EQ(macro_macro1.get(), macro->GetMacro({
"macro"}).get());
1464 ASSERT_TRUE(macro_macro1->Right());
1465 ASSERT_TRUE(macro_macro1->Right()->getTermID() == TermID::MACRO_STR) << macro_macro1->toString().c_str();
1471 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_alias1, macro_args));
1474 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_macro1, macro_args));
1476 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME,
"alias"));
1478 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_alias1, macro_args)) << macro_alias1->toString().c_str();
1482 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_macro1, macro_args)) << macro_macro1->toString().c_str();
1485 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
"("));
1487 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_alias1, macro_args));
1489 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
")"));
1492 ASSERT_NO_THROW(count = Macro::ExtractArgs(buff, macro_alias1, macro_args));
1493 ASSERT_EQ(3, count);
1495 buff.erase(buff.end());
1499 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_macro1, macro_args));
1501 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME,
"value"));
1503 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_alias1, macro_args));
1505 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
")"));
1507 ASSERT_EQ(4, buff.size());
1508 ASSERT_NO_THROW(count = Macro::ExtractArgs(buff, macro_alias1, macro_args)) << Macro::Dump(buff);
1509 ASSERT_EQ(4, count);
1510 buff.erase(buff.end());
1514 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_macro1, macro_args));
1517 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
","));
1522 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_macro1, macro_args));
1525 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME,
"value2"));
1527 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME,
"value3"));
1529 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_macro1, macro_args));
1532 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
")"));
1536 ASSERT_EQ(7, Macro::ExtractArgs(buff, macro_alias1, macro_args));
1538 ASSERT_EQ(6, macro_args.size()) << Macro::Dump(macro_args);
1543 ASSERT_EQ(7, buff.size());
1545 ASSERT_EQ(7, Macro::ExtractArgs(buff, macro_macro1, macro_args));
1547 ASSERT_EQ(6, macro_args.size()) << Macro::Dump(macro_args);
1553 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
";"));
1557 ASSERT_EQ(7, Macro::ExtractArgs(buff, macro_alias1, macro_args));
1560 ASSERT_EQ(6, macro_args.size()) << Macro::Dump(macro_args);
1562 ASSERT_EQ(8, buff.size()) << Macro::Dump(buff);
1564 ASSERT_EQ(7, Macro::ExtractArgs(buff, macro_macro1, macro_args));
1566 ASSERT_EQ(6, macro_args.size()) << Macro::Dump(macro_args);
1605 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME,
"macro"));
1606 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
"("));
1607 buff.push_back(Term::Create(parser::token_type::NUMBER, TermID::NUMBER,
"5"));
1608 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
")"));
1609 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
";"));
1611 TermPtr macro_macro = macro->GetMacro({
"macro"});
1612 ASSERT_TRUE(macro_macro);
1615 ASSERT_EQ(4, Macro::ExtractArgs(buff, macro_macro, macro_args)) << Macro::Dump(macro_args);
1617 ASSERT_EQ(5, macro_args.size()) << Macro::Dump(macro_args);
1619 std::string str = Macro::ExpandString(macro_macro, macro_args);
1620 ASSERT_STREQ(
" 3*5 ", str.c_str());
1624 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME,
"alias3"));
1625 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
"("));
1626 buff.push_back(Term::Create(parser::token_type::NUMBER, TermID::NUMBER,
"5"));
1627 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
")"));
1628 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL,
";"));
1630 TermPtr macro_alias3 = macro->GetMacro({
"alias3"});
1631 ASSERT_TRUE(macro_alias3);
1633 ASSERT_STREQ(
"@@ alias3 ( ... ) @@ := @@ replace3 ( @$# , @$... ) @@;", macro_alias3->toString().c_str());
1634 ASSERT_TRUE(macro_alias3->Right());
1635 ASSERT_EQ(6, macro_alias3->Right()->m_macro_seq.size());
1636 ASSERT_STREQ(
"replace3", macro_alias3->Right()->m_macro_seq[0]->m_text.c_str());
1640 ASSERT_EQ(4, Macro::ExtractArgs(buff, macro_alias3, macro_args)) << Macro::Dump(macro_args);
1642 ASSERT_EQ(4, macro_args.size()) << Macro::Dump(macro_args);
1644 auto iter_arg = macro_args.begin();
1645 ASSERT_TRUE(iter_arg != macro_args.end()) << Macro::Dump(macro_args);
1647 ASSERT_STREQ(
"@$#", iter_arg->first.c_str());
1648 ASSERT_EQ(1, iter_arg->second.size());
1649 ASSERT_STREQ(
"1", iter_arg->second.at(0)->m_text.c_str()) << Macro::Dump(macro_args);
1652 ASSERT_TRUE(iter_arg != macro_args.end());
1654 ASSERT_STREQ(
"@$*", iter_arg->first.c_str());
1655 ASSERT_STREQ(
"( 5 , )", Macro::Dump(iter_arg->second).c_str());
1658 ASSERT_TRUE(iter_arg != macro_args.end());
1660 ASSERT_STREQ(
"@$...", iter_arg->first.c_str());
1661 ASSERT_EQ(1, iter_arg->second.size());
1664 ASSERT_TRUE(iter_arg != macro_args.end());
1666 ASSERT_STREQ(
"@$1", iter_arg->first.c_str());
1667 ASSERT_EQ(1, iter_arg->second.size());
1670 ASSERT_TRUE(iter_arg == macro_args.end());
1691 BlockType blk = Macro::ExpandMacros(macro_alias3, macro_args);
1692 ASSERT_EQ(6, blk.size()) << Macro::Dump(blk).c_str();
1693 ASSERT_STREQ(
"replace3", blk[0]->m_text.c_str()) << macro_alias3->Right()->toString();
1694 ASSERT_STREQ(
"(", blk[1]->m_text.c_str()) << macro_alias3->Right()->toString();
1695 ASSERT_STREQ(
"1", blk[2]->m_text.c_str()) << macro_alias3->Right()->toString();
1696 ASSERT_STREQ(
",", blk[3]->m_text.c_str()) << macro_alias3->Right()->toString();
1697 ASSERT_STREQ(
"5", blk[4]->m_text.c_str()) << macro_alias3->Right()->toString();
1698 ASSERT_STREQ(
")", blk[5]->m_text.c_str()) << macro_alias3->Right()->toString();
1749TEST_F(MacroTest, MacroCheck) {
1751 MacroPtr macro = std::make_shared<Macro>();
1754 ASSERT_TRUE(macro->size() == 0);
1755 ASSERT_ANY_THROW(Parse(
"@@testargs(arg)@@ ::= @@ @$bad_arg @@", macro)) << macro->Dump();
1756 ASSERT_ANY_THROW(Parse(
"@@testargs(arg)@@ ::= @@ @$... @@", macro)) << macro->Dump();
1757 ASSERT_ANY_THROW(Parse(
"@@testargs(arg, ...)@@ ::= @@ @$2 @@", macro)) << macro->Dump();
1759 ASSERT_NO_THROW(Parse(
"@@ macro2(...) @@ ::= @@ replace2( @$#, @$... ,@$* ) @@", macro)) << macro->Dump();
1760 ASSERT_NO_THROW(Parse(
"macro2(1,9)", macro)) << macro->Dump() << LexOut().c_str();
1761 ASSERT_STREQ(
"replace2 ( 2 , 1 , 9 , ( 1 , 9 , ) )", LexOut().c_str());
1875TEST_F(MacroTest, MacroTest) {
1877 MacroPtr macro = std::make_shared<Macro>();
1880 ASSERT_EQ(0, macro->GetCount());
1882 ASSERT_NO_THROW(Parse(
"@@alias@@ := @@ replace @@", macro)) << macro->Dump();
1883 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
1884 ASSERT_EQ(1, (*macro)[
"alias"].size()) << macro->Dump();
1885 ASSERT_TRUE((*macro)[
"alias"][0]) << macro->Dump();
1886 ASSERT_STREQ(
"alias", Macro::toMacroHash((*macro)[
"alias"][0]).c_str()) << (*macro)[
"alias"][0]->toString();
1887 ASSERT_EQ(1, (*macro)[
"alias"][0]->GetMacroId().size());
1888 ASSERT_TRUE(macro->GetMacro({
"alias"}));
1890 ASSERT_NO_THROW(Parse(
"alias", macro)) << macro->Dump();
1891 ASSERT_STREQ(
"replace", LexOut().c_str()) << macro->Dump();
1893 ASSERT_NO_THROW(Parse(
"alias()", macro)) << macro->Dump();
1894 ASSERT_STREQ(
"replace ( )", LexOut().c_str()) << macro->Dump();
1896 ASSERT_NO_THROW(Parse(
"alias(...)", macro)) << macro->Dump();
1897 ASSERT_STREQ(
"replace ( ... )", LexOut().c_str()) << macro->Dump();
1899 ASSERT_NO_THROW(Parse(
"alias(1,2,3)", macro)) << macro->Dump();
1900 ASSERT_STREQ(
"replace ( 1 , 2 , 3 )", LexOut().c_str()) << macro->Dump();
1902 ASSERT_NO_THROW(Parse(
"@alias", macro)) << macro->Dump();
1903 ASSERT_STREQ(
"replace", LexOut().c_str()) << macro->Dump();
1905 ASSERT_NO_THROW(Parse(
"@alias(); @alias", macro)) << macro->Dump() <<
" LEX: \"" << LexOut().c_str() <<
"\"";
1906 ASSERT_STREQ(
"replace ( ) ; replace", LexOut().c_str()) << macro->Dump();
1908 ASSERT_NO_THROW(Parse(
"@alias(...)", macro)) << macro->Dump();
1909 ASSERT_STREQ(
"replace ( ... )", LexOut().c_str()) << macro->Dump();
1911 ASSERT_NO_THROW(Parse(
"@alias(1,2,3); none", macro)) << macro->Dump();
1912 ASSERT_STREQ(
"replace ( 1 , 2 , 3 ) ; none", LexOut().c_str()) << macro->Dump();
1915 ASSERT_NO_THROW(Parse(
"@@ macro1 @@ ::= @@ replace1 @@", macro)) << macro->Dump();
1916 ASSERT_EQ(2, macro->GetCount()) << macro->Dump();
1917 ASSERT_TRUE(macro->GetMacro({
"macro1"}));
1918 ASSERT_TRUE(macro->GetMacro({
"macro1"})->isMacro());
1920 ASSERT_NO_THROW(Parse(
"macro1", macro)) << macro->Dump();
1921 ASSERT_STREQ(
"replace1", LexOut().c_str());
1923 ASSERT_NO_THROW(Parse(
"@macro1()", macro)) << macro->Dump();
1924 ASSERT_STREQ(
"replace1 ( )", LexOut().c_str());
1926 ASSERT_NO_THROW(Parse(
"@macro1(...)", macro)) << macro->Dump();
1927 ASSERT_STREQ(
"replace1 ( ... )", LexOut().c_str());
1929 ASSERT_NO_THROW(Parse(
"@macro1(1,2,3)", macro)) << macro->Dump();
1930 ASSERT_STREQ(
"replace1 ( 1 , 2 , 3 )", LexOut().c_str());
1932 ASSERT_NO_THROW(Parse(
"@macro1", macro)) << macro->Dump();
1933 ASSERT_STREQ(
"replace1", LexOut().c_str());
1936 ASSERT_ANY_THROW(Parse(
"@macro1() @alias", macro)) << macro->Dump();
1937 ASSERT_ANY_THROW(Parse(
"none @macro1(...)", macro)) << macro->Dump();
1942 ASSERT_NO_THROW(Parse(
"@@ macro2(...) @@ ::= @@ replace2( @$... ) @@", macro)) << macro->Dump();
1943 ASSERT_EQ(3, macro->GetCount()) << macro->Dump();
1944 ASSERT_TRUE(macro->GetMacro({
"macro2"}));
1945 ASSERT_TRUE(macro->GetMacro({
"macro2"})->Left());
1946 ASSERT_EQ(TermID::MACRO_SEQ, macro->GetMacro({
"macro2"})->Left()->getTermID());
1948 ASSERT_ANY_THROW(Parse(
"macro2", macro)) << macro->Dump();
1950 ASSERT_NO_THROW(Parse(
"macro2()", macro)) << macro->Dump();
1951 ASSERT_STREQ(
"replace2 ( )", LexOut().c_str());
1953 ASSERT_NO_THROW(Parse(
"macro2()", macro)) << macro->Dump();
1954 ASSERT_STREQ(
"replace2 ( )", LexOut().c_str());
1956 ASSERT_NO_THROW(Parse(
"macro2( 1 )", macro)) << macro->Dump();
1957 ASSERT_STREQ(
"replace2 ( 1 )", LexOut().c_str());
1959 ASSERT_NO_THROW(Parse(
"macro2(1,2,3)", macro)) << macro->Dump();
1960 ASSERT_STREQ(
"replace2 ( 1 , 2 , 3 )", LexOut().c_str());
1962 ASSERT_ANY_THROW(Parse(
"@macro2", macro)) << macro->Dump();
1964 ASSERT_NO_THROW(Parse(
"@macro2(); @alias(123)", macro)) << macro->Dump();
1965 ASSERT_STREQ(
"replace2 ( ) ; replace ( 123 )", LexOut().c_str());
1967 ASSERT_NO_THROW(Parse(
"none;@macro2(...)", macro)) << macro->Dump();
1968 ASSERT_STREQ(
"none ; replace2 ( ... )", LexOut().c_str());
1970 ASSERT_NO_THROW(Parse(
"@macro2(1,2,3);\n", macro)) << macro->Dump();
1971 ASSERT_STREQ(
"replace2 ( 1 , 2 , 3 ) ;", LexOut().c_str());
std::map< std::string, BlockType > MacroArgsType
bool RegisterPredefMacro(const char *name, const char *desc)
std::map< std::string, std::string > m_predef_macro
parser::token_type ExpandPredefMacro(TermPtr &term)
TermPtr ParseFile(const std::string_view filename)
std::shared_ptr< Term > TermPtr
std::shared_ptr< Macro > MacroPtr
std::vector< TermPtr > BlockType
std::shared_ptr< Diag > DiagPtr
const char * toString(TermID type)
std::string & trim(std::string &s, const char *t=ws)
#define VERSION_DATE_BUILD_STR
#define VERSION_SOURCE_FULL_ID
#define VERSION_GIT_SOURCE