Skip to content

Commit

Permalink
chore: Update parseDirective to return ParsedDirective variant
Browse files Browse the repository at this point in the history
Signed-off-by: Roberto Raggi <[email protected]>
  • Loading branch information
robertoraggi committed Nov 8, 2024
1 parent 2c6b24c commit 97ac532
Showing 1 changed file with 80 additions and 30 deletions.
110 changes: 80 additions & 30 deletions src/parser/cxx/preprocessor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,13 @@
#include <cxx/diagnostics_client.h>
#include <cxx/lexer.h>
#include <cxx/literals.h>
#include <cxx/preprocessor.h>
#include <cxx/private/path.h>

// fmt
#include <format>

// utf8
#include <utf8/unchecked.h>

// stl
#include <cxx/preprocessor.h>

#include <algorithm>
#include <cassert>
#include <format>
#include <forward_list>
#include <fstream>
#include <functional>
Expand Down Expand Up @@ -1167,8 +1161,15 @@ struct Preprocessor::Private {
TokList *loc = nullptr;
};

struct ParsedIfDirective {
std::function<void()> resume;
};

using ParsedDirective =
std::variant<std::monostate, ParsedIncludeDirective, ParsedIfDirective>;

[[nodiscard]] auto parseDirective(SourceFile *source, TokList *start)
-> std::optional<ParsedIncludeDirective>;
-> ParsedDirective;

[[nodiscard]] auto parseIncludeDirective(TokList *directive, TokList *ts)
-> std::optional<ParsedIncludeDirective>;
Expand Down Expand Up @@ -1203,7 +1204,9 @@ struct Preprocessor::Private {
[[nodiscard]] auto copyLine(TokList *ts, bool inMacroBody = false)
-> TokList *;

[[nodiscard]] auto constantExpression(TokList *ts) -> long;
[[nodiscard]] auto prepareConstantExpression(TokList *ts) -> TokList *;

[[nodiscard]] auto evaluateConstantExpression(TokList *ts) -> long;
[[nodiscard]] auto conditionalExpression(TokList *&ts) -> long;
[[nodiscard]] auto binaryExpression(TokList *&ts) -> long;
[[nodiscard]] auto binaryExpressionHelper(TokList *&ts, long lhs, int minPrec)
Expand Down Expand Up @@ -1672,7 +1675,10 @@ auto Preprocessor::Private::expand(
// skip the rest of the line
it = skipLine(it, last);

if (auto parsedInclude = parseDirective(source, start.toTokList())) {
auto parsedDirective = parseDirective(source, start.toTokList());

if (auto parsedInclude =
std::get_if<ParsedIncludeDirective>(&parsedDirective)) {
NeedToResolveInclude status{
.preprocessor = *preprocessor_,
.include = parsedInclude->header,
Expand All @@ -1692,6 +1698,10 @@ auto Preprocessor::Private::expand(
it = last;

return status;
} else if (auto directive =
std::get_if<ParsedIfDirective>(&parsedDirective)) {
// suspend and resolve the dependencies
directive->resume();
}
} else if (skipping) {
it = skipLine(++it, last);
Expand All @@ -1707,10 +1717,10 @@ auto Preprocessor::Private::expand(
}

auto Preprocessor::Private::parseDirective(SourceFile *source, TokList *start)
-> std::optional<ParsedIncludeDirective> {
-> ParsedDirective {
auto directive = start->next;

if (!lookat(directive, TokenKind::T_IDENTIFIER)) return std::nullopt;
if (!lookat(directive, TokenKind::T_IDENTIFIER)) return std::monostate{};

dependencies_.clear();

Expand All @@ -1725,7 +1735,11 @@ auto Preprocessor::Private::parseDirective(SourceFile *source, TokList *start)
case PreprocessorDirectiveKind::T_INCLUDE_NEXT:
case PreprocessorDirectiveKind::T_INCLUDE: {
if (skipping) break;
return parseIncludeDirective(directive, ts);
auto includeDirective = parseIncludeDirective(directive, ts);
if (includeDirective.has_value()) {
return *includeDirective;
}
break;
}

case PreprocessorDirectiveKind::T_DEFINE: {
Expand Down Expand Up @@ -1781,12 +1795,25 @@ auto Preprocessor::Private::parseDirective(SourceFile *source, TokList *start)
if (skipping) {
pushState(std::tuple(true, false));
} else {
const auto value = constantExpression(ts);
if (value) {
pushState(std::tuple(skipping, false));
} else {
pushState(std::tuple(true, !skipping));
}
auto expression = prepareConstantExpression(ts);

auto resume = [=, this] {
// evaluate the deps
for (auto &d : dependencies_) {
auto resolved = resolve(d.include, d.isIncludeNext);
d.value = resolved.has_value();
}

const auto value = evaluateConstantExpression(expression);

if (value) {
pushState(std::tuple(skipping, false));
} else {
pushState(std::tuple(true, !skipping));
}
};

return ParsedIfDirective{.resume = std::move(resume)};
}

break;
Expand All @@ -1796,12 +1823,25 @@ auto Preprocessor::Private::parseDirective(SourceFile *source, TokList *start)
if (!evaluating) {
setState(std::tuple(true, false));
} else {
const auto value = constantExpression(ts);
if (value) {
setState(std::tuple(!evaluating, false));
} else {
setState(std::tuple(true, evaluating));
}
auto expression = prepareConstantExpression(ts);

auto resume = [=, this] {
// evaluate the deps
for (auto &d : dependencies_) {
auto resolved = resolve(d.include, d.isIncludeNext);
d.value = resolved.has_value();
}

const auto value = evaluateConstantExpression(expression);

if (value) {
setState(std::tuple(!evaluating, false));
} else {
setState(std::tuple(true, evaluating));
}
};

return ParsedIfDirective{.resume = std::move(resume)};
}

break;
Expand Down Expand Up @@ -1899,7 +1939,7 @@ auto Preprocessor::Private::parseDirective(SourceFile *source, TokList *start)
break;
} // switch

return std::nullopt;
return std::monostate{};
}

auto Preprocessor::Private::parseIncludeDirective(TokList *directive,
Expand Down Expand Up @@ -2348,18 +2388,28 @@ auto Preprocessor::Private::copyLine(TokList *ts, bool inMacroBody)
return line;
}

auto Preprocessor::Private::constantExpression(TokList *ts) -> long {
auto Preprocessor::Private::prepareConstantExpression(TokList *ts)
-> TokList * {
auto line = copyLine(ts);

dependencies_.clear();

auto it = expandTokens(TokIterator{line}, TokIterator{},
/*inConditionalExpression*/ true);

auto expression = it.toTokList();

return expression;
}

auto Preprocessor::Private::evaluateConstantExpression(TokList *ts) -> long {
// evaluate the deps
for (auto &d : dependencies_) {
auto resolved = resolve(d.include, d.isIncludeNext);
d.value = resolved.has_value();
}
auto e = it.toTokList();
return conditionalExpression(e);

return conditionalExpression(ts);
}

auto Preprocessor::Private::conditionalExpression(TokList *&ts) -> long {
Expand Down

0 comments on commit 97ac532

Please sign in to comment.