-
Notifications
You must be signed in to change notification settings - Fork 0
/
PreTokenLine.h
70 lines (62 loc) · 1.8 KB
/
PreTokenLine.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#pragma once
#include "PreToken.h"
#include <vector>
#include <stdexcept>
class PreTokenLine
{
public:
PreTokenLine(const std::vector<PreToken>& tokens)
: tokens(tokens)
{
}
bool IsDirective() const
{
for (auto& token : tokens)
if (IsDirectiveOperator(token))
return true;
else if (!CanSkip(token))
return false;
return false;
}
std::pair<PreToken, std::vector<PreToken>> ParseDirective() const
{
auto operatorIndex = FindDirectiveOperator();
auto identifierIndex = FindDirectiveIdentifier(operatorIndex);
if (identifierIndex == -1)
return{ tokens[operatorIndex], { tokens.begin() + operatorIndex + 1, tokens.end() } };
return{ tokens[identifierIndex], { tokens.begin() + identifierIndex + 1, tokens.end() } };
}
const std::vector<PreToken>& GetTokens() const
{
return tokens;
}
private:
static bool IsDirectiveOperator(const PreToken& token)
{
return token.GetType() == PreTokenType::Operator && token.GetValue() == "#";
}
static bool CanSkip(const PreToken& token)
{
return token.GetType() == PreTokenType::Whitespace || token.GetType() == PreTokenType::Comment;
}
std::size_t FindDirectiveOperator() const
{
for (auto index = 0u; index < tokens.size(); ++index)
if (IsDirectiveOperator(tokens[index]))
return index;
else if (!CanSkip(tokens[index]))
break;
throw std::runtime_error("Line is not a preprocessor directive (missing #).");
}
std::size_t FindDirectiveIdentifier(std::size_t operatorIndex) const
{
for (auto index = operatorIndex + 1; index < tokens.size(); ++index)
if (tokens[index].GetType() == PreTokenType::Identifier)
return index;
else if (!CanSkip(tokens[index]))
throw std::runtime_error("Line is not a preprocessor directive (missing command after #).");
return -1;
}
private:
std::vector<PreToken> tokens;
};