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