NewLang Project
Yet another programm language
Loading...
Searching...
No Matches
parser.cpp
Go to the documentation of this file.
1
2#include "parser.h"
3#include "lexer.h"
4#include "builtin.h"
5#include "system.h"
6
7#include "term.h"
8#include "context.h"
9
10using namespace newlang;
11
12int Parser::m_counter = 0;
13
14Parser::Parser(MacroPtr macro, PostLexerType *postlex, DiagPtr diag, bool pragma_enable, RunTime *rt) {
15 char *source_date_epoch = std::getenv("SOURCE_DATE_EPOCH");
16 if (source_date_epoch) {
17 std::istringstream iss(source_date_epoch);
18 iss >> m_timestamp;
19 if (iss.fail() || !iss.eof()) {
20 LOG_RUNTIME("Error: Cannot parse SOURCE_DATE_EPOCH (%s) as integer", source_date_epoch);
21 }
22 } else {
23 m_timestamp = std::time(NULL);
24 }
25
26 m_rt = rt;
27 m_is_runing = false;
28 m_is_lexer_complete = false;
29
30 m_filename = "";
31 m_file_time = "??? ??? ?? ??:??:?? ????";
32 m_file_md5 = "??????????????????????????????";
33 m_macro = macro;
34 m_postlex = postlex;
35 m_diag = diag; // ? diag : Diag::Init();
36 m_annotation = Term::Create(TermID::ARGS, "", parser::token_type::ARGS);
37 m_no_macro = false;
38 m_enable_pragma = pragma_enable;
39// m_name_module = "\\\\__main__";
40
41 m_ast = nullptr;
42}
43
44TermPtr Parser::Parse(const std::string input, bool expand_module) {
45
47 // m_ast->SetSource(std::make_shared<std::string>(input));
48 m_stream.str(input);
49 m_stream.clear();
50 Scanner scanner(&m_stream, &std::cout, std::make_shared<std::string>(input));
51 scanner.ApplyDiags(m_diag);
52
53 lexer = &scanner;
54
55 parser parser(*this);
56 if (parser.parse() != 0) {
57 return m_ast;
58 }
59
60 // Исходники требуются для вывода информации ошибках во время анализа типов
61 m_ast->SetSource(m_ast->m_source);
62 lexer = nullptr;
63 return m_ast;
64}
65
66TermPtr Parser::ParseFile(const std::string_view filename) {
67
68 llvm::SmallVector<char> path;
69 if (!llvm::sys::fs::real_path(filename, path)) {
70 m_filename = llvm::StringRef(path.data(), path.size());
71 } else {
72 m_filename = filename;
73 }
74
75 llvm::sys::fs::file_status fs;
76 std::error_code ec = llvm::sys::fs::status(filename, fs);
77 if (!ec) {
78 time_t temp = llvm::sys::toTimeT(fs.getLastModificationTime());
79 struct tm * timeinfo;
80 timeinfo = localtime(&temp);
81 m_file_time = asctime(timeinfo);
82 m_file_time = m_file_time.substr(0, 24); // Remove \n on the end line
83 }
84
85 auto md5 = llvm::sys::fs::md5_contents(filename);
86 if (md5) {
87 llvm::SmallString<32> hash;
88 llvm::MD5::stringifyResult(*md5, hash);
89 m_file_md5 = hash.c_str();
90 }
91
92 int fd = open(filename.begin(), O_RDONLY);
93 if (fd < 0) {
94 LOG_RUNTIME("Error open file '%s'", filename.begin());
95 }
96
97 struct stat sb;
98 fstat(fd, &sb);
99
100 std::string data;
101 data.resize(sb.st_size);
102
103 read(fd, const_cast<char*> (data.data()), sb.st_size);
104 close(fd);
105
106 return Parse(data);
107}
108
109
110void Parser::error(const class location& l, const std::string& m) {
111 std::cerr << l << ": " << m << std::endl;
112}
113
114void Parser::error(const std::string &m) {
115 std::cerr << m << std::endl;
116}
117
118void newlang::parser::error(const parser::location_type& l, const std::string& msg) {
119 // std::string buffer(driver.m_stream.str());
120 std::string buffer(*(driver.lexer->source_string));
121 std::cout << driver.lexer->source_string->c_str() << "\n\n";
122 std::cout.flush();
123 ParserException(msg.c_str(), buffer, l.begin.line, l.begin.column);
124}
125
127 return m_ast;
128}
129
131 ASSERT(m_ast);
132 term->m_source = lexer->source_string;
133 if (m_ast->m_id == TermID::END) {
134 m_ast = term;
135 } else {
136 if (m_ast->m_id != TermID::SEQUENCE) {
137 TermPtr temp = Term::Create(TermID::SEQUENCE, "", parser::token::END, 0, &m_ast->m_lexer_loc, m_ast->m_source);
138 m_ast.swap(temp);
139 m_ast->m_block.push_back(temp);
140 }
141 if (term->m_id == TermID::SEQUENCE) {
142 m_ast->m_block.insert(m_ast->m_block.end(), term->m_block.begin(), term->m_block.end());
143 } else {
144 m_ast->m_block.push_back(term);
145 }
146 }
147}
148
149// stub
150
152 return term;
153}
154
157}
158
159//TermPtr Parser::MacroEval(const TermPtr &term) {
160//
161// if (!m_macro && m_diag) {
162// m_diag->Emit(Diag::DIAG_MACRO_NOT_FOUND, term);
163// return term;
164// }
165//
166// if (term->m_bracket_depth) {
167// NL_PARSER(term, "Macro definitions allowed at the top level only, not inside conditions, namespace or any brackets!");
168// }
169//
170// if (m_macro) {
171// return m_macro->EvalOpMacros(term);
172// }
173// return term;
174//}
175
176bool Parser::PragmaCheck(const TermPtr& term) {
177 if (term && term->m_text.size() > 5
178 && term->m_text.find("@__") == 0
179 && term->m_text.rfind("__") == term->m_text.size() - 2) {
180 return !CheckPredefMacro(term);
181 }
182 return false;
183}
184
185bool Parser::PragmaEval(const TermPtr &term, BlockType &buffer, BlockType &seq) {
186 /*
187 *
188 * https://javarush.com/groups/posts/1896-java-annotacii-chto-ehto-i-kak-ehtim-poljhzovatjhsja
189 * https://habr.com/ru/companies/otus/articles/764244/
190 *
191 @__PRAGMA_DIAG__(push)
192 @__PRAGMA_DIAG__(ignored, "-Wundef")
193 @__PRAGMA_DIAG__(warning, "-Wformat" , "-Wundef", "-Wuninitialized")
194 @__PRAGMA_DIAG__(error, "-Wuninitialized")
195 @__PRAGMA_DIAG__(pop)
196
197 @__PRAGMA_DIAG__(once, "-Wuninitialized") ??????????????
198
199 #pragma message "Compiling " __FILE__ "..."
200 @__PRAGMA_MESSAGE__("Compiling ", __FILE__, "...")
201
202
203 #define DO_PRAGMA(x) _Pragma (#x)
204 #define TODO(x) DO_PRAGMA(message ("TODO - " #x))
205
206 @@TODO( ... )@@ := @__PRAGMA_MESSAGE__("TODO - ", @#...)
207
208 @TODO(Remember to fix this) # note: TODO - Remember to fix this
209
210 \\.__lexer__ignore_space__ = 1;
211 \\.__lexer__ignore_indent__ = 1;
212 \\.__lexer__ignore_comment__ = 1;
213 \\.__lexer__ignore_crlf__ = 1;
214 *
215 * @__PRAGMA_MACRO__(push)
216 * @__PRAGMA_MACRO__(push, if, this)
217 * @__PRAGMA_MACRO__(pop)
218 * @__PRAGMA_MACRO__(pop, if, this)
219 *
220 * @__PRAGMA_MACRO_COND__(ndef, if) @__PRAGMA_ERROR__("Macro if not defined!")
221 * @__PRAGMA_MACRO_COND__(lt, __VERSION__, 0.5) @__PRAGMA_ERROR__("This functional supported since version 0.5 only!")
222 */
223
224 static const char * __PRAGMA_DIAG__ = "@__PRAGMA_DIAG__";
225 static const char * __PRAGMA_TYPE_DEFINE__ = "@__PRAGMA_TYPE_DEFINE__";
226 static const char * __PRAGMA_IGNORE__ = "@__PRAGMA_IGNORE__";
227 static const char * __PRAGMA_MACRO__ = "@__PRAGMA_MACRO__";
228 static const char * __PRAGMA_MACRO_COND__ = "@__PRAGMA_MACRO_COND__";
229
230 static const char * __PRAGMA_MESSAGE__ = "@__PRAGMA_MESSAGE__";
231 static const char * __PRAGMA_WARNING__ = "@__PRAGMA_WARNING__";
232 static const char * __PRAGMA_ERROR__ = "@__PRAGMA_ERROR__";
233
234 static const char * __PRAGMA_EXPECTED__ = "@__PRAGMA_EXPECTED__";
235 static const char * __PRAGMA_UNEXPECTED__ = "@__PRAGMA_UNEXPECTED__";
236 static const char * __PRAGMA_FINALIZE__ = "@__PRAGMA_FINALIZE__";
237
238 static const char * __PRAGMA_NO_MACRO__ = "@__PRAGMA_NO_MACRO__";
239
240 static const char * __PRAGMA_LOCATION__ = "@__PRAGMA_LOCATION__";
241
242 static const char * __ANNOTATION_SET__ = "@__ANNOTATION_SET__";
243 static const char * __ANNOTATION_CHECK__ = "@__ANNOTATION_CHECK__";
244 static const char * __ANNOTATION_IIF__ = "@__ANNOTATION_IIF__";
245
246 static const char * __PRAGMA_STATIC_ASSERT__ = "@__PRAGMA_STATIC_ASSERT__";
247
248 ASSERT(term);
249 if (term->m_text.compare(__PRAGMA_DIAG__) == 0) {
250 if (term->size() == 0) {
251 NL_PARSER(term, "Expected argument in pragma '%s'", term->toString().c_str());
252 }
253
254 ASSERT(m_diag);
255 Diag::State state;
256 if (term->at(0).second->m_text.compare("push") == 0) {
257
258 m_diag->Push(term);
259 return true;
260
261 } else if (term->at(0).second->m_text.compare("pop") == 0) {
262
263 m_diag->Pop(term);
264 return true;
265
266 } else if (term->at(0).second->m_text.compare(Diag::toString(Diag::State::ignored)) == 0) {
267 state = Diag::State::ignored;
268 } else if (term->at(0).second->m_text.compare(Diag::toString(Diag::State::warning)) == 0) {
269 state = Diag::State::warning;
270 } else if (term->at(0).second->m_text.compare(Diag::toString(Diag::State::error)) == 0) {
271 state = Diag::State::error;
272 } else {
273 NL_PARSER(term, "Pragma '%s' not recognized!", term->toString().c_str());
274 }
275
276 for (int i = 1; i < term->size(); i++) {
277 m_diag->Apply(term->at(i).second->m_text.c_str(), state, term);
278 }
279 } else if (term->m_text.compare(__PRAGMA_TYPE_DEFINE__) == 0) {
280
281 if (term->size() != 1 || !term->at(1).first.empty()) {
282 NL_PARSER(term, "Expected argument in pragma macro '%s'", term->toString().c_str());
283 }
284
285 if (term->at(1).first.empty() && term->at(1).second->getTermID() == TermID::INTEGER && m_rt) {
286 m_rt->m_typedef_limit = std::stoi(term->at(0).second->getText().c_str()); //parseInteger
287 return true;
288 }
289
290 } else if (term->m_text.compare(__PRAGMA_MESSAGE__) == 0
291 || term->m_text.compare(__PRAGMA_WARNING__) == 0
292 || term->m_text.compare(__PRAGMA_ERROR__) == 0) {
293
294 std::string message;
295 for (int i = 0; i < term->size(); i++) {
296 message += term->at(i).second->m_text;
297 }
298
301 if (term->m_text.compare(__PRAGMA_MESSAGE__) == 0) {
302 LOG_INFO("note: %s", message.c_str());
303 } else if (term->m_text.compare(__PRAGMA_WARNING__) == 0) {
304 LOG_WARNING("warn: %s", message.c_str());
305 } else {
306 ASSERT(term->m_text.compare(__PRAGMA_ERROR__) == 0);
307 LOG_RUNTIME("error: %s", message.c_str());
308 }
310
311 } else if (term->m_text.compare(__PRAGMA_IGNORE__) == 0) {
312
313 LOG_RUNTIME("Pragma @__PRAGMA_IGNORE__ not implemented!");
314
315 static const char * ignore_space = "space";
316 static const char * ignore_indent = "indent";
317 static const char * ignore_comment = "comment";
318 static const char * ignore_crlf = "crlf";
319
320 } else if (term->m_text.compare(__PRAGMA_MACRO__) == 0) {
321
322 if (term->size() == 0) {
323 NL_PARSER(term, "Expected argument in pragma macro '%s'", term->toString().c_str());
324 }
325
326 Diag::State state;
327 if (term->at(0).second->m_text.compare("push") == 0) {
328
329 LOG_RUNTIME("Pragma push not implemented!");
330 // m_macro->Push(term);
331 return true;
332
333 } else if (term->at(0).second->m_text.compare("pop") == 0) {
334
335 LOG_RUNTIME("Pragma pop not implemented!");
336 // m_macro->Pop(term);
337 return true;
338
339 // } else if(term->at(0).second->m_text.compare(Diag::toString(Diag::State::ignored)) == 0) {
340 // state = Diag::State::ignored;
341 // } else if(term->at(0).second->m_text.compare(Diag::toString(Diag::State::warning)) == 0) {
342 // state = Diag::State::warning;
343 // } else if(term->at(0).second->m_text.compare(Diag::toString(Diag::State::error)) == 0) {
344 // state = Diag::State::error;
345 } else {
346 NL_PARSER(term, "Pragma macro '%s' not recognized!", term->toString().c_str());
347 }
348
349 // for (int i = 1; i < term->size(); i++) {
350 // m_diag->Apply(term->at(i).second->m_text.c_str(), state, term);
351 // }
352 } else if (term->m_text.compare(__PRAGMA_MACRO_COND__) == 0) {
353
354 if (term->size() == 0) {
355 NL_PARSER(term, "Expected argument in pragma macro '%s'", term->toString().c_str());
356 }
357
358 LOG_RUNTIME("Pragma @__PRAGMA_MACRO_COND__ not implemented!");
359
360
361 } else if (term->m_text.compare(__PRAGMA_EXPECTED__) == 0) {
362
363 m_expected = term;
364
365 } else if (term->m_text.compare(__PRAGMA_UNEXPECTED__) == 0) {
366
367 m_unexpected = term;
368
369 } else if (term->m_text.compare(__PRAGMA_FINALIZE__) == 0) {
370
372 LOG_RUNTIME("Nested definitions of pragma @__PRAGMA_FINALIZE__ not implemented!");
373 }
374
375 m_finalize = term;
377
378 } else if (term->m_text.compare(__PRAGMA_NO_MACRO__) == 0) {
379
380 ASSERT(term->size() == 0);
381
382 m_no_macro = true;
383
384 } else if (term->m_text.compare(__PRAGMA_LOCATION__) == 0) {
385
386 // #line 303 "location.hh"
387 // Prototype - @__PRAGMA_LOCATION__( pop )
388 // Prototype - @__PRAGMA_LOCATION__( push ) or @__PRAGMA_LOCATION__( push, 'filename') or @__PRAGMA_LOCATION__( push, 'filename', line)
389 // Prototype - @__PRAGMA_LOCATION__( line ) or @__PRAGMA_LOCATION__( line, 'filename')
390 if (term->size() == 1 && term->at(0).first.empty() && term->at(0).second->m_text.compare("pop") == 0) {
391
392 if (m_loc_stack.empty()) {
393 NL_PARSER(term, "Empty stack location!");
394 }
395 m_filename = m_loc_stack[m_loc_stack.size() - 1].filename;
396 m_location = m_loc_stack[m_loc_stack.size() - 1].location;
397 m_loc_stack.pop_back();
398 return true;
399
400 } else if (term->size() >= 1 && term->at(0).first.empty() && term->at(0).second->m_text.compare("push") == 0) {
401
402 if (term->size() == 1) {
403 m_loc_stack.push_back({m_filename, m_location});
404 return true;
405 } else if (term->size() >= 2 && term->at(1).first.empty() && term->at(1).second->isString()) {
406
407 m_loc_stack.push_back({m_filename, m_location});
408 m_filename = term->at(1).second->getText();
409
410 if (term->size() == 2) {
411 return true;
412 } else if (term->size() == 3 && term->at(2).first.empty() && term->at(2).second->getTermID() == TermID::INTEGER) {
413 m_location.begin.line = std::stoi(term->at(0).second->getText().c_str());
414 m_location.end.line = m_location.begin.line;
415 return true;
416 }
417 }
418
419 } else if (term->size() >= 1 && term->at(0).first.empty() && term->at(0).second->getTermID() == TermID::INTEGER) {
420
421 m_location.begin.line = std::stoi(term->at(0).second->getText().c_str());
422 m_location.end.line = m_location.begin.line;
423 if (term->size() == 1) {
424 return true;
425 } else if (term->size() == 2 && term->at(1).first.empty() && term->at(1).second->isString()) {
426 m_filename = term->at(1).second->getText();
427 m_location.begin.filename = &m_filename;
428 // m_loc_stack.push_back(m_location);
429 return true;
430 }
431 }
432 NL_PARSER(term, "See @__PRAGMA_LOCATION__ for usage and syntax help.");
433
434
435 } else if (term->m_text.compare(__ANNOTATION_SET__) == 0) {
436
437 if (term->size() == 1) {
438 // Set `name` = 1;
439 std::string name = term->at(0).second->m_text;
440 LOG_DEBUG("NAME: %s", name.c_str());
441
442 auto iter = m_annotation->find(term->at(0).second->m_text);
443 if (iter == m_annotation->end()) {
444 m_annotation->push_back(Term::Create(TermID::INTEGER, "1", parser::token_type::INTEGER, 1, &term->m_lexer_loc, term->m_source), name);
445 } else {
446 // iter->second =
447 m_annotation->push_back(Term::Create(TermID::INTEGER, "1", parser::token_type::INTEGER, 1, &term->m_lexer_loc, term->m_source), name);
448 }
449
450
451 } else if (term->size() == 2) {
452 // Set `name` = value;
453 m_annotation->push_back(term->at(1).second, term->at(0).second->m_text);
454 } else {
455 NL_PARSER(term, "Annotation args in '%s' not recognized!", term->toString().c_str());
456 }
457
458 // LOG_DEBUG("ANNOT: %s", m_annotation->toString().c_str());
459
460 } else if (term->m_text.compare(__ANNOTATION_CHECK__) == 0) {
461
463
464 LOG_RUNTIME("Pragma __ANNOTATION_CHECK__ not implemented!");
465
466 // if (term->size() != 3) {
467 // NL_PARSER(term, "Annotation IIF must have three arguments!");
468 // }
469 //
470 // // LOG_DEBUG("Annot %s %d", m_annotation->toString().c_str(), (int) m_annotation->size());
471 //
472 // auto iter = m_annotation->find(term->at(0).second->m_text);
473 // if (iter == m_annotation->end() || iter->second->m_text.empty() || iter->second->m_text.compare("0") == 0) {
474 // buffer.insert(buffer.begin(), term->at(2).second);
475 // } else {
476 // buffer.insert(buffer.begin(), term->at(1).second);
477 // }
478
479 } else if (term->m_text.compare(__ANNOTATION_IIF__) == 0) {
480
482
483 if (term->size() != 3) {
484 NL_PARSER(term, "Annotation IIF must have three arguments!");
485 }
486
487 // LOG_DEBUG("Annot %s %d", m_annotation->toString().c_str(), (int) m_annotation->size());
488
489 auto iter = m_annotation->find(term->at(0).second->m_text);
490 if (iter == m_annotation->end() || iter->second->m_text.empty() || iter->second->m_text.compare("0") == 0) {
491 buffer.insert(buffer.begin(), term->at(2).second);
492 } else {
493 buffer.insert(buffer.begin(), term->at(1).second);
494 }
495
496 } else if (term->m_text.compare(__PRAGMA_STATIC_ASSERT__) == 0) {
497
498 return PragmaStaticAssert(term);
499
500 } else {
501 NL_PARSER(term, "Uknown pragma '%s'", term->toString().c_str());
502 }
503 return true;
504}
505
507
508 if (term->size() < 1 || !term->at(0).first.empty()) {
509 NL_PARSER(term, "Agruments '%s' not recognized! See @__PRAGMA_STATIC_ASSERT__ for usage and syntax help.", term->toString().c_str());
510 }
511
512 bool done;
513 try {
514 // done = Context::EvalTerm(term->at(0).second, nullptr)->GetValueAsBoolean();
515 done = Context::EvalTerm(term->at(0).second, nullptr).GetVariablePair().var.GetValueAsBoolean();
516 } catch (...) {
517 done = false;
518 }
519 if (!done) {
520 NL_PARSER(term, "StaticAssert '%s' failed!", term->at(0).second->toString().c_str());
521 }
522 return true;
523}
524
525std::string newlang::ParserMessage(std::string &buffer, int row, int col, const char *format, ...) {
526
527 char va_buffer[1024];
528
529 va_list args;
530 va_start(args, format);
531 vsnprintf(va_buffer, sizeof (va_buffer), format, args);
532 va_end(args);
533
534 std::string message(va_buffer);
535
536 if (row) { // Если переданы координаты ошибки
537 message += " at line ";
538 message += std::to_string(row);
539 message += " col ";
540 message += std::to_string(col - 1);
541 message += "\n";
542 }
543
544 // Ищем нужную строку
545 size_t pos = 0;
546 if (buffer.find("\n") != std::string::npos) {
547 int count = 1;
548 while (count < row) {
549 pos = buffer.find("\n", pos + 1);
550 count++;
551 }
552 }
553 // Убираем лишние переводы строк
554 std::string tmp = buffer.substr((pos ? pos + 1 : pos), buffer.find("\n", pos + 1));
555 tmp = tmp.substr(0, tmp.find("\n", col));
556
557 if (row) { // Если переданы координаты ошибки, показываем место
558
559 // Лексер обрабатывает строки в байтах, а вывод в UTF8
560 // поэтому позиция ошибки лексера может не совпадать для многобайтных символов
561 std::wstring_convert < std::codecvt_utf8<wchar_t>, wchar_t> converter;
562 std::wstring wstr = converter.from_bytes(tmp.substr(0, col));
563
564 message += tmp;
565 if (col > 1) {
566 message += "\n";
567 std::string placeholder(col - 2 - (tmp.substr(0, col).size() - wstr.size()), ' ');
568 placeholder += "^ ";
569 message += placeholder;
570 }
571 } else {
572
573 message += tmp;
574 }
575
576 return message;
577}
578
579void newlang::ParserException(const char *msg, std::string &buffer, int row, int col) {
580 throw ParserError(ParserMessage(buffer, row, col, "%s", msg));
581}
582
583bool Parser::RegisterPredefMacro(const char * name, const char * desc) {
584 if (m_predef_macro.find(name) != m_predef_macro.end()) {
585 LOG_ERROR("Predef macro '%s' redefined!", name);
586 return false;
587 }
588 m_predef_macro.insert({name, desc});
589 return true;
590}
591
593 if (m_predef_macro.empty()) {
594
595 VERIFY(RegisterPredefMacro("@__NLC_VER__", "Version NewLang Compiler."));
596 VERIFY(RegisterPredefMacro("@__NLC_SOURCE_GIT__", "Git source code identifier of the current compiler version."));
597 VERIFY(RegisterPredefMacro("@__NLC_DATE_BUILD__", "Date build of the current compiler version."));
598 VERIFY(RegisterPredefMacro("@__NLC_SOURCE_BUILD__", "Git source code identifier and date build of the current compiler version."));
599
600 VERIFY(RegisterPredefMacro("@__FILE__", "Current file name"));
601 VERIFY(RegisterPredefMacro("@__FILE_NAME__", "Current file name"));
602
603 VERIFY(RegisterPredefMacro("@__CLASS__", "Current class name"));
604 VERIFY(RegisterPredefMacro("@__NAMESPACE__", "Current namespace"));
605 VERIFY(RegisterPredefMacro("@__FUNCTION__", "Current function name"));
606 VERIFY(RegisterPredefMacro("@__FUNCDNAME__", "Decorated of current function name"));
607 VERIFY(RegisterPredefMacro("@__FUNCSIG__", "Signature of current function"));
608 // VERIFY(RegisterPredefMacro("@__FUNC_BLOCK__", "Full namespace function name"));
609
610
611
612 VERIFY(RegisterPredefMacro("@__LINE__", "Line number in current file"));
613 VERIFY(RegisterPredefMacro("@__FILE_LINE__", "Line number in current file"));
614
615 VERIFY(RegisterPredefMacro("@__FILE_MD5__", "MD5 hash for current file"));
616 VERIFY(RegisterPredefMacro("@__FILE_TIMESTAMP__", "Timestamp current file"));
617
618 VERIFY(RegisterPredefMacro("@__DATE__", "Current date"));
619 VERIFY(RegisterPredefMacro("@__TIME__", "Current time"));
620 // определяется как строковый литерал, содержащий дату и время последнего изменения текущего исходного файла
621 //в сокращенной форме с постоянной длиной, которые возвращаются функцией asctime библиотеки CRT,
622 //например: Fri 19 Aug 13:32:58 2016. Этот макрос определяется всегда.
623 VERIFY(RegisterPredefMacro("@__TIMESTAMP__", "Current timestamp"));
624 VERIFY(RegisterPredefMacro("@__TIMESTAMP_ISO__", "Current timestamp as ISO format")); // 2013-07-06T00:50:06Z
625
626 //Развертывается до целочисленного литерала, начинающегося с 0.
627 //Значение увеличивается на 1 каждый раз, когда используется в файле исходного кода или во включенных заголовках файла исходного кода.
628 VERIFY(RegisterPredefMacro("@__COUNTER__", "Monotonically increasing counter from zero"));
629
630 VERIFY(RegisterPredefMacro("@::", "Full name of the current namespace"));
631 VERIFY(RegisterPredefMacro("$\\\\", "Full name of the current module name"));
632 VERIFY(RegisterPredefMacro("@\\\\", "Root directory with the main program module"));
633 }
634}
635
637 if (term->m_id != TermID::NAME) {
638 return false;
639 }
640
641 std::string_view text = term->m_text;
642 if (text.find("@") == 0) {
643 text.remove_prefix(1);
644 }
645
646 return m_predef_macro.find(text.begin()) != m_predef_macro.end();
647}
648
649std::string Parser::GetCurrentDate(time_t ts) {
650 std::string buf("Jul 27 2012");
651 strftime(buf.data(), buf.size(), "%b %e %Y", localtime(&ts));
652 return buf;
653}
654
655std::string Parser::GetCurrentTime(time_t ts) {
656 std::string buf("07:07:09");
657 strftime(buf.data(), buf.size(), "%T", localtime(&ts));
658 return buf;
659}
660
661std::string Parser::GetCurrentTimeStamp(time_t ts) {
662 std::string result = asctime(localtime(&ts));
663 result = result.substr(0, 24); // Remove \n on the end line
664 return result;
665}
666
667std::string Parser::GetCurrentTimeStampISO(time_t ts) {
668 std::string buf("2011-10-08T07:07:09Z");
669 strftime(buf.data(), buf.size(), "%FT%TZ", localtime(&ts));
670 return buf;
671}
672
673parser::token_type Parser::ExpandPredefMacro(TermPtr & term) {
674
676
677 if (!term) {
678 LOG_RUNTIME("Environment variable not defined!");
679 }
680 if (term->m_id != TermID::MACRO) {
681 return term->m_lexer_type;
682 }
683
684 std::string_view text = term->m_text;
685 // if (text.find("@") == 0) {
686 // text.remove_prefix(1);
687 // }
688
689 ASSERT(!m_predef_macro.empty());
690 if (m_predef_macro.find(text.begin()) == m_predef_macro.end()) {
691 return term->m_lexer_type;
692 }
693
694
695 const TermID str_type = TermID::STRWIDE;
696 const parser::token_type str_token = parser::token_type::STRWIDE;
697
698 if (text.compare("@__COUNTER__") == 0) {
699
700 term->m_id = TermID::INTEGER;
701 term->m_text = std::to_string(m_counter);
702 m_counter++;
703 term->m_lexer_type = parser::token_type::INTEGER;
704 return term->m_lexer_type;
705
706 } else if (text.compare("@__NLC_VER__") == 0) {
707
708 term->m_id = TermID::INTEGER;
709 term->m_text = std::to_string(VERSION);
710 term->m_lexer_type = parser::token_type::INTEGER;
711 return term->m_lexer_type;
712
713 } else if (text.compare("@__NLC_SOURCE_GIT__") == 0) {
714 term->m_text = GIT_SOURCE;
715 term->m_id = str_type;
716 term->m_lexer_type = str_token;
717 return term->m_lexer_type;
718
719 } else if (text.compare("@__NLC_DATE_BUILD__") == 0) {
720 term->m_text = DATE_BUILD_STR;
721 term->m_id = str_type;
722 term->m_lexer_type = str_token;
723 return term->m_lexer_type;
724
725 } else if (text.compare("@__NLC_SOURCE_BUILD__") == 0) {
726 term->m_text = SOURCE_FULL_ID;
727 term->m_id = str_type;
728 term->m_lexer_type = str_token;
729 return term->m_lexer_type;
730
731 } else if (text.compare("@__LINE__") == 0 || text.compare("@__FILE_LINE__") == 0) {
732
733 term->m_id = TermID::INTEGER;
734 term->m_text = std::to_string(m_location.begin.line);
735 term->m_lexer_type = parser::token_type::INTEGER;
736 return term->m_lexer_type;
737
738 } else if (text.compare("@__FILE__") == 0 || text.compare("@__FILE_NAME__") == 0) {
739
740 term->m_id = str_type;
741 if (!m_filename.empty()) {
742 term->m_text = m_filename;
743 } else {
744 term->m_text = "File name undefined!!!";
745 }
746 term->m_lexer_type = str_token;
747 return term->m_lexer_type;
748
749 } else if (text.compare("@__FILE_TIMESTAMP__") == 0) {
750
751 term->m_id = str_type;
752 if (!m_file_time.empty()) {
753 term->m_text = m_file_time;
754 } else {
755 term->m_text = "??? ??? ?? ??:??:?? ????";
756 }
757 term->m_lexer_type = str_token;
758 return term->m_lexer_type;
759
760 } else if (text.compare("@__FILE_MD5__") == 0) {
761
762 term->m_id = str_type;
763 if (!m_file_md5.empty()) {
764 term->m_text = m_file_md5;
765 } else {
766 term->m_text = "?????????????????????????????????";
767 }
768 term->m_lexer_type = str_token;
769 return term->m_lexer_type;
770
771
772 } else if (text.compare("@__DATE__") == 0) {
773
774 term->m_text = GetCurrentDate(m_timestamp);
775 term->m_id = str_type;
776 term->m_lexer_type = str_token;
777 return term->m_lexer_type;
778
779 } else if (text.compare("@__TIME__") == 0) {
780
781 term->m_text = GetCurrentTime(m_timestamp);
782 term->m_id = str_type;
783 term->m_lexer_type = str_token;
784 return term->m_lexer_type;
785
786 } else if (text.compare("@__TIMESTAMP__") == 0) {
787
788 term->m_text = GetCurrentTimeStamp(m_timestamp);
789 term->m_text = term->m_text.substr(0, 24); // Remove \n on the end line
790 term->m_id = str_type;
791 term->m_lexer_type = str_token;
792 return term->m_lexer_type;
793
794 } else if (text.compare("@__TIMESTAMP_ISO__") == 0) {
795
796 term->m_text = GetCurrentTimeStampISO(m_timestamp);
797 term->m_id = str_type;
798 term->m_lexer_type = str_token;
799 return term->m_lexer_type;
800
801 } else if (text.compare("@__CLASS__") == 0 || text.compare("@__NAMESPACE__") == 0 || //text.compare("@__FUNC_BLOCK__") == 0 ||
802 text.compare("@__FUNCTION__") == 0 || text.compare("@__FUNCDNAME__") == 0 || text.compare("@__FUNCSIG__") == 0) {
803
804 term->m_id = TermID::NAMESPACE;
805 term->m_lexer_type = parser::token_type::NAMESPACE;
806 return term->m_lexer_type;
807
808 } else if (text.compare("@::") == 0) {
809
810 term->m_id = TermID::NAMESPACE;
811 term->m_lexer_type = parser::token_type::NAMESPACE;
812 return term->m_lexer_type;
813
814 // ASSERT(text.compare("@::") != 0);
815
816 } else if (text.compare("@$$") == 0) {
817
818 term->m_id = TermID::NAMESPACE;
819 term->m_lexer_type = parser::token_type::NAMESPACE;
820 return term->m_lexer_type;
821
822 // // Внешний блок или функция
823 // ASSERT(text.compare("@$$") != 0);
824
825 } else if (text.compare("@\\\\") == 0) {
826
827 if (m_rt) {
828 term->m_text = m_rt->m_exec_dir;
829 }
830 term->m_id = TermID::NAME;
831 term->m_lexer_type = parser::token_type::NAME;
832 return term->m_lexer_type;
833
834 } else if (text.compare("$\\\\") == 0) {
835
836 term->m_text = m_name_module;
837 term->m_id = TermID::MODULE;
838 term->m_lexer_type = parser::token_type::MODULE;
839 return term->m_lexer_type;
840 }
841
842 NL_PARSER(term, "Predef macro '%s' not implemented!", term->toString().c_str());
843}
844
845TermPtr Parser::ParseTerm(const char *proto, MacroPtr macro, bool pragma_enable) {
846 try {
847 // Термин или термин + тип парсятся без ошибок
848 Parser p(macro, nullptr, nullptr, pragma_enable);
849 return p.Parse(proto);
850 } catch (std::exception &) {
851 std::string func(proto);
852 try {
853 func += ":={}";
854 Parser p(macro, nullptr, nullptr, pragma_enable);
855 return p.Parse(func)->m_left;
856 } catch (std::exception &e) {
857 LOG_RUNTIME("Fail parsing prototype '%s' as '%s'!", func.c_str(), e.what());
858 }
859 }
860}
861
862size_t Parser::SkipBrackets(const BlockType& buffer, const size_t offset) {
863
864 if (offset >= buffer.size()) {
865 return 0;
866 }
867
868 std::string br_end;
869 if (buffer[offset]->m_text.compare("(") == 0) {
870 br_end = ")";
871 // } else if (buffer[offset]->m_text.compare("<") == 0) {
872 // br_end = ">";
873 } else if (buffer[offset]->m_text.compare("[") == 0) {
874 br_end = "]";
875 } else {
876 return 0;
877 }
878
879 size_t shift = 1;
880 int count = 1;
881 while (offset + shift < buffer.size()) {
882 if (buffer[offset]->m_text.compare(buffer[offset + shift]->m_text) == 0) {
883 count++; // Next level bracket
884 } else if (br_end.compare(buffer[offset + shift]->m_text) == 0) {
885 count--; // // Leave level bracket
886 if (count == 0) {
887 return shift + 1;
888 }
889 }
890 shift++;
891 }
892 NL_PARSER(buffer[offset], "Closed bracket '%s' not found!", br_end.c_str());
893}
894
895size_t Parser::ParseTerm(TermPtr &result, const BlockType &buffer, size_t offset, bool pragma_enable) {
896
897 if (offset >= buffer.size()) {
898 LOG_RUNTIME("Fail skip count %d or buffer size %d!", (int) offset, (int) buffer.size());
899 }
900
901 /* term
902 * func()
903 *
904 * term: type
905 * func(): type
906 *
907 * term: type[]
908 * func(): type[]
909 *
910 */
911
912 std::string source = buffer[offset]->toString();
913 offset++;
914 size_t skip = SkipBrackets(buffer, offset);
915
916 if (skip) {
917 /*
918 * term
919 * func()
920 */
921 for (size_t i = 0; i < skip; i++) {
922 if (buffer[offset + i]) {
923 source += buffer[offset + i]->toString();
924 }
925 }
926 offset += skip;
927 }
928
929 if (offset + 1 < buffer.size() && buffer[offset + 1]->m_text.compare(":") == 0) {
930 offset++;
931 source += buffer[offset]->toString();
932
933 /*
934 * term: type
935 * func(): type
936 */
937
938 if (offset + 1 >= buffer.size()) {
939 NL_PARSER(buffer[offset + 1], "Typename missing!");
940 }
941
942 offset++;
943 source += buffer[offset]->toString();
944
945 skip = SkipBrackets(buffer, offset + 1);
946 if (skip) {
947 /*
948 * term: type[]
949 * func(): type[]
950 *
951 */
952 for (size_t i = 0; i < skip; i++) {
953 source += buffer[offset + i]->toString();
954 }
955
956 offset += (skip + 1);
957 }
958 }
959 // LOG_DEBUG("ParseTerm: '%s' - %d", source.c_str(), (int) offset);
960 result = ParseTerm(source.c_str(), nullptr, pragma_enable);
961 return offset;
962}
963
965 if (!isModuleName(term->m_text)) {
966 return term;
967 }
968 if (!CheckCharModuleName(term->m_text)) {
969 NL_PARSER(term, "Module name - backslash, underscore, lowercase English letters or number!");
970 }
971 return term;
972}
973
974
975
976
977
978using namespace newlang;
979
980
981#define MAKE_TYPE(type_name) {type_name, Term::Create(TermID::TYPE, type_name)}
982
983static const std::map<const std::string, const TermPtr> default_types{
984 MAKE_TYPE(":None"),
985
986 MAKE_TYPE(":Bool"),
987 MAKE_TYPE(":Int8"),
988 MAKE_TYPE(":Int16"),
989 MAKE_TYPE(":Int32"),
990 MAKE_TYPE(":Int64"),
991
992 MAKE_TYPE(":Float16"),
993 MAKE_TYPE(":Float32"),
994 MAKE_TYPE(":Float64"),
995
996 MAKE_TYPE(":Complex16"),
997 MAKE_TYPE(":Complex32"),
998 MAKE_TYPE(":Complex64"),
999
1000 MAKE_TYPE(":Rational"),
1001
1002 MAKE_TYPE(":StrChar"),
1003 MAKE_TYPE(":StrWide"),
1004
1005 MAKE_TYPE(":Range"),
1006 MAKE_TYPE(":Iterator"),
1007
1008 MAKE_TYPE(":Dictionary"),
1009
1010 MAKE_TYPE(":Any")};
1011
1012#undef MAKE_TYPE
1013
1014static const TermPtr type_default_none = default_types.find(":None")->second;
1015static const TermPtr type_default_any = default_types.find(":Any")->second;
1016//static const TermPtr type_default_dict = default_types.find(":Dict")->second;
1017static const TermPtr term_none = Term::Create(TermID::NAME, "_", parser::token_type::NAME);
1018static const TermPtr term_ellipsys = Term::Create(TermID::ELLIPSIS, "...", parser::token_type::ELLIPSIS);
1019static const TermPtr term_required = Term::Create(TermID::NONE, "_", parser::token_type::END);
1020
1023
1025static const VariablePtr var_ellipsys = std::make_shared<Variable>(obj_ellipsys);
1027
1029 return term_none;
1030}
1031
1035
1039
1041 return obj_none;
1042}
1043
1045 return var_none;
1046}
1047
1049 return obj_ellipsys;
1050}
1051
1055
1059
1061 if (term) {
1062 TermPtr def = getDefaultType(term->m_text);
1063 return def && (term.get() == def.get());
1064 }
1065 return true; // Not defined type as type default
1066}
1067
1069 return getDefaultType(toString(type));
1070}
1071
1072const TermPtr newlang::getDefaultType(const std::string_view text) {
1073 if (!text.empty()) {
1074 auto iter = default_types.find(text.begin());
1075 if (iter != default_types.end()) {
1076 return iter->second;
1077 }
1078 } else {
1079 ASSERT(type_default_none->m_text.compare(":None") == 0);
1080 ASSERT(type_default_any->m_text.compare(":Any") == 0);
1081
1082 return type_default_any;
1083 }
1084 return nullptr;
1085}
1086
1087bool newlang::canCast(const TermPtr &from, const ObjType to) {
1088 if (!from->m_type) {
1089 return true; // Empty type cast any type
1090 }
1091 ObjType test_type = GetBaseTypeFromString(from->m_type->m_text);
1092 return canCast(test_type, to);
1093}
1094
1095bool newlang::canCast(const TermPtr &from, const TermPtr &to) {
1096 if (!from || !to || !from->m_type || !to->m_type) {
1097 return true; // Empty type cast any type
1098 }
1099 return canCast(GetBaseTypeFromString(from->m_type->m_text), GetBaseTypeFromString(to->m_type->m_text));
1100}
1101
1102ObjType newlang::GetBaseTypeFromString(const std::string_view type_arg, bool *has_error) {
1103
1104 std::string type(type_arg);
1105
1106 if (type.find("~") != std::string::npos) {
1107 type.erase(std::remove(type.begin(), type.end(), '~'), type.end());
1108 }
1109
1110 if (type.empty()) {
1111 return ObjType::None;
1112 } else if (type.compare("_") == 0) {
1113 return ObjType::None;
1114 }
1115
1116#define DEFINE_CASE(name, _) \
1117 else if (type.compare(":"#name) == 0) { \
1118 return ObjType:: name; \
1119 }
1120
1122#undef DEFINE_CASE
1123
1124 if (has_error) {
1125 *has_error = true;
1126 return ObjType::None;
1127 }
1128 LOG_RUNTIME("Undefined type name '%s'!", type.c_str());
1129}
1130
1131parser::token_type Parser::GetNextToken(TermPtr * yylval, parser::location_type * yylloc) {
1132
1133 parser::token_type result;
1134
1135 ASSERT(yylval);
1136 ASSERT(yylloc);
1137
1138 /*
1139 * Новая логика работы парсера.
1140 *
1141 * Термины считываются из лексера до символа ';' или до конца файла.
1142 * Каждый термин буфера проверяется на макрос и если находится - заменяется.
1143 * Для обычного макроса просто заменяются токены и тела макроса,
1144 * а для текстового макроса используется отдельный буфер до завершения работы лексичсекского анализатора,
1145 * после чего этот буфер вставляется на место макроса в основонм бефере данных.
1146 * После обработки всего буфера его элеменеты передаются в парсер для обработки.
1147 */
1148
1149 parser::token_type type;
1150 bool lexer_complete;
1151
1152
1153go_parse_string:
1154
1155 m_is_runing = true;
1156
1157 TermPtr term;
1158 bool is_escape = false;
1159
1160 if (m_macro_analisys_buff.empty() || lexer->m_macro_iss) {
1161
1162 lexer_complete = false;
1163
1164 while (!m_is_lexer_complete) {
1165
1166next_escape_token:
1167
1168 term = Term::Create(TermID::END, "", parser::token_type::END, 0);
1169 type = lexer->lex(&term, &m_location);
1170 term->m_lexer_loc = m_location;
1171
1172 ASSERT(type == term->m_lexer_type);
1173
1174 if (is_escape) {
1175
1176 if (type == parser::token_type::END) {
1177 NL_PARSER(term, "Unexpected end of file '%s'", term->toString().c_str());
1178 }
1179 is_escape = false;
1180 term->m_id = TermID::ESCAPE;
1181 term->m_lexer_type = parser::token_type::ESCAPE;
1182 type = parser::token_type::ESCAPE;
1183
1184 } else if (type == parser::token_type::ESCAPE) {
1185
1186 is_escape = true;
1187 goto next_escape_token;
1188 }
1189
1190
1191 // if (type == parser::token_type::MACRO && term->m_text.compare("@::") == 0) {
1192 //
1193 // type = parser::token_type::NAMESPACE;
1194 // term->m_lexer_type = type;
1195 // term->m_id = TermID::NAMESPACE;
1196 // term->m_text = m_ns_stack.NamespaceCurrent();
1197 //
1198 // } else
1199
1200 // if (type == MACRO_MODULE) {
1201 //
1202 // type = parser::token_type::MODULE;
1203 // term->m_lexer_type = type;
1204 // term->m_id = TermID::MODULE;
1205 // term->m_text = GetCurrentModule();
1206 //
1207 // }
1208
1209
1210 // if (m_next_string != static_cast<uint8_t> (TermID::NONE)) {
1211 //
1212 // if (m_next_string == static_cast<uint8_t> (TermID::STRCHAR)) {
1213 // type = parser::token_type::STRCHAR;
1214 // } else {
1215 // ASSERT(m_next_string == static_cast<uint8_t> (TermID::STRWIDE));
1216 // type = parser::token_type::STRWIDE;
1217 // }
1218 //
1219 // term->m_lexer_type = type;
1220 // term->m_id = static_cast<TermID> (m_next_string);
1221 //
1222 // m_next_string = static_cast<uint8_t> (TermID::NONE);
1223 //
1224 // } else if (type == parser::token_type::MACRO_TOSTR && lexer->m_macro_count == 0) {
1225 //
1226 // if (term->m_text.compare("@#\"") == 0) {
1227 // m_next_string = static_cast<uint8_t> (TermID::STRWIDE);
1228 // } else if (term->m_text.compare("@#'") == 0) {
1229 // m_next_string = static_cast<uint8_t> (TermID::STRCHAR);
1230 // } else {
1231 // ASSERT(term->m_text.compare("@#") == 0);
1232 // //@todo Set string type default by global settings
1233 // m_next_string = static_cast<uint8_t> (TermID::STRWIDE);
1234 // }
1235 //
1236 // goto next_escape_token;
1237 // }
1238
1239
1240
1241 if (type == parser::token_type::END) {
1242
1243 if (lexer->m_macro_iss == nullptr) {
1244 m_is_lexer_complete = true;
1245 } else {
1246 lexer->yypop_buffer_state();
1247 *lexer->m_loc = lexer->m_macro_loc; // restore
1248
1249 delete lexer->m_macro_iss;
1250 lexer->m_macro_iss = nullptr;
1251
1253
1254 continue;
1255 }
1256 // if(lexer->m_data.empty()) {
1257 // m_is_lexer_complete = true;
1258 // } else {
1259 // lexer->yypop_buffer_state();
1260 // *lexer->m_loc = lexer->m_data[lexer->m_data.size() - 1].loc;
1261 //
1262 // delete lexer->m_data[lexer->m_data.size() - 1].iss;
1263 // lexer->m_data.pop_back();
1264 //
1265 // if(lexer->m_data.empty()) {
1266 // lexer->source_string = lexer->source_base;
1267 // } else {
1268 // lexer->source_string = lexer->m_data[lexer->m_data.size() - 1].data;
1269 // }
1270 // continue;
1271 // }
1272 } else if (lexer->m_macro_count == 1) {
1273
1274 ASSERT(type == parser::token_type::MACRO_SEQ);
1275
1276 if (lexer->m_macro_del) {
1277 NL_PARSER(term, "Invalid token '%s' at given position!", term->m_text.c_str());
1278 }
1279
1280 lexer->m_macro_count = 2;
1281 lexer->m_macro_body = term;
1282 continue;
1283
1284 } else if (lexer->m_macro_count == 3) {
1285
1287 ASSERT(type == parser::token_type::MACRO_SEQ);
1288
1289 lexer->m_macro_count = 0;
1290 term.swap(lexer->m_macro_body);
1291 lexer->m_macro_body = nullptr;
1292
1293 } else if (lexer->m_macro_count == 2 || lexer->m_macro_del == 2) {
1294
1296
1297 if (lexer->m_macro_del && !(type == parser::token_type::NAME || type == parser::token_type::LOCAL)) {
1298 NL_PARSER(term, "Invalid token '%s' at given position!", term->m_text.c_str());
1299 }
1300
1301 lexer->m_macro_body->m_macro_seq.push_back(term);
1302 continue;
1303
1304 } else if (lexer->m_macro_del == 1) {
1305
1306 ASSERT(type == parser::token_type::MACRO_DEL);
1307
1308 if (lexer->m_macro_count) {
1309 NL_PARSER(term, "Invalid token '%s' at given position!", term->m_text.c_str());
1310 }
1311
1312 lexer->m_macro_del = 2;
1313 lexer->m_macro_body = term;
1314 continue;
1315
1316 } else if (lexer->m_macro_del == 3) {
1317
1318 ASSERT(type == parser::token_type::MACRO_DEL);
1319 if (!lexer->m_macro_body) {
1321 }
1322
1323 if (lexer->m_macro_body->m_macro_seq.empty()) {
1324 NL_PARSER(term, "Empty sequence not allowed!");
1325 }
1326
1327 lexer->m_macro_del = 0;
1328
1329 if (lexer->m_macro_body) {
1330 term.swap(lexer->m_macro_body);
1331 }
1332 lexer->m_macro_body = nullptr;
1333 }
1334
1335 m_macro_analisys_buff.push_back(term);
1336 if (term->m_text.compare(";") == 0) {
1337 lexer_complete = true;
1338 break;
1339 }
1340
1341 // if(lexer_complete && lexer->m_macro_iss == nullptr) {
1342 // break;
1343 // }
1344 }
1345
1347 TermPtr bag_position;
1348
1349 bag_position = (m_macro_analisys_buff.size() > 1) ? m_macro_analisys_buff[m_macro_analisys_buff.size() - 2] : term;
1350 if (!bag_position) {
1351 ASSERT(bag_position);
1352 }
1353
1354 if (term->m_lexer_loc.begin.filename) {
1355 NL_PARSER(bag_position, "Incomplete syntax near '%s' in file %s!", bag_position->m_text.c_str(), term->m_lexer_loc.begin.filename->c_str());
1356 } else {
1357 NL_PARSER(bag_position, "Incomplete syntax near '%s'!", bag_position->m_text.c_str());
1358 }
1359 }
1360 }
1361
1362
1363 TermPtr pragma;
1364 while (lexer->m_macro_count == 0 && !m_macro_analisys_buff.empty()) {
1365
1366 if (m_enable_pragma) {
1367
1369
1370 // Обработка команд парсера @__PRAGMA ... __
1372
1373 size_t size;
1374 size = Parser::ParseTerm(pragma, m_macro_analisys_buff, 0, false);
1375
1376 ASSERT(size);
1377 ASSERT(pragma);
1378
1379 // LOG_DEBUG("Pragma '%s' size %d", pragma->toString().c_str(), (int) size);
1380
1381 BlockType temp(m_macro_analisys_buff.begin(), m_macro_analisys_buff.begin() + size);
1382
1384
1385 // while (!m_macro_analisys_buff.empty() && m_macro_analisys_buff[0]->m_text.compare(";") == 0) {
1386 // LOG_DEBUG("Erase '%s' !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", m_macro_analisys_buff[0]->toString().c_str());
1387 // m_macro_analisys_buff.erase(m_macro_analisys_buff.begin());
1388 // }
1389
1390
1391 PragmaEval(pragma, m_macro_analisys_buff, temp);
1392 continue;
1393 }
1394 }
1395
1396
1397 // Обработка команды проверка следующего термина @__PRAGMA_EXPECTED__
1398 if (m_expected) {
1399 for (int i = 0; i < m_expected->size(); i++) {
1400 if (m_macro_analisys_buff[0]->m_text.compare(m_expected->at(i).second->m_text) == 0) {
1401 m_expected.reset();
1402 break;
1403 }
1404 }
1405 if (m_expected) {
1406 std::string msg;
1407 for (int i = 0; i < m_expected->size(); i++) {
1408 if (!msg.empty()) {
1409 msg += ", ";
1410 }
1411 msg += "'";
1412 msg += m_expected->at(i).second->m_text;
1413 msg += "'";
1414 }
1415 NL_PARSER(m_macro_analisys_buff[0], "Term %s expected!", msg.c_str());
1416 }
1417 }
1418
1419 // Обработка команды проверка следующего термина @__PRAGMA_UNEXPECTED__
1420 if (m_unexpected) {
1421 for (int i = 0; i < m_unexpected->size(); i++) {
1422 if (m_macro_analisys_buff[0]->m_text.compare(m_unexpected->at(i).second->m_text) == 0) {
1423 NL_PARSER(m_macro_analisys_buff[0], "Term '%s' unexpected!", m_macro_analisys_buff[0]->m_text.c_str());
1424 }
1425 }
1426 m_unexpected.reset();
1427 }
1428
1429 if (m_no_macro) {
1430 m_no_macro = false;
1431 break;
1432 }
1433
1434 switch (ExpandTermMacro(*this)) {
1436 continue;
1438 goto go_parse_string;
1439 default:
1440 break;
1441 };
1442 // if (m_macro) {
1443 //
1444 // // Макрос должне начинаться всегда с термина
1445 // if (!(m_macro_analisys_buff[0]->getTermID() == TermID::MACRO || m_macro_analisys_buff[0]->getTermID() == TermID::NAME)) {
1446 // break;
1447 // }
1448 //
1449 // TermPtr macro_done = nullptr;
1450 //
1451 // // Итератор для списка макросов, один из которых может соответствовать текущему буферу (по первому термину буфера)
1452 // Macro::iterator found = m_macro->map::find(Macro::toMacroHash(m_macro_analisys_buff[0]));
1453 //
1454 // if (found == m_macro->end()) {
1455 //
1456 // // // Если макрос не найден - ошибка
1457 // // if(isMacro(m_macro_analisys_buff[0]->m_text)) {
1458 // // LOG_RUNTIME("Macro '%s' not found!", m_macro_analisys_buff[0]->toString().c_str());
1459 // // }
1460 //
1461 // break;
1462 // }
1463 //
1464 // macro_done.reset();
1465 // // Перебрать все макросы и сравнить с буфером
1466 // for (auto iter = found->second.begin(); iter != found->second.end(); ++iter) {
1467 //
1468 // if (Macro::IdentityMacro(m_macro_analisys_buff, *iter)) {
1469 //
1470 // if (macro_done) {
1471 // LOG_RUNTIME("Macro duplication %s and '%s'!", macro_done->toString().c_str(), (*iter)->toString().c_str());
1472 // }
1473 // macro_done = *iter;
1474 // }
1475 // }
1476 //
1477 // ASSERT(found != m_macro->end());
1478 //
1479 // if (macro_done) {
1480 //
1481 // counter++;
1482 // if (counter > 100) {
1483 // LOG_RUNTIME("Macro expansion '%s' stack overflow?", macro_done->toString().c_str());
1484 // }
1485 //
1486 // // compare_macro = true; // Раскрывать макросы в теле раскрытого макроса
1487 //
1488 // ASSERT(m_macro_analisys_buff.size() >= macro_done->m_macro_seq.size());
1489 // ASSERT(macro_done->m_right);
1490 //
1491 // Macro::MacroArgsType macro_args;
1492 // size_t size_remove = Macro::ExtractArgs(m_macro_analisys_buff, macro_done, macro_args);
1493 //
1494 // // LOG_TEST_DUMP("buffer '%s' DumpArgs: %s", Macro::Dump(m_macro_analisys_buff).c_str(), Macro::Dump(macro_args).c_str());
1495 //
1496 //
1497 // ASSERT(size_remove);
1498 // ASSERT(size_remove <= m_macro_analisys_buff.size());
1499 //
1500 // std::string temp = "";
1501 // for (auto &elem : m_macro_analisys_buff) {
1502 // if (!temp.empty()) {
1503 // temp += " ";
1504 // }
1505 // temp += elem->m_text;
1506 // temp += ":";
1507 // temp += toString(elem->m_id);
1508 // }
1509 // // LOG_TEST("From: %s (remove %d)", temp.c_str(), (int) size_remove);
1510 //
1511 // m_macro_analisys_buff.erase(m_macro_analisys_buff.begin(), m_macro_analisys_buff.begin() + size_remove);
1512 //
1513 // if (macro_done->m_right->getTermID() == TermID::MACRO_STR) {
1514 //
1515 // std::string macro_str = Macro::ExpandString(macro_done, macro_args);
1516 // lexer->source_string = std::make_shared<std::string>(Macro::ExpandString(macro_done, macro_args));
1517 // lexer->m_macro_iss = new std::istringstream(*lexer->source_string);
1518 // lexer->m_macro_loc = *lexer->m_loc; // save
1519 // lexer->m_loc->initialize();
1520 // lexer->yypush_buffer_state(lexer->yy_create_buffer(lexer->m_macro_iss, lexer->source_string->size()));
1521 //
1522 // // if(lexer->m_data.size() > 100) {
1523 // // LOG_RUNTIME("Macro expansion '%s' stack overflow?", macro_done->toString().c_str());
1524 // // }
1525 // //
1526 // // std::string macro_str = MacroBuffer::ExpandString(macro_done, macro_args);
1527 // // lexer->source_string = std::make_shared<std::string>(MacroBuffer::ExpandString(macro_done, macro_args));
1528 // // lexer->m_data.push_back({lexer->source_string, new std::istringstream(*lexer->source_string), *lexer->m_loc});
1529 // // lexer->m_loc->initialize();
1530 // // lexer->yypush_buffer_state(lexer->yy_create_buffer(lexer->m_data[lexer->m_data.size() - 1].iss, lexer->source_string->size()));
1531 //
1532 // m_is_lexer_complete = false;
1533 // goto go_parse_string;
1534 //
1535 // } else {
1536 //
1537 // ASSERT(macro_done->m_right);
1538 // BlockType macro_block = Macro::ExpandMacros(macro_done, macro_args);
1539 // m_macro_analisys_buff.insert(m_macro_analisys_buff.begin(), macro_block.begin(), macro_block.end());
1540 //
1541 // std::string temp = "";
1542 // for (auto &elem : m_macro_analisys_buff) {
1543 // if (!temp.empty()) {
1544 // temp += " ";
1545 // }
1546 // temp += elem->m_text;
1547 // temp += ":";
1548 // temp += toString(elem->m_id);
1549 // }
1550 // // LOG_TEST("To: %s", temp.c_str());
1551 // }
1552 //
1553 // continue;
1554 //
1555 // } else {
1556 // // if(m_macro_analisys_buff[0]->getTermID() == TermID::MACRO) { // || found != m_macro->end()
1557 //
1558 // LOG_RUNTIME("Macro mapping '%s' not found!\nThe following macro mapping are available:\n%s",
1559 // m_macro_analisys_buff[0]->toString().c_str(),
1560 // m_macro->GetMacroMaping(Macro::toMacroHash(m_macro_analisys_buff[0]), "\n").c_str());
1561 //
1562 // // }
1563 // }
1564 // }
1565
1566 break;
1567
1568 }
1569
1570 //LOG_DEBUG("LexerToken count %d", (int) m_prep_buff.size());
1571
1572 if (!m_macro_analisys_buff.empty()) {
1573
1574 // if (m_macro_analisys_buff[0]->m_id == TermID::END) {
1575 // *yylval = nullptr;
1576 // return parser::token_type::END;
1577 // }
1578
1579 // if (m_macro_analisys_buff.at(0)->m_id) {
1580 // LOG_DEBUG("%d %s", (int)m_prep_buff.at(0)->m_lexer_type, m_prep_buff.at(0)->m_text.c_str());
1581
1583 *yylloc = m_macro_analisys_buff.at(0)->m_lexer_loc;
1584 result = m_macro_analisys_buff.at(0)->m_lexer_type;
1585
1586 // LOG_TEST("Token (%d=%s): '%s'", result, toString((*yylval)->m_id), (*yylval)->m_text.c_str());
1587
1588 if (m_postlex) {
1589
1590 m_postlex->push_back((*yylval)->m_text);
1591
1592 // Раскрыть последовательность токенов, т.к. они собираются в термин в лексере, а не парсере
1593 if ((*yylval)->getTermID() == TermID::MACRO_SEQ || (*yylval)->getTermID() == TermID::MACRO_DEL) {
1594 for (int i = 0; i < (*yylval)->m_macro_seq.size(); i++) {
1595 m_postlex->push_back((*yylval)->m_macro_seq[i]->m_text);
1596 }
1597 m_postlex->push_back((*yylval)->m_text);
1598 }
1599
1600 }
1601 // }
1602
1604 return result;
1605 }
1606
1607 *yylval = nullptr;
1608
1609 return parser::token_type::END;
1610}
1611
1613// *
1614// * Parser - парсинг для строк, а модули в AST как отдельные термины
1615// * FileParser - парсинг для файлов, а модули - поиск и загрузка файлов + раскрытие в AST
1616// *
1617// */
1618//parser::token_type FileParser::ExpandPredefMacro(TermPtr &term) {
1619//
1620// if (term && term->m_id == TermID::MACRO) {
1621//
1622// std::string_view text(term->m_text);
1623// const TermID str_type = TermID::STRWIDE;
1624// const parser::token_type str_token = parser::token_type::STRWIDE;
1625//
1626// if (text.compare("@__FILE_TIMESTAMP__") == 0) {
1627//
1628// term->m_id = str_type;
1629// if (!m_file_time.empty()) {
1630// term->m_text = m_file_time;
1631// } else {
1632// term->m_text = "??? ??? ?? ??:??:?? ????";
1633// }
1634// term->m_lexer_type = str_token;
1635// return term->m_lexer_type;
1636//
1637// } else if (text.compare("@__FILE_MD5__") == 0) {
1638//
1639// term->m_id = str_type;
1640// if (!m_file_md5.empty()) {
1641// term->m_text = m_file_md5;
1642// } else {
1643// term->m_text = "?????????????????????????????????";
1644// }
1645// term->m_lexer_type = str_token;
1646// return term->m_lexer_type;
1647//
1648// } else if (text.compare("@\\\\") == 0) {
1649//
1650// // if (m_rt) {
1651// // term->m_text = m_rt->m_exec_dir;
1652// // }
1653// term->m_id = TermID::NAME;
1654// term->m_lexer_type = parser::token_type::NAME;
1655// return term->m_lexer_type;
1656//
1657// } else if (text.compare("$\\\\") == 0) {
1658//
1659// term->m_text = "FIX MODULE NAME"; //GetCurrentModule();
1660// term->m_id = TermID::MODULE;
1661// term->m_lexer_type = parser::token_type::MODULE;
1662// return term->m_lexer_type;
1663//
1664// }
1665// }
1666//
1667// return Parser::ExpandPredefMacro(term);
1668//}
1669//
static LatterType EvalTerm(TermPtr term, Context *runner, bool rvalue=true)
Definition context.cpp:1670
static const char * toString(State state)
Definition diag.h:50
VariablePair & GetVariablePair(bool editable=false)
Definition context.h:69
uint8_t LogLevelType
Definition logger.h:319
LogLevelType GetLogLevel()
Definition logger.h:322
LogLevelType SetLogLevel(const LogLevelType level)
Definition logger.h:330
static Logger * Instance()
Definition logger.h:377
static ObjPtr CreateNone(Sync *sync=nullptr)
Definition object.h:1510
static ObjPtr CreateType(ObjType type, ObjType fixed=ObjType::None, bool is_init=false, Sync *sync=nullptr)
Definition object.h:1376
void error(const class location &l, const std::string &m)
Definition parser.cpp:110
TermPtr Parse(const std::string str, bool expand_module=false)
Definition parser.cpp:44
TermPtr m_ast
Definition parser.h:142
RunTime * m_rt
Definition parser.h:145
bool m_is_lexer_complete
Definition parser.h:140
TermPtr m_expected
Definition parser.h:93
static size_t SkipBrackets(const BlockType &buffer, size_t offset)
Definition parser.cpp:862
std::istringstream m_stream
Definition parser.h:57
bool RegisterPredefMacro(const char *name, const char *desc)
Definition parser.cpp:583
Parser(MacroPtr macro=nullptr, PostLexerType *postlex=nullptr, DiagPtr diag=nullptr, bool pragma_enable=true, RunTime *rt=nullptr)
Definition parser.cpp:14
bool PragmaCheck(const TermPtr &term)
Definition parser.cpp:176
TermPtr m_finalize
Definition parser.h:95
static size_t ParseTerm(TermPtr &term, const BlockType &buffer, const size_t skip=0, bool pragma_enable=true)
Definition parser.cpp:895
std::map< std::string, std::string > m_predef_macro
Definition parser.h:63
std::string m_file_md5
Definition parser.h:136
int m_finalize_counter
Definition parser.h:96
bool m_is_runing
Definition parser.h:143
void AstAddTerm(TermPtr &term)
Definition parser.cpp:130
static std::string GetCurrentTimeStampISO(time_t ts=std::time(NULL))
Definition parser.cpp:667
void InitPredefMacro()
Definition parser.cpp:592
std::string m_name_module
Definition parser.h:47
std::vector< ParserLocation > m_loc_stack
Definition parser.h:55
TermPtr m_unexpected
Definition parser.h:94
bool PragmaEval(const TermPtr &term, BlockType &buffer, BlockType &seq)
Definition parser.cpp:185
static std::string GetCurrentDate(time_t ts=std::time(NULL))
Definition parser.cpp:649
static int m_counter
Definition parser.h:62
std::string m_file_time
Definition parser.h:135
static std::string GetCurrentTime(time_t ts=std::time(NULL))
Definition parser.cpp:655
DiagPtr m_diag
Definition parser.h:138
bool m_no_macro
Definition parser.h:98
PostLexerType * m_postlex
Definition parser.h:144
parser::token_type GetNextToken(TermPtr *yylval, parser::location_type *yylloc)
Definition parser.cpp:1131
bool m_enable_pragma
Definition parser.h:99
class Scanner * lexer
Definition parser.h:83
parser::token_type ExpandPredefMacro(TermPtr &term)
Definition parser.cpp:673
TermPtr GetAst()
Definition parser.cpp:126
static std::string GetCurrentTimeStamp(time_t ts=std::time(NULL))
Definition parser.cpp:661
bool CheckPredefMacro(const TermPtr &term)
Definition parser.cpp:636
TermPtr CheckModuleTerm(const TermPtr &term)
Definition parser.cpp:964
time_t m_timestamp
Definition parser.h:133
TermPtr m_annotation
Definition parser.h:97
std::string m_filename
stream name (file or input stream) used for error messages.
Definition parser.h:46
bool PragmaStaticAssert(const TermPtr &term)
Definition parser.cpp:506
TermPtr ParseFile(const std::string_view filename)
Definition parser.cpp:66
MacroPtr m_macro
Definition parser.h:139
parser::location_type m_location
Definition parser.h:48
BlockType m_macro_analisys_buff
Последовательность лексем для анализа на наличие макросов
Definition parser.h:91
std::string m_exec_dir
Definition runtime.h:383
void ApplyDiags(DiagPtr diag=nullptr)
Definition lexer.cpp:33
size_t m_macro_del
Definition lexer.h:65
SourceType source_base
Definition lexer.h:48
SourceType source_string
Definition lexer.h:49
std::istringstream * m_macro_iss
Definition lexer.h:61
parser::location_type m_macro_loc
Definition lexer.h:62
TermPtr m_macro_body
Definition lexer.h:66
size_t m_macro_count
Definition lexer.h:64
parser::location_type * m_loc
Definition lexer.h:50
virtual parser::token_type lex(TermPtr *yylval, parser::location_type *yylloc)
static TermPtr Create(TermID id, const char *text, parser::token_type lex_type=parser::token_type::END, size_t len=std::string::npos, location *loc=nullptr, std::shared_ptr< std::string > source=nullptr)
Definition term.h:335
bool GetValueAsBoolean() const
Definition variable.cpp:265
#define DEFINE_CASE(name)
int result
Definition lexer.l:367
* yylval
Definition lexer.l:131
__attribute__((weak)) std
Definition logger.cpp:264
#define LOG_RUNTIME(format,...)
Definition logger.h:26
#define LOG_LEVEL_INFO
Definition logger.h:87
#define LOG_INFO(...)
Definition logger.h:120
#define VERIFY(exp)
Definition logger.h:65
#define LOG_DEBUG(...)
Definition logger.h:119
#define ASSERT(condition)
Definition logger.h:60
#define LOG_ERROR(...)
Definition logger.h:122
#define LOG_WARNING(...)
Definition logger.h:121
Definition nlc.h:59
const VariablePtr getEllipsysVar()
Definition parser.cpp:1052
TermID
Definition term.h:119
const TermPtr getDefaultType(const std::string_view text)
Definition parser.cpp:1072
const TermPtr getRequiredTerm()
Definition parser.cpp:1032
std::vector< std::string > PostLexerType
Definition types.h:255
std::string ParserMessage(std::string &buffer, int row, int col, const char *format,...)
Definition parser.cpp:525
bool CheckCharModuleName(const std::string_view name)
Definition types.h:1207
const VariablePair & getNonePair()
Definition parser.cpp:1056
bool isModuleName(const std::string_view name)
Definition types.h:1057
ExpandMacroResult
Definition parser.h:19
std::shared_ptr< Variable > VariablePtr
Definition variable.h:131
std::shared_ptr< Term > TermPtr
Definition variable.h:33
std::shared_ptr< Obj > ObjPtr
Definition variable.h:28
ExpandMacroResult ExpandTermMacro(Parser &parser)
Definition macro.cpp:45
void ParserException(const char *msg, std::string &buffer, int row, int col)
Definition parser.cpp:579
const ObjPtr getNoneObj()
Definition parser.cpp:1040
const Variable & getNoneVar()
Definition parser.cpp:1044
std::shared_ptr< Macro > MacroPtr
Definition types.h:244
std::vector< TermPtr > BlockType
Definition types.h:239
ObjType GetBaseTypeFromString(const std::string_view type_arg, bool *has_error=nullptr)
Definition parser.cpp:1102
std::shared_ptr< Diag > DiagPtr
Definition types.h:243
ObjType
Definition types.h:524
const char * toString(TermID type)
Definition term.h:126
const TermPtr getNoneTerm()
Definition parser.cpp:1028
bool isDefaultType(const TermPtr &term)
Definition parser.cpp:1060
TermPtr ProcessMacro(Parser &parser, TermPtr &term)
Definition macro.cpp:26
const ObjPtr getEllipsysObj()
Definition parser.cpp:1048
const TermPtr getEllipsysTerm()
Definition parser.cpp:1036
bool canCast(const ObjType from, const ObjType to)
Definition types.h:967
static const Variable var_none
Definition parser.cpp:1022
static const ObjPtr obj_ellipsys
Definition parser.cpp:1024
static const ObjPtr obj_none
Definition parser.cpp:1021
static const TermPtr term_ellipsys
Definition parser.cpp:1018
static const TermPtr type_default_none
Definition parser.cpp:1014
static const VariablePair var_none_pair
Definition parser.cpp:1026
static const TermPtr type_default_any
Definition parser.cpp:1015
#define MAKE_TYPE(type_name)
Definition parser.cpp:981
static const TermPtr term_none
Definition parser.cpp:1017
static const std::map< const std::string, const TermPtr > default_types
Definition parser.cpp:983
static const VariablePtr var_ellipsys
Definition parser.cpp:1025
static const TermPtr term_required
Definition parser.cpp:1019
#define NL_PARSER(term, format,...)
Definition types.h:310
#define NL_TYPES(_)
Definition types.h:359
const char * DATE_BUILD_STR
Definition version.cpp:13
const char * GIT_SOURCE
Definition version.cpp:12
const char * SOURCE_FULL_ID
Definition version.cpp:14
#define VERSION
Definition version.h:14