diff options
author | Aryadev Chavali <aryadev@aryadevchavali.com> | 2024-04-15 04:49:18 +0630 |
---|---|---|
committer | Aryadev Chavali <aryadev@aryadevchavali.com> | 2024-04-15 04:55:51 +0630 |
commit | ec87245724cd2746a40f349151137a89deb00bee (patch) | |
tree | f5459a4a2fe7d7f031aae24184b1259d0d102c23 | |
parent | 81efc9006d9ebcb0587d1d4d5ee7a1b9d2996026 (diff) | |
download | ovm-ec87245724cd2746a40f349151137a89deb00bee.tar.gz ovm-ec87245724cd2746a40f349151137a89deb00bee.tar.bz2 ovm-ec87245724cd2746a40f349151137a89deb00bee.zip |
Implemented preprocess_const_blocks
Once again quite similar to preprocess_macro_blocks but shorter,
easier to use and easier to read. (76 vs 109)
-rw-r--r-- | asm/preprocesser.cpp | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/asm/preprocesser.cpp b/asm/preprocesser.cpp index 31cf6a7..dd7067a 100644 --- a/asm/preprocesser.cpp +++ b/asm/preprocesser.cpp @@ -63,6 +63,87 @@ preprocess_use_blocks(vector<token_t *> tokens) return VAL(new_tokens); } +struct const_t +{ + size_t start, end; +}; + +pair<vector<token_t *>, pp_err_t> +preprocess_const_blocks(vector<token_t *> &tokens) +{ + std::unordered_map<string_view, const_t> blocks; + for (size_t i = 0; i < tokens.size(); ++i) + { + token_t *t = tokens[i]; + if (t->type == token_type_t::PP_CONST) + { + string_view capture; + if (t->content == "" && (i == tokens.size() - 1 || + tokens[i + 1]->type != token_type_t::SYMBOL)) + return ERR(pp_err_t{pp_err_type_t::EXPECTED_NAME}); + else if (t->content != "") + capture = t->content; + else + capture = tokens[++i]->content; + + // Check for brackets + auto start = capture.find('('); + auto end = capture.find(')'); + if (start == string::npos || end == string::npos) + return ERR(pp_err_t{pp_err_type_t::EXPECTED_NAME}); + + ++i; + size_t block_start = i, block_end = 0; + for (; i < tokens.size() && tokens[i]->type != token_type_t::PP_END; ++i) + continue; + + if (i == tokens.size()) + return ERR(pp_err_t{pp_err_type_t::EXPECTED_END}); + + block_end = i - 1; + + blocks[capture.substr(start + 1, end - 1)] = + const_t{block_start, block_end}; + } + } + + vector<token_t *> new_tokens; + if (blocks.size() == 0) + { + // Just construct a new vector and carry on + for (token_t *token : tokens) + new_tokens.push_back(new token_t{*token}); + } + else + { + for (size_t i = 0; i < tokens.size(); ++i) + { + token_t *token = tokens[i]; + // Skip the tokens that construct the const + if (token->type == token_type_t::PP_CONST) + for (; i < tokens.size() && tokens[i]->type != token_type_t::PP_END; + ++i) + continue; + else if (token->type == token_type_t::PP_REFERENCE) + { + auto it = blocks.find(token->content); + if (it == blocks.end()) + { + new_tokens.clear(); + return ERR(pp_err_t(pp_err_type_t::UNKNOWN_NAME, token)); + } + + const_t block = it->second; + for (size_t i = block.start; i < block.end; ++i) + new_tokens.push_back(new token_t{*tokens[i]}); + } + else + new_tokens.push_back(new token_t{*token}); + } + } + + return VAL(new_tokens); +} std::ostream &operator<<(std::ostream &os, pp_err_t &err) { |