mirror of https://github.com/x64dbg/btparser
Basic support for #pragma once and #if defined
This commit is contained in:
parent
b24d73c7b7
commit
962b648019
|
@ -35,7 +35,7 @@ struct Tokenizer
|
||||||
struct exception : public std::runtime_error
|
struct exception : public std::runtime_error
|
||||||
{
|
{
|
||||||
exception(const Line& line, const std::string& message = std::string())
|
exception(const Line& line, const std::string& message = std::string())
|
||||||
: std::runtime_error(message + " === " + line.str())
|
: std::runtime_error(message + "\n=========\n" + line.str() + "\n=========")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -131,6 +131,34 @@ struct Tokenizer
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void expect(int expected)
|
||||||
|
{
|
||||||
|
auto actual = peek();
|
||||||
|
if(actual != expected)
|
||||||
|
{
|
||||||
|
auto chstr = [](int ch)
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
if(ch == EOF)
|
||||||
|
{
|
||||||
|
result = "EOF";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result += "'";
|
||||||
|
result += (char)ch;
|
||||||
|
result += "'";
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
error("expected character " + chstr(expected) + ", got " + chstr(actual));
|
||||||
|
}
|
||||||
|
if(expected != EOF)
|
||||||
|
{
|
||||||
|
consume();
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string remove_block_comments(const std::string& input)
|
std::string remove_block_comments(const std::string& input)
|
||||||
|
@ -275,6 +303,22 @@ std::string preprocess(const std::string& input, std::string& error, const std::
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
auto evaluate = [&state](Tokenizer& t)
|
||||||
|
{
|
||||||
|
// TODO: support proper expression evaluation
|
||||||
|
auto id = t.identifier();
|
||||||
|
if(id == "defined")
|
||||||
|
{
|
||||||
|
t.expect('(');
|
||||||
|
auto name = t.identifier();
|
||||||
|
t.expect(')');
|
||||||
|
t.expect(EOF);
|
||||||
|
return state.count(name) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
t.error("unsupported expression '" + id + "'");
|
||||||
|
return false;
|
||||||
|
};
|
||||||
for (size_t i = 0; i < lines.size(); i++)
|
for (size_t i = 0; i < lines.size(); i++)
|
||||||
{
|
{
|
||||||
const auto& line = lines[i];
|
const auto& line = lines[i];
|
||||||
|
@ -289,7 +333,19 @@ std::string preprocess(const std::string& input, std::string& error, const std::
|
||||||
auto directive = t.identifier();
|
auto directive = t.identifier();
|
||||||
//line.print();
|
//line.print();
|
||||||
|
|
||||||
if (directive == "ifndef")
|
if (directive == "if")
|
||||||
|
{
|
||||||
|
t.skip_spaces(true);
|
||||||
|
auto pos = t.position;
|
||||||
|
auto expression = t.remainder();
|
||||||
|
while(!expression.empty() && std::isspace(expression.back()))
|
||||||
|
expression.pop_back();
|
||||||
|
t.position = pos;
|
||||||
|
auto result = evaluate(t);
|
||||||
|
//printf("#if(%s): %d\n", expression.c_str(), result);
|
||||||
|
stack.push_back({i, expression, result});
|
||||||
|
}
|
||||||
|
else if (directive == "ifndef")
|
||||||
{
|
{
|
||||||
t.skip_spaces(true);
|
t.skip_spaces(true);
|
||||||
auto identifier = t.identifier();
|
auto identifier = t.identifier();
|
||||||
|
@ -308,7 +364,7 @@ std::string preprocess(const std::string& input, std::string& error, const std::
|
||||||
else if (directive == "else")
|
else if (directive == "else")
|
||||||
{
|
{
|
||||||
if (stack.empty())
|
if (stack.empty())
|
||||||
throw std::runtime_error("no matching #if for #else");
|
t.error("no matching #if for #else");
|
||||||
if (!stack.back().value)
|
if (!stack.back().value)
|
||||||
{
|
{
|
||||||
stack.back().value = true;
|
stack.back().value = true;
|
||||||
|
@ -319,8 +375,8 @@ std::string preprocess(const std::string& input, std::string& error, const std::
|
||||||
else if (directive == "endif")
|
else if (directive == "endif")
|
||||||
{
|
{
|
||||||
if (stack.empty())
|
if (stack.empty())
|
||||||
throw std::runtime_error("no matching #if for #endif");
|
t.error("no matching #if for #endif");
|
||||||
//("#endif (%s)\n", stack.back().condition.c_str());
|
//printf("#endif (%s)\n", stack.back().condition.c_str());
|
||||||
stack.pop_back();
|
stack.pop_back();
|
||||||
//printf("emitting: %d\n", emitting());
|
//printf("emitting: %d\n", emitting());
|
||||||
}
|
}
|
||||||
|
@ -353,7 +409,7 @@ std::string preprocess(const std::string& input, std::string& error, const std::
|
||||||
t.skip_spaces();
|
t.skip_spaces();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw std::runtime_error("expect ',' or ')' got something else (too lazy sry)");
|
t.error("expect ',' or ')' got something else (too lazy sry)");
|
||||||
}
|
}
|
||||||
t.consume();
|
t.consume();
|
||||||
t.skip_spaces();
|
t.skip_spaces();
|
||||||
|
@ -368,10 +424,10 @@ std::string preprocess(const std::string& input, std::string& error, const std::
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("#define %s('%s' = '%s')\n", identifier.c_str(), pretty.c_str(), token.c_str());
|
//printf("#define %s('%s' = '%s')\n", identifier.c_str(), pretty.c_str(), token.c_str());
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// TODO: cut out comments
|
||||||
t.skip_spaces();
|
t.skip_spaces();
|
||||||
auto token = t.remainder();
|
auto token = t.remainder();
|
||||||
if (token.empty())
|
if (token.empty())
|
||||||
|
@ -406,13 +462,27 @@ std::string preprocess(const std::string& input, std::string& error, const std::
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw std::runtime_error("invalid syntax for #include");
|
t.error("invalid syntax for #include");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(directive == "pragma")
|
||||||
|
{
|
||||||
|
t.skip_spaces(true);
|
||||||
|
auto type = t.identifier();
|
||||||
|
if(type == "once")
|
||||||
|
{
|
||||||
|
//printf("#pragma once");
|
||||||
|
// TODO: implement something?
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t.error("unsupported #pragma type '" + type + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//printf("directive: '%s'\n", directive.c_str());
|
//printf("directive: '%s'\n", directive.c_str());
|
||||||
throw std::runtime_error("unknown directive '" + directive + "'");
|
t.error("unknown directive '" + directive + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (emitting())
|
else if (emitting())
|
||||||
|
|
Loading…
Reference in New Issue