yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Julius IkkalaParse char literals as integers (#6989)cf8e75fae

master
5.1 KiB191 linesraw
1#ifndef SLANG_LEXER_H
2#define SLANG_LEXER_H
3
4#include "../core/slang-basic.h"
5#include "slang-diagnostic-sink.h"
6
7namespace Slang
8{
9struct NamePool;
10
11//
12
13struct TokenList
14{
15    const Token* begin() const;
16    const Token* end() const;
17
18    SLANG_FORCE_INLINE void add(const Token& token) { m_tokens.add(token); }
19
20    List<Token> m_tokens;
21};
22
23struct TokenSpan
24{
25    TokenSpan();
26    TokenSpan(TokenList const& tokenList)
27        : m_begin(tokenList.begin()), m_end(tokenList.end())
28    {
29    }
30
31    const Token* begin() const { return m_begin; }
32    const Token* end() const { return m_end; }
33
34    int getCount() { return (int)(m_end - m_begin); }
35
36    const Token* m_begin;
37    const Token* m_end;
38};
39
40struct TokenReader
41{
42    Token m_nextToken;
43    TokenReader();
44    explicit TokenReader(TokenSpan const& tokens)
45        : m_cursor(tokens.begin()), m_end(tokens.end())
46    {
47        _updateLookaheadToken();
48    }
49    explicit TokenReader(TokenList const& tokens)
50        : m_cursor(tokens.begin()), m_end(tokens.end())
51    {
52        _updateLookaheadToken();
53    }
54    explicit TokenReader(Token const* begin, Token const* end)
55        : m_cursor(begin), m_end(end)
56    {
57        _updateLookaheadToken();
58    }
59    struct ParsingCursor
60    {
61        bool operator==(const ParsingCursor& rhs) const
62        {
63            return tokenReaderCursor == rhs.tokenReaderCursor;
64        }
65        bool operator!=(const ParsingCursor& rhs) const { return !(*this == rhs); }
66
67        bool isValid() const { return tokenReaderCursor != nullptr; }
68
69        Token nextToken;
70        const Token* tokenReaderCursor = nullptr;
71    };
72    ParsingCursor getCursor()
73    {
74        ParsingCursor rs;
75        rs.nextToken = m_nextToken;
76        rs.tokenReaderCursor = m_cursor;
77        return rs;
78    }
79    void setCursor(ParsingCursor cursor)
80    {
81        m_cursor = cursor.tokenReaderCursor;
82        m_nextToken = cursor.nextToken;
83    }
84    bool isAtCursor(const ParsingCursor& cursor) const
85    {
86        return cursor.tokenReaderCursor == m_cursor;
87    }
88    bool isAtEnd() const { return m_cursor == m_end; }
89    Token& peekToken();
90    TokenType peekTokenType() const;
91    SourceLoc peekLoc() const;
92
93    Token advanceToken();
94
95    int getCount() { return (int)(m_end - m_cursor); }
96
97    const Token* m_cursor;
98    const Token* m_end;
99    static Token getEndOfFileToken();
100
101private:
102    /// Update the lookahead token in `m_nextToken` to reflect the cursor state
103    void _updateLookaheadToken();
104};
105
106typedef unsigned int LexerFlags;
107enum
108{
109    kLexerFlag_SuppressDiagnostics = 1
110                                     << 2, ///< Suppress errors about invalid/unsupported characters
111};
112
113struct Lexer
114{
115    void initialize(
116        SourceView* sourceView,
117        DiagnosticSink* sink,
118        NamePool* namePool,
119        MemoryArena* memoryArena);
120
121    ~Lexer();
122
123    /// Runs the lexer to try and extract a single token, which is returned.
124    /// This can be used by the DiagnosticSink to be able to display more appropriate
125    /// information when displaying a source location - such as underscoring the
126    /// token at that location.
127    ///
128    /// NOTE! This function is relatively slow, and is designed for use around this specific
129    /// purpose. It does not return a token or a token type, because that information is
130    /// not needed by the DiagnosticSink.
131    static UnownedStringSlice sourceLocationLexer(const UnownedStringSlice& in);
132
133    /// Lex the next token in the input stream, returning an EOF token if at end.
134    Token lexToken();
135
136    /// Lex all tokens (up to the end of the stream) that are semantically relevant
137    TokenList lexAllSemanticTokens();
138
139    /// Lex all tokens (up to the end of the stream) that are relevant to things like markup
140    TokenList lexAllMarkupTokens();
141
142    /// Lex all tokens (up to the end of the stream) whether relevant or not.
143    TokenList lexAllTokens();
144
145    /// Get the diagnostic sink, taking into account flags. Will return null if suppressing
146    /// diagnostics.
147    DiagnosticSink* getDiagnosticSink()
148    {
149        return ((m_lexerFlags & kLexerFlag_SuppressDiagnostics) == 0) ? m_sink : nullptr;
150    }
151
152    SourceLoc findNextLineEnd(SourceLoc from, UInt& lineCount) const;
153
154    SourceView* m_sourceView;
155    DiagnosticSink* m_sink;
156    NamePool* m_namePool;
157
158    char const* m_cursor;
159
160    char const* m_begin;
161    char const* m_end;
162
163    /// The starting sourceLoc (same as first location of SourceView)
164    SourceLoc m_startLoc;
165
166    TokenFlags m_tokenFlags;
167    LexerFlags m_lexerFlags;
168
169    MemoryArena* m_memoryArena;
170};
171
172
173// Helper routines for extracting values from tokens
174String getStringLiteralTokenValue(Token const& token);
175String getFileNameTokenValue(Token const& token);
176
177typedef int64_t IntegerLiteralValue;
178typedef double FloatingPointLiteralValue;
179
180IntegerLiteralValue getIntegerLiteralValue(
181    Token const& token,
182    UnownedStringSlice* outSuffix = 0,
183    bool* outIsDecimalBase = 0);
184FloatingPointLiteralValue getFloatingPointLiteralValue(
185    Token const& token,
186    UnownedStringSlice* outSuffix = 0);
187
188IntegerLiteralValue getCharLiteralValue(Token const& token);
189} // namespace Slang
190
191#endif