yum-mirror/slang

Making it easier to work with shaders

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

Ellie Hermaszewskaformatf65d756bf

master
7.6 KiB356 linesraw
1#ifndef SLANG_CORE_TOKEN_READER_H
2#define SLANG_CORE_TOKEN_READER_H
3
4#include "slang-basic.h"
5
6namespace Slang
7{
8namespace Misc
9{
10
11/* NOTE! This TokenReader is NOT used by the main slang compiler !*/
12
13enum class TokenType
14{
15    EndOfFile = -1,
16    // illegal
17    Unknown,
18    // identifier
19    Identifier,
20    // constant
21    IntLiteral,
22    DoubleLiteral,
23    StringLiteral,
24    CharLiteral,
25    // operators
26    Semicolon,
27    Comma,
28    Dot,
29    LBrace,
30    RBrace,
31    LBracket,
32    RBracket,
33    LParent,
34    RParent,
35    OpAssign,
36    OpAdd,
37    OpSub,
38    OpMul,
39    OpDiv,
40    OpMod,
41    OpNot,
42    OpBitNot,
43    OpLsh,
44    OpRsh,
45    OpEql,
46    OpNeq,
47    OpGreater,
48    OpLess,
49    OpGeq,
50    OpLeq,
51    OpAnd,
52    OpOr,
53    OpBitXor,
54    OpBitAnd,
55    OpBitOr,
56    OpInc,
57    OpDec,
58    OpAddAssign,
59    OpSubAssign,
60    OpMulAssign,
61    OpDivAssign,
62    OpModAssign,
63    OpShlAssign,
64    OpShrAssign,
65    OpOrAssign,
66    OpAndAssign,
67    OpXorAssign,
68
69    QuestionMark,
70    Colon,
71    RightArrow,
72    At,
73    Pound,
74    PoundPound,
75    Scope,
76};
77
78class CodePosition
79{
80public:
81    int Line = -1, Col = -1, Pos = -1;
82    String FileName;
83    String ToString()
84    {
85        StringBuilder sb(100);
86        sb << FileName;
87        if (Line != -1)
88            sb << "(" << Line << ")";
89        return sb.produceString();
90    }
91    CodePosition() = default;
92    CodePosition(int line, int col, int pos, String fileName)
93    {
94        Line = line;
95        Col = col;
96        Pos = pos;
97        this->FileName = fileName;
98    }
99    bool operator<(const CodePosition& pos) const
100    {
101        return FileName < pos.FileName || (FileName == pos.FileName && Line < pos.Line) ||
102               (FileName == pos.FileName && Line == pos.Line && Col < pos.Col);
103    }
104    bool operator==(const CodePosition& pos) const
105    {
106        return FileName == pos.FileName && Line == pos.Line && Col == pos.Col;
107    }
108};
109
110enum TokenFlag : unsigned int
111{
112    AtStartOfLine = 1 << 0,
113    AfterWhitespace = 1 << 1,
114};
115typedef unsigned int TokenFlags;
116
117class Token
118{
119public:
120    TokenType Type = TokenType::Unknown;
121    String Content;
122    CodePosition Position;
123    TokenFlags flags = 0;
124    Token() = default;
125    Token(
126        TokenType type,
127        const String& content,
128        int line,
129        int col,
130        int pos,
131        String fileName,
132        TokenFlags flags = 0)
133        : flags(flags)
134    {
135        Type = type;
136        Content = content;
137        Position = CodePosition(line, col, pos, fileName);
138    }
139};
140
141class TextFormatException : public Exception
142{
143public:
144    TextFormatException(String message)
145        : Exception(message)
146    {
147    }
148};
149
150class TokenReader
151{
152private:
153    bool legal;
154    List<Token> tokens;
155    int tokenPtr;
156
157public:
158    TokenReader(String text);
159    int ReadInt()
160    {
161        auto token = ReadToken();
162        bool neg = false;
163        if (token.Content.getUnownedSlice().isChar('-'))
164        {
165            neg = true;
166            token = ReadToken();
167        }
168        if (token.Type == TokenType::IntLiteral)
169        {
170            if (neg)
171                return -stringToInt(token.Content);
172            else
173                return stringToInt(token.Content);
174        }
175        throw TextFormatException("Text parsing error: int expected.");
176    }
177    unsigned int ReadUInt()
178    {
179        auto token = ReadToken();
180        if (token.Type == TokenType::IntLiteral)
181        {
182            return stringToUInt(token.Content);
183        }
184        throw TextFormatException("Text parsing error: int expected.");
185    }
186    double ReadDouble()
187    {
188        auto token = ReadToken();
189        bool neg = false;
190        if (token.Content.getUnownedSlice().isChar('-'))
191        {
192            neg = true;
193            token = ReadToken();
194        }
195        if (token.Type == TokenType::DoubleLiteral || token.Type == TokenType::IntLiteral)
196        {
197            if (neg)
198                return -stringToDouble(token.Content);
199            else
200                return stringToDouble(token.Content);
201        }
202        throw TextFormatException("Text parsing error: floating point value expected.");
203    }
204    float ReadFloat() { return (float)ReadDouble(); }
205    String ReadWord()
206    {
207        auto token = ReadToken();
208        if (token.Type == TokenType::Identifier)
209        {
210            return token.Content;
211        }
212        throw TextFormatException("Text parsing error: identifier expected.");
213    }
214    String Read(const char* expectedStr)
215    {
216        auto token = ReadToken();
217        if (token.Content == expectedStr)
218        {
219            return token.Content;
220        }
221        throw TextFormatException("Text parsing error: \'" + String(expectedStr) + "\' expected.");
222    }
223    String Read(String expectedStr)
224    {
225        auto token = ReadToken();
226        if (token.Content == expectedStr)
227        {
228            return token.Content;
229        }
230        throw TextFormatException("Text parsing error: \'" + expectedStr + "\' expected.");
231    }
232    bool Read(TokenType tokenType)
233    {
234        if (NextToken().Type == tokenType)
235        {
236            ReadToken();
237            return true;
238        }
239        throw TextFormatException("Text parsing error: unexpected '" + NextToken().Content + "'.");
240    }
241
242    String ReadStringLiteral()
243    {
244        auto token = ReadToken();
245        if (token.Type == TokenType::StringLiteral)
246        {
247            return token.Content;
248        }
249        throw TextFormatException("Text parsing error: string literal expected.");
250    }
251    void Back(int count) { tokenPtr -= count; }
252    Token ReadMatchingToken(TokenType type)
253    {
254        auto token = ReadToken();
255        if (token.Type != type)
256        {
257            throw TextFormatException("Text parsing error: unexpected token.");
258        }
259        return token;
260    }
261    Token ReadToken()
262    {
263        if (tokenPtr < (int)tokens.getCount())
264        {
265            auto& rs = tokens[tokenPtr];
266            tokenPtr++;
267            return rs;
268        }
269        throw TextFormatException("Unexpected ending.");
270    }
271    Token NextToken(int offset = 0)
272    {
273        if (tokenPtr + offset < (int)tokens.getCount())
274            return tokens[tokenPtr + offset];
275        else
276        {
277            Token rs;
278            rs.Type = TokenType::Unknown;
279            return rs;
280        }
281    }
282    bool LookAhead(String token)
283    {
284        if (tokenPtr < (int)tokens.getCount())
285        {
286            auto next = NextToken();
287            return next.Content == token;
288        }
289        else
290        {
291            return false;
292        }
293    }
294    bool LookAhead(TokenType tokenType)
295    {
296        if (tokenPtr < (int)tokens.getCount())
297        {
298            auto next = NextToken();
299            return next.Type == tokenType;
300        }
301        else
302        {
303            return false;
304        }
305    }
306    bool AdvanceIf(String token)
307    {
308        if (LookAhead(token))
309        {
310            ReadToken();
311            return true;
312        }
313        return false;
314    }
315    bool AdvanceIf(TokenType token)
316    {
317        if (LookAhead(token))
318        {
319            ReadToken();
320            return true;
321        }
322        return false;
323    }
324    bool IsEnd() { return tokenPtr == (int)tokens.getCount(); }
325
326public:
327    bool IsLegalText() { return legal; }
328};
329
330inline List<String> Split(String text, char c)
331{
332    List<String> result;
333    StringBuilder sb;
334    for (Index i = 0; i < text.getLength(); i++)
335    {
336        if (text[i] == c)
337        {
338            auto str = sb.toString();
339            if (str.getLength() != 0)
340                result.add(str);
341            sb.clear();
342        }
343        else
344            sb << text[i];
345    }
346    auto lastStr = sb.toString();
347    if (lastStr.getLength())
348        result.add(lastStr);
349    return result;
350}
351
352} // namespace Misc
353} // namespace Slang
354
355
356#endif