17 if (term->isMacro()) {
33 if (term->m_bracket_depth) {
34 NL_PARSER(term,
"Macro definitions allowed at the top level only, not inside conditions, namespace or any brackets!");
38 return parser.
m_macro->EvalOpMacros(term);
60 if (found == parser.
m_macro->end()) {
72 for (
auto iter = found->second.begin(); iter != found->second.end(); ++iter) {
77 LOG_RUNTIME(
"Macro duplication %s and '%s'!", macro_done->toString().c_str(), (*iter)->toString().c_str());
89 LOG_RUNTIME(
"Macro expansion '%s' stack overflow?", macro_done->toString().c_str());
95 ASSERT(macro_done->m_right);
106 std::string temp =
"";
111 temp += elem->m_text;
145 ASSERT(macro_done->m_right);
149 std::string temp =
"";
154 temp += elem->m_text;
166 LOG_RUNTIME(
"Macro mapping '%s' not found!\nThe following macro mapping are available:\n%s",
183 while (pos < seq.size()) {
186 NL_PARSER(seq[pos],
"Symbol '%c' in lexem sequence not allowed!", seq[pos]->m_text[0]);
205 if (!term->isMacro()) {
209 if (term->m_macro_id.empty()) {
212 ASSERT(term->m_macro_seq.size());
220 ASSERT(term->m_left->m_macro_seq.size());
222 term->m_macro_id =
MakeMacroId(term->m_left->m_macro_seq);
223 term->m_left->m_macro_id = term->m_macro_id;
226 ASSERT(term->m_macro_id.size());
228 return term->m_macro_id;
253 iterator found = this->map::find(str);
255 for (
auto iter = found->second.begin(); found != end() && iter != found->second.end(); ++iter) {
257 if (!
result.empty() && separator) {
261 result += (*iter)->toString();
274 if (term->isPure()) {
275 NL_PARSER(term,
"Hygienic macros are not implemented!");
279 bool is_operator =
false;
281 std::set<std::string> tmpl;
283 ASSERT(!term->m_left->m_macro_seq.empty());
284 for (
auto &elem :
MakeMacroId(term->m_left->m_macro_seq)) {
285 if (elem->isCall()) {
287 NL_PARSER(elem,
"Only one term in a macro can have arguments");
291 if (tmpl.find(elem->m_text) != tmpl.end()) {
292 NL_PARSER(elem,
"Reuse of argument name!");
294 if (elem->m_text.compare(
"$...") == 0) {
296 NL_PARSER(elem,
"Statement pattern should be only one!");
301 tmpl.insert(elem->m_text);
304 NL_PARSER(elem,
"Reserved term name used!");
308 NL_PARSER(elem,
"Unexpected term in macro!");
313 if (term->m_left->m_macro_seq.back()->m_text.compare(
"$...") != 0) {
314 NL_PARSER(op_term,
"Statement pattern must be the last term!");
317 NL_PARSER(args,
"The statement macro cannot be a function call!");
321 std::set<std::string> args_name;
323 int arg_count = args ? args->size() : 0;
325 bool is_ellips =
false;
326 for (
int i = 0; args && i < args->size(); i++) {
327 if (!args->at(i).first.empty()) {
329 if (args_name.find(args->at(i).first) != args_name.end()) {
330 NL_PARSER(args->at(i).second,
"Reuse of argument name!");
332 args_name.insert(args->at(i).first);
335 if (i + 1 != args->size()) {
336 NL_PARSER(args->at(i).second,
"The ellipsis can only be the last in the list of arguments!");
343 NL_PARSER(args->at(i).second,
"Positional arguments must come before named arguments!");
346 if (args_name.find(args->at(i).second->m_text) != args_name.end()) {
347 NL_PARSER(args->at(i).second,
"Reuse of argument name!");
349 args_name.insert(args->at(i).second->m_text);
364 for (
auto &elem : term->m_right->m_macro_seq) {
366 if (!is_ellips && !is_operator) {
367 NL_PARSER(elem,
"The macro has a fixed number of arguments, ellipsis cannot be used!");
370 int64_t num =
parseInteger(elem->m_text.substr(2).c_str());
371 if (num >= arg_count) {
372 NL_PARSER(elem,
"Invalid argument number!");
375 if (args_name.find(elem->m_text.substr(2)) == args_name.end() && tmpl.find(elem->m_text.substr(1)) == tmpl.end()) {
376 NL_PARSER(elem,
"Macro argument name not found!");
405 NL_PARSER(term,
"Operand '%s' not a macros!", term->m_left->toString().c_str());
409 NL_PARSER(term,
"For remove macro use operator @@@@ %s @@@@;)", term->m_left->m_text.c_str());
420 NL_PARSER(term,
"Macros '%s' already exists!", term->m_left->toString().c_str());
424 Macro::iterator found = map::find(
toMacroHash(term));
425 for (
auto iter = found->second.begin(); found != end() && iter != found->second.end(); ++iter) {
429 LOG_RUNTIME(
"Macro duplication '%s' and '%s'!", term->m_left->toString().c_str(), (*iter)->toString().c_str());
434 macro->m_right = term->m_right;
439 NL_PARSER(term,
"Macros '%s' not exists!", term->m_left->toString().c_str());
444 Macro::iterator found = map::find(
toMacroHash(temp));
445 for (
auto iter = found->second.begin(); found != end() && iter != found->second.end(); ++iter) {
448 LOG_RUNTIME(
"Macro duplication '%s' and '%s'!", term->m_left->toString().c_str(), (*iter)->toString().c_str());
462 insert(std::make_pair<std::string, BlockType>(
toMacroHash(macro),{macro}));
464 iter->second.push_back(macro);
478 if (term->m_id ==
TermID::MACRO_DEL && list.size() == 1 && list[0]->m_text.compare(
"_") == 0) {
485 if (found != end()) {
486 for (BlockType::iterator iter = found->second.begin(); iter != found->second.end(); ++iter) {
495 if (names.size() != list.size()) {
499 for (
int pos = 0; pos < list.size(); pos++) {
500 if (!
CompareMacroName(list[pos]->m_text.c_str(), names[pos]->m_text.c_str())) {
505 found->second.erase(iter);
507 if (found->second.empty()) {
509 erase(list[0]->m_text.c_str());
524 while (iter != end()) {
529 for (
int pos = 0; pos < iter->second.size(); pos++) {
532 for (
auto &elem : iter->second[pos]->m_macro_id) {
537 if (iter->second[pos]->isCall()) {
541 result += iter->first +
"->'" + str +
"'";
542 if (pos + 1 < iter->second.size()) {
555 auto iter = var.begin();
556 while (iter != var.end()) {
562 for (
int pos = 0; pos < iter->second.size(); pos++) {
567 str += iter->second[pos]->toString();
570 result += iter->first +
"->'" + str +
"'";
578 auto iter = arr.begin();
579 while (iter != arr.end()) {
584 result += (*iter)->toString();
592 auto iter = arr.begin();
593 while (iter != arr.end()) {
598 result += (*iter)->m_text;
613 return macro_name.compare(term_name) == 0;
616 return macro_name.compare(&term_name.c_str()[1]) == 0;
621 return macro_name.compare(term_name) == 0;
624 return term_name.compare(¯o_name.c_str()[1]) == 0;
632 return term_name.compare(macro_name) == 0;
755 if (!macro || !macro->isMacro()) {
761 int macro_offset = 0;
762 while (buff_offset < buffer.size() && macro_offset <
GetMacroId(macro).size()) {
764 if (buffer[buff_offset]->getTermID() ==
TermID::END) {
777 if (
GetMacroId(macro)[macro_offset]->isCall()) {
790 if (macro_offset ==
GetMacroId(macro).size()) {
804 if (args.find(name) != args.end()) {
809 if (pos ==
static_cast<size_t> (-1)) {
810 for (
auto &elem : buffer) {
811 vect.push_back(elem->Clone());
814 if (pos >= buffer.size()) {
816 LOG_RUNTIME(
"No data for input buffer! Pos %d for size %d!", (
int) pos, (
int) buffer.size());
818 vect.push_back(buffer[pos]->Clone());
820 args.insert(std::make_pair(name, vect));
827 while (pos < buffer.size()) {
829 for (
auto &elem : sym) {
830 if (buffer[pos]->m_text.compare(elem) == 0) {
838 for (
int i = 0; skip && i < skip - 1; i++) {
839 result.push_back(buffer[pos]->Clone());
843 result.push_back(buffer[pos]->Clone());
847 for (
auto &elem : sym) {
848 if (!error.empty()) {
856 error.insert(0,
"Expected symbol ");
866 if (!term->isMacro()) {
867 LOG_RUNTIME(
"Term is not a macro! '%s'", term->toString().c_str());
875 std::string arg_name;
879 size_t arg_count = 0;
880 size_t arg_offset = 0;
882 bool arg_ellipsys =
false;
883 bool all_args_done =
false;
889 if (
GetMacroId(term)[pos_id]->m_text.compare(
"$...") == 0) {
891 size_t stmt_start = pos_buf;
892 for (
int i = pos_buf; i < buffer.size(); i++) {
893 if (buffer[pos_buf]->getTermID() ==
TermID::END || buffer[pos_buf]->m_text.compare(
";") == 0) {
900 args_exta.insert(args_exta.end(), buffer.begin() + stmt_start, buffer.begin() + pos_buf);
910 }
else if (
GetMacroId(term)[pos_id]->isCall()) {
916 all_args_done =
true;
921 if (pos_buf >= buffer.size() || buffer[pos_buf]->getTermID() !=
TermID::SYMBOL || buffer[pos_buf]->m_text.compare(
"(") != 0) {
926 std::string error_str;
932 if (!error_str.empty()) {
936 if (!arg_seq.empty()) {
938 args_dict.insert(args_dict.end(), arg_seq.begin(), arg_seq.end());
940 pos_buf += arg_seq.size();
942 ASSERT(pos_buf < buffer.size());
948 arg_name += std::to_string(arg_count);
951 if (arg_count - 1 <
GetMacroId(term)[pos_id]->size()) {
954 arg_name =
GetMacroId(term)[pos_id]->at(arg_count - 1).second->m_text;
956 if (arg_name.compare(
"...") == 0) {
968 arg_name.insert(0,
"@$");
981 if (!args_exta.empty()) {
984 args_exta.insert(args_exta.end(), arg_seq.begin(), arg_seq.end());
987 }
else if (buffer[pos_buf]->m_text ==
",") {
988 args_dict.push_back(buffer[pos_buf]);
990 }
else if (buffer[pos_buf]->m_text ==
")") {
993 LOG_RUNTIME(
"Unexpected symbol %s ?????????", buffer[pos_buf]->m_text.c_str());
1020 for (
size_t j = 0; j <
GetMacroId(term).size(); j++) {
1031 && pos_buf + arg_offset <= buffer.size()) {
1032 ASSERT(pos_buf + arg_offset <= buffer.size());
1034 return pos_buf + arg_offset;
1037 NL_PARSER(buffer[0],
"Input buffer empty for extract args macros %s (%d+%d)=%d!", term->toString().c_str(), (
int) pos_buf, (
int) arg_offset, (
int) buffer.size());
1046 BlockType seq = macro->m_right->m_macro_seq;
1050 seq.push_back(macro->m_right);
1053 for (
int i = 0; i < seq.size(); i++) {
1057 if (i + 1 >= seq.size()) {
1058 NL_PARSER(seq[i],
"Next element to string not found!");
1062 if ((*
result.rbegin())->m_text.find(
"@$") == 0) {
1063 auto iter = args.find((*
result.rbegin())->m_text);
1064 if (iter == args.end()) {
1065 LOG_RUNTIME(
"Argument name '%s' not found!", seq[i]->m_text.c_str());
1068 for (
auto & elem : iter->second) {
1069 text += elem->m_text;
1071 (*
result.rbegin())->m_text = text;
1074 if (seq[i]->m_text.compare(
"@#\"") == 0) {
1076 }
else if (seq[i]->m_text.compare(
"@#'") == 0) {
1079 ASSERT(seq[i]->m_text.compare(
"@#") == 0);
1087 ASSERT(seq[i]->m_text.compare(
"@##") == 0);
1089 if (
result.empty() || i + 1 >= seq.size()) {
1090 NL_PARSER(seq[i],
"Concat elements not exist!");
1092 (*
result.rbegin())->m_text.append(seq[i + 1]->m_text);
1095 }
else if (seq[i]->m_text.find(
"@$") == 0) {
1097 auto iter = args.find(seq[i]->m_text);
1098 if (iter == args.end()) {
1099 LOG_RUNTIME(
"Argument name '%s' not found!", seq[i]->m_text.c_str());
1102 if (seq[i]->m_text.compare(
"@$...") == 0) {
1105 if (iter->second.empty() &&
result.rbegin() !=
result.rend() && (*
result.rbegin())->m_text.compare(
",") == 0) {
1110 for (
auto & elem : iter->second) {
1111 result.push_back(elem->Clone());
1122std::string
ReplaceAll(std::string str,
const std::string& from,
const std::string & to) {
1123 size_t start_pos = 0;
1124 while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
1126 str.replace(start_pos, from.length(), to);
1127 start_pos += to.length();
1136 LOG_RUNTIME(
"Fail convert term type %s as macros string!",
toString(macro->m_right->m_id));
1139 std::string body(macro->m_right->m_text);
1141 for (
auto &elem : args) {
1144 for (
auto &lex : elem.second) {
1146 text += lex->toString();
1158 std::vector<std::string> list;
1159 for (
auto &elem : block) {
1161 list.push_back(elem->m_text);
1172 if (found != end()) {
1173 for (BlockType::iterator iter = found->second.begin(); iter != found->second.end(); ++iter) {
1182 if (names.size() != list.size()) {
1186 for (
int pos = 0; pos < list.size(); pos++) {
1320 LOG_RUNTIME(
"Type name '%s' not found!", name.begin());
static const char * DIAG_MACRO_NOT_FOUND
static BlockType SymbolSeparateArg_(const BlockType &buffer, size_t pos, std::vector< std::string > name, std::string &error)
TermPtr GetMacroById(const BlockType block)
static std::string ExpandString(const TermPtr ¯o, MacroArgsType &args)
static BlockType MakeMacroId(const BlockType &seq)
TermPtr FindTerm(std::string_view name)
static void InsertArg_(MacroArgsType &args, std::string name, BlockType &buffer, size_t pos=static_cast< size_t >(-1))
static bool CompareMacroName(const std::string &term_name, const std::string ¯o_name)
static BlockType ExpandMacros(const TermPtr ¯o, MacroArgsType &args)
std::map< std::string, BlockType > MacroArgsType
static size_t ExtractArgs(BlockType &buffer, TermPtr &term, MacroArgsType &args)
static const std::string deny_chars_from_macro
TermPtr GetMacro(std::vector< std::string > list)
static std::string toMacroHashName(const std::string str)
bool CheckMacro(const TermPtr &term)
static std::string DumpText(const BlockType &arr)
static BlockType GetMacroId(TermPtr &term)
static bool IdentityMacro(const BlockType &buffer, TermPtr &term)
bool RemoveMacro(TermPtr &term)
std::string GetMacroMaping(const std::string str, const char *separator=", ")
static std::string toMacroHash(TermPtr &term)
TermPtr EvalOpMacros(TermPtr &term)
static size_t SkipBrackets(const BlockType &buffer, size_t offset)
static size_t ParseTerm(TermPtr &term, const BlockType &buffer, const size_t skip=0, bool pragma_enable=true)
BlockType m_macro_analisys_buff
Последовательность лексем для анализа на наличие макросов
std::istringstream * m_macro_iss
parser::location_type m_macro_loc
parser::location_type * m_loc
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)
static TermPtr CreateSymbol(char sym)
#define LOG_RUNTIME(format,...)
#define ASSERT(condition)
std::string ReplaceAll(std::string str, const std::string &from, const std::string &to)
bool isLocalName(const std::string_view name)
std::shared_ptr< Term > TermPtr
int64_t parseInteger(const char *str)
ExpandMacroResult ExpandTermMacro(Parser &parser)
bool isReservedName(const std::string_view name)
std::vector< TermPtr > BlockType
bool isLocalAnyName(const std::string_view name)
bool isMacroName(const std::string_view name)
const char * toString(TermID type)
TermPtr ProcessMacro(Parser &parser, TermPtr &term)
#define NL_PARSER(term, format,...)