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 Parser p(buffer, &m_postlex, diag);
52 int Count(
TermID token_id) {
54 for (
int c = 0; c < ast->size(); c++) {
55 if ((*ast)[c].second->m_id == token_id) {
62 std::string LexOut() {
64 for (
int i = 0; i < m_postlex.size(); i++) {
225TEST_F(MacroTest, Escape) {
227 ASSERT_TRUE(Parse(
"@\\ {+"));
228 ASSERT_EQ(TermID::ESCAPE, ast->getTermID());
229 EXPECT_STREQ(
"{+", ast->m_text.c_str());
232TEST_F(MacroTest, PredefMacro) {
235 TermPtr term = Term::Create(TermID::MACRO,
"@__NLC_VER__", parser::token_type::MACRO);
243 for (
auto &elem : p.m_predef_macro) {
244 ASSERT_FALSE(elem.first.empty());
245 ASSERT_FALSE(elem.second.empty());
247 term->m_text = elem.first;
248 term->m_id = TermID::MACRO;
249 term->m_lexer_type = parser::token_type::MACRO;
256 ASSERT_TRUE(Parse(
"@__NLC_VER__"));
257 ASSERT_STREQ(std::to_string(
VERSION).c_str(), ast->toString().c_str());
258 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
261 ASSERT_NO_THROW(Parse(
"@__COUNTER__"));
262 ASSERT_STREQ(
"0", ast->toString().c_str());
264 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
266 ASSERT_NO_THROW(Parse(
"@__COUNTER__"));
267 ASSERT_STREQ(
"1", ast->toString().c_str());
268 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
270 ASSERT_NO_THROW(Parse(
"@__COUNTER__"));
271 ASSERT_STREQ(
"2", ast->toString().c_str());
272 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
274 ASSERT_NO_THROW(Parse(
"@__COUNTER__"));
275 ASSERT_STREQ(
"3", ast->toString().c_str());
276 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
279 ASSERT_NO_THROW(Parse(
"@__TIME__"));
280 ASSERT_EQ(10, ast->toString().size()) << ast->toString();
281 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
283 ASSERT_NO_THROW(Parse(
"@__DATE__"));
284 ASSERT_EQ(13, ast->toString().size()) << ast->toString();
285 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
287 ASSERT_NO_THROW(Parse(
"@__TIMESTAMP__"));
288 ASSERT_EQ(26, ast->toString().size()) << ast->toString();
289 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
291 ASSERT_NO_THROW(Parse(
"@__TIMESTAMP_ISO__"));
292 ASSERT_EQ(22, ast->toString().size()) << ast->toString();
293 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
296 ASSERT_NO_THROW(Parse(
"@__LINE__"));
297 ASSERT_STREQ(std::to_string(1).c_str(), ast->toString().c_str());
298 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
300 ASSERT_NO_THROW(Parse(
"\n@__LINE__"));
301 ASSERT_STREQ(std::to_string(2).c_str(), ast->toString().c_str());
302 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
304 ASSERT_NO_THROW(Parse(
"\n\n@__FILE_LINE__"));
305 ASSERT_STREQ(std::to_string(3).c_str(), ast->toString().c_str());
306 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
309 ASSERT_NO_THROW(Parse(
"@__FILE__"));
310 ASSERT_STREQ(
"\"File name undefined!!!\"", ast->toString().c_str());
311 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
313 ASSERT_NO_THROW(Parse(
"@__FILE_NAME__"));
314 ASSERT_STREQ(
"\"File name undefined!!!\"", ast->toString().c_str());
315 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
318 ASSERT_NO_THROW(Parse(
"@__FILE_TIMESTAMP__"));
319 ASSERT_EQ(26, ast->toString().size()) << ast->toString();
320 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
322 ASSERT_NO_THROW(Parse(
"@__FILE_MD5__"));
323 ASSERT_TRUE(ast->toString().size() > 30) << ast->toString();
324 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
327 ASSERT_NO_THROW(Parse(
"@__NLC_SOURCE_GIT__"));
329 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
331 ASSERT_NO_THROW(Parse(
"@__NLC_DATE_BUILD__"));
333 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
335 ASSERT_NO_THROW(Parse(
"@__NLC_SOURCE_BUILD__"));
337 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
341 std::filesystem::create_directories(
"temp");
342 ASSERT_TRUE(std::filesystem::is_directory(
"temp"));
344 std::ofstream out(
"temp/file.md5.test");
345 out <<
"@__LINE__; @__FILE__; @__FILE_TIMESTAMP__; @__FILE_MD5__;";
349 ASSERT_TRUE(ast = p.
ParseFile(
"temp/file.md5.test"))
352 ASSERT_EQ(4, ast->m_block.size()) << ast->toString().c_str();
354 ASSERT_STREQ(
"1", ast->m_block[0]->toString().c_str());
355 ASSERT_EQ(TermID::INTEGER, ast->m_block[0]->getTermID());
357 ASSERT_TRUE(ast->m_block[1]->toString().find(
"temp/file.md5.test\"") != std::string::npos);
358 ASSERT_EQ(TermID::STRWIDE, ast->m_block[1]->getTermID());
360 ASSERT_EQ(26, ast->m_block[2]->toString().size()) << ast->m_block[2]->toString();
361 ASSERT_EQ(TermID::STRWIDE, ast->m_block[2]->getTermID());
363 ASSERT_STREQ(
"\"c3b16159b22333f2b0d1abe7f2960ce0\"", ast->m_block[3]->toString().c_str());
364 ASSERT_EQ(TermID::STRWIDE, ast->m_block[3]->getTermID());
366 std::remove(
"temp/file.md5.test");
370 term->m_text =
"@__NOT_FOUND__";
371 term->m_id = TermID::MACRO;
372 term->m_lexer_type = parser::token_type::MACRO;
382TEST_F(MacroTest, ParseTerm) {
389 buff.push_back(Term::Create(TermID::NAME,
"alias", parser::token_type::NAME));
391 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
394 ASSERT_FALSE(term->isCall());
395 ASSERT_STREQ(
"alias", term->toString().c_str());
398 buff.push_back(Term::Create(TermID::NAME,
"alias", parser::token_type::NAME));
400 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
403 ASSERT_FALSE(term->isCall());
404 ASSERT_STREQ(
"alias", term->toString().c_str());
406 buff.push_back(Term::Create(TermID::NAME,
"second", parser::token_type::NAME));
408 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
411 ASSERT_FALSE(term->isCall());
412 ASSERT_STREQ(
"alias", term->toString().c_str());
414 buff.erase(buff.begin(), buff.begin() + 2);
415 buff.push_back(Term::Create(TermID::SYMBOL,
"(", parser::token_type::SYMBOL));
417 ASSERT_ANY_THROW(Parser::ParseTerm(term, buff, 0));
419 buff.push_back(Term::Create(TermID::SYMBOL,
")", parser::token_type::SYMBOL));
421 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
424 ASSERT_TRUE(term->isCall());
425 ASSERT_STREQ(
"second()", term->toString().c_str());
427 buff.erase(buff.end());
429 buff.push_back(Term::Create(TermID::NAME,
"name", parser::token_type::NAME));
430 ASSERT_ANY_THROW(Parser::ParseTerm(term, buff, 0));
432 buff.push_back(Term::Create(TermID::SYMBOL,
")", parser::token_type::SYMBOL));
434 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
437 ASSERT_TRUE(term->isCall());
438 ASSERT_STREQ(
"second(name)", term->toString().c_str());
441 buff.erase(buff.end());
442 buff.push_back(Term::Create(TermID::SYMBOL,
"=", parser::token_type::SYMBOL));
443 ASSERT_ANY_THROW(Parser::ParseTerm(term, buff, 0));
445 buff.push_back(Term::Create(TermID::NAME,
"value", parser::token_type::NAME));
446 ASSERT_ANY_THROW(Parser::ParseTerm(term, buff, 0));
448 buff.push_back(Term::Create(TermID::SYMBOL,
")", parser::token_type::SYMBOL));
450 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
453 ASSERT_TRUE(term->isCall());
454 ASSERT_EQ(1, term->size());
455 ASSERT_STREQ(
"name", term->name(0).c_str());
456 ASSERT_STREQ(
"second(name=value)", term->toString().c_str());
459 buff = Scanner::ParseLexem(
"second2 ( 1 , ( 123 , ) );\n\n\n\n;");
461 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
464 ASSERT_TRUE(term->isCall());
465 ASSERT_EQ(2, term->size());
466 ASSERT_STREQ(
"1", term->at(0).second->toString().c_str());
467 ASSERT_STREQ(
"(123,)", term->at(1).second->toString().c_str());
468 ASSERT_STREQ(
"second2(1, (123,))", term->toString().c_str());
472TEST_F(MacroTest, Pragma) {
476 ASSERT_NO_THROW(Parse(
"; 100",
nullptr,
nullptr)) << LexOut().c_str();
477 ASSERT_NO_THROW(Parse(
"; ; ; ; 100; ",
nullptr,
nullptr)) << LexOut().c_str();
478 ASSERT_NO_THROW(Parse(
"@__PRAGMA_LOCATION__(9) @__PRAGMA_LOCATION__(100) @__LINE__",
nullptr,
nullptr)) << LexOut().c_str();
479 ASSERT_NO_THROW(Parse(
"@__PRAGMA_LOCATION__(9); @__PRAGMA_LOCATION__(100); @__LINE__",
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();
591 ASSERT_NO_THROW(Parse(
"@__PRAGMA_LOCATION__(9) @__PRAGMA_LOCATION__(100) @__LINE__",
nullptr, diag)) << LexOut().c_str();
592 ASSERT_STREQ(
"100", LexOut().c_str());
595 ASSERT_NO_THROW(Parse(
"@__PRAGMA_LOCATION__(99, 'file_name.test') @__LINE__; @__FILE__",
nullptr, diag)) << LexOut().c_str();
596 ASSERT_STREQ(
"99 ; file_name.test", LexOut().c_str());
599 ASSERT_NO_THROW(Parse(
"@__PRAGMA_LOCATION__(push) @__PRAGMA_LOCATION__(42) @__LINE__; @__PRAGMA_LOCATION__(pop) @__LINE__",
nullptr, diag));
600 ASSERT_STREQ(
"42 ; 1", LexOut().c_str());
603 ASSERT_NO_THROW(Parse(
"@__PRAGMA_LOCATION__(push) @__PRAGMA_LOCATION__(44, 'filename') @__LINE__; @__FILE__; @__PRAGMA_LOCATION__(pop) @__LINE__; @__FILE__",
nullptr, diag));
604 ASSERT_STREQ(
"44 ; filename ; 1 ; File name undefined!!!", LexOut().c_str());
608TEST_F(MacroTest, Annotate) {
611 ASSERT_ANY_THROW(Parse(
"@__ANNOTATION_SET__"));
612 ASSERT_STREQ(
"", LexOut().c_str());
613 ASSERT_TRUE(m_output.find(
"Annotation args in '@__ANNOTATION_SET__' not recognized!") != std::string::npos) << m_output;
617 ASSERT_ANY_THROW(Parse(
"@__ANNOTATION_SET__()"));
618 ASSERT_STREQ(
"", LexOut().c_str());
619 ASSERT_TRUE(m_output.find(
"Annotation args in '@__ANNOTATION_SET__()' not recognized!") != std::string::npos) << m_output;
622 ASSERT_NO_THROW(Parse(
"@__ANNOTATION_SET__(name)"));
623 ASSERT_STREQ(
"", LexOut().c_str());
626 ASSERT_NO_THROW(Parse(
"@__ANNOTATION_SET__(name, \"value\")"));
627 ASSERT_STREQ(
"", LexOut().c_str());
630 ASSERT_NO_THROW(Parse(
"@__ANNOTATION_SET__(name, 1)"));
631 ASSERT_STREQ(
"", LexOut().c_str());
636 ASSERT_ANY_THROW(Parse(
"@__ANNOTATION_IIF__"));
637 ASSERT_STREQ(
"", LexOut().c_str());
638 ASSERT_TRUE(m_output.find(
"Annotation IIF must have three arguments!") != std::string::npos) << m_output;
641 ASSERT_ANY_THROW(Parse(
"@__ANNOTATION_IIF__()"));
642 ASSERT_STREQ(
"", LexOut().c_str());
643 ASSERT_TRUE(m_output.find(
"Annotation IIF must have three arguments!") != std::string::npos) << m_output;
646 ASSERT_ANY_THROW(Parse(
"@__ANNOTATION_IIF__(name)"));
647 ASSERT_STREQ(
"", LexOut().c_str());
648 ASSERT_TRUE(m_output.find(
"Annotation IIF must have three arguments!") != std::string::npos) << m_output;
651 ASSERT_ANY_THROW(Parse(
"@__ANNOTATION_IIF__(name, 1)"));
652 ASSERT_STREQ(
"", LexOut().c_str());
653 ASSERT_TRUE(m_output.find(
"Annotation IIF must have three arguments!") != std::string::npos) << m_output;
657 ASSERT_NO_THROW(Parse(
"@__ANNOTATION_SET__(name, 1) @__ANNOTATION_IIF__(name, 1, 2)"));
658 ASSERT_STREQ(
"1", LexOut().c_str());
665 ASSERT_NO_THROW(Parse(
"@__ANNOTATION_SET__(name, 0) @__ANNOTATION_IIF__(name, 1, 2)"));
666 ASSERT_STREQ(
"2", LexOut().c_str());
669TEST_F(MacroTest, Buffer) {
671 ASSERT_STREQ(
"name", Macro::toMacroHashName(
"name").c_str());
672 ASSERT_STREQ(
"$", Macro::toMacroHashName(
"$name").c_str());
673 ASSERT_STREQ(
"name", Macro::toMacroHashName(
"@name").c_str());
677 MacroPtr macro_buf = std::make_shared<Macro>();
679 ASSERT_FALSE(Macro::IdentityMacro(buffer, term));
681#define CREATE_TERM(type, text) Term::Create(TermID:: type, text, parser::token_type:: type)
683 term = Parse(
"@@ macro @@ := @@ name @@", macro_buf);
685 ASSERT_TRUE(term->isMacro());
686 ASSERT_TRUE(term->m_left);
688 buffer.push_back(CREATE_TERM(NAME,
"macro"));
689 ASSERT_TRUE(Macro::IdentityMacro(buffer, term));
692 buffer.push_back(CREATE_TERM(NAME,
"macro2"));
693 ASSERT_TRUE(Macro::IdentityMacro(buffer, term));
696 term->m_text =
"macro2";
697 ASSERT_TRUE(term->m_macro_id.size());
698 term->m_macro_id[0]->m_text =
"macro2";
699 term->m_left->m_macro_seq[0]->m_text =
"macro2";
700 term->m_left->m_macro_id[0]->m_text =
"macro2";
701 ASSERT_FALSE(Macro::IdentityMacro(buffer, term));
703 ASSERT_EQ(2, buffer.size());
704 buffer.erase(buffer.begin(), buffer.begin() + 1);
705 ASSERT_EQ(1, buffer.size());
706 ASSERT_TRUE(Macro::IdentityMacro(buffer, term));
712 TermPtr hash = Parse(
"@@ name1 name2 @@ := @@ @@", macro_buf);
714 ASSERT_TRUE(hash->isMacro());
715 ASSERT_TRUE(hash->m_left);
716 ASSERT_TRUE(hash->m_right);
718 ASSERT_STREQ(
"name1", Macro::toMacroHash(hash).c_str());
723 MacroPtr macro = std::make_shared<Macro>();
724 ASSERT_EQ(0, macro->size());
726 ASSERT_TRUE(term = Parse(
"@@alias@@ := alias_name", macro));
727 ASSERT_STREQ(
"@@ alias @@ := alias_name", LexOut().c_str());
729 ASSERT_STREQ(
"@@ alias @@ := alias_name;", term->toString().c_str());
730 ASSERT_TRUE(term->m_left->m_macro_seq[0]);
731 ASSERT_EQ(1, term->m_left->m_macro_seq.size());
732 ASSERT_TRUE(term->m_left->m_macro_seq[0]);
733 ASSERT_STREQ(
"alias", term->m_left->m_macro_seq[0]->toString().c_str());
735 BlockType id = Macro::GetMacroId(macro->begin()->second[0]);
736 ASSERT_EQ(1,
id.size()) << macro->begin()->second[0]->toString().c_str();
737 ASSERT_STREQ(
"alias",
id[0]->m_text.c_str());
740 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
741 ASSERT_TRUE(macro->GetMacro({
"alias"})) << macro->Dump();
744 ASSERT_ANY_THROW(Parse(
"@@alias@@ ::= alias_name2;", macro)) << macro->Dump();
745 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
752 ASSERT_TRUE(term = Parse(
"@@alias2@@ := alias_name", macro));
753 ASSERT_EQ(2, macro->GetCount());
754 ASSERT_STREQ(
"@@ alias2 @@ := alias_name", LexOut().c_str());
756 ASSERT_TRUE(term->m_left);
757 ASSERT_EQ(1, term->m_left->m_macro_seq.size());
758 ASSERT_TRUE(term->m_left->m_macro_seq[0]);
759 ASSERT_STREQ(
"alias2", term->m_left->m_macro_seq[0]->toString().c_str());
762 ASSERT_ANY_THROW(Parse(
"@@@@ @@@@", macro));
764 ASSERT_TRUE(Parse(
"@@@@alias@@@@", macro));
765 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
766 ASSERT_STREQ(
"@@@@ alias @@@@", LexOut().c_str());
768 ASSERT_TRUE(Parse(
"@@@@_@@@@;", macro));
769 ASSERT_EQ(0, macro->GetCount()) << macro->Dump();
770 ASSERT_STREQ(
"@@@@ _ @@@@ ;", LexOut().c_str());
773 ASSERT_TRUE(term = Parse(
"@@if(args)@@ := @@ [@$args] --> @@", macro));
774 ASSERT_EQ(1, macro->size()) << macro->Dump();
775 ASSERT_STREQ(
"@@ if ( args ) @@ := @@ [ @$args ] --> @@", LexOut().c_str());
777 ASSERT_TRUE(term->m_left);
778 ASSERT_EQ(4, term->m_left->m_macro_seq.size());
779 ASSERT_EQ(1, Macro::GetMacroId(term).size());
780 ASSERT_STREQ(
"if(args)", Macro::GetMacroId(term)[0]->
toString().c_str());
783 id = Macro::GetMacroId(macro->begin()->second[0]);
784 ASSERT_EQ(1,
id.size()) << macro->begin()->second[0]->toString().c_str();
785 ASSERT_STREQ(
"if",
id[0]->m_text.c_str());
788 ASSERT_TRUE(macro->GetMacro({
"if"})) << macro->Dump();
789 ASSERT_TRUE(macro->GetMacro({
"if"})->m_right);
790 ASSERT_EQ(4, macro->GetMacro({
"if"})->m_right->m_macro_seq.size()) << macro->GetMacro({
"if"})->m_right->toString().c_str();
792 ASSERT_TRUE(term = Parse(
"@@if2(...)@@ := @@@ [ @__LINE__ ] --> @@@", macro));
793 ASSERT_STREQ(
"@@ if2 ( ... ) @@ := [ @__LINE__ ] -->", LexOut().c_str());
795 ASSERT_TRUE(term = Parse(
"@@if2(...)@@ := @@ [ @__LINE__ ] --> @@", macro));
796 ASSERT_STREQ(
"@@ if2 ( ... ) @@ := @@ [ @__LINE__ ] --> @@", LexOut().c_str());
799 ASSERT_TRUE(term->m_left);
800 ASSERT_EQ(4, term->m_left->m_macro_seq.size());
801 ASSERT_EQ(1, term->m_macro_id.size());
802 ASSERT_EQ(1, term->m_left->m_macro_id.size());
803 ASSERT_TRUE(term->m_macro_id[0]);
804 ASSERT_STREQ(
"if2(...)", term->m_macro_id[0]->toString().c_str());
807 ASSERT_EQ(2, macro->size());
808 ASSERT_TRUE(macro->GetMacro({
"if2"}));
809 ASSERT_TRUE(macro->GetMacro({
"if2"})->m_right);
810 ASSERT_STREQ(
"@@ [ @__LINE__ ] --> @@", macro->GetMacro({
"if2"})->m_right->toString().c_str());
815 ASSERT_TRUE(term = Parse(
"@@ func $name(arg= @__LINE__ , ...) @@ := @@@ [ @__LINE__ ] --> @@@", macro));
816 ASSERT_STREQ(
"@@ func $name ( arg = @__LINE__ , ... ) @@ := [ @__LINE__ ] -->", LexOut().c_str());
818 ASSERT_EQ(2, term->m_macro_id.size());
819 ASSERT_TRUE(term->m_macro_id[0]);
820 ASSERT_STREQ(
"func", term->m_macro_id[0]->toString().c_str());
821 ASSERT_TRUE(term->m_macro_id[1]);
822 ASSERT_STREQ(
"$name(arg=1, ...)", term->m_macro_id[1]->toString().c_str());
825 ASSERT_EQ(3, macro->size());
826 ASSERT_TRUE(macro->GetMacro(std::vector<std::string>({
"func",
"$"})));
827 ASSERT_TRUE(macro->GetMacro(std::vector<std::string>({
"func",
"$"}))->m_right);
828 ASSERT_STREQ(
"@@@ [ @__LINE__ ] --> @@@", macro->GetMacro(std::vector<std::string>({
"func",
"$"}))->m_right->toString().c_str());
834TEST_F(MacroTest, MacroMacro) {
835 MacroPtr macro = std::make_shared<Macro>();
836 ASSERT_EQ(0, macro->size());
838 ASSERT_TRUE(Parse(
"@@alias replace@@ := @@replace@@", macro));
839 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
840 ASSERT_TRUE(Parse(
"@@alias second@@ := @@second@@", macro));
841 ASSERT_EQ(2, macro->GetCount()) << macro->Dump();
842 ASSERT_TRUE(Parse(
"@@text@@ := @@@text;\n text@@@", macro));
843 ASSERT_EQ(3, macro->GetCount()) << macro->Dump();
844 ASSERT_TRUE(Parse(
"@@dsl@@ := @@@ @@m1@@ := @@mm@@;\n @@m2@@ := @@mm@@;\n@@@", macro));
846 ASSERT_EQ(4, macro->GetCount()) << macro->Dump();
847 ASSERT_TRUE(macro->GetMacro({
"alias",
"replace"}));
848 TermPtr macro_replace = macro->GetMacro({
"alias",
"replace"});
849 ASSERT_TRUE(macro->GetMacro({
"alias",
"second"}));
850 TermPtr macro_second = macro->GetMacro({
"alias",
"second"});
851 ASSERT_TRUE(macro->GetMacro({
"text"}));
852 TermPtr macro_text = macro->GetMacro({
"text"});
853 ASSERT_TRUE(macro->GetMacro({
"dsl"}));
854 TermPtr macro_dsl = macro->GetMacro({
"dsl"});
857 TermPtr term = Term::Create(TermID::NAME,
"alias", parser::token_type::NAME);
859 ASSERT_TRUE(macro->GetMacro({
"alias",
"replace"}));
860 ASSERT_TRUE(macro->GetMacro({
"alias",
"second"}));
864 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace));
865 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
866 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
867 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
870 buff.push_back(term);
872 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace));
873 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
874 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
875 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
877 buff.push_back(term);
879 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace));
880 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
881 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
882 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
884 buff.push_back(Term::Create(TermID::NAME,
"second", parser::token_type::NAME));
886 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace));
887 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
888 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
889 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
891 buff.push_back(Term::Create(TermID::SYMBOL,
"(", parser::token_type::SYMBOL));
893 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace));
894 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
895 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
896 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
898 buff.push_back(Term::Create(TermID::SYMBOL,
")", parser::token_type::SYMBOL));
900 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace));
901 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
902 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
903 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
905 buff.erase(buff.begin());
907 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace));
908 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_second));
909 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
910 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
918 ASSERT_TRUE(Parse(
"alias replace", macro));
919 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
920 ASSERT_STREQ(
"replace", ast->m_text.c_str());
922 ASSERT_TRUE(Parse(
"alias second", macro));
923 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
924 ASSERT_STREQ(
"second", ast->m_text.c_str());
928 ASSERT_EQ(4, macro->GetCount());
929 ASSERT_FALSE(macro->GetMacro({
"m1"})) << macro->Dump();
930 ASSERT_FALSE(macro->GetMacro({
"m2"})) << macro->Dump();
940TEST_F(MacroTest, Simple) {
941 MacroPtr macro = std::make_shared<Macro>();
942 ASSERT_EQ(0, macro->size());
944 ASSERT_NO_THROW(Parse(
"@@alias@@ ::= @@replace@@", macro));
945 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
947 ASSERT_NO_THROW(Parse(
"@@alias()@@ := @@replace@@", macro));
948 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
950 ASSERT_ANY_THROW(Parse(
"@@alias(...)@@ ::= @@error@@", macro));
951 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
953 ASSERT_NO_THROW(Parse(
"@@second(...)@@ := @@second2(@$#, @$...)@@", macro));
954 ASSERT_EQ(2, macro->GetCount()) << macro->Dump();
956 ASSERT_NO_THROW(Parse(
"@@second@@ := @@second2(@$#, @$*)@@", macro));
957 ASSERT_EQ(2, macro->GetCount()) << macro->Dump();
959 ASSERT_NO_THROW(Parse(
"@@text(...)@@ := @@text1(@$#, @$*)@@", macro));
960 ASSERT_EQ(3, macro->GetCount()) << macro->Dump();
961 ASSERT_NO_THROW(Parse(
"@@dsl@@ := @@@\n @@m1@@ := @@mm@@;\n @@m2@@ := @@mm@@;\n@@@", macro));
963 ASSERT_EQ(4, macro->GetCount()) << macro->Dump();
964 ASSERT_TRUE(macro->GetMacro({
"alias"}));
965 TermPtr macro_alias = macro->GetMacro({
"alias"});
966 ASSERT_TRUE(macro->GetMacro({
"second"}));
967 TermPtr macro_second = macro->GetMacro({
"second"});
968 ASSERT_TRUE(macro->GetMacro({
"text"}));
969 TermPtr macro_text = macro->GetMacro({
"text"});
970 ASSERT_TRUE(macro->GetMacro({
"dsl"}));
971 TermPtr macro_dsl = macro->GetMacro({
"dsl"});
974 TermPtr term = Term::Create(TermID::NAME,
"alias", parser::token_type::NAME);
976 ASSERT_TRUE(macro->GetMacro({
"alias"}));
977 ASSERT_TRUE(macro->GetMacro({
"second"}));
981 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_alias));
982 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
983 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
984 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
987 buff.push_back(term);
989 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
990 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
991 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
992 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
994 buff.push_back(term);
996 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
997 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
998 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
999 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
1001 buff.push_back(Term::Create(TermID::NAME,
"second", parser::token_type::NAME));
1003 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
1004 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
1005 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
1006 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
1008 buff.push_back(Term::Create(TermID::SYMBOL,
"(", parser::token_type::SYMBOL));
1010 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
1011 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
1012 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
1013 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
1015 buff.push_back(Term::Create(TermID::NAME,
"arg", parser::token_type::NAME));
1017 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
1018 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
1019 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
1020 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
1022 buff.push_back(Term::Create(TermID::SYMBOL,
")", parser::token_type::SYMBOL));
1024 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
1025 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
1026 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
1027 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
1029 buff.erase(buff.begin());
1031 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
1032 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second));
1033 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
1034 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
1036 buff.erase(buff.begin());
1038 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_alias));
1039 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_second));
1040 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text));
1041 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl));
1044 ASSERT_NO_THROW(Parse(
"@alias", macro));
1045 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
1046 ASSERT_STREQ(
"replace", ast->toString().c_str());
1048 ASSERT_NO_THROW(Parse(
"alias", macro));
1049 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
1050 ASSERT_STREQ(
"replace", ast->m_text.c_str());
1052 ASSERT_NO_THROW(Parse(
"second()", macro));
1053 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
1054 ASSERT_STREQ(
"second2", ast->m_text.c_str());
1056 ASSERT_NO_THROW(Parse(
"@second()", macro));
1057 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
1058 ASSERT_STREQ(
"second2", ast->m_text.c_str());
1061 ASSERT_NO_THROW(Parse(
"second(123)", macro));
1062 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
1063 ASSERT_EQ(2, ast->size()) << LexOut();
1064 ASSERT_STREQ(
"second2(1, (123,))", ast->toString().c_str());
1066 ASSERT_NO_THROW(Parse(
"@second(123, 456)", macro));
1067 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
1068 ASSERT_STREQ(
"second2(2, (123, 456,))", ast->toString().c_str());
1070 ASSERT_ANY_THROW(Parse(
"second", macro));
1071 ASSERT_ANY_THROW(Parse(
"@second", macro));
1086 ASSERT_EQ(4, macro->GetCount());
1087 ASSERT_FALSE(macro->GetMacro({
"m1"})) << macro->Dump();
1088 ASSERT_FALSE(macro->GetMacro({
"m2"})) << macro->Dump();
1215TEST_F(MacroTest, MacroAlias) {
1216 MacroPtr macro = std::make_shared<Macro>();
1217 ASSERT_EQ(0, macro->size());
1219 ASSERT_ANY_THROW(Parse(
"@@@@ macro @@ @@@@"));
1220 ASSERT_ANY_THROW(Parse(
"@@@@ @@ macro @@@@"));
1221 ASSERT_ANY_THROW(Parse(
"@@ macro @@@@ @@"));
1222 ASSERT_ANY_THROW(Parse(
"@@ @@@@ macro @@"));
1223 ASSERT_ANY_THROW(Parse(
"@@ @macro @@"));
1224 ASSERT_ANY_THROW(Parse(
"@@ @$macro @@"));
1226 ASSERT_TRUE(Parse(
"@@@@ alias @@@@", macro));
1227 ASSERT_EQ(0, macro->size());
1228 ASSERT_TRUE(Parse(
"@@@@ alias $alias2 @@@@", macro));
1229 ASSERT_EQ(0, macro->size());
1231 ASSERT_TRUE(Parse(
"@@alias@@ ::= @@replace@@", macro));
1232 ASSERT_TRUE(Parse(
"@@alias2@@ := @@alias@@", macro));
1233 ASSERT_TRUE(Parse(
"@@fail@@ := @@fail@@", macro));
1235 ASSERT_EQ(3, macro->size()) << macro->Dump();
1236 ASSERT_TRUE(macro->GetMacro({
"alias"}));
1237 TermPtr macro_alias = macro->GetMacro({
"alias"});
1238 ASSERT_TRUE(macro_alias);
1239 ASSERT_EQ(TermID::CREATE_NEW, macro_alias->getTermID()) <<
toString(macro_alias->getTermID());
1240 ASSERT_TRUE(macro_alias->m_left);
1241 ASSERT_EQ(TermID::MACRO_SEQ, macro_alias->m_left->getTermID()) <<
toString(macro_alias->m_left->getTermID());
1242 ASSERT_TRUE(macro_alias->m_right);
1243 ASSERT_TRUE(macro_alias->m_right->m_macro_seq.size()) << macro_alias->m_right->toString();
1244 ASSERT_STREQ(
"replace", macro_alias->m_right->m_macro_seq[0]->m_text.c_str());
1246 ASSERT_TRUE(macro->GetMacro({
"alias2"})) << macro->Dump();
1247 TermPtr macro_alias2 = macro->GetMacro({
"alias2"});
1248 ASSERT_TRUE(macro_alias2);
1249 ASSERT_TRUE(macro_alias2->isMacro());
1250 ASSERT_EQ(TermID::CREATE_USE, macro_alias2->getTermID()) <<
toString(macro_alias2->getTermID());
1251 ASSERT_TRUE(macro_alias2->m_left);
1252 ASSERT_EQ(TermID::MACRO_SEQ, macro_alias2->m_left->getTermID()) <<
toString(macro_alias2->m_left->getTermID());
1253 ASSERT_STREQ(
"alias", macro_alias2->m_right->m_macro_seq[0]->m_text.c_str());
1255 ASSERT_TRUE(macro->GetMacro({
"fail"})) << macro->Dump();
1256 TermPtr macro_fail = macro->GetMacro({
"fail"});
1257 ASSERT_TRUE(macro_fail);
1258 ASSERT_TRUE(macro_fail->m_left);
1259 ASSERT_EQ(TermID::MACRO_SEQ, macro_fail->m_left->getTermID());
1260 ASSERT_STREQ(
"fail", macro_fail->m_right->m_macro_seq[0]->m_text.c_str());
1264 TermPtr term = Term::Create(TermID::NAME,
"alias", parser::token_type::NAME);
1266 ASSERT_TRUE(macro->map::find(term->m_text) != macro->end());
1268 BlockType vals = macro->map::find(term->m_text)->second;
1269 ASSERT_EQ(1, vals.size());
1272 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_alias));
1273 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_alias2));
1274 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_fail));
1277 buff.push_back(term);
1279 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
1280 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_alias2));
1281 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_fail));
1284 term = Term::Create(TermID::NAME,
"alias", parser::token_type::NAME);
1285 buff.push_back(term);
1288 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
1289 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_alias2));
1290 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_fail));
1295 ASSERT_EQ(1, Macro::ExtractArgs(buff, macro_alias, macro_args));
1296 ASSERT_EQ(3, macro_args.size()) << Macro::Dump(macro_args);
1301 ASSERT_ANY_THROW(Macro::ExpandString(macro_alias, macro_args));
1304 block = Macro::ExpandMacros(macro_alias, macro_args);
1305 ASSERT_EQ(1, block.size());
1306 ASSERT_TRUE(block[0]);
1307 ASSERT_STREQ(
"replace", block[0]->m_text.c_str());
1311 ASSERT_EQ(3, macro->size());
1312 for (
auto &elem : *macro) {
1314 LOG_DEBUG(
"Hash: %s", elem.first.c_str());
1317 ASSERT_TRUE(Parse(
"alias", macro));
1318 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
1319 ASSERT_STREQ(
"replace", ast->toString().c_str());
1321 ASSERT_TRUE(Parse(
"alias2", macro));
1322 ASSERT_EQ(TermID::NAME, ast->getTermID()) <<
newlang::toString(ast->getTermID());
1323 ASSERT_STREQ(
"replace", ast->toString().c_str());
1328TEST_F(MacroTest, MacroArgs) {
1330 MacroPtr macro = std::make_shared<Macro>();
1334 Macro::iterator iter;
1358 ASSERT_EQ(0, macro->GetCount());
1360 ASSERT_NO_THROW(Parse(
"@@alias@@ := @@ replace1 @@", macro)) << macro->Dump();
1361 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
1363 ASSERT_ANY_THROW(Parse(
"@@alias@@ ::= @@replace2@@", macro)) << macro->Dump();
1364 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
1365 ASSERT_NO_THROW(Parse(
"@@alias@@ = @@replace3@@", macro)) << macro->Dump();
1366 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
1368 ASSERT_ANY_THROW(Parse(
"@@alias(arg)@@ ::= @@ replace2(@$arg) @@", macro)) << macro->Dump();
1371 ASSERT_NO_THROW(Parse(
"@@@@ alias @@@@", macro)) << macro->Dump();
1372 ASSERT_EQ(0, macro->GetCount()) << macro->Dump();
1374 ASSERT_NO_THROW(Parse(
"@@alias(arg, ... )@@ := @@ replace2(@$arg) @@", macro)) << macro->Dump();
1375 ASSERT_TRUE(macro->GetMacro({
"alias"}));
1376 ASSERT_STREQ(
"@@ alias ( arg , ... ) @@ := @@ replace2 ( @$arg ) @@;", macro->GetMacro({
"alias"})->toString().c_str());
1378 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
1379 ASSERT_ANY_THROW(Parse(
"@@alias(arg, ... )@@ ::= @@ replace3(@$arg) @@", macro)) << macro->Dump();
1380 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
1382 ASSERT_NO_THROW(Parse(
"@@alias(arg, ... )@@ = @@ replace4(@$arg) @@", macro)) << macro->Dump();
1383 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
1384 ASSERT_TRUE(macro->GetMacro({
"alias"}));
1385 ASSERT_STREQ(
"@@ alias ( arg , ... ) @@ := @@ replace4 ( @$arg ) @@;", macro->GetMacro({
"alias"})->toString().c_str());
1387 ASSERT_NO_THROW(Parse(
"@@alias3(...)@@ := @@replace3(@$#, @$...)@@", macro)) << macro->Dump();
1388 ASSERT_EQ(2, macro->GetCount()) << macro->Dump();
1390 ASSERT_ANY_THROW(Parse(
"@@alias3(...)@@ ::= @@ error double macros@@", macro)) << macro->Dump();
1391 ASSERT_EQ(2, macro->GetCount()) << macro->Dump();
1405 ASSERT_NO_THROW(Parse(
"@@macro(arg, ... )@@ ::= @@@ 3*@$arg @@@", macro)) << macro->Dump();
1406 ASSERT_EQ(3, macro->GetCount()) << macro->Dump();
1408 iter = macro->map::find(
"alias");
1409 ASSERT_TRUE(iter != macro->end());
1411 vect = iter->second;
1413 ASSERT_EQ(1, vect.size());
1415 macro_alias1 = vect[0];
1416 ASSERT_TRUE(macro_alias1);
1417 ASSERT_STREQ(
"@@ alias ( arg , ... ) @@ := @@ replace4 ( @$arg ) @@;", macro_alias1->toString().c_str());
1418 ASSERT_TRUE(macro_alias1->m_right);
1419 ASSERT_EQ(4, macro_alias1->m_right->m_macro_seq.size());
1420 ASSERT_STREQ(
"replace4", macro_alias1->m_right->m_macro_seq[0]->m_text.c_str());
1453 iter = macro->map::find(
"macro");
1454 ASSERT_TRUE(iter != macro->end());
1456 vect = iter->second;
1457 ASSERT_EQ(1, vect.size());
1458 TermPtr macro_macro1 = vect[0];
1459 ASSERT_TRUE(macro_macro1);
1460 ASSERT_STREQ(
"@@ macro ( arg , ... ) @@ ::= @@@ 3*@$arg @@@;", macro_macro1->toString().c_str());
1461 ASSERT_EQ(macro_macro1.get(), macro->GetMacro({
"macro"}).get());
1462 ASSERT_TRUE(macro_macro1->m_right);
1463 ASSERT_TRUE(macro_macro1->m_right->getTermID() == TermID::MACRO_STR) << macro_macro1->toString().c_str();
1469 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_alias1, macro_args));
1472 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_macro1, macro_args));
1474 buff.push_back(Term::Create(TermID::NAME,
"alias", parser::token_type::NAME));
1476 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_alias1, macro_args)) << macro_alias1->toString().c_str();
1480 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_macro1, macro_args)) << macro_macro1->toString().c_str();
1483 buff.push_back(Term::Create(TermID::SYMBOL,
"(", parser::token_type::SYMBOL));
1485 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_alias1, macro_args));
1487 buff.push_back(Term::Create(TermID::SYMBOL,
")", parser::token_type::SYMBOL));
1490 ASSERT_NO_THROW(count = Macro::ExtractArgs(buff, macro_alias1, macro_args));
1491 ASSERT_EQ(3, count);
1493 buff.erase(buff.end());
1497 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_macro1, macro_args));
1499 buff.push_back(Term::Create(TermID::NAME,
"value", parser::token_type::NAME));
1501 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_alias1, macro_args));
1503 buff.push_back(Term::Create(TermID::SYMBOL,
")", parser::token_type::SYMBOL));
1505 ASSERT_EQ(4, buff.size());
1506 ASSERT_NO_THROW(count = Macro::ExtractArgs(buff, macro_alias1, macro_args)) << Macro::Dump(buff);
1507 ASSERT_EQ(4, count);
1508 buff.erase(buff.end());
1512 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_macro1, macro_args));
1515 buff.push_back(Term::Create(TermID::SYMBOL,
",", parser::token_type::SYMBOL));
1520 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_macro1, macro_args));
1523 buff.push_back(Term::Create(TermID::NAME,
"value2", parser::token_type::NAME));
1525 buff.push_back(Term::Create(TermID::NAME,
"value3", parser::token_type::NAME));
1527 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_macro1, macro_args));
1530 buff.push_back(Term::Create(TermID::SYMBOL,
")", parser::token_type::SYMBOL));
1534 ASSERT_EQ(7, Macro::ExtractArgs(buff, macro_alias1, macro_args));
1536 ASSERT_EQ(6, macro_args.size()) << Macro::Dump(macro_args);
1541 ASSERT_EQ(7, buff.size());
1543 ASSERT_EQ(7, Macro::ExtractArgs(buff, macro_macro1, macro_args));
1545 ASSERT_EQ(6, macro_args.size()) << Macro::Dump(macro_args);
1551 buff.push_back(Term::Create(TermID::SYMBOL,
";", parser::token_type::SYMBOL));
1555 ASSERT_EQ(7, Macro::ExtractArgs(buff, macro_alias1, macro_args));
1558 ASSERT_EQ(6, macro_args.size()) << Macro::Dump(macro_args);
1560 ASSERT_EQ(8, buff.size()) << Macro::Dump(buff);
1562 ASSERT_EQ(7, Macro::ExtractArgs(buff, macro_macro1, macro_args));
1564 ASSERT_EQ(6, macro_args.size()) << Macro::Dump(macro_args);
1603 buff.push_back(Term::Create(TermID::NAME,
"macro", parser::token_type::NAME));
1604 buff.push_back(Term::Create(TermID::SYMBOL,
"(", parser::token_type::SYMBOL));
1605 buff.push_back(Term::Create(TermID::NUMBER,
"5", parser::token_type::NUMBER));
1606 buff.push_back(Term::Create(TermID::SYMBOL,
")", parser::token_type::SYMBOL));
1607 buff.push_back(Term::Create(TermID::SYMBOL,
";", parser::token_type::SYMBOL));
1609 TermPtr macro_macro = macro->GetMacro({
"macro"});
1610 ASSERT_TRUE(macro_macro);
1613 ASSERT_EQ(4, Macro::ExtractArgs(buff, macro_macro, macro_args)) << Macro::Dump(macro_args);
1615 ASSERT_EQ(5, macro_args.size()) << Macro::Dump(macro_args);
1617 std::string str = Macro::ExpandString(macro_macro, macro_args);
1618 ASSERT_STREQ(
" 3*5 ", str.c_str());
1622 buff.push_back(Term::Create(TermID::NAME,
"alias3", parser::token_type::NAME));
1623 buff.push_back(Term::Create(TermID::SYMBOL,
"(", parser::token_type::SYMBOL));
1624 buff.push_back(Term::Create(TermID::NUMBER,
"5", parser::token_type::NUMBER));
1625 buff.push_back(Term::Create(TermID::SYMBOL,
")", parser::token_type::SYMBOL));
1626 buff.push_back(Term::Create(TermID::SYMBOL,
";", parser::token_type::SYMBOL));
1628 TermPtr macro_alias3 = macro->GetMacro({
"alias3"});
1629 ASSERT_TRUE(macro_alias3);
1631 ASSERT_STREQ(
"@@ alias3 ( ... ) @@ := @@ replace3 ( @$# , @$... ) @@;", macro_alias3->toString().c_str());
1632 ASSERT_TRUE(macro_alias3->m_right);
1633 ASSERT_EQ(6, macro_alias3->m_right->m_macro_seq.size());
1634 ASSERT_STREQ(
"replace3", macro_alias3->m_right->m_macro_seq[0]->m_text.c_str());
1638 ASSERT_EQ(4, Macro::ExtractArgs(buff, macro_alias3, macro_args)) << Macro::Dump(macro_args);
1640 ASSERT_EQ(4, macro_args.size()) << Macro::Dump(macro_args);
1642 auto iter_arg = macro_args.begin();
1643 ASSERT_TRUE(iter_arg != macro_args.end()) << Macro::Dump(macro_args);
1645 ASSERT_STREQ(
"@$#", iter_arg->first.c_str());
1646 ASSERT_EQ(1, iter_arg->second.size());
1647 ASSERT_STREQ(
"1", iter_arg->second.at(0)->m_text.c_str()) << Macro::Dump(macro_args);
1650 ASSERT_TRUE(iter_arg != macro_args.end());
1652 ASSERT_STREQ(
"@$*", iter_arg->first.c_str());
1653 ASSERT_STREQ(
"( 5 , )", Macro::Dump(iter_arg->second).c_str());
1656 ASSERT_TRUE(iter_arg != macro_args.end());
1658 ASSERT_STREQ(
"@$...", iter_arg->first.c_str());
1659 ASSERT_EQ(1, iter_arg->second.size());
1662 ASSERT_TRUE(iter_arg != macro_args.end());
1664 ASSERT_STREQ(
"@$1", iter_arg->first.c_str());
1665 ASSERT_EQ(1, iter_arg->second.size());
1668 ASSERT_TRUE(iter_arg == macro_args.end());
1689 BlockType blk = Macro::ExpandMacros(macro_alias3, macro_args);
1690 ASSERT_EQ(6, blk.size()) << Macro::Dump(blk).c_str();
1691 ASSERT_STREQ(
"replace3", blk[0]->m_text.c_str()) << macro_alias3->m_right->toString();
1692 ASSERT_STREQ(
"(", blk[1]->m_text.c_str()) << macro_alias3->m_right->toString();
1693 ASSERT_STREQ(
"1", blk[2]->m_text.c_str()) << macro_alias3->m_right->toString();
1694 ASSERT_STREQ(
",", blk[3]->m_text.c_str()) << macro_alias3->m_right->toString();
1695 ASSERT_STREQ(
"5", blk[4]->m_text.c_str()) << macro_alias3->m_right->toString();
1696 ASSERT_STREQ(
")", blk[5]->m_text.c_str()) << macro_alias3->m_right->toString();
1747TEST_F(MacroTest, MacroCheck) {
1749 MacroPtr macro = std::make_shared<Macro>();
1752 ASSERT_TRUE(macro->size() == 0);
1753 ASSERT_ANY_THROW(Parse(
"@@testargs(arg)@@ ::= @@ @$bad_arg @@", macro)) << macro->Dump();
1754 ASSERT_ANY_THROW(Parse(
"@@testargs(arg)@@ ::= @@ @$... @@", macro)) << macro->Dump();
1755 ASSERT_ANY_THROW(Parse(
"@@testargs(arg, ...)@@ ::= @@ @$2 @@", macro)) << macro->Dump();
1757 ASSERT_NO_THROW(Parse(
"@@ macro2(...) @@ ::= @@ replace2( @$#, @$... ,@$* ) @@", macro)) << macro->Dump();
1758 ASSERT_NO_THROW(Parse(
"macro2(1,9)", macro)) << macro->Dump() << LexOut().c_str();
1759 ASSERT_STREQ(
"replace2 ( 2 , 1 , 9 , ( 1 , 9 , ) )", LexOut().c_str());
1761 ASSERT_ANY_THROW(Parse(
"@@ return $... $... @@ ::= @@ @$... @@", macro)) << macro->Dump();
1762 ASSERT_ANY_THROW(Parse(
"@@ return() $... @@ ::= @@ @$... @@", macro)) << macro->Dump();
1764 ASSERT_NO_THROW(Parse(
"@@ return $... @@ ::= @@ :: ++ @$... ++ @@", macro)) << macro->Dump();
1765 ASSERT_NO_THROW(Parse(
"return (1, 2, 3,)", macro)) << macro->Dump() <<
" ------ "<< LexOut().c_str();
1766 ASSERT_STREQ(
":: ++ ( 1 , 2 , 3 , ) ++", LexOut().c_str());
1880TEST_F(MacroTest, MacroTest) {
1882 MacroPtr macro = std::make_shared<Macro>();
1885 ASSERT_EQ(0, macro->GetCount());
1887 ASSERT_NO_THROW(Parse(
"@@alias@@ := @@ replace @@", macro)) << macro->Dump();
1888 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
1889 ASSERT_EQ(1, (*macro)[
"alias"].size()) << macro->Dump();
1890 ASSERT_TRUE((*macro)[
"alias"][0]) << macro->Dump();
1891 ASSERT_STREQ(
"alias", Macro::toMacroHash((*macro)[
"alias"][0]).c_str()) << (*macro)[
"alias"][0]->toString();
1892 ASSERT_EQ(1, Macro::GetMacroId((*macro)[
"alias"][0]).size());
1893 ASSERT_TRUE(macro->GetMacro({
"alias"}));
1895 ASSERT_NO_THROW(Parse(
"alias", macro)) << macro->Dump();
1896 ASSERT_STREQ(
"replace", LexOut().c_str()) << macro->Dump();
1898 ASSERT_NO_THROW(Parse(
"alias()", macro)) << macro->Dump();
1899 ASSERT_STREQ(
"replace ( )", LexOut().c_str()) << macro->Dump();
1901 ASSERT_NO_THROW(Parse(
"alias(...)", macro)) << macro->Dump();
1902 ASSERT_STREQ(
"replace ( ... )", LexOut().c_str()) << macro->Dump();
1904 ASSERT_NO_THROW(Parse(
"alias(1,2,3)", macro)) << macro->Dump();
1905 ASSERT_STREQ(
"replace ( 1 , 2 , 3 )", LexOut().c_str()) << macro->Dump();
1907 ASSERT_NO_THROW(Parse(
"@alias", macro)) << macro->Dump();
1908 ASSERT_STREQ(
"replace", LexOut().c_str()) << macro->Dump();
1910 ASSERT_NO_THROW(Parse(
"@alias(); @alias", macro)) << macro->Dump() <<
" LEX: \"" << LexOut().c_str() <<
"\"";
1911 ASSERT_STREQ(
"replace ( ) ; replace", LexOut().c_str()) << macro->Dump();
1913 ASSERT_NO_THROW(Parse(
"@alias(...)", macro)) << macro->Dump();
1914 ASSERT_STREQ(
"replace ( ... )", LexOut().c_str()) << macro->Dump();
1916 ASSERT_NO_THROW(Parse(
"@alias(1,2,3); none", macro)) << macro->Dump();
1917 ASSERT_STREQ(
"replace ( 1 , 2 , 3 ) ; none", LexOut().c_str()) << macro->Dump();
1920 ASSERT_NO_THROW(Parse(
"@@ macro1 @@ ::= @@ replace1 @@", macro)) << macro->Dump();
1921 ASSERT_EQ(2, macro->GetCount()) << macro->Dump();
1922 ASSERT_TRUE(macro->GetMacro({
"macro1"}));
1923 ASSERT_TRUE(macro->GetMacro({
"macro1"})->isMacro());
1925 ASSERT_NO_THROW(Parse(
"macro1", macro)) << macro->Dump();
1926 ASSERT_STREQ(
"replace1", LexOut().c_str());
1928 ASSERT_NO_THROW(Parse(
"@macro1()", macro)) << macro->Dump();
1929 ASSERT_STREQ(
"replace1 ( )", LexOut().c_str());
1931 ASSERT_NO_THROW(Parse(
"@macro1(...)", macro)) << macro->Dump();
1932 ASSERT_STREQ(
"replace1 ( ... )", LexOut().c_str());
1934 ASSERT_NO_THROW(Parse(
"@macro1(1,2,3)", macro)) << macro->Dump();
1935 ASSERT_STREQ(
"replace1 ( 1 , 2 , 3 )", LexOut().c_str());
1937 ASSERT_NO_THROW(Parse(
"@macro1", macro)) << macro->Dump();
1938 ASSERT_STREQ(
"replace1", LexOut().c_str());
1941 ASSERT_ANY_THROW(Parse(
"@macro1() @alias", macro)) << macro->Dump();
1942 ASSERT_ANY_THROW(Parse(
"none @macro1(...)", macro)) << macro->Dump();
1947 ASSERT_NO_THROW(Parse(
"@@ macro2(...) @@ ::= @@ replace2( @$... ) @@", macro)) << macro->Dump();
1948 ASSERT_EQ(3, macro->GetCount()) << macro->Dump();
1949 ASSERT_TRUE(macro->GetMacro({
"macro2"}));
1950 ASSERT_TRUE(macro->GetMacro({
"macro2"})->m_left);
1951 ASSERT_EQ(TermID::MACRO_SEQ, macro->GetMacro({
"macro2"})->m_left->getTermID());
1953 ASSERT_ANY_THROW(Parse(
"macro2", macro)) << macro->Dump();
1955 ASSERT_NO_THROW(Parse(
"macro2()", macro)) << macro->Dump();
1956 ASSERT_STREQ(
"replace2 ( )", LexOut().c_str());
1958 ASSERT_NO_THROW(Parse(
"macro2()", macro)) << macro->Dump();
1959 ASSERT_STREQ(
"replace2 ( )", LexOut().c_str());
1961 ASSERT_NO_THROW(Parse(
"macro2( 1 )", macro)) << macro->Dump();
1962 ASSERT_STREQ(
"replace2 ( 1 )", LexOut().c_str());
1964 ASSERT_NO_THROW(Parse(
"macro2(1,2,3)", macro)) << macro->Dump();
1965 ASSERT_STREQ(
"replace2 ( 1 , 2 , 3 )", LexOut().c_str());
1967 ASSERT_ANY_THROW(Parse(
"@macro2", macro)) << macro->Dump();
1969 ASSERT_NO_THROW(Parse(
"@macro2(); @alias(123)", macro)) << macro->Dump();
1970 ASSERT_STREQ(
"replace2 ( ) ; replace ( 123 )", LexOut().c_str());
1972 ASSERT_NO_THROW(Parse(
"none;@macro2(...)", macro)) << macro->Dump();
1973 ASSERT_STREQ(
"none ; replace2 ( ... )", LexOut().c_str());
1975 ASSERT_NO_THROW(Parse(
"@macro2(1,2,3);\n", macro)) << macro->Dump();
1976 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