Implemented preprocess_const_blocks
Once again quite similar to preprocess_macro_blocks but shorter, easier to use and easier to read. (76 vs 109)
This commit is contained in:
@@ -63,6 +63,87 @@ preprocess_use_blocks(vector<token_t *> tokens)
|
|||||||
return VAL(new_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)
|
std::ostream &operator<<(std::ostream &os, pp_err_t &err)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user