aboutsummaryrefslogtreecommitdiff
path: root/backend/include/rcc/MIR/MILexer.h
blob: f54f2557b929693bfa62dcd49df4742dfff70e26 (plain)
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef RCC_MIR_MILEXER_H
#define RCC_MIR_MILEXER_H

#include "rcc/Support/TextDiagnostic.h"

#include <cstddef>
#include <cstdint>
#include <memory>
#include <span>
#include <string>
#include <string_view>
#include <utility>
#include <variant>

namespace rcc::mir {

enum class MITokenKind : std::uint8_t {
  EndOfFile,
  Error,
  Newline,

  Comma,
  Equal,
  Underscore,
  Colon,
  DoubleColon,
  Dot,
  Exclaim,
  LeftParen,
  RightParen,
  LeftBrace,
  RightBrace,
  Plus,
  Minus,
  Less,
  Greater,

  Keyword,
  MetadataKeyword,
  Identifier,
  NamedRegister,
  NamedVirtualRegister,
  MachineBasicBlockLabel,
  MachineBasicBlock,
  StackObject,
  FixedStackObject,
  NamedGlobalValue,
  GlobalValue,
  ExternalSymbol,
  MCSymbol,
  IntegerLiteral,
  FloatingPointLiteral,
  HexLiteral,
  VirtualRegister,
  ConstantPoolItem,
  JumpTableIndex,
  NamedIRBlock,
  IRBlock,
  NamedIRValue,
  IRValue,
  QuotedIRValue,
  SubRegisterIndex,
  StringConstant,
};

[[nodiscard]] std::string_view getMITokenKindName(MITokenKind Kind) noexcept;
[[nodiscard]] bool isMIKeyword(std::string_view Spelling) noexcept;
[[nodiscard]] bool isMIMetadataKeyword(std::string_view Spelling) noexcept;

class MIToken final {
public:
  [[nodiscard]] MITokenKind kind() const noexcept {
    return Kind;
  }

  [[nodiscard]] const TextRange &range() const noexcept {
    return Range;
  }

  [[nodiscard]] std::string_view spelling() const noexcept {
    return Spelling;
  }

  [[nodiscard]] bool hasStringValue() const noexcept {
    return !std::holds_alternative<std::monostate>(StringValue);
  }

  [[nodiscard]] std::string_view stringValue() const noexcept;

  [[nodiscard]] bool hasIntegerValue() const noexcept {
    return !IntegerValue.empty();
  }

  [[nodiscard]] std::string_view integerValue() const noexcept {
    return IntegerValue;
  }

  [[nodiscard]] bool is(MITokenKind Expected) const noexcept {
    return Kind == Expected;
  }

  [[nodiscard]] bool isKeyword(std::string_view Expected) const noexcept {
    return Kind == MITokenKind::Keyword && stringValue() == Expected;
  }

  [[nodiscard]] bool isMetadataKeyword(std::string_view Expected) const noexcept {
    return Kind == MITokenKind::MetadataKeyword && stringValue() == Expected;
  }

  [[nodiscard]] bool isNewlineOrEnd() const noexcept {
    return Kind == MITokenKind::Newline || Kind == MITokenKind::EndOfFile;
  }

  [[nodiscard]] bool isErrorOrEnd() const noexcept {
    return Kind == MITokenKind::Error || Kind == MITokenKind::EndOfFile;
  }

  [[nodiscard]] bool isRegister() const noexcept;
  [[nodiscard]] bool isRegisterFlag() const noexcept;
  [[nodiscard]] bool isMemoryOperandFlag() const noexcept;

private:
  using StringValueStorage = std::variant<std::monostate, std::string_view, std::string>;

  MIToken(MITokenKind Kind, TextRange Range, std::string_view Spelling,
          StringValueStorage StringValue = {}, std::string_view IntegerValue = {})
      : Kind(Kind), Range(Range), Spelling(Spelling), StringValue(std::move(StringValue)),
        IntegerValue(IntegerValue) {}

  MITokenKind Kind = MITokenKind::Error;
  TextRange Range;
  std::string_view Spelling;
  StringValueStorage StringValue;
  std::string_view IntegerValue;

  friend class MILexer;
};

struct MILexerOptions final {
  std::size_t MaximumTokenLength = std::size_t{1} << 24U;
  std::size_t MaximumTokens = std::size_t{1} << 24U;
};

class MILexer final {
public:
  MILexer(std::string SourceName, std::string SourceText, MILexerOptions Options = {});
  MILexer(const MILexer &) = delete;
  MILexer &operator=(const MILexer &) = delete;
  MILexer(MILexer &&) noexcept;
  MILexer &operator=(MILexer &&) noexcept;
  ~MILexer();

  [[nodiscard]] MIToken next();

  [[nodiscard]] const TextSource &source() const noexcept;
  [[nodiscard]] std::span<const TextDiagnostic> diagnostics() const noexcept;
  [[nodiscard]] bool failed() const noexcept;
  [[nodiscard]] std::size_t tokenCount() const noexcept;

private:
  [[nodiscard]] static MIToken makeToken(MITokenKind Kind, TextRange Range,
                                         std::string_view Spelling,
                                         std::string_view IntegerValue = {});
  [[nodiscard]] static MIToken makeStringToken(MITokenKind Kind, TextRange Range,
                                               std::string_view Spelling,
                                               std::string_view StringValue,
                                               std::string_view IntegerValue = {});
  [[nodiscard]] static MIToken makeOwnedStringToken(MITokenKind Kind, TextRange Range,
                                                    std::string_view Spelling,
                                                    std::string StringValue,
                                                    std::string_view IntegerValue = {});

  class Impl;
  std::unique_ptr<Impl> Implementation;
};

} // namespace rcc::mir

#endif // RCC_MIR_MILEXER_H