NewLang Project
Yet another programm language
Loading...
Searching...
No Matches
macro_test.cpp
Go to the documentation of this file.
1#ifdef BUILD_UNITTEST
2
3#include "warning_push.h"
4#include <gtest/gtest.h>
5#include "warning_pop.h"
6
7#include "macro.h"
8#include "runtime.h"
9//#include "nlc.h"
10#include "lexer.h"
11
12using namespace newlang;
13
14class MacroTest : public ::testing::Test {
15protected:
16
17
18
19 std::vector<std::string> m_postlex;
20
21 Logger::FuncCallback *m_log_callback_save;
22 void *m_log_callback_arg_save;
23 std::string m_output;
24
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);
28 if (flush) {
29 fflush(stdout);
30 }
31 if (p) {
32 p->m_output += str;
33 }
34 }
35
36 void SetUp() {
37 Logger::Instance()->SaveCallback(m_log_callback_save, m_log_callback_arg_save);
38 Logger::Instance()->SetCallback(&LoggerCallback, this);
39 }
40
41 void TearDown() {
42 Logger::Instance()->SetCallback(m_log_callback_save, m_log_callback_arg_save);
43 }
44
45 TermPtr Parse(std::string str, MacroPtr buffer = nullptr, DiagPtr diag = nullptr) {
46 m_postlex.clear();
47 ast = Parser::ParseString(str, buffer, &m_postlex, diag);
48 return ast;
49 }
50
51 int Count(TermID token_id) {
52 int result = 0;
53 for (int c = 0; c < ast->size(); c++) {
54 if ((*ast)[c].second->m_id == token_id) {
55 result++;
56 }
57 }
58 return result;
59 }
60
61 std::string LexOut() {
62 std::string result;
63 for (int i = 0; i < m_postlex.size(); i++) {
64 if (!result.empty()) {
65 result += " ";
66 }
67 result += m_postlex[i];
68 }
69 trim(result);
70 return result;
71 }
72
73 TermPtr ast;
74};
75
76
77
78
79/*
80 * Макросы хрянтся как фрагменты AST в виде объектов типа Term,
81 * так как создаются после обработки парсером по правилам стандратной грамматики.
82 *
83 * Но анализ входных данных на предмет раскрытия макросов проиходит из потока (последовательности) лексем,
84 * т.е. **ДО** обработки парсером, так как при раскрытии макросов может меняться сама грамматика выражений.
85 *
86 * Функция \ref IdentityMacro сравнивает входной буфер (последовательность лексем)
87 * на предмет возможного соответствия одному конкретному макросу.
88 * Сравниваются только ключевые словам без учета аргументов в скобках, только наличие или отсуствие скобок,
89 * так с аргументами и без аргументов, это два разных макроса.
90 * Проверка аргументов макроса выполняется в функции \ref ExtractArgs
91 *
92 * Проблема:
93 * К функции можно обратится с целью её вызова (указав после имени скобки),
94 * так и по имени без скобок (например для получения ссылки на объект).
95 * Так и к переменной можно обратиться только по имени,
96 * так и указав скобки после имени как к функции (при копировании объекта).
97 *
98 * Сделать один макрос под оба сценария (со скобками и без скобок) не получится, так как непонятно,
99 * что делать с аргументами при раскрытии тела макроса, когда они не указаны.
100 *
101 * Но может быть следует переименовывать только одно имя без учета скобок,
102 * например, оставив такую возможность только для одиночных макросов.
103 *
104 *
105 * @macro() := with_bracket;
106 * @macro := without_bracket;
107 * или
108 * @macro :- ignore_bracket;
109 *
110 * macro() -> ignore_bracket();
111 * macro -> ignore_bracket;
112 *
113 *
114 * \\name -> name или name (...), hash: name
115 * но \\name(...) -> name(...), а name - ошибка !!!! hash: name
116 *
117 * Или все же следует различать макросы со скобками и без скобок как два разных объекта???
118 * \\name := name2; и \\name(...) := name2(...); будут разными объектами
119 *
120 * Или добавить макросы-алиасы без аргументов только для переименования отдельных терминов?
121 * @alias :- name2; но как их отличать от обычных макросов в операции удаления?
122 * Или вообще не нужно отличать и оставить только один варинат (либо макрос, либо алиас)
123 * Тода вопрос со скобками закрывается сам собой, алиасы всегда без скобок,
124 * макросы со скбками или без скобок, но должно быть полное соответствие.
125 *
126 * @@ name name2 @@ -> name name2, но name name2(...) - ошибка!!! (hash: name,name2)
127 * @@ name name2(...) @@ -> name name2(...), но name name2 - ошибка !!!! (hash: name,name2)
128 * @@ name name2[...](...) @@ -> name name2[...](...), но name name2 - ошибка !!!! ( hash: name,name2 )
129 * @@ name $tmpl[...](...) name3@@ -> name $tmpl[...](...) name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )
130 *
131 * Но!
132 * @@ name name2 @@ ::- -> name name2 - ок, но name name2(...) - ок
133 * @@ name $tmpl name3 @@ ::- -> name $tmpl[...](...) name3 - ок, name $tmpl(...) name3[...] - ок
134 *
135 *
136 *
137 * Для последовательности лексем требуется полное соответствие с учетом скобок ???
138 * и может ли быть несколько скобок одного типа (несколько круглых, или несколько квадратных????
139 * <Может быть несколько скобок одного типа, например, при указании типа у аргументов или типа возвращаемого значения.>
140 *
141 * @@ name name2 @@ -> name name2, но name name2(...) - ошибка!!! (hash: name,name2)
142 * @@ name name2(...) @@ -> name name2(...), но name name2 - ошибка !!!! (hash: name,name2)
143 * @@ name name2[...](...) @@ -> name name2[...](...), но name name2 - ошибка !!!! ( hash: name,name2 )
144 * @@ name $tmpl[...](...) name3 @@ -> name $tmpl[...](...) name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )
145 *
146 * Проблема скобок возникает из-за сценария замены одного термина на другой,
147 * который есть в препроцессоре С/С++, но отсутствует при реализации с использованием шаблонов.
148 *
149 *
150 *
151 *
152 * ```python
153
154try:
155 a = float(input("Введите число: ")
156 print (100 / a)
157except ValueError:
158 print ("Это не число!")
159except ZeroDivisionError:
160 print ("На ноль делить нельзя!")
161except:
162 print ("Неожиданная ошибка.")
163else:
164 print ("Код выполнился без ошибок")
165finally:
166 print ("Я выполняюсь в любом случае!")
167
168```
169```
170
171[1] =>{
172
173 [1] --> {
174
175 },[2] --> {*
176
177 *},[...] --> {
178 other
179 }
180 on_exit();
181};
182
183
184{* # try:
185 a = float(input("Введите число: ");
186 print (100 / a);
187 *} ~> {
188
189 [:ValueError] --> print ("Это не число!"), # except ValueError:
190 [:ZeroDivisionError] --> print ("На ноль делить нельзя!"), # except ZeroDivisionError
191 [:IntMinus] --> print ("Неожиданная ошибка."), # except:
192 [...] --> print ("Код выполнился без ошибок"); # else:
193
194 print ("Я выполняюсь в любом случае!"); # finally:
195}
196 * try := @ __TERM_EXPECTED__('{*') @
197 *
198 * catch := @ *} ~> @
199 *
200 *
201 */
202
203/*
204 @##
205 @#
206
207@func(...) := call(?);
208
209@$name
210
211@$name(...)
212@$name[...]
213@$name<...>
214
215@$name(*)
216@$name[*]
217@$name<*>
218
219@$name(#)
220@$name[#]
221@$name<#>
222
223 * */
224TEST_F(MacroTest, Escape) {
225
226 ASSERT_TRUE(Parse("@\\ {+"));
227 ASSERT_EQ(TermID::ESCAPE, ast->getTermID());
228 EXPECT_STREQ("{+", ast->m_text.c_str());
229}
230
231TEST_F(MacroTest, PredefMacro) {
232 Parser p;
233
234 ASSERT_TRUE(p.m_predef_macro.empty());
235 ASSERT_EQ(0, p.m_predef_macro.size());
236
237 TermPtr term = Term::Create(parser::token_type::MACRO, TermID::MACRO, "@__NLC_VER__");
238 ASSERT_EQ(parser::token_type::INTEGER, p.ExpandPredefMacro(term));
239
240 ASSERT_FALSE(p.m_predef_macro.empty());
241 ASSERT_TRUE(p.m_predef_macro.size() > 5);
242
243
244 ASSERT_EQ(0, p.m_counter);
245 for (auto &elem : p.m_predef_macro) {
246 ASSERT_FALSE(elem.first.empty());
247 ASSERT_FALSE(elem.second.empty());
248
249 term->m_text = elem.first;
250 term->m_id = TermID::MACRO;
251 term->m_lexer_type = parser::token_type::MACRO;
252
253 ASSERT_NE(parser::token_type::MACRO, p.ExpandPredefMacro(term));
254 }
255 ASSERT_EQ(1, p.m_counter);
256
257
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());
261
262 p.m_counter = 0;
263 ASSERT_NO_THROW(Parse("@__COUNTER__"));
264 ASSERT_STREQ("0", ast->toString().c_str());
265 ASSERT_EQ(1, p.m_counter);
266 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
267
268 ASSERT_NO_THROW(Parse("@__COUNTER__"));
269 ASSERT_STREQ("1", ast->toString().c_str());
270 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
271
272 ASSERT_NO_THROW(Parse("@__COUNTER__"));
273 ASSERT_STREQ("2", ast->toString().c_str());
274 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
275
276 ASSERT_NO_THROW(Parse("@__COUNTER__"));
277 ASSERT_STREQ("3", ast->toString().c_str());
278 ASSERT_EQ(TermID::INTEGER, ast->getTermID());
279
280
281 ASSERT_NO_THROW(Parse("@__TIME__"));
282 ASSERT_EQ(10, ast->toString().size()) << ast->toString();
283 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
284
285 ASSERT_NO_THROW(Parse("@__DATE__"));
286 ASSERT_EQ(13, ast->toString().size()) << ast->toString();
287 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
288
289 ASSERT_NO_THROW(Parse("@__TIMESTAMP__"));
290 ASSERT_EQ(26, ast->toString().size()) << ast->toString();
291 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
292
293 ASSERT_NO_THROW(Parse("@__TIMESTAMP_ISO__"));
294 ASSERT_EQ(22, ast->toString().size()) << ast->toString();
295 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
296
297
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());
301
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());
305
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());
309
310
311 ASSERT_NO_THROW(Parse("@__FILE__"));
312 ASSERT_STREQ("\"File name undefined!!!\"", ast->toString().c_str());
313 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
314
315 ASSERT_NO_THROW(Parse("@__FILE_NAME__"));
316 ASSERT_STREQ("\"File name undefined!!!\"", ast->toString().c_str());
317 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
318
319
320 ASSERT_NO_THROW(Parse("@__FILE_TIMESTAMP__"));
321 ASSERT_EQ(26, ast->toString().size()) << ast->toString();
322 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
323
324 ASSERT_NO_THROW(Parse("@__FILE_MD5__"));
325 ASSERT_TRUE(ast->toString().size() > 30) << ast->toString();
326 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
327
328
329 ASSERT_NO_THROW(Parse("@__NLC_SOURCE_GIT__"));
330 ASSERT_STREQ("\"" VERSION_GIT_SOURCE "\"", ast->toString().c_str());
331 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
332
333 ASSERT_NO_THROW(Parse("@__NLC_DATE_BUILD__"));
334 ASSERT_STREQ("\"" VERSION_DATE_BUILD_STR "\"", ast->toString().c_str());
335 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
336
337 ASSERT_NO_THROW(Parse("@__NLC_SOURCE_BUILD__"));
338 ASSERT_STREQ("\"" VERSION_SOURCE_FULL_ID "\"", ast->toString().c_str());
339 ASSERT_EQ(TermID::STRWIDE, ast->getTermID());
340
341
342
343 std::filesystem::create_directories("temp");
344 ASSERT_TRUE(std::filesystem::is_directory("temp"));
345
346 std::ofstream out("temp/file.md5.test");
347 out << "@__LINE__; @__FILE__; @__FILE_TIMESTAMP__; @__FILE_MD5__;";
348 out.close();
349
350 ASSERT_NO_THROW(
351 ASSERT_TRUE(ast = p.ParseFile("temp/file.md5.test"))
352 );
353
354 ASSERT_EQ(4, ast->m_block.size()) << ast->toString().c_str();
355
356 ASSERT_STREQ("1", ast->m_block[0]->toString().c_str());
357 ASSERT_EQ(TermID::INTEGER, ast->m_block[0]->getTermID());
358
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());
361
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());
364
365 ASSERT_STREQ("\"c3b16159b22333f2b0d1abe7f2960ce0\"", ast->m_block[3]->toString().c_str());
366 ASSERT_EQ(TermID::STRWIDE, ast->m_block[3]->getTermID());
367
368 std::remove("temp/file.md5.test");
369
370
371
372 term->m_text = "@__NOT_FOUND__";
373 term->m_id = TermID::MACRO;
374 term->m_lexer_type = parser::token_type::MACRO;
375
376 ASSERT_NO_THROW(p.ExpandPredefMacro(term));
377
378 ASSERT_TRUE(p.RegisterPredefMacro("@__NOT_FOUND__", ""));
379 ASSERT_ANY_THROW(p.ExpandPredefMacro(term));
380 ASSERT_FALSE(p.RegisterPredefMacro("@__NOT_FOUND__", ""));
381
382}
383
384TEST_F(MacroTest, ParseTerm) {
385
386 TermPtr term;
387 BlockType buff;
388 size_t size;
389
390
391 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME, "alias")); // alias
392
393 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
394 ASSERT_EQ(1, size);
395 ASSERT_TRUE(term);
396 ASSERT_FALSE(term->isCall());
397 ASSERT_STREQ("alias", term->toString().c_str());
398
399
400 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME, "alias")); // alias alias
401
402 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
403 ASSERT_EQ(1, size);
404 ASSERT_TRUE(term);
405 ASSERT_FALSE(term->isCall());
406 ASSERT_STREQ("alias", term->toString().c_str());
407
408 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME, "second")); // alias alias second
409
410 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
411 ASSERT_EQ(1, size);
412 ASSERT_TRUE(term);
413 ASSERT_FALSE(term->isCall());
414 ASSERT_STREQ("alias", term->toString().c_str());
415
416 buff.erase(buff.begin(), buff.begin() + 2);
417 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL, "(")); // second (
418
419 ASSERT_ANY_THROW(Parser::ParseTerm(term, buff, 0));
420
421 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL, ")")); // second ( )
422
423 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
424 ASSERT_EQ(3, size);
425 ASSERT_TRUE(term);
426 ASSERT_TRUE(term->isCall());
427 ASSERT_STREQ("second()", term->toString().c_str());
428
429 buff.erase(buff.end()); // second (
430
431 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME, "name")); // second ( name
432 ASSERT_ANY_THROW(Parser::ParseTerm(term, buff, 0));
433
434 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL, ")")); // second ( name )
435
436 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
437 ASSERT_EQ(4, size);
438 ASSERT_TRUE(term);
439 ASSERT_TRUE(term->isCall());
440 ASSERT_STREQ("second(name)", term->toString().c_str());
441
442
443 buff.erase(buff.end()); // second ( name
444 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL, "=")); // second ( name =
445 ASSERT_ANY_THROW(Parser::ParseTerm(term, buff, 0));
446
447 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME, "value")); // second ( name = value
448 ASSERT_ANY_THROW(Parser::ParseTerm(term, buff, 0));
449
450 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL, ")")); // second ( name = value )
451
452 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
453 ASSERT_EQ(6, size);
454 ASSERT_TRUE(term);
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());
459
460
461 buff = Scanner::ParseLexem("second2 ( 1 , ( 123 , ) );\n\n\n\n;");
462
463 ASSERT_NO_THROW(size = Parser::ParseTerm(term, buff, 0));
464 ASSERT_EQ(9, size);
465 ASSERT_TRUE(term);
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());
471
472}
473
474TEST_F(MacroTest, Pragma) {
475
476 DiagPtr diag = Diag::Init();
477
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();
484
485 // m_output.clear();
486 // ASSERT_ANY_THROW(Parse("@__PRAGMA_NOT_FOUND__()"));
487 // ASSERT_STREQ("", LexOut().c_str());
488 // ASSERT_TRUE(m_output.find("Uknown pragma '@__PRAGMA_NOT_FOUND__()") != std::string::npos) << m_output;
489 //
490 // m_output.clear();
491 // ASSERT_ANY_THROW(Parse("@__PRAGMA_DIAG__("));
492 // ASSERT_STREQ("", LexOut().c_str());
493 // ASSERT_TRUE(m_output.find("Closed bracket ')' not found!") != std::string::npos) << m_output;
494 //
495 // m_output.clear();
496 // ASSERT_ANY_THROW(Parse("@__PRAGMA_DIAG__)"));
497 // ASSERT_STREQ("", LexOut().c_str());
498 // ASSERT_TRUE(m_output.find("Expected") != std::string::npos) << m_output;
499 //
500 // m_output.clear();
501 // ASSERT_ANY_THROW(Parse("@__PRAGMA_DIAG__(,)"));
502 // ASSERT_STREQ("", LexOut().c_str());
503 // ASSERT_TRUE(m_output.find("unexpected ','") != std::string::npos) << m_output;
504 //
505 // m_output.clear();
506 // ASSERT_ANY_THROW(Parse("@__PRAGMA_DIAG__(push,)"));
507 // ASSERT_STREQ("", LexOut().c_str());
508 // ASSERT_TRUE(m_output.find("syntax error, unexpected ')'") != std::string::npos) << m_output;
509 //
510 //
511 // ASSERT_EQ(1, diag->m_diag_stack.size());
512 // ASSERT_TRUE(Parse("@__PRAGMA_DIAG__(push)", nullptr, diag));
513 // ASSERT_EQ(2, diag->m_diag_stack.size());
514 // ASSERT_STREQ("", LexOut().c_str());
515 //
516 // ASSERT_TRUE(Parse("@__PRAGMA_DIAG__( pop )", nullptr, diag));
517 // ASSERT_EQ(1, diag->m_diag_stack.size());
518 // ASSERT_STREQ("", LexOut().c_str());
519 //
520 //
521 // m_output.clear();
522 // ASSERT_TRUE(Parse("@__PRAGMA_MESSAGE__(test)", nullptr, diag));
523 // ASSERT_STREQ("", LexOut().c_str());
524 // ASSERT_TRUE(m_output.find("note: test") != std::string::npos) << m_output;
525 //
526 // m_output.clear();
527 // ASSERT_TRUE(Parse("@__PRAGMA_MESSAGE__(\"test\")", nullptr, diag));
528 // ASSERT_STREQ("", LexOut().c_str());
529 // ASSERT_TRUE(m_output.find("note: test") != std::string::npos) << m_output;
530 //
531 // m_output.clear();
532 // ASSERT_TRUE(Parse("@__PRAGMA_MESSAGE__(\"test test2\")", nullptr, diag));
533 // ASSERT_STREQ("", LexOut().c_str());
534 // ASSERT_TRUE(m_output.find("note: test test2") != std::string::npos) << m_output;
535 //
536 // m_output.clear();
537 // ASSERT_TRUE(Parse("@__PRAGMA_MESSAGE__(test,\"test2\")", nullptr, diag));
538 // ASSERT_STREQ("", LexOut().c_str());
539 // ASSERT_TRUE(m_output.find("note: testtest2") != std::string::npos) << m_output;
540 //
541 // m_output.clear();
542 // ASSERT_ANY_THROW(Parse("@__PRAGMA_EXPECTED__( @\\ {, @\\ {*, @\\ {+)", nullptr, diag));
543 // ASSERT_STREQ("", LexOut().c_str());
544 // ASSERT_TRUE(m_output.find("Term '{', '{*', '{+' expected!") != std::string::npos) << m_output;
545 //
546 // m_output.clear();
547 // ASSERT_ANY_THROW(Parse("@__PRAGMA_EXPECTED__( @\\ {, @\\ {*, @\\ {+) {- -}", nullptr, diag));
548 // ASSERT_STREQ("", LexOut().c_str());
549 // ASSERT_TRUE(m_output.find("Term '{', '{*', '{+' expected!") != std::string::npos) << m_output;
550 //
551 // m_output.clear();
552 // ASSERT_NO_THROW(Parse("@__PRAGMA_EXPECTED__( @\\ {, @\\ {*, @\\ {+ ){}", nullptr, diag));
553 // ASSERT_STREQ("{ }", LexOut().c_str());
554 // ASSERT_TRUE(m_output.find("Term '{', '{*', '{+' expected!") == std::string::npos) << m_output;
555 //
556 // m_output.clear();
557 // ASSERT_NO_THROW(Parse("@__PRAGMA_EXPECTED__( @\\ {, @\\ {*, @\\ {+){+ +}", nullptr, diag));
558 // ASSERT_STREQ("{+ +}", LexOut().c_str());
559 // ASSERT_TRUE(m_output.find("Term '{', '{*', '{+' expected!") == std::string::npos) << m_output;
560 //
561 //
562 // m_output.clear();
563 // ASSERT_ANY_THROW(Parse("@__PRAGMA_UNEXPECTED__( @\\{, @\\{*, @\\{+) {", nullptr, diag));
564 // ASSERT_STREQ("", LexOut().c_str());
565 // ASSERT_TRUE(m_output.find("Term '{' unexpected!") != std::string::npos) << m_output;
566 //
567 // m_output.clear();
568 // ASSERT_NO_THROW(Parse("@__PRAGMA_UNEXPECTED__( @\\{, @\\{*, @\\{+){- -}", nullptr, diag));
569 // ASSERT_STREQ("{- -}", LexOut().c_str());
570 // ASSERT_TRUE(m_output.find("expected") == std::string::npos) << m_output;
571 //
572 // m_output.clear();
573 // ASSERT_NO_THROW(Parse("@__PRAGMA_UNEXPECTED__( @\\{*, @\\{+){}", nullptr, diag));
574 // ASSERT_STREQ("{ }", LexOut().c_str());
575 // ASSERT_TRUE(m_output.find("expected") == std::string::npos) << m_output;
576 //
577 // m_output.clear();
578 // ASSERT_ANY_THROW(Parse("@__PRAGMA_UNEXPECTED__( name ) name", nullptr, diag));
579 // ASSERT_STREQ("", LexOut().c_str());
580 // ASSERT_TRUE(m_output.find("Term 'name' unexpected!") != std::string::npos) << m_output;
581 //
582 //
583 // m_output.clear();
584 // ASSERT_ANY_THROW(Parse("@__PRAGMA_LOCATION__", nullptr, diag));
585 // ASSERT_STREQ("", LexOut().c_str()) << LexOut().c_str();
586 // ASSERT_TRUE(m_output.find("See @__PRAGMA_LOCATION__") != std::string::npos) << m_output;
587 //
588 // m_output.clear();
589 // ASSERT_NO_THROW(Parse("@__PRAGMA_LOCATION__(100);", nullptr, diag));
590 // ASSERT_STREQ("", LexOut().c_str());
591
592 m_output.clear();
593 ASSERT_NO_THROW(Parse("@__PRAGMA_LOCATION__(9) @__PRAGMA_LOCATION__(100) @__LINE__", nullptr, diag)) << LexOut().c_str();
594 ASSERT_STREQ("100", LexOut().c_str());
595
596 m_output.clear();
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());
599
600 m_output.clear();
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());
603
604 m_output.clear();
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());
607
608}
609
610TEST_F(MacroTest, Annotate) {
611
612 m_output.clear();
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;
616
617
618 m_output.clear();
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;
622
623 m_output.clear();
624 ASSERT_NO_THROW(Parse("@__ANNOTATION_SET__(name)"));
625 ASSERT_STREQ("", LexOut().c_str());
626
627 m_output.clear();
628 ASSERT_NO_THROW(Parse("@__ANNOTATION_SET__(name, \"value\")"));
629 ASSERT_STREQ("", LexOut().c_str());
630
631 m_output.clear();
632 ASSERT_NO_THROW(Parse("@__ANNOTATION_SET__(name, 1)"));
633 ASSERT_STREQ("", LexOut().c_str());
634
635
636
637 m_output.clear();
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;
641
642 m_output.clear();
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;
646
647 m_output.clear();
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;
651
652 m_output.clear();
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;
656
657
658 m_output.clear();
659 ASSERT_NO_THROW(Parse("@__ANNOTATION_SET__(name, 1) @__ANNOTATION_IIF__(name, 1, 2)"));
660 ASSERT_STREQ("1", LexOut().c_str());
661
662 // m_output.clear();
663 // ASSERT_NO_THROW(Parse("@__ANNOTATION_SET__(name, 1);\n @__ANNOTATION_IIF__(other, 1, 2);\n"));
664 // ASSERT_STREQ("2", LexOut().c_str());
665
666 m_output.clear();
667 ASSERT_NO_THROW(Parse("@__ANNOTATION_SET__(name, 0) @__ANNOTATION_IIF__(name, 1, 2)"));
668 ASSERT_STREQ("2", LexOut().c_str());
669}
670
671TEST_F(MacroTest, Buffer) {
672
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());
676
677 TermPtr term;
678 BlockType buffer;
679 MacroPtr macro_buf = std::make_shared<Macro>();
680
681 ASSERT_FALSE(Macro::IdentityMacro(buffer, term));
682
683#define CREATE_TERM(type, text) Term::Create(parser::token_type:: type, TermID:: type, text)
684
685 term = Parse("@@ macro @@ := @@ name @@", macro_buf);
686 ASSERT_TRUE(term);
687 ASSERT_TRUE(term->isMacro());
688 ASSERT_TRUE(term->Left());
689
690 buffer.push_back(CREATE_TERM(NAME, "macro"));
691 ASSERT_TRUE(Macro::IdentityMacro(buffer, term));
692
693 // Входной буфер больше
694 buffer.push_back(CREATE_TERM(NAME, "macro2"));
695 ASSERT_TRUE(Macro::IdentityMacro(buffer, term));
696
697 // Разные имена терминов
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));
704
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));
709
710
711
712
713
714 TermPtr hash = Parse("@@ name1 name2 @@ := @@ @@", macro_buf);
715 ASSERT_TRUE(hash);
716 ASSERT_TRUE(hash->isMacro());
717 ASSERT_TRUE(hash->Left());
718 ASSERT_TRUE(hash->Right());
719
720 ASSERT_STREQ("name1", Macro::toMacroHash(hash).c_str());
721
722
723
724
725 MacroPtr macro = std::make_shared<Macro>();
726 ASSERT_EQ(0, macro->size());
727
728 ASSERT_TRUE(term = Parse("@@alias@@ := alias_name", macro));
729 ASSERT_STREQ("@@ alias @@ := alias_name", LexOut().c_str());
730 ASSERT_TRUE(term);
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());
736
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());
740
741
742 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
743 ASSERT_TRUE(macro->GetMacro({"alias"})) << macro->Dump();
744
745 // FAIL REDEFINE
746 ASSERT_ANY_THROW(Parse("@@alias@@ ::= alias_name2;", macro)) << macro->Dump();
747 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
748 // ASSERT_TRUE(macro->GetMacro({"alias"})) << macro->Dump();
749 // ASSERT_STREQ("@@ alias @@ ::= alias_name2 ;", LexOut().c_str());
750
751 // ASSERT_ANY_THROW(Parse("@alias+alias := alias_name;", macro)) << macro->Dump();
752 // ASSERT_EQ(1, macro->GetCount());
753
754 ASSERT_TRUE(term = Parse("@@alias2@@ := alias_name", macro));
755 ASSERT_EQ(2, macro->GetCount());
756 ASSERT_STREQ("@@ alias2 @@ := alias_name", LexOut().c_str());
757
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());
762
763
764 ASSERT_ANY_THROW(Parse("@@@@ @@@@", macro));
765
766 ASSERT_TRUE(Parse("@@@@alias@@@@", macro));
767 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
768 ASSERT_STREQ("@@@@ alias @@@@", LexOut().c_str());
769
770 ASSERT_TRUE(Parse("@@@@_@@@@;", macro));
771 ASSERT_EQ(0, macro->GetCount()) << macro->Dump();
772 ASSERT_STREQ("@@@@ _ @@@@ ;", LexOut().c_str());
773
774
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());
778
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());
783
784
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());
788
789
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();
793
794 ASSERT_TRUE(term = Parse("@@if2(...)@@ := @@@ [ @__LINE__ ] --> @@@", macro));
795 ASSERT_STREQ("@@ if2 ( ... ) @@ := [ @__LINE__ ] -->", LexOut().c_str());
796
797 ASSERT_TRUE(term = Parse("@@if2(...)@@ := @@ [ @__LINE__ ] --> @@", macro));
798 ASSERT_STREQ("@@ if2 ( ... ) @@ := @@ [ @__LINE__ ] --> @@", LexOut().c_str());
799
800
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());
807
808
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());
813
814
815
816
817 ASSERT_TRUE(term = Parse("@@ func $name(arg= @__LINE__ , ...) @@ := @@@ [ @__LINE__ ] --> @@@", macro));
818 ASSERT_STREQ("@@ func $name ( arg = @__LINE__ , ... ) @@ := [ @__LINE__ ] -->", LexOut().c_str());
819
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());
825
826
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());
831
832#undef CREATE_TERM
833
834}
835
836TEST_F(MacroTest, MacroMacro) {
837 MacroPtr macro = std::make_shared<Macro>();
838 ASSERT_EQ(0, macro->size());
839
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));
847
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"});
857
858
859 TermPtr term = Term::Create(parser::token_type::NAME, TermID::NAME, "alias");
860
861 ASSERT_TRUE(macro->GetMacro({"alias", "replace"}));
862 ASSERT_TRUE(macro->GetMacro({"alias", "second"}));
863
864
865 BlockType buff;
866 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace)); // alias replace
867 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second)); // alias second
868 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text)); // text
869 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl)); // dsl
870
871
872 buff.push_back(term); // alias
873
874 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace)); // alias replace
875 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second)); // alias second
876 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text)); // text
877 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl)); // dsl
878
879 buff.push_back(term); // alias alias
880
881 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace)); // alias replace
882 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second)); // alias second
883 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text)); // text
884 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl)); // dsl
885
886 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME, "second")); // alias alias second
887
888 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace)); // alias replace
889 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second)); // alias second
890 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text)); // text
891 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl)); // dsl
892
893 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL, "(")); // alias alias second (
894
895 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace)); // alias replace
896 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second)); // alias second
897 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text)); // text
898 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl)); // dsl
899
900 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL, ")")); // alias alias second ( )
901
902 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace)); // alias replace
903 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second)); // alias second
904 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text)); // text
905 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl)); // dsl
906
907 buff.erase(buff.begin()); // alias second ( )
908
909 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_replace)); // alias replace
910 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_second)); // alias second
911 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text)); // text
912 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl)); // dsl
913
914
915
916 // ASSERT_TRUE(Parse("alias", macro));
917 // ASSERT_EQ(TermID::NAME, ast->getTermID()) << newlang::toString(ast->getTermID());
918 // ASSERT_STREQ("alias", ast->toString().c_str());
919
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());
923
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());
927
928
929
930 ASSERT_EQ(4, macro->GetCount());
931 ASSERT_FALSE(macro->GetMacro({"m1"})) << macro->Dump();
932 ASSERT_FALSE(macro->GetMacro({"m2"})) << macro->Dump();
933
934 //@todo Bug: https://github.com/rsashka/newlang/issues/22
935 // ASSERT_TRUE(Parse("dsl", macro));
936 //
937 // ASSERT_EQ(6, macro->GetCount());
938 // ASSERT_TRUE(macro->GetMacro({"m1"})) << macro->Dump();
939 // ASSERT_TRUE(macro->GetMacro({"m2"})) << macro->Dump();
940}
941
942TEST_F(MacroTest, Simple) {
943 MacroPtr macro = std::make_shared<Macro>();
944 ASSERT_EQ(0, macro->size());
945
946 ASSERT_NO_THROW(Parse("@@alias@@ ::= @@replace@@", macro));
947 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
948
949 ASSERT_NO_THROW(Parse("@@alias()@@ := @@replace@@", macro));
950 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
951
952 ASSERT_ANY_THROW(Parse("@@alias(...)@@ ::= @@error@@", macro));
953 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
954
955 ASSERT_NO_THROW(Parse("@@second(...)@@ := @@second2(@$#, @$...)@@", macro));
956 ASSERT_EQ(2, macro->GetCount()) << macro->Dump();
957
958 ASSERT_NO_THROW(Parse("@@second@@ := @@second2(@$#, @$*)@@", macro));
959 ASSERT_EQ(2, macro->GetCount()) << macro->Dump();
960
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));
964
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"});
974
975
976 TermPtr term = Term::Create(parser::token_type::NAME, TermID::NAME, "alias");
977
978 ASSERT_TRUE(macro->GetMacro({"alias"}));
979 ASSERT_TRUE(macro->GetMacro({"second"}));
980
981
982 BlockType buff; //
983 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_alias)); // alias
984 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second)); // second(...)
985 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text)); // text(...)
986 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl)); // dsl
987
988
989 buff.push_back(term); // alias
990
991 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias)); // alias
992 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second)); // second(...)
993 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text)); // text(...)
994 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl)); // dsl
995
996 buff.push_back(term); // alias alias
997
998 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias)); // alias
999 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second)); // second(...)
1000 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text)); // text(...)
1001 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl)); // dsl
1002
1003 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME, "second")); // alias alias second
1004
1005 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias)); // alias
1006 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second)); // second(...)
1007 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text)); // text(...)
1008 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl)); // dsl
1009
1010 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL, "(")); // alias alias second (
1011
1012 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias)); // alias
1013 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second)); // second(...)
1014 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text)); // text(...)
1015 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl)); // dsl
1016
1017 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME, "arg")); // alias alias second ( arg
1018
1019 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias)); // alias
1020 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second)); // second(...)
1021 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text)); // text(...)
1022 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl)); // dsl()
1023
1024 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL, ")")); // alias alias second ( arg )
1025
1026 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias)); // alias
1027 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second)); // second(...)
1028 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text)); // text(...)
1029 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl)); // dsl
1030
1031 buff.erase(buff.begin()); // alias second ( arg )
1032
1033 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias)); // alias
1034 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_second)); // second(...)
1035 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text)); // text(...)
1036 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl)); // dsl
1037
1038 buff.erase(buff.begin()); // second ( arg )
1039
1040 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_alias)); // alias
1041 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_second)); // second(...)
1042 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_text)); // text(...)
1043 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_dsl)); // dsl
1044
1045
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());
1049
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());
1053
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());
1057
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());
1061
1062
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());
1067
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());
1071
1072 ASSERT_ANY_THROW(Parse("second", macro));
1073 ASSERT_ANY_THROW(Parse("@second", macro));
1074
1075 // ASSERT_ANY_THROW(Parse("text", macro));
1076 // ASSERT_NO_THROW(Parse("text()", macro));
1077 // ASSERT_EQ(TermID::NAME, ast->getTermID()) << newlang::toString(ast->getTermID());
1078 // ASSERT_STREQ("text1(0, (,))", ast->toString().c_str());
1079 //
1080 // ASSERT_NO_THROW(Parse("text(123)", macro));
1081 // ASSERT_EQ(TermID::NAME, ast->getTermID()) << newlang::toString(ast->getTermID());
1082 // ASSERT_STREQ("text1(1, (123,) )", ast->toString().c_str());
1083 //
1084 // ASSERT_NO_THROW(Parse("text(123, 456)", macro));
1085 // ASSERT_EQ(TermID::NAME, ast->getTermID()) << newlang::toString(ast->getTermID());
1086 // ASSERT_STREQ("text1(2, (123, 456,))", ast->toString().c_str());
1087
1088 ASSERT_EQ(4, macro->GetCount());
1089 ASSERT_FALSE(macro->GetMacro({"m1"})) << macro->Dump();
1090 ASSERT_FALSE(macro->GetMacro({"m2"})) << macro->Dump();
1091
1092 //@todo Bug: https://github.com/rsashka/newlang/issues/22
1093
1094 // ASSERT_NO_THROW(
1095 // ASSERT_TRUE(Parse("dsl", macro));
1096 // );
1097 //
1098 //
1099 // ASSERT_EQ(6, macro->GetCount());
1100 // ASSERT_TRUE(macro->GetMacro({"m1"})) << macro->Dump();
1101 // ASSERT_TRUE(macro->GetMacro({"m2"})) << macro->Dump();
1102}
1103
1104
1105//TEST_F(NamedTest, Multiple) {
1106// MacroBuffer macro;
1107// ASSERT_EQ(0, macro->size());
1108//
1109// ASSERT_NO_THROW(Parse("@@alias@@ := @@replace@@", macro));
1110// ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
1111// ASSERT_NO_THROW(Parse("@@alias second(...)@@ := @@second(@$#, @$*)@@", macro));
1112// ASSERT_EQ(2, macro->GetCount()) << macro->Dump();
1113// ASSERT_NO_THROW(Parse("@@text(...)@@ := @@@text1(@$#, @$*);\n text1@@@", macro));
1114// ASSERT_EQ(3, macro->GetCount()) << macro->Dump();
1115// ASSERT_NO_THROW(Parse("@@dsl()@@ := @@@ @@m1@@ := @@mm@@;\n @@m2@@ := @@mm@@;\n@@@", macro));
1116//
1117// ASSERT_EQ(4, macro->GetCount()) << macro->Dump();
1118// ASSERT_TRUE(macro->GetMacro({"alias"}));
1119// TermPtr macro_alias = macro->GetMacro({"alias"});
1120// ASSERT_TRUE(macro->GetMacro({"alias", "second"}));
1121// TermPtr macro_second = macro->GetMacro({"alias", "second"});
1122// ASSERT_TRUE(macro->GetMacro({"text"}));
1123// TermPtr macro_text = macro->GetMacro({"text"});
1124// ASSERT_TRUE(macro->GetMacro({"dsl"}));
1125// TermPtr macro_dsl = macro->GetMacro({"dsl"});
1126//
1127//
1128// TermPtr term = Term::Create(parser::token_type::NAME, TermID::NAME, "alias");
1129//
1130// ASSERT_TRUE(macro->GetMacro({"alias"}));
1131// ASSERT_TRUE(macro->GetMacro({"alias", "second"}));
1132//
1133//
1134// BlockType buff; //
1135// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_alias)); // alias
1136// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_second)); // alias second(...)
1137// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_text)); // text(...)
1138// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_dsl)); // dsl()
1139//
1140//
1141// buff.push_back(term); // alias
1142//
1143// ASSERT_TRUE(MacroBuffer::IdentityMacro(buff, macro_alias)); // alias
1144// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_second)); // alias second(...)
1145// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_text)); // text(...)
1146// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_dsl)); // dsl()
1147//
1148// buff.push_back(term); // alias alias
1149//
1150// ASSERT_TRUE(MacroBuffer::IdentityMacro(buff, macro_alias)); // alias
1151// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_second)); // alias second(...)
1152// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_text)); // text(...)
1153// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_dsl)); // dsl()
1154//
1155// buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME, "second")); // alias alias second
1156//
1157// ASSERT_TRUE(MacroBuffer::IdentityMacro(buff, macro_alias)); // alias
1158// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_second)); // alias second(...)
1159// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_text)); // text(...)
1160// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_dsl)); // dsl()
1161//
1162// buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL, "(")); // alias alias second (
1163//
1164// ASSERT_TRUE(MacroBuffer::IdentityMacro(buff, macro_alias)); // alias replace(...)
1165// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_second)); // alias second(...)
1166// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_text)); // text(...)
1167// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_dsl)); // dsl()
1168//
1169// buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME, "arg")); // alias alias second ( arg
1170//
1171// ASSERT_TRUE(MacroBuffer::IdentityMacro(buff, macro_alias)); // alias replace(...)
1172// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_second)); // alias second(...)
1173// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_text)); // text(...)
1174// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_dsl)); // dsl()
1175//
1176// buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL, ")")); // alias alias second ( arg )
1177//
1178// ASSERT_TRUE(MacroBuffer::IdentityMacro(buff, macro_alias)); // alias replace(...)
1179// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_second)); // alias second(...)
1180// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_text)); // text(...)
1181// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_dsl)); // dsl()
1182//
1183// buff.erase(buff.begin()); // alias second ( arg )
1184//
1185// ASSERT_TRUE(MacroBuffer::IdentityMacro(buff, macro_alias)); // alias replace
1186// ASSERT_TRUE(MacroBuffer::IdentityMacro(buff, macro_second)); // alias second(...)
1187// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_text)); // text(...)
1188// ASSERT_FALSE(MacroBuffer::IdentityMacro(buff, macro_dsl)); // dsl()
1189//
1190//
1191// ASSERT_TRUE(Parse("@alias", macro));
1192// ASSERT_EQ(TermID::NAME, ast->getTermID()) << newlang::toString(ast->getTermID());
1193// ASSERT_STREQ("replace", ast->toString().c_str());
1194//
1195// ASSERT_TRUE(Parse("alias", macro));
1196// ASSERT_EQ(TermID::NAME, ast->getTermID()) << newlang::toString(ast->getTermID());
1197// ASSERT_STREQ("replace", ast->m_text.c_str());
1198//
1199// ASSERT_TRUE(Parse("alias second", macro));
1200// ASSERT_EQ(TermID::NAME, ast->getTermID()) << newlang::toString(ast->getTermID());
1201// ASSERT_STREQ("second", ast->m_text.c_str());
1202//
1203//
1204//
1205// ASSERT_EQ(4, macro->GetCount());
1206// ASSERT_FALSE(macro->GetMacro({"m1"})) << macro->Dump();
1207// ASSERT_FALSE(macro->GetMacro({"m2"})) << macro->Dump();
1208//
1209// //@todo Bug: https://github.com/rsashka/newlang/issues/22
1210// // ASSERT_TRUE(Parse("dsl", macro));
1211// //
1212// // ASSERT_EQ(6, macro->GetCount());
1213// // ASSERT_TRUE(macro->GetMacro({"m1"})) << macro->Dump();
1214// // ASSERT_TRUE(macro->GetMacro({"m2"})) << macro->Dump();
1215//}
1216
1217TEST_F(MacroTest, MacroAlias) {
1218 MacroPtr macro = std::make_shared<Macro>();
1219 ASSERT_EQ(0, macro->size());
1220
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 @@"));
1227
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());
1232
1233 ASSERT_TRUE(Parse("@@alias@@ ::= @@replace@@", macro));
1234 ASSERT_TRUE(Parse("@@alias2@@ := @@alias@@", macro));
1235 ASSERT_TRUE(Parse("@@fail@@ := @@fail@@", macro));
1236
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());
1247
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());
1256
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());
1263
1264
1265
1266 TermPtr term = Term::Create(parser::token_type::NAME, TermID::NAME, "alias");
1267
1268 ASSERT_TRUE(macro->map::find(term->m_text) != macro->end());
1269
1270 BlockType vals = macro->map::find(term->m_text)->second;
1271 ASSERT_EQ(1, vals.size());
1272
1273 BlockType buff;
1274 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_alias));
1275 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_alias2));
1276 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_fail));
1277
1278
1279 buff.push_back(term);
1280
1281 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
1282 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_alias2));
1283 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_fail));
1284
1285
1286 term = Term::Create(parser::token_type::NAME, TermID::NAME, "alias");
1287 buff.push_back(term);
1288
1289
1290 ASSERT_TRUE(Macro::IdentityMacro(buff, macro_alias));
1291 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_alias2));
1292 ASSERT_FALSE(Macro::IdentityMacro(buff, macro_fail));
1293
1294
1295 Macro::MacroArgsType macro_args;
1296
1297 ASSERT_EQ(1, Macro::ExtractArgs(buff, macro_alias, macro_args));
1298 ASSERT_EQ(3, macro_args.size()) << Macro::Dump(macro_args);
1299
1300 // ASSERT_ANY_THROW(MacroBuffer::ExtractArgs(buff, macro_alias2, macro_args));
1301 // ASSERT_ANY_THROW(MacroBuffer::ExtractArgs(buff, macro_fail, macro_args));
1302
1303 ASSERT_ANY_THROW(Macro::ExpandString(macro_alias, macro_args));
1304
1305 BlockType block;
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());
1310
1311
1312
1313 ASSERT_EQ(3, macro->size());
1314 for (auto &elem : *macro) {
1315
1316 LOG_DEBUG("Hash: %s", elem.first.c_str());
1317 }
1318
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());
1322
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());
1326
1327 // ASSERT_ANY_THROW(Parse("fail", macro));
1328}
1329
1330TEST_F(MacroTest, MacroArgs) {
1331
1332 MacroPtr macro = std::make_shared<Macro>();
1333 BlockType buffer;
1334
1335 BlockType vect;
1336 Macro::iterator iter;
1337 TermPtr macro_alias1;
1338 //
1339 // ASSERT_TRUE(Parse("@@alias@@replace1@@;@@alias2@@replace2@@", macro));
1340 // ASSERT_EQ(2, macro->GetCount());
1341 //
1342 // iter = macro.map::find("alias");
1343 // ASSERT_TRUE(iter != macro.end());
1344 //
1345 // vect = iter->second;
1346 //
1347 // ASSERT_EQ(1, vect.size()) << macro->Dump();
1348 //
1349 // macro_alias1 = vect[0].macro;
1350 // ASSERT_TRUE(macro_alias1);
1351 // ASSERT_STREQ("alias", macro_alias1->m_text.c_str());
1352 // ASSERT_FALSE(macro_alias1->isCall()) << macro_alias1->toString().c_str();
1353 // ASSERT_TRUE(macro_alias1->getTermID() == TermID::MACRO_DEF) << macro_alias1->toString().c_str();
1354 // ASSERT_TRUE(macro_alias1->Right());
1355 // ASSERT_EQ(1, macro_alias1->Right()->m_macro_seq.size());
1356 // ASSERT_STREQ("replace1", macro_alias1->Right()->m_macro_seq[0]->m_text.c_str());
1357
1358
1359 macro->clear();
1360 ASSERT_EQ(0, macro->GetCount());
1361
1362 ASSERT_NO_THROW(Parse("@@alias@@ := @@ replace1 @@", macro)) << macro->Dump();
1363 ASSERT_EQ(1, macro->GetCount()) << macro->Dump();
1364
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();
1369
1370 ASSERT_ANY_THROW(Parse("@@alias(arg)@@ ::= @@ replace2(@$arg) @@", macro)) << macro->Dump();
1371
1372
1373 ASSERT_NO_THROW(Parse("@@@@ alias @@@@", macro)) << macro->Dump();
1374 ASSERT_EQ(0, macro->GetCount()) << macro->Dump();
1375
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());
1379
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();
1383
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());
1388
1389 ASSERT_NO_THROW(Parse("@@alias3(...)@@ := @@replace3(@$#, @$...)@@", macro)) << macro->Dump();
1390 ASSERT_EQ(2, macro->GetCount()) << macro->Dump();
1391
1392 ASSERT_ANY_THROW(Parse("@@alias3(...)@@ ::= @@ error double macros@@", macro)) << macro->Dump();
1393 ASSERT_EQ(2, macro->GetCount()) << macro->Dump();
1394
1395 // ASSERT_NO_THROW(Parse("@@alias(arg) second@@ ::= @@replace3(@$*)@@;", macro)) << macro->Dump();
1396 // TermPtr test = macro->GetMacro({"alias", "second"});
1397 // ASSERT_TRUE(test) << macro->Dump();
1398 // ASSERT_EQ(TermID::MACRO_SEQ, test->getTermID()) << test->toString().c_str();
1399 // ASSERT_EQ(2, macro->GetCount()) << macro->Dump();
1400 //
1401 // std::vector<std::string> id = MacroBuffer::GetMacroId(test);
1402 // ASSERT_EQ(2, id.size()) << test->toString().c_str();
1403 // ASSERT_STREQ("alias", id[0].c_str());
1404 // ASSERT_STREQ("second", id[1].c_str());
1405
1406
1407 ASSERT_NO_THROW(Parse("@@macro(arg, ... )@@ ::= @@@ 3*@$arg @@@", macro)) << macro->Dump();
1408 ASSERT_EQ(3, macro->GetCount()) << macro->Dump();
1409
1410 iter = macro->map::find("alias");
1411 ASSERT_TRUE(iter != macro->end());
1412
1413 vect = iter->second;
1414
1415 ASSERT_EQ(1, vect.size());
1416
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());
1423
1424
1425 // TermPtr macro_alias2 = vect[1];
1426 // ASSERT_TRUE(macro_alias2);
1427 // ASSERT_STREQ("alias", macro_alias2->m_text.c_str());
1428 // ASSERT_TRUE(macro_alias2->getTermID() == TermID::MACRO_SEQ) << macro_alias2->toString().c_str();
1429 // ASSERT_EQ(4, macro_alias2->m_macro_seq.size());
1430 // ASSERT_TRUE(macro_alias2->Right());
1431 // ASSERT_EQ(4, macro_alias2->Right()->m_macro_seq.size()) << macro_alias2->Right()->m_macro_seq[0]->m_text.c_str();
1432 // ASSERT_STREQ("replace2", macro_alias2->Right()->m_macro_seq[0]->m_text.c_str());
1433 // ASSERT_STREQ("(", macro_alias2->Right()->m_macro_seq[1]->m_text.c_str());
1434 // ASSERT_STREQ("@$arg", macro_alias2->Right()->m_macro_seq[2]->m_text.c_str());
1435 // ASSERT_STREQ(")", macro_alias2->Right()->m_macro_seq[3]->m_text.c_str());
1436
1437 // TermPtr macro_alias3 = vect[2];
1438 // ASSERT_TRUE(macro_alias3);
1439 // ASSERT_STREQ("alias", macro_alias3->m_text.c_str());
1440 // ASSERT_TRUE(macro_alias3->getTermID() == TermID::MACRO_SEQ) << macro_alias3->toString().c_str();
1441 // ASSERT_EQ(5, macro_alias3->m_macro_seq.size());
1442 // ASSERT_STREQ("(", macro_alias3->m_macro_seq[1]->m_text.c_str());
1443 // ASSERT_TRUE(macro_alias3->Right());
1444 // ASSERT_EQ(4, macro_alias3->Right()->m_macro_seq.size());
1445 // ASSERT_STREQ("replace3", macro_alias3->Right()->m_macro_seq[0]->m_text.c_str());
1446 // ASSERT_STREQ("(", macro_alias3->Right()->m_macro_seq[1]->m_text.c_str());
1447 // ASSERT_STREQ("@$*", macro_alias3->Right()->m_macro_seq[2]->m_text.c_str());
1448 // ASSERT_STREQ(")", macro_alias3->Right()->m_macro_seq[3]->m_text.c_str());
1449
1450 // ASSERT_EQ(macro_alias1.get(), macro->GetMacro({"alias"}).get()) << macro->Dump();
1451 // // ASSERT_EQ(macro_alias2.get(), macro->GetMacro({"alias", "second"}).get()) << macro->Dump();
1452 // // ASSERT_EQ(macro_alias3.get(), macro->GetMacro({"alias", "(", "$", ")", "second"}).get()) << macro->Dump();
1453 //
1454 //
1455 iter = macro->map::find("macro"); // Это поиск для map - возвращает итератор
1456 ASSERT_TRUE(iter != macro->end());
1457
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()); // Поиск по MacroID и возврат TermPtr
1464 ASSERT_TRUE(macro_macro1->Right());
1465 ASSERT_TRUE(macro_macro1->Right()->getTermID() == TermID::MACRO_STR) << macro_macro1->toString().c_str();
1466 //
1467
1468 BlockType buff;
1469 Macro::MacroArgsType macro_args;
1470
1471 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_alias1, macro_args));
1472 // ASSERT_ANY_THROW(MacroBuffer::ExtractArgs(buff, macro_alias2, macro_args));
1473 // ASSERT_ANY_THROW(MacroBuffer::ExtractArgs(buff, macro_alias3, macro_args));
1474 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_macro1, macro_args));
1475
1476 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME, "alias"));
1477
1478 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_alias1, macro_args)) << macro_alias1->toString().c_str();
1479
1480 // ASSERT_ANY_THROW(MacroBuffer::ExtractArgs(buff, macro_alias2, macro_args));
1481 // ASSERT_ANY_THROW(MacroBuffer::ExtractArgs(buff, macro_alias3, macro_args));
1482 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_macro1, macro_args)) << macro_macro1->toString().c_str();
1483
1484
1485 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL, "("));
1486
1487 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_alias1, macro_args));
1488
1489 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL, ")"));
1490
1491 size_t count;
1492 ASSERT_NO_THROW(count = Macro::ExtractArgs(buff, macro_alias1, macro_args));
1493 ASSERT_EQ(3, count);
1494
1495 buff.erase(buff.end());
1496
1497 // ASSERT_ANY_THROW(MacroBuffer::ExtractArgs(buff, macro_alias2, macro_args));
1498 // ASSERT_ANY_THROW(MacroBuffer::ExtractArgs(buff, macro_alias3, macro_args));
1499 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_macro1, macro_args));
1500
1501 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME, "value"));
1502
1503 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_alias1, macro_args));
1504
1505 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL, ")"));
1506
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());
1511
1512 // ASSERT_ANY_THROW(MacroBuffer::ExtractArgs(buff, macro_alias2, macro_args));
1513 // ASSERT_ANY_THROW(MacroBuffer::ExtractArgs(buff, macro_alias3, macro_args));
1514 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_macro1, macro_args));
1515
1516
1517 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL, ","));
1518
1519
1520 // ASSERT_ANY_THROW(MacroBuffer::ExtractArgs(buff, macro_alias2, macro_args));
1521 // ASSERT_ANY_THROW(MacroBuffer::ExtractArgs(buff, macro_alias3, macro_args));
1522 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_macro1, macro_args));
1523
1524
1525 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME, "value2"));
1526
1527 buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME, "value3"));
1528
1529 ASSERT_ANY_THROW(Macro::ExtractArgs(buff, macro_macro1, macro_args));
1530
1531
1532 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL, ")"));
1533
1534
1535 ASSERT_NO_THROW(
1536 ASSERT_EQ(7, Macro::ExtractArgs(buff, macro_alias1, macro_args));
1537 );
1538 ASSERT_EQ(6, macro_args.size()) << Macro::Dump(macro_args);
1539
1540 // ASSERT_EQ(7, MacroBuffer::ExtractArgs(buff, macro_alias2, macro_args));
1541 // ASSERT_EQ(4, macro_args.size()) << MacroBuffer::Dump(macro_args);
1542
1543 ASSERT_EQ(7, buff.size());
1544 ASSERT_NO_THROW(
1545 ASSERT_EQ(7, Macro::ExtractArgs(buff, macro_macro1, macro_args));
1546 );
1547 ASSERT_EQ(6, macro_args.size()) << Macro::Dump(macro_args);
1548
1549 // ASSERT_ANY_THROW(MacroBuffer::ExtractArgs(buff, macro_alias3, macro_args));
1550
1551
1552
1553 buff.push_back(Term::Create(parser::token_type::SYMBOL, TermID::SYMBOL, ";"));
1554
1555
1556 ASSERT_NO_THROW(
1557 ASSERT_EQ(7, Macro::ExtractArgs(buff, macro_alias1, macro_args));
1558 );
1559
1560 ASSERT_EQ(6, macro_args.size()) << Macro::Dump(macro_args);
1561
1562 ASSERT_EQ(8, buff.size()) << Macro::Dump(buff);
1563 ASSERT_NO_THROW(
1564 ASSERT_EQ(7, Macro::ExtractArgs(buff, macro_macro1, macro_args));
1565 );
1566 ASSERT_EQ(6, macro_args.size()) << Macro::Dump(macro_args);
1567
1568
1569 // buff.push_back(Term::Create(parser::token_type::NAME, TermID::NAME, "last_term"));
1570 //
1571 // ASSERT_EQ(1, MacroBuffer::ExtractArgs(buff, macro_alias1, macro_args));
1572 // ASSERT_EQ(0, macro_args.size()) << MacroBuffer::Dump(macro_args);
1573 //
1574 // BlockType res = MacroBuffer::ExpandMacros(macro_alias1, macro_args);
1575 // ASSERT_EQ(1, res.size());
1576 // ASSERT_STREQ("replace1", res[0]->m_text.c_str());
1577
1578
1579 // ASSERT_EQ(7, MacroBuffer::ExtractArgs(buff, macro_alias2, macro_args));
1580 // ASSERT_EQ(4, macro_args.size()) << MacroBuffer::Dump(macro_args);
1581 //
1582 // res = MacroBuffer::ExpandMacros(macro_alias2, macro_args);
1583 // ASSERT_EQ(4, res.size());
1584 // ASSERT_STREQ("replace2", res[0]->m_text.c_str());
1585 // ASSERT_STREQ("(", res[1]->m_text.c_str());
1586 // ASSERT_STREQ("value", res[2]->m_text.c_str()) << MacroBuffer::Dump(macro_args);
1587 // ASSERT_STREQ(")", res[3]->m_text.c_str());
1588 //
1589 // // Нет анализаи на соотеветстви макроса, только извлечение значений шаблона
1590 // ASSERT_EQ(8, MacroBuffer::ExtractArgs(buff, macro_alias3, macro_args)) << MacroBuffer::Dump(macro_args);
1591 // ASSERT_EQ(4, macro_args.size()) << MacroBuffer::Dump(macro_args);
1592
1593 // res = MacroBuffer::ExpandMacros(macro_alias3, macro_args);
1594 // ASSERT_EQ(7, res.size());
1595 // ASSERT_STREQ("replace3", res[0]->m_text.c_str());
1596 // ASSERT_STREQ("(", res[1]->m_text.c_str());
1597 // ASSERT_STREQ("value", res[2]->m_text.c_str()) << MacroBuffer::Dump(macro_args);
1598 // ASSERT_STREQ(",", res[3]->m_text.c_str()) << MacroBuffer::Dump(macro_args);
1599 // ASSERT_STREQ("value2", res[4]->m_text.c_str()) << MacroBuffer::Dump(macro_args);
1600 // ASSERT_STREQ("value3", res[5]->m_text.c_str()) << MacroBuffer::Dump(macro_args);
1601 // ASSERT_STREQ(")", res[6]->m_text.c_str());
1602
1603
1604 buff.clear();
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, ";"));
1610
1611 TermPtr macro_macro = macro->GetMacro({"macro"});
1612 ASSERT_TRUE(macro_macro);
1613
1614 ASSERT_NO_THROW(
1615 ASSERT_EQ(4, Macro::ExtractArgs(buff, macro_macro, macro_args)) << Macro::Dump(macro_args);
1616 );
1617 ASSERT_EQ(5, macro_args.size()) << Macro::Dump(macro_args);
1618
1619 std::string str = Macro::ExpandString(macro_macro, macro_args);
1620 ASSERT_STREQ(" 3*5 ", str.c_str());
1621
1622
1623 buff.clear();
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, ";"));
1629
1630 TermPtr macro_alias3 = macro->GetMacro({"alias3"});
1631 ASSERT_TRUE(macro_alias3);
1632
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());
1637
1638
1639 ASSERT_NO_THROW(
1640 ASSERT_EQ(4, Macro::ExtractArgs(buff, macro_alias3, macro_args)) << Macro::Dump(macro_args);
1641 );
1642 ASSERT_EQ(4, macro_args.size()) << Macro::Dump(macro_args);
1643
1644 auto iter_arg = macro_args.begin();
1645 ASSERT_TRUE(iter_arg != macro_args.end()) << Macro::Dump(macro_args);
1646
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);
1650
1651 iter_arg++;
1652 ASSERT_TRUE(iter_arg != macro_args.end());
1653
1654 ASSERT_STREQ("@$*", iter_arg->first.c_str());
1655 ASSERT_STREQ("( 5 , )", Macro::Dump(iter_arg->second).c_str());
1656
1657 iter_arg++;
1658 ASSERT_TRUE(iter_arg != macro_args.end());
1659
1660 ASSERT_STREQ("@$...", iter_arg->first.c_str());
1661 ASSERT_EQ(1, iter_arg->second.size());
1662
1663 iter_arg++;
1664 ASSERT_TRUE(iter_arg != macro_args.end());
1665
1666 ASSERT_STREQ("@$1", iter_arg->first.c_str());
1667 ASSERT_EQ(1, iter_arg->second.size());
1668
1669 iter_arg++;
1670 ASSERT_TRUE(iter_arg == macro_args.end());
1671
1672 // ASSERT_EQ(1, macro_args[1].size());
1673 // ASSERT_STREQ("@$...", (macro_args.begin() + 1)->first.c_str());
1674
1675 // ASSERT_EQ(1, macro_args[0].size());
1676 // ASSERT_STREQ("@$1", macro_args[0][0]->name(0).c_str());
1677 //
1678 // ASSERT_EQ(1, macro_args[1].size());
1679 // ASSERT_STREQ("@$1", macro_args[1][0]->name(0).c_str());
1680 // ASSERT_EQ(1, macro_args[1].size());
1681 //
1682 // ASSERT_EQ(1, macro_args[2].size());
1683 // ASSERT_STREQ("@$#", macro_args[2][0]->name(0).c_str());
1684 // ASSERT_EQ(1, macro_args[2].size());
1685 //
1686 // ASSERT_EQ(1, macro_args[3].size());
1687 // ASSERT_STREQ("@$*", macro_args[3][0]->name(0).c_str());
1688 // ASSERT_EQ(1, macro_args[3].size());
1689
1690 // alias3(5) -> replace3(@$#, @$*) т.е replace3(1,5)
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();
1699
1700 // body = "@macro(11, ...)";
1701 // args = Parser::ParseMacroArgs(body);
1702 // ASSERT_EQ(2, args.size());
1703 // ASSERT_STREQ("11", args[0].c_str());
1704 // ASSERT_STREQ("...", args[1].c_str());
1705 //
1706 // body = "@return(...) --@$*--";
1707 // args = Parser::ParseMacroArgs(body);
1708 // ASSERT_EQ(1, args.size());
1709 // ASSERT_STREQ("...", args[0].c_str());
1710 //
1711 // ASSERT_ANY_THROW(
1712 // body = "@macro(,)";
1713 // args = Parser::ParseMacroArgs(body);
1714 // );
1715 // ASSERT_ANY_THROW(
1716 // body = "@macro( , )";
1717 // args = Parser::ParseMacroArgs(body);
1718 // );
1719 // ASSERT_ANY_THROW(
1720 // body = "@macro(,,)";
1721 // args = Parser::ParseMacroArgs(body);
1722 // );
1723 //
1724 // body = "@macro)";
1725 // args = Parser::ParseMacroArgs(body);
1726 // ASSERT_EQ(0, args.size());
1727 //
1728 // body = "@macro\n";
1729 // args = Parser::ParseMacroArgs(body);
1730 // ASSERT_EQ(0, args.size());
1731 //
1732 // body = "@macro)";
1733 // args = Parser::ParseMacroArgs(body);
1734 // ASSERT_EQ(0, args.size());
1735 //
1736 // body = "@@macro()";
1737 // args = Parser::ParseMacroArgs(body);
1738 // ASSERT_EQ(0, args.size());
1739 //
1740 // body = "macro";
1741 // args = Parser::ParseMacroArgs(body);
1742 // ASSERT_EQ(0, args.size());
1743 //
1744 // body = "";
1745 // args = Parser::ParseMacroArgs(body);
1746 // ASSERT_EQ(0, args.size());
1747}
1748
1749TEST_F(MacroTest, MacroCheck) {
1750
1751 MacroPtr macro = std::make_shared<Macro>();
1752 BlockType buffer;
1753
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();
1758
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());
1762
1763}
1764//TEST_F(NamedTest, MacroExpand) {
1765//
1766// std::string macro = "@macro 12345";
1767// std::string body = "@macro";
1768// std::string result = MacroBuffer::ExpandMacro(macro, body);
1769// ASSERT_STREQ("12345", result.c_str());
1770//
1771// body = "@macro @macro";
1772// result = MacroBuffer::ExpandMacro(macro, body);
1773// ASSERT_STREQ("12345 12345", result.c_str());
1774//
1775// body = "@macro @macro @macro";
1776// result = MacroBuffer::ExpandMacro(macro, body);
1777// ASSERT_STREQ("12345 12345 12345", result.c_str());
1778//
1779// macro = "@macro() 12345";
1780// body = "@macro @macro @macro";
1781// result = MacroBuffer::ExpandMacro(macro, body);
1782// ASSERT_STREQ("@macro @macro @macro", result.c_str());
1783//
1784// macro = "@macro()12345";
1785// body = "@macro() @macro() @macro";
1786// result = MacroBuffer::ExpandMacro(macro, body);
1787// ASSERT_STREQ("12345 12345 @macro", result.c_str());
1788//
1789// macro = "@macro()12345";
1790// body = "@macro(88) @macro(99) @macro";
1791// result = MacroBuffer::ExpandMacro(macro, body);
1792// ASSERT_STREQ("12345 12345 @macro", result.c_str());
1793//
1794//
1795// macro = "@macro(arg)@$arg";
1796// body = "@macro(88)";
1797// result = MacroBuffer::ExpandMacro(macro, body);
1798// ASSERT_STREQ("88", result.c_str());
1799//
1800// macro = "@macro(arg)no arg @$arg";
1801// body = "@macro(99)";
1802// result = MacroBuffer::ExpandMacro(macro, body);
1803// ASSERT_STREQ("no arg 99", result.c_str());
1804//
1805// macro = "@macro(arg) no arg @$arg no arg";
1806// body = "@macro(88) @macro(99)";
1807// result = MacroBuffer::ExpandMacro(macro, body);
1808// ASSERT_STREQ(" no arg 88 no arg no arg 99 no arg", result.c_str());
1809//
1810// macro = "@macro(arg1,arg2) @$arg1 arg @$arg2 @$arg2";
1811// body = "@macro(88,99)";
1812// result = MacroBuffer::ExpandMacro(macro, body);
1813// ASSERT_STREQ(" 88 arg 99 99", result.c_str());
1814//
1815// macro = "@macro(arg1,arg2) @$arg1 @$arg2 @$arg2";
1816// body = "@macro(1,2) @macro(3,44)";
1817// result = MacroBuffer::ExpandMacro(macro, body);
1818// ASSERT_STREQ(" 1 2 2 3 44 44", result.c_str());
1819//
1820// macro = "@macro(arg1,arg2) @$1 @$2 @$1";
1821// body = "@macro(1,2) @macro(3,44)";
1822// result = MacroBuffer::ExpandMacro(macro, body);
1823// ASSERT_STREQ(" 1 2 1 3 44 3", result.c_str());
1824//
1825// macro = "@macro(arg1,arg2)@$*";
1826// body = "@macro(1,2)";
1827// result = MacroBuffer::ExpandMacro(macro, body);
1828// ASSERT_STREQ("1,2", result.c_str());
1829//
1830// macro = "@macro(arg1,arg2)@$* @$1 @$arg2@$*";
1831// body = "@macro(1,2)";
1832// result = MacroBuffer::ExpandMacro(macro, body);
1833// ASSERT_STREQ("1,2 1 21,2", result.c_str());
1834//
1835// macro = "@macro(arg1,arg2)@$* @$1 @$arg2@$*";
1836// body = "@macro(1,2)@macro(1,2)";
1837// result = MacroBuffer::ExpandMacro(macro, body);
1838// ASSERT_STREQ("1,2 1 21,21,2 1 21,2", result.c_str());
1839//
1840// macro = "@@return --@@@";
1841// body = "@return(100);";
1842// result = MacroBuffer::ExpandMacro(macro, body);
1843// ASSERT_STREQ("@return(100);", result.c_str());
1844//
1845// macro = "@return(...)--@$*--";
1846// body = "@return(100);";
1847// result = MacroBuffer::ExpandMacro(macro, body);
1848// ASSERT_STREQ("--100--;", result.c_str());
1849//
1850//}
1851
1852//TEST_F(NamedTest, MacroDSL) {
1853//
1854// Parser::MacrosStore macros;
1855// std::string dsl = ""
1856// "@if(cond)@@ [$cond]-->@@"
1857// "@elseif(cond)@@ ,[$cond]-->@@"
1858// "@else@@ ,[...]-->@@"
1859// ""
1860// "@while(cond)@@ [$cond]<->@@"
1861// "@dowhile(cond)@@<->[$cond]@@"
1862// "@return@ --@"
1863// "@return(...)@ --$...--@"
1864// "@dowhile(cond)@@@"
1865// "@@@"
1866// "";
1867//
1868// while(Parser::ExtractMacros(dsl, macros))
1869// ;
1870// ASSERT_EQ(7, macros.size());
1871//
1872//
1873//}
1874
1875TEST_F(MacroTest, MacroTest) {
1876
1877 MacroPtr macro = std::make_shared<Macro>();
1878 BlockType buffer;
1879
1880 ASSERT_EQ(0, macro->GetCount());
1881
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"}));
1889
1890 ASSERT_NO_THROW(Parse("alias", macro)) << macro->Dump();
1891 ASSERT_STREQ("replace", LexOut().c_str()) << macro->Dump();
1892
1893 ASSERT_NO_THROW(Parse("alias()", macro)) << macro->Dump();
1894 ASSERT_STREQ("replace ( )", LexOut().c_str()) << macro->Dump();
1895
1896 ASSERT_NO_THROW(Parse("alias(...)", macro)) << macro->Dump();
1897 ASSERT_STREQ("replace ( ... )", LexOut().c_str()) << macro->Dump();
1898
1899 ASSERT_NO_THROW(Parse("alias(1,2,3)", macro)) << macro->Dump();
1900 ASSERT_STREQ("replace ( 1 , 2 , 3 )", LexOut().c_str()) << macro->Dump();
1901
1902 ASSERT_NO_THROW(Parse("@alias", macro)) << macro->Dump();
1903 ASSERT_STREQ("replace", LexOut().c_str()) << macro->Dump();
1904
1905 ASSERT_NO_THROW(Parse("@alias(); @alias", macro)) << macro->Dump() << " LEX: \"" << LexOut().c_str() << "\"";
1906 ASSERT_STREQ("replace ( ) ; replace", LexOut().c_str()) << macro->Dump();
1907
1908 ASSERT_NO_THROW(Parse("@alias(...)", macro)) << macro->Dump();
1909 ASSERT_STREQ("replace ( ... )", LexOut().c_str()) << macro->Dump();
1910
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();
1913
1914
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());
1919
1920 ASSERT_NO_THROW(Parse("macro1", macro)) << macro->Dump();
1921 ASSERT_STREQ("replace1", LexOut().c_str());
1922
1923 ASSERT_NO_THROW(Parse("@macro1()", macro)) << macro->Dump();
1924 ASSERT_STREQ("replace1 ( )", LexOut().c_str());
1925
1926 ASSERT_NO_THROW(Parse("@macro1(...)", macro)) << macro->Dump();
1927 ASSERT_STREQ("replace1 ( ... )", LexOut().c_str());
1928
1929 ASSERT_NO_THROW(Parse("@macro1(1,2,3)", macro)) << macro->Dump();
1930 ASSERT_STREQ("replace1 ( 1 , 2 , 3 )", LexOut().c_str());
1931
1932 ASSERT_NO_THROW(Parse("@macro1", macro)) << macro->Dump();
1933 ASSERT_STREQ("replace1", LexOut().c_str());
1934
1935 // Макрос macro1 определн без скобок, а тут скобки есть
1936 ASSERT_ANY_THROW(Parse("@macro1() @alias", macro)) << macro->Dump();
1937 ASSERT_ANY_THROW(Parse("none @macro1(...)", macro)) << macro->Dump();
1938
1939
1940
1941
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());
1947
1948 ASSERT_ANY_THROW(Parse("macro2", macro)) << macro->Dump();
1949
1950 ASSERT_NO_THROW(Parse("macro2()", macro)) << macro->Dump();
1951 ASSERT_STREQ("replace2 ( )", LexOut().c_str());
1952
1953 ASSERT_NO_THROW(Parse("macro2()", macro)) << macro->Dump();
1954 ASSERT_STREQ("replace2 ( )", LexOut().c_str());
1955
1956 ASSERT_NO_THROW(Parse("macro2( 1 )", macro)) << macro->Dump();
1957 ASSERT_STREQ("replace2 ( 1 )", LexOut().c_str());
1958
1959 ASSERT_NO_THROW(Parse("macro2(1,2,3)", macro)) << macro->Dump();
1960 ASSERT_STREQ("replace2 ( 1 , 2 , 3 )", LexOut().c_str());
1961
1962 ASSERT_ANY_THROW(Parse("@macro2", macro)) << macro->Dump();
1963
1964 ASSERT_NO_THROW(Parse("@macro2(); @alias(123)", macro)) << macro->Dump();
1965 ASSERT_STREQ("replace2 ( ) ; replace ( 123 )", LexOut().c_str());
1966
1967 ASSERT_NO_THROW(Parse("none;@macro2(...)", macro)) << macro->Dump();
1968 ASSERT_STREQ("none ; replace2 ( ... )", LexOut().c_str());
1969
1970 ASSERT_NO_THROW(Parse("@macro2(1,2,3);\n", macro)) << macro->Dump();
1971 ASSERT_STREQ("replace2 ( 1 , 2 , 3 ) ;", LexOut().c_str());
1972 // ASSERT_NO_THROW(Parse("@macro2(1,2,3);\nnone", macro)) << macro->Dump();
1973 // ASSERT_STREQ("replace2 ( 1 , 2 , 3 ) ; none", LexOut().c_str());
1974
1975}
1976
1977#endif // UNITTEST
uint8_t LogLevelType
Definition logger.h:319
std::map< std::string, BlockType > MacroArgsType
Definition macro.h:192
bool RegisterPredefMacro(const char *name, const char *desc)
Definition parser.cpp:583
std::map< std::string, std::string > m_predef_macro
Definition parser.h:63
static int m_counter
Definition parser.h:62
parser::token_type ExpandPredefMacro(TermPtr &term)
Definition parser.cpp:673
TermPtr ParseFile(const std::string_view filename)
Definition parser.cpp:66
int result
Definition lexer.l:367
#define LOG_DEBUG(...)
Definition logger.h:119
Definition nlc.h:59
TermID
Definition term.h:119
std::shared_ptr< Term > TermPtr
Definition variable.h:33
std::shared_ptr< Macro > MacroPtr
Definition types.h:244
std::vector< TermPtr > BlockType
Definition types.h:239
std::shared_ptr< Diag > DiagPtr
Definition types.h:243
const char * toString(TermID type)
Definition term.h:126
std::string & trim(std::string &s, const char *t=ws)
Definition types.h:111
#define VERSION
Definition version.h:14
#define VERSION_DATE_BUILD_STR
Definition version.h:6
#define VERSION_SOURCE_FULL_ID
Definition version.h:7
#define VERSION_GIT_SOURCE
Definition version.h:15