1 | /* |
2 | * Copyright (C) 2018 Apple Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions |
6 | * are met: |
7 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
19 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
20 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
21 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
22 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
23 | * THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | #pragma once |
27 | |
28 | #if ENABLE(WEBGPU) |
29 | |
30 | #include <wtf/Optional.h> |
31 | #include <wtf/Vector.h> |
32 | #include <wtf/text/StringConcatenate.h> |
33 | #include <wtf/text/StringConcatenateNumbers.h> |
34 | #include <wtf/text/StringView.h> |
35 | #include <wtf/text/WTFString.h> |
36 | |
37 | namespace WebCore { |
38 | |
39 | namespace WHLSL { |
40 | |
41 | class Lexer { |
42 | public: |
43 | Lexer() = default; |
44 | |
45 | Lexer(StringView stringView) |
46 | : m_stringView(stringView) |
47 | { |
48 | skipWhitespaceAndComments(); |
49 | } |
50 | |
51 | Lexer(const Lexer&) = delete; |
52 | Lexer(Lexer&&) = default; |
53 | |
54 | Lexer& operator=(const Lexer&) = delete; |
55 | Lexer& operator=(Lexer&&) = default; |
56 | |
57 | struct Token { |
58 | Token() = delete; |
59 | Token(const Token&) = default; |
60 | Token(Token&&) = default; |
61 | Token& operator=(const Token&) = default; |
62 | Token& operator=(Token&&) = default; |
63 | |
64 | StringView stringView; |
65 | unsigned lineNumber; |
66 | enum class Type { |
67 | IntLiteral, |
68 | UintLiteral, |
69 | FloatLiteral, |
70 | Struct, |
71 | Typedef, |
72 | Enum, |
73 | Operator, |
74 | If, |
75 | Else, |
76 | Continue, |
77 | Break, |
78 | Switch, |
79 | Case, |
80 | Default, |
81 | Fallthrough, |
82 | For, |
83 | While, |
84 | Do, |
85 | Return, |
86 | Trap, |
87 | Null, |
88 | True, |
89 | False, |
90 | Constant, |
91 | Device, |
92 | Threadgroup, |
93 | Thread, |
94 | Space, |
95 | Vertex, |
96 | Fragment, |
97 | Compute, |
98 | NumThreads, |
99 | SVInstanceID, |
100 | SVVertexID, |
101 | PSize, |
102 | SVPosition, |
103 | SVIsFrontFace, |
104 | SVSampleIndex, |
105 | SVInnerCoverage, |
106 | SVTarget, |
107 | SVDepth, |
108 | SVCoverage, |
109 | SVDispatchThreadID, |
110 | SVGroupID, |
111 | SVGroupIndex, |
112 | SVGroupThreadID, |
113 | Attribute, |
114 | Register, |
115 | Specialized, |
116 | Native, |
117 | Restricted, |
118 | Underscore, |
119 | Auto, |
120 | Protocol, |
121 | Const, |
122 | Static, |
123 | Qualifier, |
124 | Identifier, |
125 | OperatorName, |
126 | EqualsSign, |
127 | Semicolon, |
128 | LeftCurlyBracket, |
129 | RightCurlyBracket, |
130 | Colon, |
131 | Comma, |
132 | LeftParenthesis, |
133 | RightParenthesis, |
134 | SquareBracketPair, |
135 | LeftSquareBracket, |
136 | RightSquareBracket, |
137 | Star, |
138 | LessThanSign, |
139 | GreaterThanSign, |
140 | FullStop, |
141 | PlusEquals, |
142 | MinusEquals, |
143 | TimesEquals, |
144 | DivideEquals, |
145 | ModEquals, |
146 | XorEquals, |
147 | AndEquals, |
148 | OrEquals, |
149 | RightShiftEquals, |
150 | LeftShiftEquals, |
151 | PlusPlus, |
152 | MinusMinus, |
153 | Arrow, |
154 | QuestionMark, |
155 | OrOr, |
156 | AndAnd, |
157 | Or, |
158 | Xor, |
159 | And, |
160 | LessThanOrEqualTo, |
161 | GreaterThanOrEqualTo, |
162 | EqualComparison, |
163 | NotEqual, |
164 | RightShift, |
165 | LeftShift, |
166 | Plus, |
167 | Minus, |
168 | Divide, |
169 | Mod, |
170 | Tilde, |
171 | ExclamationPoint, |
172 | At, |
173 | } type; |
174 | |
175 | static const char* typeName(Type); |
176 | }; |
177 | |
178 | Optional<Token> consumeToken() |
179 | { |
180 | if (!m_stack.isEmpty()) |
181 | return m_stack.takeLast(); |
182 | return consumeTokenFromStream(); |
183 | } |
184 | |
185 | void unconsumeToken(Token&& token) |
186 | { |
187 | m_stack.append(WTFMove(token)); |
188 | } |
189 | |
190 | struct State { |
191 | Vector<Token> stack; |
192 | unsigned offset; |
193 | unsigned lineNumber; |
194 | }; |
195 | |
196 | State state() const |
197 | { |
198 | return { m_stack, m_offset, m_lineNumber }; |
199 | } |
200 | |
201 | void setState(const State& state) |
202 | { |
203 | m_stack = state.stack; |
204 | m_offset = state.offset; |
205 | m_lineNumber = state.lineNumber; |
206 | } |
207 | |
208 | void setState(State&& state) |
209 | { |
210 | m_stack = WTFMove(state.stack); |
211 | m_offset = WTFMove(state.offset); |
212 | m_lineNumber = WTFMove(state.lineNumber); |
213 | } |
214 | |
215 | bool isFullyConsumed() const |
216 | { |
217 | return m_offset == m_stringView.length(); |
218 | } |
219 | |
220 | String errorString(const Token& token, const String& message) |
221 | { |
222 | return makeString("Parse error at line " , token.lineNumber, ": " , message); |
223 | } |
224 | |
225 | private: |
226 | Optional<Token> consumeTokenFromStream(); |
227 | |
228 | void skipWhitespaceAndComments(); |
229 | void skipWhitespace(); |
230 | void skipLineComment(); |
231 | void skipLongComment(); |
232 | |
233 | Optional<Token::Type> recognizeKeyword(unsigned end); |
234 | |
235 | Optional<unsigned> coreDecimalIntLiteral(unsigned) const; |
236 | Optional<unsigned> decimalIntLiteral(unsigned) const; |
237 | Optional<unsigned> decimalUintLiteral(unsigned) const; |
238 | Optional<unsigned> coreHexadecimalIntLiteral(unsigned) const; |
239 | Optional<unsigned> hexadecimalIntLiteral(unsigned) const; |
240 | Optional<unsigned> hexadecimalUintLiteral(unsigned) const; |
241 | Optional<unsigned> intLiteral(unsigned) const; |
242 | Optional<unsigned> uintLiteral(unsigned) const; |
243 | Optional<unsigned> digit(unsigned) const; |
244 | unsigned digitStar(unsigned) const; |
245 | Optional<unsigned> character(char, unsigned) const; |
246 | template<unsigned length> Optional<unsigned> anyCharacter(const char (&string)[length], unsigned) const; |
247 | Optional<unsigned> coreFloatLiteralType1(unsigned) const; |
248 | Optional<unsigned> coreFloatLiteral(unsigned) const; |
249 | Optional<unsigned> floatLiteral(unsigned) const; |
250 | template<unsigned length> Optional<unsigned> string(const char (&string)[length], unsigned) const; |
251 | Optional<unsigned> validIdentifier(unsigned) const; |
252 | Optional<unsigned> identifier(unsigned) const; |
253 | Optional<unsigned> operatorName(unsigned) const; |
254 | |
255 | StringView m_stringView; |
256 | Vector<Token> m_stack; |
257 | unsigned m_offset { 0 }; |
258 | unsigned m_lineNumber { 0 }; |
259 | }; |
260 | |
261 | template<unsigned length> Optional<unsigned> Lexer::string(const char (&string)[length], unsigned offset) const |
262 | { |
263 | for (unsigned i = 0; i < length - 1; ++i) { |
264 | if (offset + i >= m_stringView.length() || m_stringView[offset + i] != string[i]) |
265 | return WTF::nullopt; |
266 | } |
267 | return offset + length - 1; |
268 | } |
269 | |
270 | template<unsigned length> Optional<unsigned> Lexer::anyCharacter(const char (&string)[length], unsigned offset) const |
271 | { |
272 | if (offset >= m_stringView.length()) |
273 | return WTF::nullopt; |
274 | for (unsigned i = 0; i < length - 1; ++i) { |
275 | if (m_stringView[offset] == string[i]) |
276 | return offset + 1; |
277 | } |
278 | return WTF::nullopt; |
279 | } |
280 | |
281 | } // namespace WHLSL |
282 | |
283 | } // namespace WebCore |
284 | |
285 | #endif // ENABLE(WEBGPU) |
286 | |