Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
glsllexer.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5
7#include "glsllexer_p.h"
8#include "glslparser_p.h"
9#include "glslengine_p.h"
10#include <cctype>
11#include <iostream>
12#include <cstdio>
13
14QT_BEGIN_NAMESPACE
15
16using namespace GLSL;
17
18Lexer::Lexer(Engine *engine, const char *source, unsigned size)
19 : _engine(engine),
20 _source(source),
21 _it(source),
22 _size(size),
23 _yychar('\n'),
24 _lineno(0),
25 _state(0),
26 _variant(Variant_Mask & ~Variant_Reserved), // everything except reserved
27 _scanKeywords(true),
28 _scanComments(false)
29{
30}
31
32Lexer::~Lexer()
33{
34}
35
36void Lexer::yyinp()
37{
38 _yychar = (unsigned char) *_it++;
39 if (_yychar == '\n')
40 ++_lineno;
41}
42
43int Lexer::yylex(Token *tk)
44{
45 const char *pos = nullptr;
46 int line = 0;
47 _yyval.ptr = nullptr;
48 const int kind = yylex_helper(&pos, &line);
49 tk->kind = kind;
50 tk->position = pos - _source;
51 tk->length = _it - pos - 1;
52 tk->line = line;
53 tk->ptr = _yyval.ptr;
54 return kind;
55}
56
57enum {
60};
61
62int Lexer::yylex_helper(const char **position, int *line)
63{
64 using namespace GLSL;
65 again:
66 while (std::isspace(_yychar))
67 yyinp();
68
69 *position = _it - 1;
70 *line = _lineno;
71
72 if (_yychar == 0)
73 return Parser::EOF_SYMBOL;
74
75 if (_state == State_comment) {
76 while (_yychar) {
77 if (_yychar == '*') {
78 yyinp();
79 if (_yychar == '/') {
80 yyinp();
81 _state = State_normal;
82 break;
83 }
84 } else {
85 yyinp();
86 }
87 }
88 return Parser::T_COMMENT;
89 }
90
91 const int ch = _yychar;
92 yyinp();
93
94 switch (ch) {
95 case '#':
96 for (; _yychar; yyinp()) {
97 if (_yychar == '\n')
98 break;
99 }
100 goto again;
101
102 // one of `!', `!='
103 case '!':
104 if (_yychar == '=') {
105 yyinp();
106 return Parser::T_NE_OP;
107 }
108 return Parser::T_BANG;
109
110 // one of
111 // %
112 // %=
113 case '%':
114 if (_yychar == '=') {
115 yyinp();
116 return Parser::T_MOD_ASSIGN;
117 }
118 return Parser::T_PERCENT;
119
120 // one of
121 // &
122 // &&
123 // &=
124 case '&':
125 if (_yychar == '=') {
126 yyinp();
127 return Parser::T_AND_ASSIGN;
128 } else if (_yychar == '&') {
129 yyinp();
130 return Parser::T_AND_OP;
131 }
132 return Parser::T_AMPERSAND;
133
134 // (
135 case '(':
136 return Parser::T_LEFT_PAREN;
137
138 // )
139 case ')':
140 return Parser::T_RIGHT_PAREN;
141
142 // one of
143 // *
144 // *=
145 case '*':
146 if (_yychar == '=') {
147 yyinp();
148 return Parser::T_MUL_ASSIGN;
149 }
150 return Parser::T_STAR;
151
152 // one of
153 // ++
154 // +=
155 // +
156 case '+':
157 if (_yychar == '=') {
158 yyinp();
159 return Parser::T_ADD_ASSIGN;
160 } else if (_yychar == '+') {
161 yyinp();
162 return Parser::T_INC_OP;
163 }
164 return Parser::T_PLUS;
165
166 // ,
167 case ',':
168 return Parser::T_COMMA;
169
170 // one of
171 // -
172 // --
173 // -=
174 case '-':
175 if (_yychar == '=') {
176 yyinp();
177 return Parser::T_SUB_ASSIGN;
178 } else if (_yychar == '-') {
179 yyinp();
180 return Parser::T_DEC_OP;
181 }
182 return Parser::T_DASH;
183
184 // one of
185 // .
186 // float constant
187 case '.':
188 if (std::isdigit(_yychar)) {
189 const char *word = _it - 2;
190 while (std::isalnum(_yychar)) {
191 yyinp();
192 }
193 if (_engine)
194 _yyval.string = _engine->number(word, _it - word - 1);
195 return Parser::T_NUMBER;
196 }
197 return Parser::T_DOT;
198
199 // one of
200 // /
201 // /=
202 // comment
203 case '/':
204 if (_yychar == '/') {
205 for (; _yychar; yyinp()) {
206 if (_yychar == '\n')
207 break;
208 }
209 if (_scanComments)
210 return Parser::T_COMMENT;
211 goto again;
212 } else if (_yychar == '*') {
213 yyinp();
214 while (_yychar) {
215 if (_yychar == '*') {
216 yyinp();
217 if (_yychar == '/') {
218 yyinp();
219 if (_scanComments)
220 return Parser::T_COMMENT;
221 goto again;
222 }
223 } else {
224 yyinp();
225 }
226 }
227 if (_scanComments) {
228 _state = State_comment;
229 return Parser::T_COMMENT;
230 }
231 goto again;
232 } else if (_yychar == '=') {
233 yyinp();
234 return Parser::T_DIV_ASSIGN;
235 }
236 return Parser::T_SLASH;
237
238 // :
239 case ':':
240 return Parser::T_COLON;
241
242 // ;
243 case ';':
244 return Parser::T_SEMICOLON;
245
246 // one of
247 // <
248 // <=
249 // <<
250 // <<=
251 case '<':
252 if (_yychar == '=') {
253 yyinp();
254 return Parser::T_LE_OP;
255 } else if (_yychar == '<') {
256 yyinp();
257 if (_yychar == '=') {
258 yyinp();
259 return Parser::T_LEFT_ASSIGN;
260 }
261 return Parser::T_LEFT_OP;
262 }
263 return Parser::T_LEFT_ANGLE;
264
265 // one of
266 // =
267 // ==
268 case '=':
269 if (_yychar == '=') {
270 yyinp();
271 return Parser::T_EQ_OP;
272 }
273 return Parser::T_EQUAL;
274
275 // one of
276 // >
277 // >=
278 // >>=
279 // >>
280 case '>':
281 if (_yychar == '=') {
282 yyinp();
283 return Parser::T_GE_OP;
284 } else if (_yychar == '>') {
285 yyinp();
286 if (_yychar == '=') {
287 yyinp();
288 return Parser::T_RIGHT_ASSIGN;
289 }
290 return Parser::T_RIGHT_OP;
291 }
292 return Parser::T_RIGHT_ANGLE;
293
294 // ?
295 case '?':
296 return Parser::T_QUESTION;
297
298 // [
299 case '[':
300 return Parser::T_LEFT_BRACKET;
301
302 // ]
303 case ']':
304 return Parser::T_RIGHT_BRACKET;
305
306 // one of
307 // ^
308 // ^=
309 case '^':
310 if (_yychar == '=') {
311 yyinp();
312 return Parser::T_XOR_ASSIGN;
313 } else if (_yychar == '^') {
314 yyinp();
315 return Parser::T_XOR_OP;
316 }
317 return Parser::T_CARET;
318
319 // {
320 case '{':
321 return Parser::T_LEFT_BRACE;
322
323 // one of
324 // |
325 // |=
326 // ||
327 case '|':
328 if (_yychar == '=') {
329 yyinp();
330 return Parser::T_OR_ASSIGN;
331 } else if (_yychar == '|') {
332 yyinp();
333 return Parser::T_OR_OP;
334 }
335 return Parser::T_VERTICAL_BAR;
336
337 // }
338 case '}':
339 return Parser::T_RIGHT_BRACE;
340
341 // ~
342 case '~':
343 return Parser::T_TILDE;
344
345 default:
346 if (std::isalpha(ch) || ch == '_') {
347 const char *word = _it - 2;
348 while (std::isalnum(_yychar) || _yychar == '_') {
349 yyinp();
350 }
351 if (_scanKeywords) {
352 const int k = findKeyword(word, _it - word - 1);
353
354 if (k != Parser::T_IDENTIFIER)
355 return k;
356 }
357 if (_engine)
358 _yyval.string = _engine->identifier(word, _it - word - 1);
359 return Parser::T_IDENTIFIER;
360 } else if (std::isdigit(ch)) {
361 const char *word = _it - 2;
362 while (std::isalnum(_yychar) || _yychar == '.') {
363 yyinp();
364 }
365 if (_engine)
366 _yyval.string = _engine->number(word, _it - word - 1);
367 return Parser::T_NUMBER;
368 }
369
370 } // switch
371
372 return Parser::T_ERROR;
373}
374
375int Lexer::findKeyword(const char *word, int length) const
376{
377 int t = classify(word, length);
378 if (!(t & Variant_Mask))
379 return t;
380 if ((_variant & t & Variant_Mask) == 0) {
381 // Return a "reserved word" token if this keyword is not permitted
382 // in the current language variant so that the syntax highlighter
383 // can warn the user about the word.
384 if (!_scanKeywords)
385 return Parser::T_RESERVED;
386 }
387 return t & ~Variant_Mask;
388}
389
390void Lexer::warning(int line, const QString &message)
391{
392 _engine->warning(line, message);
393}
394
395void Lexer::error(int line, const QString &message)
396{
397 _engine->error(line, message);
398}
399
400QT_END_NAMESPACE
@ State_comment
Definition glsllexer.cpp:59
@ State_normal
Definition glsllexer.cpp:58