diff --git a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.hpp b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.hpp index 1bac451ee..737202d97 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.hpp @@ -31,6 +31,7 @@ #include #include #include +#include namespace Opm { @@ -76,6 +77,7 @@ public: void required_summary(std::unordered_set& summary_keys) const; void update_status(UDQUpdate update_status, std::size_t report_step); std::pair status() const; + std::vector tokens() const; bool operator==(const UDQDefine& data) const; @@ -93,6 +95,7 @@ public: private: std::string m_keyword; + std::vector m_tokens; std::shared_ptr ast; UDQVarType m_var_type; KeywordLocation m_location; diff --git a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp index eb9982765..0b1a84753 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp @@ -125,6 +125,59 @@ enum class UDQTokenType{ end = 100 }; +#if 0 +enum class UDQTokenPrec{ + + open_paren = 2, + close_paren = 3, + // + binary_op_add = 8, + binary_op_sub = 9, + binary_op_div = 10, + binary_op_mul = 11, + binary_op_pow = 12, + binary_op_uadd = 13, + binary_op_umul = 14, + binary_op_umin = 15, + binary_op_umax = 16, + binary_cmp_eq = 17, + binary_cmp_ne = 18, + binary_cmp_le = 19, + binary_cmp_ge = 20, + binary_cmp_lt = 21, + binary_cmp_gt = 22, + // + elemental_func_randn = 23, + elemental_func_randu = 24, + elemental_func_rrandn = 25, + elemental_func_rrandu = 26, + elemental_func_abs = 27, + elemental_func_def = 28, + elemental_func_exp = 29, + elemental_func_idv = 30, + elemental_func_ln = 31, + elemental_func_log = 32, + elemental_func_nint = 33, + elemental_func_sorta = 34, + elemental_func_sortd = 35, + elemental_func_undef = 36, + // + scalar_func_sum = 37, + scalar_func_avea = 38, + scalar_func_aveg = 39, + scalar_func_aveh = 40, + scalar_func_max = 41, + scalar_func_min = 42, + scalar_func_norm1 = 43, + scalar_func_norm2 = 44, + scalar_func_normi = 45, + scalar_func_prod = 46, + // + table_lookup = 47, + // + end = 100 +}; +#endif enum class UDQAction { ASSIGN, diff --git a/src/opm/output/eclipse/AggregateUDQData.cpp b/src/opm/output/eclipse/AggregateUDQData.cpp index 2066a028e..006709acc 100644 --- a/src/opm/output/eclipse/AggregateUDQData.cpp +++ b/src/opm/output/eclipse/AggregateUDQData.cpp @@ -64,30 +64,475 @@ namespace { return inteHead[163]; } - // Categorize function in terms of which token-types are used in formula - int define_type(const std::set tokens) { - int type = -4; - std::vector type_1 = { - Opm::UDQTokenType::elemental_func_sorta, - Opm::UDQTokenType::elemental_func_sortd, - Opm::UDQTokenType::elemental_func_undef, - Opm::UDQTokenType::scalar_func_sum, - Opm::UDQTokenType::scalar_func_avea, - Opm::UDQTokenType::scalar_func_aveg, - Opm::UDQTokenType::scalar_func_aveh, - Opm::UDQTokenType::scalar_func_max, - Opm::UDQTokenType::scalar_func_min, - Opm::UDQTokenType::binary_op_div - }; - int num_type_1 = 0; + // function to return true if token is a function + bool tokenTypeFunc(const Opm::UDQTokenType& token) { + bool type = false; + std::vector type_1 = { + Opm::UDQTokenType::elemental_func_randn, + Opm::UDQTokenType::elemental_func_randu, + Opm::UDQTokenType::elemental_func_rrandn, + Opm::UDQTokenType::elemental_func_rrandu, + Opm::UDQTokenType::elemental_func_abs, + Opm::UDQTokenType::elemental_func_def, + Opm::UDQTokenType::elemental_func_exp, + Opm::UDQTokenType::elemental_func_idv, + Opm::UDQTokenType::elemental_func_ln, + Opm::UDQTokenType::elemental_func_log, + Opm::UDQTokenType::elemental_func_nint, + Opm::UDQTokenType::elemental_func_sorta, + Opm::UDQTokenType::elemental_func_sortd, + Opm::UDQTokenType::elemental_func_undef, + // + Opm::UDQTokenType::scalar_func_sum, + Opm::UDQTokenType::scalar_func_avea, + Opm::UDQTokenType::scalar_func_aveg, + Opm::UDQTokenType::scalar_func_aveh, + Opm::UDQTokenType::scalar_func_max, + Opm::UDQTokenType::scalar_func_min, + Opm::UDQTokenType::scalar_func_norm1, + Opm::UDQTokenType::scalar_func_norm2, + Opm::UDQTokenType::scalar_func_normi, + Opm::UDQTokenType::scalar_func_prod, + Opm::UDQTokenType::table_lookup + }; for (const auto& tok_type : type_1) { - num_type_1 += tokens.count(tok_type); + if (token == tok_type) { + type = true; + break; + } } - type = (num_type_1 > 0) ? -1 : -4; return type; } +// function to return true if token is a binary operator: type compare + bool tokenTypeBinaryCmpOp(const Opm::UDQTokenType& token) { + bool type = false; + std::vector type_1 = { + Opm::UDQTokenType::binary_cmp_eq, + Opm::UDQTokenType::binary_cmp_ne, + Opm::UDQTokenType::binary_cmp_le, + Opm::UDQTokenType::binary_cmp_ge, + Opm::UDQTokenType::binary_cmp_lt, + Opm::UDQTokenType::binary_cmp_gt + + }; + for (const auto& tok_type : type_1) { + if (token == tok_type) { + type = true; + break; + } + } + return type; + } + + // function to return true if token is a binary operator: type power (exponentiation) + bool tokenTypeBinaryPowOp(const Opm::UDQTokenType& token) { + return (token == Opm::UDQTokenType::binary_op_pow) ? true: false; + } + + // function to return true if token is a binary operator: type multiply or divide + bool tokenTypeBinaryMulDivOp(const Opm::UDQTokenType& token) { + bool type = false; + std::vector type_1 = { + Opm::UDQTokenType::binary_op_div, + Opm::UDQTokenType::binary_op_mul + }; + for (const auto& tok_type : type_1) { + if (token == tok_type) { + type = true; + break; + } + } + return type; + } + + // function to return true if token is a binary operator: type add or subtract + bool tokenTypeBinaryAddSubOp(const Opm::UDQTokenType& token) { + bool type = false; + std::vector type_1 = { + Opm::UDQTokenType::binary_op_add, + Opm::UDQTokenType::binary_op_sub + }; + for (const auto& tok_type : type_1) { + if (token == tok_type) { + type = true; + break; + } + } + return type; + } + + // function to return true if token is a binary operator: type + bool tokenTypeBinaryUnionOp(const Opm::UDQTokenType& token) { + bool type = false; + std::vector type_1 = { + Opm::UDQTokenType::binary_op_uadd, + Opm::UDQTokenType::binary_op_umul, + Opm::UDQTokenType::binary_op_umin, + Opm::UDQTokenType::binary_op_umax + }; + for (const auto& tok_type : type_1) { + if (token == tok_type) { + type = true; + break; + } + } + return type; + } + + // function to return true if token is a binary operator: anytype + bool tokenTypeBinaryOp(const Opm::UDQTokenType& token) { + bool type = false; + std::vector type_1 = { + Opm::UDQTokenType::binary_op_add, + Opm::UDQTokenType::binary_op_sub, + Opm::UDQTokenType::binary_op_div, + Opm::UDQTokenType::binary_op_mul, + Opm::UDQTokenType::binary_op_pow, + Opm::UDQTokenType::binary_op_uadd, + Opm::UDQTokenType::binary_op_umul, + Opm::UDQTokenType::binary_op_umin, + Opm::UDQTokenType::binary_op_umax, + Opm::UDQTokenType::binary_cmp_eq, + Opm::UDQTokenType::binary_cmp_ne, + Opm::UDQTokenType::binary_cmp_le, + Opm::UDQTokenType::binary_cmp_ge, + Opm::UDQTokenType::binary_cmp_lt, + Opm::UDQTokenType::binary_cmp_gt + + }; + for (const auto& tok_type : type_1) { + if (token == tok_type) { + type = true; + break; + } + } + return type; + } + + // function to return the number of sets of () outside any function / operator or variable + int noOutsideOpencloseParen(const std::vector& tokens) { + bool last_paren = false; + int noOpenPar = 0; + int noOCPPairs = 0; + auto modTokens = tokens; + bool lastTokCP = true; + std::cout << "noOutsideOpencloseParen" << std::endl; + while (lastTokCP) { + bool firstTokenOpenParen = (modTokens[0].type() == Opm::UDQTokenType::open_paren) ? true : false; + if (firstTokenOpenParen) { + noOpenPar += 1 ; + for (std::size_t ti = 1; ti < modTokens.size()-1; ti++) { + if (modTokens[ti].type() == Opm::UDQTokenType::open_paren) noOpenPar +=1; + if (modTokens[ti].type() == Opm::UDQTokenType::close_paren) noOpenPar -=1; + if (noOpenPar <= 0) { + goto endLastParamBeforeLastToken; + } + } + if (modTokens.back().type() == Opm::UDQTokenType::close_paren) { + // remove outer set of () and repeat procedure on reduced string + modTokens = {modTokens.begin()+1, modTokens.end()-1}; + noOCPPairs += 1; + std::cout << "modTokens " << std::endl; + for (std::size_t ind = 0; ind < modTokens.size(); ind++) { + std::cout << "ind: " << ind << " modTokens[ind].str() " << modTokens[ind].str() << std::endl; + } + } + } + else { + lastTokCP = false; + } + } + endLastParamBeforeLastToken: + return noOCPPairs; + } + + // function to return index number of last binary token not inside bracket that is ending the expression + std::size_t indexOfLastOp_nib(const std::vector& modTokens) { + std::size_t tok_no = 0; + std::size_t i_start = 0; + int noOpenPar = 0; + std::cout << "indexOfLastOp_nib " << std::endl; + int noOCPPairs = noOutsideOpencloseParen(modTokens); + i_start = noOCPPairs; + //std::size_t i_start = (modTokens[0].type() == Opm::UDQTokenType::open_paren) ? 1 : 0; + //if ((modTokens[0].type() == Opm::UDQTokenType::open_paren) && !lastTokCP) noOpenPar = 1; + for (std::size_t ti = i_start; ti < modTokens.size(); ti++) { + if (modTokens[ti].type() == Opm::UDQTokenType::open_paren) noOpenPar +=1; + if (modTokens[ti].type() == Opm::UDQTokenType::close_paren) noOpenPar -=1; + if ((noOpenPar < 1) && (tokenTypeBinaryOp(modTokens[ti].type()) || tokenTypeFunc(modTokens[ti].type()))) tok_no = ti; + } + std::cout << " tok_no " << tok_no << " noOCPPairs: " << noOCPPairs << std::endl; + return tok_no + noOCPPairs; + } + + // function to return the precedence of the current operator/function + int opFuncPrec(const Opm::UDQTokenType& token) { + int prec = 0; + if (tokenTypeFunc(token)) prec = 6; + if (tokenTypeBinaryCmpOp(token)) prec = 5; + if (tokenTypeBinaryPowOp(token)) prec = 4; + if (tokenTypeBinaryMulDivOp(token)) prec = 3; + if (tokenTypeBinaryAddSubOp(token)) prec = 2; + if (tokenTypeBinaryUnionOp(token)) prec = 1; + return prec; + } + + // function to return + // a vector of functions and operators at the highest level plus, + // a map of substituted tokens + // the number of leading open_paren that bracket the whole expression + struct simplifiedExpression { + std::vector highestLevOperators; + std::map substitutedTokens; + int leadingOpenPar; + }; + + struct substOuterParentheses { + std::vector highestLevOperators; + std::vector operatorPos; + std::map substitutedTokens; + int leadingOpenPar; + }; + substOuterParentheses substitute_outer_parenthesis(const std::vector& modTokens, int noLeadOpenPar) { + std::map subst_tok; + std::vector high_lev_op; + std::vector operatorPos; + std::vector par_pos; + std::vector start_paren; + std::vector end_paren; + std::size_t level = 0; + std::size_t search_pos = 0; + std::size_t subS_max = 0; + int noOpenPar = 0; + std::cout << "start handleParentheses" << std::endl; + while (search_pos < modTokens.size()) { + if (modTokens[search_pos].type() == Opm::UDQTokenType::open_paren && level == 0) { + start_paren.emplace_back(search_pos); + level +=1; + } + else if (modTokens[search_pos].type() == Opm::UDQTokenType::open_paren) { + level +=1; + } + else if (modTokens[search_pos].type() == Opm::UDQTokenType::close_paren && level == +1) { + end_paren.emplace_back(search_pos); + level -=1; + } + else if (modTokens[search_pos].type() == Opm::UDQTokenType::close_paren) { + level -=1; + } + std::cout << " search_pos " << search_pos << " level " << level << std::endl; + if (start_paren.size() >= 1) { + std::cout << " start_paren " << start_paren[start_paren.end() - 1] + << " size_start_paren: " << start_paren.size() << std::endl; + } + if (end_paren.size() >= 1) { + std::cout << " end_paren " << end_paren[end_paren.end() - 1] << " size_end_paren: " << end_paren.size() + << std::endl; + } + search_pos += 1; + } + + // Replace content of all parentheses at the highest level by an ecl_expr + // and store the location of all the removed parentheses + + //First store all tokens before the first start_paren + for (std::size_t i = 0; i < start_paren[0]; i++) { + high_lev_op.emplace_back(modTokens[i]); + } + for (std::size_t ind = 0; ind < start_paren.size(); ind++) { + par_pos.emplace_back(start_paren[ind]); + std::vector substringToken; + for (std::size_t i = start_paren[ind]; i < end_paren[ind]+1; i++) { + substringToken.emplace_back(modTokens[search_pos]); + } + // store the content inside the parenthesis + std::pair groupPair = std::make_pair(ind, substringToken); + subst_tok.insert(groupPair); + // + // make the vector of high level tokens + // + //first add ecl_expr instead of content of (...) + + high_lev_op.emplace_back(Opm::UDQTokenType::ecl_expr); + // + // store all tokens including excluding end_paren before and start_paren after + if (ind == start_paren.size()-1) { + subS_max = modTokens.size(); + } + else { + subS_max = start_paren[ind+1]; + } + for (std::size_t i = end_paren[ind] + 1; i < subS_max; i++) { + high_lev_op.emplace_back(modTokens[i]); + } + } + + std::cout << " tok_no " << tok_no << " noOCPPairs: " << noOCPPairs << std::endl; + return tok_no + noOCPPairs; + } + + +// Categorize function in terms of which token-types are used in formula +// +// The define_type is (-) the location among a set of tokens of the "top" of the parse tree (AST - abstract syntax tree) +// i.e. the location of the lowest precedence operator relative to the total set of operators, functions and open-/close - parenthesis + int define_type(const std::vector& tokens) + { + int def_type = 0; + // first token determines how the rest of the definition is handled + bool firstTokenOpenParen = false; + int noOpenCloseParen = noOutsideOpencloseParen(tokens); + std::size_t ti = 0; + // noOpenPar is a parameter that counts how many "net" open_paren has been processed + int noOpenPar = 0; + // + // keep track of previous and current operator or function precedence + int prevPrec = 100; + int curPrec = 100; + // branch according to formula + // + // find the index of the last binary operator in the expression not inside parenthesis + std::size_t indLastBinOpTok = indexOfLastOp_nib(tokens); + //std::cout << "indLastBinOpTok: " << indLastBinOpTok << " token string: " << tokens[indLastBinOpTok].str() << std::endl; + // + if ((tokens[ti].type() == Opm::UDQTokenType::ecl_expr) || (tokens[ti].type() == Opm::UDQTokenType::number)) { + // first token in formula is ecl_expr or number + //std::cout << "first token- ecl_expr or number: " << tokens[ti].str() << std::endl; + goto endTreatmentFirstToken; + } + else if (tokenTypeFunc(tokens[ti].type())) { + // first token is a function + def_type = -1; + curPrec = opFuncPrec(tokens[ti].type()); + prevPrec = curPrec; + //std::cout << "first token- function: " << tokens[ti].str() << std::endl; + //std::cout << "prevPrec " << prevPrec << " curPrec: " << curPrec << std::endl; + } + else if (tokens[ti].type() == Opm::UDQTokenType::open_paren) { + // first token is open_paren + firstTokenOpenParen = true; + if (noOpenCloseParen > 0) { + if (indLastBinOpTok == 0) { + // adust noOpenPar for case with first token = open_paren and last token is close_paren plus no operator in between + noOpenPar = 0; + def_type = 1; + //std::cout << "first token- open_paren: " << tokens[ti].str() << std::endl; + //std::cout << "last token- close_paren: " << tokens.back().str() << std::endl; + } + else { + noOpenPar = 1 - noOpenCloseParen; + def_type = -1; + //std::cout << "first token- open_paren: " << tokens[ti].str() << " noOpenPar: " << noOpenPar << std::endl; + } + } + else { + noOpenPar = 1; + def_type = -1; + //std::cout << "first token- open_paren: " << tokens[ti].str() << " noOpenPar: " << noOpenPar << std::endl; + } + } + else if (tokens[ti].type() == Opm::UDQTokenType::binary_op_sub) { + //The minus sign in the first location is sign change - highest precedence (6) + def_type = -1; + curPrec = 6; + prevPrec = curPrec; + //std::cout << "first token- minus-sign: " << tokens[ti].str() << std::endl; + //std::cout << "prevPrec " << prevPrec << " curPrec: " << curPrec << std::endl; + } + else { + // print error message for unhandled formula + //std::stringstream str; + //str << "this token cannot be handled: " << tokens[ti].str(); + //throw std::invalid_argument(str.str()); + std::cout << "this token cannot be handled: " << tokens[ti].str() << std::endl; + } + endTreatmentFirstToken: + ti = 1; + if (tokens.size()==1) { + def_type = 1; + return def_type; + } + else { + Opm::UDQTokenType prevTokenType = tokens[0].type(); + // temporary int counter for possible intermediate operators and parentheses before next equal or lower precedence operator + int tcount = 0; + while (ti < indLastBinOpTok+1) { + // treat ecl_expr + if ((tokens[ti].type() == Opm::UDQTokenType::ecl_expr) || (tokens[ti].type() == Opm::UDQTokenType::number)) { + //std::cout << "token no: " << ti << " ecl_expr or number: " << tokens[ti].str() << std::endl; + prevTokenType = tokens[ti].type(); + ti += 1; + } + else if (tokens[ti].type() == Opm::UDQTokenType::open_paren) { + //std::cout << "token no: " << ti << " open_paren: " << tokens[ti].str() << std::endl; + noOpenPar += 1; + tcount += 1; + prevTokenType = tokens[ti].type(); + ti += 1; + } + else if (tokens[ti].type() == Opm::UDQTokenType::close_paren) { + //std::cout << "token no: " << ti << " close_paren: " << tokens[ti].str() << std::endl; + noOpenPar -= 1; + tcount += 1; + prevTokenType = tokens[ti].type(); + ti += 1; + } + else if (tokenTypeBinaryOp(tokens[ti].type()) || tokenTypeFunc(tokens[ti].type())) { + // + // update the previous operator precedence only if outside all parenthesis + //std::cout << "token no: " << ti << " bin_op or function " << tokens[ti].str() << std::endl; + // + if (noOpenPar <= 0) { + //check if operator is a change sign operator - if so set appropriate precedence level and increment + if ((tokens[ti].type() == Opm::UDQTokenType::binary_op_sub) && prevTokenType == Opm::UDQTokenType::open_paren) { + curPrec = 6; + } + else { + curPrec = opFuncPrec(tokens[ti].type()); + } + //std::cout << " Outside parenthesis - prevPrec " << prevPrec << " curPrec: " << tokens[ti].str() << curPrec << std::endl; + if (curPrec <= prevPrec) { + // if current precedence is lower than previous add minus (tcount + 1) to def_type and find next operator/function + // + //std::cout << " LowerOrEqual: prevPrec " << prevPrec << " curPrec: " << curPrec << tokens[ti].str() << std::endl; + def_type -= tcount + 1; + tcount = 0; + prevTokenType = tokens[ti].type(); + prevPrec = curPrec; + ti += 1; + } + else { + // found operator / function with higher precedence - increment tcount and ti + //std::cout << " Higher: prevPrec " << prevPrec << " curPrec: " << curPrec << tokens[ti].str() << std::endl; + tcount += 1; + ti += 1; + } + } + else { + // current token is inside one or more prentheses - increment def_type until outside + //std::cout << "inside parenthesis - token no: " << ti << " " << tokens[ti].str() << std::endl; + tcount += 1; + prevTokenType = tokens[ti].type(); + ti += 1; + } + } + else { + // print error message for unhandled formula + //std::stringstream str; + //str << "this token cannot be handled: " << tokens[ti].str(); + //throw std::invalid_argument(str.str()); + std::cout << "this token cannot be handled: " << tokens[ti].str() << std::endl; + ti = indLastBinOpTok+1; + } + + } +// } + return def_type; + } + } + namespace iUdq { Opm::RestartIO::Helpers::WindowedArray @@ -106,12 +551,40 @@ namespace { { if (udq_input.is()) { const auto& udq_define = udq_input.get(); - const auto& tokens = udq_define.func_tokens(); + const auto& tokens = udq_define.tokens(); +#if 0 + std::cout << "UDQ-DEFINE - keyword: " << udq_define.keyword() << std::endl; + std::size_t icnt = 0; + for (auto it = tokens.begin(); it != tokens.end(); it++) { + icnt+=1; + const int s_key = static_cast(*it); + std::cout << "func_token no: " << icnt << " token type: " << s_key << std::endl; + } + icnt = 0; + double val = 0.; + std::string val_string = ""; + for (const auto& token : all_tokens) { + icnt+=1; + val = 0.; + val_string = ""; + try { + val = std::get(token.value()); + } + catch (const std::bad_variant_access&) { + val_string = std::get(token.value()); + std::cout << "token: " << token.str() << " no double value" << std::endl; + } + const int token_type = static_cast(token.type()); + + std::cout << "token no: " << icnt << " token type: " << token_type << " token_string: " << token.str() << std::endl; + std::cout << " value_string " << val_string << " value_double: " << val << std::endl; + } +#endif iUdq[0] = 2; iUdq[1] = define_type(tokens); } else { iUdq[0] = 0; - iUdq[1] = -4; + iUdq[1] = 0; } iUdq[2] = udq_input.index.typed_insert_index; } @@ -192,6 +665,7 @@ namespace { { int l_sstr = 8; int max_l_str = 128; + std::string temp_str = ""; // write out the input formula if key is a DEFINE udq if (input.is()) { const auto& udq_define = input.get(); @@ -203,7 +677,17 @@ namespace { } else { for (int i = 0; i < n_sstr; i++) { - zUdl[i] = z_data.substr(i*l_sstr, l_sstr); + if (i == 0) { + temp_str = z_data.substr(i*l_sstr, l_sstr); + //if first character is a minus sign, change to ~ + if (temp_str.compare(0,1,"-") == 0) { + temp_str.replace(0,1,"~"); + } + zUdl[i] = temp_str; + } + else { + zUdl[i] = z_data.substr(i*l_sstr, l_sstr); + } } //add remainder of last non-zero string if ((z_data.size() % l_sstr) > 0) diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.cpp index 04e1c60af..b733e53cf 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.cpp @@ -198,6 +198,7 @@ UDQDefine::UDQDefine(const UDQParams& udq_params, } std::vector tokens = make_tokens(string_tokens); this->ast = std::make_shared( UDQParser::parse(udq_params, this->m_var_type, this->m_keyword, this->m_location, tokens, parseContext, errors) ); + this->m_tokens = tokens; this->string_data = ""; for (std::size_t index = 0; index < deck_data.size(); index++) { this->string_data += deck_data[index]; @@ -339,7 +340,9 @@ std::pair UDQDefine::status() const { return std::make_pair(this->m_update_status, this->m_report_step); } - +std::vector UDQDefine::tokens() const { + return this->m_tokens; +} bool UDQDefine::operator==(const UDQDefine& data) const { if ((ast && !data.ast) || (!ast && data.ast))