├── .gitignore ├── EXAMPLE_ERRORS.md ├── LICENSE ├── Makefile ├── README.md ├── ast.cpp ├── ast.h ├── lexemes.h ├── lexer.cpp ├── lexer.h ├── main.cpp ├── parser.cpp ├── parser.h ├── test.py ├── tests ├── arrays.glsl ├── arrays.test ├── booleans.glsl ├── booleans.test ├── builtin_types.glsl ├── builtin_types.test ├── comments.glsl ├── comments.test ├── constants.glsl ├── constants.test ├── continuations.glsl ├── continuations.test ├── directives.glsl ├── directives.test ├── do_statement.glsl ├── do_statement.test ├── first_character_invalid.glsl ├── first_character_invalid.test ├── floating_point_literals.glsl ├── floating_point_literals.test ├── for_statement.glsl ├── for_statement.test ├── integer_literals.glsl ├── integer_literals.test ├── interface_blocks.glsl ├── interface_blocks.test ├── sequence.glsl ├── sequence.test ├── structures.glsl ├── structures.test ├── switch.glsl ├── switch.test ├── ternary.glsl ├── ternary.test ├── uniforms.glsl ├── uniforms.test ├── while_statement.glsl └── while_statement.test ├── util.cpp └── util.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.P 3 | /glsl-parser 4 | -------------------------------------------------------------------------------- /EXAMPLE_ERRORS.md: -------------------------------------------------------------------------------- 1 | # Error samples 2 | 3 | Here are some example diagnostics to show how superior glsl-parser is compared to 4 | that of driver-specific diagnostics. 5 | 6 | $ echo "layout(error)" | ./glsl-parser - 7 | :1:13: error: unknown layout qualifier `error' 8 | 9 | $ echo "layout(shared = 1)" | ./glsl-parser - 10 | :1:16: error: unexpected layout qualifier value on `shared' layout qualifier 11 | 12 | $ echo "layout(location)" | ./glsl-parser - 13 | :1:17: error: expected layout qualifier value for `location' layout qualifier 14 | 15 | $ echo "patch in vec3 foo;" | ./glsl-parser - 16 | :1:15: error: applying `patch' qualifier to input can only be done in tessellation evaluation shaders 17 | 18 | $ echo "smooth out vec3 foo;" | ./glsl-parser - 19 | :1:16: error: cannot use interpolation qualifier on fragment shader output 20 | 21 | $ echo "const out vec3 foo;" | ./glsl-parser - 22 | :1:15: error: multiple storage qualifiers in declaration 23 | 24 | $ echo "centroid sample vec3 foo;" | ./glsl-parser - 25 | :1:21: error: multiple auxiliary storage qualifiers in declaration 26 | 27 | $ echo "lowp mediump vec3 foo;" | ./glsl-parser - 28 | :1:18: error: multiple precision qualifiers in declaration 29 | 30 | $ echo "const foo;" | ./glsl-parser - 31 | :1:11: error: expected typename 32 | 33 | $ echo "const float foo;" | ./glsl-parser - 34 | :1:17: error: const-qualified variable declared but not initialized 35 | 36 | $ echo "float a; const float b = a;" | ./glsl-parser - 37 | :1:28: error: not a valid constant expression 38 | 39 | $ echo "void a;" | ./glsl-parser - 40 | :1:8: error: `void' cannot be used in declaration 41 | 42 | $ echo "void (void);" | ./glsl-parser - 43 | :1:7: error: expected name for declaration 44 | 45 | $ echo "void foo() { 1 = 1; }" | ./glsl-parser - 46 | :1:20: error: not a valid lvalue 47 | 48 | $ echo "in float a; void foo() { a = 1; }" | ./glsl-parser - 49 | :1:32: error: cannot write to a variable declared as input 50 | 51 | $ echo "const float a = 0; void foo() { a = 1; }" | ./glsl-parser - 52 | :1:39: error: cannot write to a const variable outside of its declaration 53 | 54 | $ echo "void foo() { a = 0; }" | ./glsl-parser - 55 | :1:15: error: `a' was not declared in this scope 56 | 57 | $ echo "vec3 a; void foo() { a.; }" | ./glsl-parser - 58 | :1:25: error: expected field identifier or swizzle after `.' 59 | 60 | $ echo "void foo() { 1[0] = 1; }" | ./glsl-parser - 61 | :1:17: error: cannot be subscripted 62 | 63 | $ echo "float a; void foo() { switch(0) { case a: break; } }" | ./glsl-parser - 64 | :1:42: error: case label is not a valid constant expression 65 | 66 | $ echo "void foo() { switch(0) { case 0: case 0: break; } }" | ./glsl-parser - 67 | :1:41: error: duplicate case label `0' 68 | 69 | $ echo "void foo() { switch(0) { default; } }" | ./glsl-parser - 70 | :1:34: error: expected `:' after `default' in case label 71 | 72 | $ echo "void main(float) { }" | ./glsl-parser - 73 | :1:19: error: `main' cannot have parameters 74 | 75 | $ echo "float main() { }" | ./glsl-parser - 76 | :1:15: error: `main' must be declared to return void 77 | 78 | $ echo "const uint big = 0xFFFFFFFFFU;" | ./glsl-parser - 79 | :1:30: error: literal needs more than 32-bits 80 | 81 | $ echo "const float foo = 0.1u;" | ./glsl-parser - 82 | :1:23: error: invalid use of suffix on literal 83 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Dale Weiler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CXX ?= clang++ 2 | CXXFLAGS = \ 3 | -fno-rtti \ 4 | -fno-exceptions \ 5 | -Wall \ 6 | -Wextra \ 7 | -Wformat \ 8 | -O3 9 | 10 | BIN = glsl-parser 11 | 12 | SOURCES = \ 13 | ast.cpp \ 14 | lexer.cpp \ 15 | parser.cpp \ 16 | main.cpp \ 17 | util.cpp 18 | 19 | OBJECTS = $(SOURCES:.cpp=.o) 20 | 21 | all: $(BIN) 22 | 23 | $(BIN): $(OBJECTS) 24 | $(CXX) $(OBJECTS) -o $@ 25 | 26 | .cpp.o: 27 | $(CXX) -MD -c $(CXXFLAGS) $< -o $@ 28 | @cp $*.d $*.P; \ 29 | sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ 30 | -e '/^$$/ d' -e 's/$$/ :/' < $*.d >> $*.P; \ 31 | rm -f $*.d 32 | 33 | clean: 34 | rm -f $(OBJECTS) $(OBJECTS:.o=.P) 35 | rm -f $(BIN) 36 | 37 | test: $(BIN) 38 | @python3 ./test.py 39 | 40 | -include *.P 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # glsl-parser 2 | 3 | **glsl-parser** is an offline GLSL parser which can be used to do many things with GLSL source code. 4 | 5 | The straight-forward API allows you to parse GLSL into an abstact-syntax-tree in only a couple lines, for example 6 | 7 | glsl::parser parse(sourceCode); 8 | glsl::astTU *translationUnit = parse.parse(astTU::kFragment); 9 | if (translationUnit) { 10 | // Do something with the AST here 11 | } else { 12 | // A parse error occured 13 | fprintf(stderr, "%s\n", parse.error()); 14 | } 15 | 16 | A test-suite and GLSL source-generator is included to get you started. 17 | 18 | Check out the superior diagnostics [here](EXAMPLE_ERRORS.md) 19 | 20 | ### Known limitations 21 | * Does not support preprocessor directives 22 | * Does support `#version` and `#extension` though. 23 | * Does not handle new-line termination with the backslack character `\` 24 | * Not all of GLSL is supported, if you run into a missing feature open an issue. 25 | * None of the builtin functions or variables are provided, you must provide those yourself. 26 | 27 | ### Possible uses 28 | * Verify a shader without running it 29 | * Find hard-to-find syntax or semantic errors with the superior diagnostics 30 | * Extend GLSL 31 | * Transcompile GLSL to other languages 32 | * Quickly check or verify something 33 | * Optimize shaders 34 | * Generate introspection information 35 | 36 | ### Portable and embeddable 37 | * Written in portable C++03. 38 | * Only uses *std::vector* from the standard library 39 | * Exception free 40 | * Doesn't use virtual functions 41 | * Small (~90 KB) 42 | * Permissive (MIT) 43 | -------------------------------------------------------------------------------- /ast.cpp: -------------------------------------------------------------------------------- 1 | #include "ast.h" 2 | 3 | namespace glsl { 4 | 5 | const char *astStatement::name() const { 6 | switch (type) { 7 | case kCompound: return "compound"; 8 | case kDeclaration: return "declaration"; 9 | case kExpression: return "expression"; 10 | case kIf: return "if"; 11 | case kSwitch: return "switch"; 12 | case kCaseLabel: return "case label"; 13 | case kWhile: return "while"; 14 | case kDo: return "do"; 15 | case kFor: return "for"; 16 | case kContinue: return "continue"; 17 | case kBreak: return "break"; 18 | case kReturn: return "return"; 19 | case kDiscard: return "discard"; 20 | } 21 | return "(unknown)"; 22 | } 23 | 24 | astTU::astTU(int type) 25 | : type(type) 26 | , versionDirective(0) 27 | { 28 | } 29 | 30 | astType::astType(bool builtin) 31 | : builtin(builtin) 32 | { 33 | } 34 | 35 | astStruct::astStruct() 36 | : astType(false) 37 | , name(0) 38 | { 39 | } 40 | 41 | astInterfaceBlock::astInterfaceBlock() 42 | : astType(false) 43 | , name(0) 44 | , storage(0) 45 | { 46 | } 47 | 48 | astExtensionDirective::astExtensionDirective() 49 | : astType(false) 50 | , name(0) 51 | , behavior(-1) 52 | { 53 | } 54 | 55 | astVersionDirective::astVersionDirective() 56 | : astType(false) 57 | , version(-1) 58 | , type(-1) 59 | { 60 | } 61 | 62 | astBuiltin::astBuiltin(int type) 63 | : astType(true) 64 | , type(type) 65 | { 66 | } 67 | 68 | astVariable::astVariable(int type) 69 | : name(0) 70 | , baseType(0) 71 | , isArray(false) 72 | , isPrecise(false) 73 | , type(type) 74 | { 75 | } 76 | 77 | astFunctionVariable::astFunctionVariable() 78 | : astVariable(astVariable::kFunction) 79 | , isConst(false) 80 | , initialValue(0) 81 | { 82 | } 83 | 84 | astFunctionParameter::astFunctionParameter() 85 | : astVariable(astVariable::kParameter) 86 | , storage(-1) 87 | , auxiliary(-1) 88 | , memory(0) 89 | , precision(-1) 90 | { 91 | } 92 | 93 | astGlobalVariable::astGlobalVariable() 94 | : astVariable(astVariable::kGlobal) 95 | , storage(-1) 96 | , auxiliary(-1) 97 | , memory(0) 98 | , precision(-1) 99 | , interpolation(-1) 100 | , isInvariant(false) 101 | , initialValue(0) 102 | { 103 | } 104 | 105 | astSimpleStatement::astSimpleStatement(int type) 106 | : astStatement(type) 107 | { 108 | } 109 | 110 | astCompoundStatement::astCompoundStatement() 111 | : astStatement(astStatement::kCompound) 112 | { 113 | } 114 | 115 | astEmptyStatement::astEmptyStatement() 116 | : astSimpleStatement(astStatement::kEmpty) 117 | { 118 | } 119 | 120 | astDeclarationStatement::astDeclarationStatement() 121 | : astSimpleStatement(astStatement::kDeclaration) 122 | { 123 | } 124 | 125 | astLayoutQualifier::astLayoutQualifier() 126 | : name(0) 127 | , initialValue(0) 128 | { 129 | } 130 | 131 | astFunction::astFunction() 132 | : returnType(0) 133 | , name(0) 134 | , isPrototype(false) 135 | { 136 | } 137 | 138 | astDeclaration::astDeclaration() 139 | : variable(0) 140 | { 141 | } 142 | 143 | astStatement::astStatement(int type) 144 | : type(type) 145 | { 146 | } 147 | 148 | astExpressionStatement::astExpressionStatement(astExpression *expression) 149 | : astSimpleStatement(astStatement::kExpression) 150 | , expression(expression) 151 | { 152 | } 153 | 154 | astIfStatement::astIfStatement() 155 | : astSimpleStatement(astStatement::kIf) 156 | , condition(0) 157 | , thenStatement(0) 158 | , elseStatement(0) 159 | { 160 | } 161 | 162 | astSwitchStatement::astSwitchStatement() 163 | : astSimpleStatement(astStatement::kSwitch) 164 | , expression(0) 165 | { 166 | } 167 | 168 | astCaseLabelStatement::astCaseLabelStatement() 169 | : astSimpleStatement(astStatement::kCaseLabel) 170 | , condition(0) 171 | , isDefault(false) 172 | { 173 | } 174 | 175 | astIterationStatement::astIterationStatement(int type) 176 | : astSimpleStatement(type) 177 | { 178 | } 179 | 180 | astWhileStatement::astWhileStatement() 181 | : astIterationStatement(astStatement::kWhile) 182 | , condition(0) 183 | , body(0) 184 | { 185 | } 186 | 187 | astDoStatement::astDoStatement() 188 | : astIterationStatement(astStatement::kDo) 189 | , body(0) 190 | , condition(0) 191 | { 192 | } 193 | 194 | astForStatement::astForStatement() 195 | : astIterationStatement(astStatement::kFor) 196 | , init(0) 197 | , condition(0) 198 | , loop(0) 199 | , body(0) 200 | { 201 | } 202 | 203 | astJumpStatement::astJumpStatement(int type) 204 | : astStatement(type) 205 | { 206 | } 207 | 208 | astContinueStatement::astContinueStatement() 209 | : astJumpStatement(astStatement::kContinue) 210 | { 211 | } 212 | 213 | astBreakStatement::astBreakStatement() 214 | : astJumpStatement(astStatement::kBreak) 215 | { 216 | } 217 | 218 | astReturnStatement::astReturnStatement() 219 | : astJumpStatement(astStatement::kReturn) 220 | , expression(0) 221 | { 222 | } 223 | 224 | astDiscardStatement::astDiscardStatement() 225 | : astJumpStatement(astStatement::kDiscard) 226 | { 227 | } 228 | 229 | astExpression::astExpression(int type) 230 | : type(type) 231 | { 232 | } 233 | 234 | astIntConstant::astIntConstant(int value) 235 | : astExpression(astExpression::kIntConstant) 236 | , value(value) 237 | { 238 | } 239 | 240 | astUIntConstant::astUIntConstant(unsigned int value) 241 | : astExpression(astExpression::kUIntConstant) 242 | , value(value) 243 | { 244 | } 245 | 246 | astFloatConstant::astFloatConstant(float value) 247 | : astExpression(astExpression::kFloatConstant) 248 | , value(value) 249 | { 250 | } 251 | 252 | astDoubleConstant::astDoubleConstant(double value) 253 | : astExpression(astExpression::kDoubleConstant) 254 | , value(value) 255 | { 256 | } 257 | 258 | astBoolConstant::astBoolConstant(bool value) 259 | : astExpression(astExpression::kBoolConstant) 260 | , value(value) 261 | { 262 | } 263 | 264 | astVariableIdentifier::astVariableIdentifier(astVariable *variable) 265 | : astExpression(astExpression::kVariableIdentifier) 266 | , variable(variable) 267 | { 268 | } 269 | 270 | astFieldOrSwizzle::astFieldOrSwizzle() 271 | : astExpression(kFieldOrSwizzle) 272 | , operand(0) 273 | , name(0) 274 | { 275 | } 276 | 277 | astArraySubscript::astArraySubscript() 278 | : astExpression(kArraySubscript) 279 | , operand(0) 280 | , index(0) 281 | { 282 | } 283 | 284 | astFunctionCall::astFunctionCall() 285 | : astExpression(astExpression::kFunctionCall) 286 | , name(0) 287 | { 288 | } 289 | 290 | astConstructorCall::astConstructorCall() 291 | : astExpression(astExpression::kConstructorCall) 292 | , type(0) 293 | { 294 | } 295 | 296 | astUnaryExpression::astUnaryExpression(int type, astExpression *operand) 297 | : astExpression(type) 298 | , operand(operand) 299 | { 300 | } 301 | 302 | astBinaryExpression::astBinaryExpression(int type) 303 | : astExpression(type) 304 | , operand1(0) 305 | , operand2(0) 306 | { 307 | } 308 | 309 | astPostIncrementExpression::astPostIncrementExpression(astExpression *operand) 310 | : astUnaryExpression(astExpression::kPostIncrement, operand) 311 | { 312 | } 313 | 314 | astPostDecrementExpression::astPostDecrementExpression(astExpression *operand) 315 | : astUnaryExpression(astExpression::kPostDecrement, operand) 316 | { 317 | } 318 | 319 | astUnaryPlusExpression::astUnaryPlusExpression(astExpression *operand) 320 | : astUnaryExpression(astExpression::kUnaryPlus, operand) 321 | { 322 | } 323 | 324 | astUnaryMinusExpression::astUnaryMinusExpression(astExpression *operand) 325 | : astUnaryExpression(astExpression::kUnaryMinus, operand) 326 | { 327 | } 328 | 329 | astUnaryBitNotExpression::astUnaryBitNotExpression(astExpression *operand) 330 | : astUnaryExpression(astExpression::kBitNot, operand) 331 | { 332 | } 333 | 334 | astUnaryLogicalNotExpression::astUnaryLogicalNotExpression(astExpression *operand) 335 | : astUnaryExpression(astExpression::kLogicalNot, operand) 336 | { 337 | } 338 | 339 | astPrefixIncrementExpression::astPrefixIncrementExpression(astExpression *operand) 340 | : astUnaryExpression(astExpression::kPrefixIncrement, operand) 341 | { 342 | } 343 | 344 | astPrefixDecrementExpression::astPrefixDecrementExpression(astExpression *operand) 345 | : astUnaryExpression(astExpression::kPrefixDecrement, operand) 346 | { 347 | } 348 | 349 | astSequenceExpression::astSequenceExpression() 350 | : astBinaryExpression(astExpression::kSequence) 351 | { 352 | } 353 | 354 | astAssignmentExpression::astAssignmentExpression(int assignment) 355 | : astBinaryExpression(astExpression::kAssign) 356 | , assignment(assignment) 357 | { 358 | } 359 | 360 | astOperationExpression::astOperationExpression(int operation) 361 | : astBinaryExpression(astExpression::kOperation) 362 | , operation(operation) 363 | { 364 | } 365 | 366 | astTernaryExpression::astTernaryExpression() 367 | : astExpression(astExpression::kTernary) 368 | , condition(0) 369 | , onTrue(0) 370 | , onFalse(0) 371 | { 372 | } 373 | 374 | } 375 | -------------------------------------------------------------------------------- /ast.h: -------------------------------------------------------------------------------- 1 | #ifndef AST_HDR 2 | #define AST_HDR 3 | #include // free, malloc, size_t 4 | #include "util.h" 5 | 6 | namespace glsl { 7 | 8 | // Type-erasure 9 | template 10 | static inline void astDestroy(void *self) { 11 | ((T*)self)->~T(); 12 | free(self); 13 | } 14 | 15 | struct astMemory { 16 | astMemory() : data(0), dtor(0) { } 17 | template 18 | astMemory(T *data) : data((void*)data), dtor(&astDestroy) { } 19 | void *data; 20 | void (*dtor)(void*); 21 | void destroy() { 22 | dtor(data); 23 | } 24 | }; 25 | 26 | // Nodes are to inherit from astNode or astCollector 27 | template 28 | struct astNode { 29 | void *operator new(size_t size, vector *collector) throw() { 30 | void *data = malloc(size); 31 | if (data) 32 | collector->push_back(astMemory((T*)data)); 33 | return data; 34 | } 35 | private: 36 | void *operator new(size_t); 37 | void operator delete(void *); 38 | }; 39 | 40 | 41 | struct astFunction; 42 | struct astType; 43 | struct astGlobalVariable; 44 | struct astExpression; 45 | struct astLayoutQualifier; 46 | struct astStatement; 47 | struct astStruct; 48 | struct astInterfaceBlock; 49 | struct astVersionDirective; 50 | struct astExtensionDirective; 51 | struct astVariable; 52 | 53 | struct astTU { 54 | astTU(int type); 55 | 56 | enum { 57 | kCompute, 58 | kVertex, 59 | kTessControl, 60 | kTessEvaluation, 61 | kGeometry, 62 | kFragment 63 | }; 64 | 65 | int type; 66 | 67 | astVersionDirective* versionDirective; 68 | vector extensionDirectives; 69 | vector functions; 70 | vector globals; 71 | vector structures; 72 | vector interfaceBlocks; 73 | 74 | private: 75 | astTU(const astTU&); 76 | astTU &operator=(const astTU&); 77 | }; 78 | 79 | struct astType : astNode { 80 | astType(bool builtin); 81 | bool builtin; 82 | }; 83 | 84 | struct astBuiltin : astType { 85 | astBuiltin(int type); 86 | int type; // kKeyword_* 87 | }; 88 | 89 | struct astStruct : astType { 90 | astStruct(); 91 | char *name; 92 | vector fields; 93 | }; 94 | 95 | struct astInterfaceBlock : astType { 96 | astInterfaceBlock(); 97 | char *name; 98 | int storage; // one of the storage qualifiers: kIn, kOut, kUniform, kBuffer 99 | vector fields; 100 | }; 101 | 102 | struct astVersionDirective : astType { 103 | astVersionDirective(); 104 | int version; 105 | int type; 106 | }; 107 | 108 | struct astExtensionDirective : astType { 109 | astExtensionDirective(); 110 | char *name; 111 | int behavior; 112 | }; 113 | 114 | typedef astExpression astConstantExpression; 115 | 116 | enum { 117 | kHighp, 118 | kMediump, 119 | kLowp 120 | }; 121 | 122 | struct astVariable : astNode { 123 | enum { 124 | kFunction, 125 | kParameter, 126 | kGlobal, 127 | kField 128 | }; 129 | astVariable(int type); 130 | char *name; 131 | astType *baseType; 132 | bool isArray; 133 | bool isPrecise; 134 | int type; 135 | vector arraySizes; 136 | }; 137 | 138 | struct astFunctionVariable : astVariable { 139 | astFunctionVariable(); 140 | bool isConst; 141 | astExpression *initialValue; 142 | }; 143 | 144 | // Storage qualifiers 145 | enum { 146 | kConst, 147 | kIn, 148 | kOut, 149 | kInOut, 150 | kAttribute, 151 | kUniform, 152 | kVarying, 153 | kBuffer, 154 | kShared 155 | }; 156 | 157 | // Auxiliary storage qualifiers 158 | enum { 159 | kCentroid, 160 | kSample, 161 | kPatch, 162 | }; 163 | 164 | // Memory qualifiers 165 | enum { 166 | kCoherent = 1 << 0, 167 | kVolatile = 1 << 1, 168 | kRestrict = 1 << 2, 169 | kReadOnly = 1 << 3, 170 | kWriteOnly = 1 << 4 171 | }; 172 | 173 | struct astFunctionParameter : astVariable { 174 | astFunctionParameter(); 175 | int storage; // in or out only 176 | int auxiliary; 177 | int memory; 178 | int precision; 179 | }; 180 | 181 | enum { 182 | kSmooth, 183 | kFlat, 184 | kNoPerspective 185 | }; 186 | 187 | struct astGlobalVariable : astVariable { 188 | astGlobalVariable(); 189 | int storage; 190 | int auxiliary; 191 | int memory; 192 | int precision; 193 | int interpolation; 194 | bool isInvariant; 195 | astConstantExpression *initialValue; 196 | vector layoutQualifiers; 197 | }; 198 | 199 | struct astLayoutQualifier : astNode { 200 | astLayoutQualifier(); 201 | char *name; 202 | astConstantExpression *initialValue; 203 | }; 204 | 205 | struct astFunction : astNode { 206 | astFunction(); 207 | astType *returnType; 208 | char *name; 209 | vector parameters; 210 | vector statements; 211 | bool isPrototype; 212 | }; 213 | 214 | struct astDeclaration : astNode { 215 | astDeclaration(); 216 | astVariable *variable; 217 | }; 218 | 219 | struct astStatement : astNode { 220 | astStatement(int type); 221 | enum { 222 | kCompound, 223 | kEmpty, 224 | kDeclaration, 225 | kExpression, 226 | kIf, 227 | kSwitch, 228 | kCaseLabel, 229 | kWhile, 230 | kDo, 231 | kFor, 232 | kContinue, 233 | kBreak, 234 | kReturn, 235 | kDiscard 236 | }; 237 | int type; 238 | const char *name() const; 239 | }; 240 | 241 | struct astSimpleStatement : astStatement { 242 | astSimpleStatement(int type); 243 | }; 244 | 245 | struct astCompoundStatement : astStatement { 246 | astCompoundStatement(); 247 | vector statements; 248 | }; 249 | 250 | struct astEmptyStatement : astSimpleStatement { 251 | astEmptyStatement(); 252 | }; 253 | 254 | struct astDeclarationStatement : astSimpleStatement { 255 | astDeclarationStatement(); 256 | vector variables; 257 | }; 258 | 259 | struct astExpressionStatement : astSimpleStatement { 260 | astExpressionStatement(astExpression *expression); 261 | astExpression *expression; 262 | }; 263 | 264 | struct astIfStatement : astSimpleStatement { 265 | astIfStatement(); 266 | astExpression *condition; 267 | astStatement *thenStatement; 268 | astStatement *elseStatement; 269 | }; 270 | 271 | struct astSwitchStatement : astSimpleStatement { 272 | astSwitchStatement(); 273 | astExpression *expression; 274 | vector statements; 275 | }; 276 | 277 | struct astCaseLabelStatement : astSimpleStatement { 278 | astCaseLabelStatement(); 279 | astConstantExpression *condition; 280 | bool isDefault; 281 | }; 282 | 283 | struct astIterationStatement : astSimpleStatement { 284 | astIterationStatement(int type); 285 | }; 286 | 287 | struct astWhileStatement : astIterationStatement { 288 | astWhileStatement(); 289 | astSimpleStatement *condition; // astExpressionStatement or astDeclarationStatement only 290 | astStatement *body; 291 | }; 292 | 293 | struct astDoStatement : astIterationStatement { 294 | astDoStatement(); 295 | astStatement *body; 296 | astExpression *condition; 297 | }; 298 | 299 | struct astForStatement : astIterationStatement { 300 | astForStatement(); 301 | astSimpleStatement *init; // astExpressionStatement or astDeclarationStatement only 302 | astExpression *condition; 303 | astExpression *loop; 304 | astStatement *body; 305 | }; 306 | 307 | struct astJumpStatement : astStatement { 308 | astJumpStatement(int type); 309 | }; 310 | 311 | struct astContinueStatement : astJumpStatement { 312 | astContinueStatement(); 313 | }; 314 | 315 | struct astBreakStatement : astJumpStatement { 316 | astBreakStatement(); 317 | }; 318 | 319 | struct astReturnStatement : astJumpStatement { 320 | astReturnStatement(); 321 | astExpression *expression; 322 | }; 323 | 324 | struct astDiscardStatement : astJumpStatement { 325 | astDiscardStatement(); 326 | }; 327 | 328 | struct astExpression : astNode { 329 | astExpression(int type); 330 | // Base class 331 | enum { 332 | kIntConstant, 333 | kUIntConstant, 334 | kFloatConstant, 335 | kDoubleConstant, 336 | kBoolConstant, 337 | kVariableIdentifier, 338 | kFieldOrSwizzle, 339 | kArraySubscript, 340 | kFunctionCall, 341 | kConstructorCall, 342 | kPostIncrement, 343 | kPostDecrement, 344 | kUnaryMinus, 345 | kUnaryPlus, 346 | kBitNot, 347 | kLogicalNot, 348 | kPrefixIncrement, 349 | kPrefixDecrement, 350 | kSequence, 351 | kAssign, 352 | kOperation, 353 | kTernary 354 | }; 355 | int type; 356 | }; 357 | 358 | struct astIntConstant : astExpression { 359 | astIntConstant(int value); 360 | int value; 361 | }; 362 | 363 | struct astUIntConstant : astExpression { 364 | astUIntConstant(unsigned int value); 365 | unsigned int value; 366 | }; 367 | 368 | struct astFloatConstant : astExpression { 369 | astFloatConstant(float value); 370 | float value; 371 | }; 372 | 373 | struct astDoubleConstant : astExpression { 374 | astDoubleConstant(double value); 375 | double value; 376 | }; 377 | 378 | struct astBoolConstant : astExpression { 379 | astBoolConstant(bool value); 380 | bool value; 381 | }; 382 | 383 | struct astVariableIdentifier : astExpression { 384 | astVariableIdentifier(astVariable *variable); 385 | astVariable *variable; 386 | }; 387 | 388 | struct astFieldOrSwizzle : astExpression { 389 | astFieldOrSwizzle(); 390 | astExpression *operand; 391 | char *name; 392 | }; 393 | 394 | struct astArraySubscript : astExpression { 395 | astArraySubscript(); 396 | astExpression *operand; 397 | astExpression *index; 398 | }; 399 | 400 | struct astFunctionCall : astExpression { 401 | astFunctionCall(); 402 | char *name; 403 | vector parameters; 404 | }; 405 | 406 | struct astConstructorCall : astExpression { 407 | astConstructorCall(); 408 | astType *type; 409 | vector parameters; 410 | }; 411 | 412 | struct astUnaryExpression : astExpression { 413 | // Base class 414 | astUnaryExpression(int type, astExpression *operand); 415 | astExpression *operand; 416 | }; 417 | 418 | struct astBinaryExpression : astExpression { 419 | // Base class 420 | astBinaryExpression(int type); 421 | astExpression *operand1; 422 | astExpression *operand2; 423 | }; 424 | 425 | struct astPostIncrementExpression : astUnaryExpression { 426 | astPostIncrementExpression(astExpression *operand); 427 | }; 428 | 429 | struct astPostDecrementExpression : astUnaryExpression { 430 | astPostDecrementExpression(astExpression *operand); 431 | }; 432 | 433 | struct astUnaryPlusExpression : astUnaryExpression { 434 | astUnaryPlusExpression(astExpression *operand); 435 | }; 436 | 437 | struct astUnaryMinusExpression : astUnaryExpression { 438 | astUnaryMinusExpression(astExpression *operand); 439 | }; 440 | 441 | struct astUnaryBitNotExpression : astUnaryExpression { 442 | astUnaryBitNotExpression(astExpression *operand); 443 | }; 444 | 445 | struct astUnaryLogicalNotExpression : astUnaryExpression { 446 | astUnaryLogicalNotExpression(astExpression *operand); 447 | }; 448 | 449 | struct astPrefixIncrementExpression : astUnaryExpression { 450 | astPrefixIncrementExpression(astExpression *operand); 451 | }; 452 | 453 | struct astPrefixDecrementExpression : astUnaryExpression { 454 | astPrefixDecrementExpression(astExpression *operand); 455 | }; 456 | 457 | struct astSequenceExpression : astBinaryExpression { 458 | astSequenceExpression(); 459 | }; 460 | 461 | struct astAssignmentExpression : astBinaryExpression { 462 | astAssignmentExpression(int assignment); 463 | int assignment; 464 | }; 465 | 466 | struct astOperationExpression : astBinaryExpression { 467 | astOperationExpression(int operation); 468 | int operation; 469 | }; 470 | 471 | struct astTernaryExpression : astExpression { 472 | astTernaryExpression(); 473 | astExpression *condition; 474 | astExpression *onTrue; 475 | astExpression *onFalse; 476 | }; 477 | 478 | } 479 | 480 | #endif 481 | -------------------------------------------------------------------------------- /lexemes.h: -------------------------------------------------------------------------------- 1 | // Types 2 | TYPE(eof) 3 | TYPE(whitespace) 4 | TYPE(comment) 5 | TYPE(keyword) 6 | TYPE(identifier) 7 | TYPE(constant_int) 8 | TYPE(constant_uint) 9 | TYPE(constant_float) 10 | TYPE(constant_double) 11 | TYPE(operator) 12 | TYPE(semicolon) 13 | TYPE(scope_begin) 14 | TYPE(scope_end) 15 | TYPE(directive) 16 | 17 | // Keywords 18 | KEYWORD(attribute) 19 | KEYWORD(const) 20 | KEYWORD(uniform) 21 | KEYWORD(varying) 22 | KEYWORD(buffer) 23 | KEYWORD(shared) 24 | KEYWORD(coherent) 25 | KEYWORD(volatile) 26 | KEYWORD(restrict) 27 | KEYWORD(readonly) 28 | KEYWORD(writeonly) 29 | KEYWORD(atomic_uint) 30 | KEYWORD(layout) 31 | KEYWORD(centroid) 32 | KEYWORD(flat) 33 | KEYWORD(smooth) 34 | KEYWORD(noperspective) 35 | KEYWORD(patch) 36 | KEYWORD(sample) 37 | KEYWORD(break) 38 | KEYWORD(continue) 39 | KEYWORD(do) 40 | KEYWORD(for) 41 | KEYWORD(while) 42 | KEYWORD(switch) 43 | KEYWORD(case) 44 | KEYWORD(default) 45 | KEYWORD(if) 46 | KEYWORD(else) 47 | KEYWORD(subroutine) 48 | KEYWORD(in) 49 | KEYWORD(out) 50 | KEYWORD(inout) 51 | 52 | KEYWORD(float) 53 | KEYWORD(double) 54 | KEYWORD(int) 55 | KEYWORD(void) 56 | KEYWORD(bool) 57 | KEYWORD(true) 58 | KEYWORD(false) 59 | 60 | KEYWORD(invariant) 61 | KEYWORD(precise) 62 | 63 | KEYWORD(discard) 64 | KEYWORD(return) 65 | 66 | KEYWORD(mat2) 67 | KEYWORD(mat3) 68 | KEYWORD(mat4) 69 | KEYWORD(dmat2) 70 | KEYWORD(dmat3) 71 | KEYWORD(dmat4) 72 | 73 | KEYWORD(mat2x2) 74 | KEYWORD(mat2x3) 75 | KEYWORD(mat2x4) 76 | KEYWORD(dmat2x2) 77 | KEYWORD(dmat2x3) 78 | KEYWORD(dmat2x4) 79 | 80 | KEYWORD(mat3x2) 81 | KEYWORD(mat3x3) 82 | KEYWORD(mat3x4) 83 | KEYWORD(dmat3x2) 84 | KEYWORD(dmat3x3) 85 | KEYWORD(dmat3x4) 86 | 87 | KEYWORD(mat4x2) 88 | KEYWORD(mat4x3) 89 | KEYWORD(mat4x4) 90 | KEYWORD(dmat4x2) 91 | KEYWORD(dmat4x3) 92 | KEYWORD(dmat4x4) 93 | 94 | KEYWORD(vec2) 95 | KEYWORD(vec3) 96 | KEYWORD(vec4) 97 | KEYWORD(ivec2) 98 | KEYWORD(ivec3) 99 | KEYWORD(ivec4) 100 | KEYWORD(bvec2) 101 | KEYWORD(bvec3) 102 | KEYWORD(bvec4) 103 | KEYWORD(dvec2) 104 | KEYWORD(dvec3) 105 | KEYWORD(dvec4) 106 | 107 | KEYWORD(uint) 108 | KEYWORD(uvec2) 109 | KEYWORD(uvec3) 110 | KEYWORD(uvec4) 111 | 112 | KEYWORD(lowp) 113 | KEYWORD(mediump) 114 | KEYWORD(highp) 115 | KEYWORD(precision) 116 | 117 | KEYWORD(sampler1D) 118 | KEYWORD(sampler2D) 119 | KEYWORD(sampler3D) 120 | KEYWORD(samplerCube) 121 | 122 | KEYWORD(sampler1DShadow) 123 | KEYWORD(sampler2DShadow) 124 | KEYWORD(samplerCubeShadow) 125 | 126 | KEYWORD(sampler1DArray) 127 | KEYWORD(sampler2DArray) 128 | 129 | KEYWORD(sampler1DArrayShadow) 130 | KEYWORD(sampler2DArrayShadow) 131 | 132 | KEYWORD(isampler1D) 133 | KEYWORD(isampler2D) 134 | KEYWORD(isampler3D) 135 | KEYWORD(isamplerCube) 136 | 137 | KEYWORD(isampler1DArray) 138 | KEYWORD(isampler2DArray) 139 | 140 | KEYWORD(usampler1D) 141 | KEYWORD(usampler2D) 142 | KEYWORD(usampler3D) 143 | KEYWORD(usamplerCube) 144 | 145 | KEYWORD(usampler1DArray) 146 | KEYWORD(usampler2DArray) 147 | 148 | KEYWORD(sampler2DRect) 149 | KEYWORD(sampler2DRectShadow) 150 | KEYWORD(isampler2DRect) 151 | KEYWORD(usampler2DRect) 152 | 153 | KEYWORD(samplerBuffer) 154 | KEYWORD(isamplerBuffer) 155 | KEYWORD(usamplerBuffer) 156 | 157 | KEYWORD(sampler2DMS) 158 | KEYWORD(isampler2DMS) 159 | KEYWORD(usampler2DMS) 160 | 161 | KEYWORD(sampler2DMSArray) 162 | KEYWORD(isampler2DMSArray) 163 | KEYWORD(usampler2DMSArray) 164 | 165 | KEYWORD(samplerCubeArray) 166 | KEYWORD(samplerCubeArrayShadow) 167 | KEYWORD(isamplerCubeArray) 168 | KEYWORD(usamplerCubeArray) 169 | 170 | KEYWORD(image1D) 171 | KEYWORD(iimage1D) 172 | KEYWORD(uimage1D) 173 | 174 | KEYWORD(image2D) 175 | KEYWORD(iimage2D) 176 | KEYWORD(uimage2D) 177 | 178 | KEYWORD(image3D) 179 | KEYWORD(iimage3D) 180 | KEYWORD(uimage3D) 181 | 182 | KEYWORD(image2DRect) 183 | KEYWORD(iimage2DRect) 184 | KEYWORD(uimage2DRect) 185 | 186 | KEYWORD(imageCube) 187 | KEYWORD(iimageCube) 188 | KEYWORD(uimageCube) 189 | 190 | KEYWORD(imageBuffer) 191 | KEYWORD(iimageBuffer) 192 | KEYWORD(uimageBuffer) 193 | 194 | KEYWORD(image1DArray) 195 | KEYWORD(iimage1DArray) 196 | KEYWORD(uimage1DArray) 197 | 198 | KEYWORD(image2DArray) 199 | KEYWORD(iimage2DArray) 200 | KEYWORD(uimage2DArray) 201 | 202 | KEYWORD(imageCubeArray) 203 | KEYWORD(iimageCubeArray) 204 | KEYWORD(uimageCubeArray) 205 | 206 | KEYWORD(image2DMS) 207 | KEYWORD(iimage2DMS) 208 | KEYWORD(uimage2DMS) 209 | 210 | KEYWORD(image2DMSArray) 211 | KEYWORD(iimage2DMSArray) 212 | KEYWORD(uimage2DMSArray) 213 | 214 | KEYWORD(struct) 215 | 216 | // Reserved for future use 217 | KEYWORD(common) 218 | KEYWORD(partition) 219 | KEYWORD(active) 220 | 221 | KEYWORD(asm) 222 | 223 | KEYWORD(class) 224 | KEYWORD(union) 225 | KEYWORD(enum) 226 | KEYWORD(typedef) 227 | KEYWORD(template) 228 | KEYWORD(this) 229 | 230 | KEYWORD(resource) 231 | 232 | KEYWORD(goto) 233 | 234 | KEYWORD(inline) 235 | KEYWORD(noinline) 236 | KEYWORD(public) 237 | KEYWORD(static) 238 | KEYWORD(extern) 239 | KEYWORD(external) 240 | KEYWORD(interface) 241 | 242 | KEYWORD(long) 243 | KEYWORD(short) 244 | KEYWORD(half) 245 | KEYWORD(fixed) 246 | KEYWORD(unsigned) 247 | KEYWORD(superp) 248 | 249 | KEYWORD(input) 250 | KEYWORD(output) 251 | 252 | KEYWORD(hvec2) 253 | KEYWORD(hvec3) 254 | KEYWORD(hvec4) 255 | KEYWORD(fvec2) 256 | KEYWORD(fvec3) 257 | KEYWORD(fvec4) 258 | 259 | KEYWORD(sampler3DRect) 260 | 261 | KEYWORD(filter) 262 | 263 | KEYWORD(sizeof) 264 | KEYWORD(cast) 265 | 266 | KEYWORD(namespace) 267 | KEYWORD(using) 268 | 269 | 270 | // Operators 271 | // name, string, precedence 272 | OPERATOR(paranthesis_begin, "(", 17) 273 | OPERATOR(paranthesis_end, ")", 17) 274 | OPERATOR(bracket_begin, "[", 16) 275 | OPERATOR(bracket_end, "]", 16) 276 | OPERATOR(dot, ".", 16) 277 | OPERATOR(increment, "++", 15) // Note: 16 when used as post-fix 278 | OPERATOR(decrement, "--", 15) // Note: 16 when used as post-fix 279 | OPERATOR(bit_not, "~", 15) 280 | OPERATOR(logical_not, "!", 15) 281 | OPERATOR(multiply, "*", 14) 282 | OPERATOR(divide, "/", 14) 283 | OPERATOR(modulus, "%", 14) 284 | OPERATOR(plus, "+", 13) // Note: 15 when unary 285 | OPERATOR(minus, "-", 13) // Note: 15 when unary 286 | OPERATOR(shift_left, "<<", 12) 287 | OPERATOR(shift_right, ">>", 12) 288 | OPERATOR(less, "<", 11) 289 | OPERATOR(greater, ">", 11) 290 | OPERATOR(less_equal, "<=", 11) 291 | OPERATOR(greater_equal, ">=", 11) 292 | OPERATOR(equal, "==", 10) 293 | OPERATOR(not_equal, "!=", 10) 294 | OPERATOR(bit_and, "&", 9) 295 | OPERATOR(bit_xor, "^", 8) 296 | OPERATOR(bit_or, "|", 7) 297 | OPERATOR(logical_and, "&&", 6) 298 | OPERATOR(logical_xor, "^^", 5) 299 | OPERATOR(logical_or, "||", 4) 300 | OPERATOR(questionmark, "?", 3) 301 | OPERATOR(colon, ":", 3) 302 | OPERATOR(assign, "=", 2) 303 | OPERATOR(add_assign, "+=", 2) 304 | OPERATOR(sub_assign, "-=", 2) 305 | OPERATOR(multiply_assign, "*=", 2) 306 | OPERATOR(divide_assign, "/=", 2) 307 | OPERATOR(modulus_assign, "%=", 2) 308 | OPERATOR(shift_left_assign, "<<=", 2) 309 | OPERATOR(shift_right_assign, ">>=", 2) 310 | OPERATOR(bit_and_assign, "&=", 2) 311 | OPERATOR(bit_xor_assign, "^=", 2) 312 | OPERATOR(bit_or_assign, "|=", 2) 313 | OPERATOR(comma, ",", 1) 314 | 315 | TYPENAME(void) 316 | TYPENAME(bool) 317 | TYPENAME(int) 318 | TYPENAME(uint) 319 | TYPENAME(float) 320 | TYPENAME(double) 321 | TYPENAME(vec2) 322 | TYPENAME(vec3) 323 | TYPENAME(vec4) 324 | TYPENAME(dvec2) 325 | TYPENAME(dvec3) 326 | TYPENAME(dvec4) 327 | TYPENAME(bvec2) 328 | TYPENAME(bvec3) 329 | TYPENAME(bvec4) 330 | TYPENAME(ivec2) 331 | TYPENAME(ivec3) 332 | TYPENAME(ivec4) 333 | TYPENAME(uvec2) 334 | TYPENAME(uvec3) 335 | TYPENAME(uvec4) 336 | TYPENAME(mat2) 337 | TYPENAME(mat3) 338 | TYPENAME(mat4) 339 | TYPENAME(mat2x2) 340 | TYPENAME(mat2x3) 341 | TYPENAME(mat2x4) 342 | TYPENAME(mat3x2) 343 | TYPENAME(mat3x3) 344 | TYPENAME(mat3x4) 345 | TYPENAME(mat4x2) 346 | TYPENAME(mat4x3) 347 | TYPENAME(mat4x4) 348 | TYPENAME(dmat2) 349 | TYPENAME(dmat3) 350 | TYPENAME(dmat4) 351 | TYPENAME(dmat2x2) 352 | TYPENAME(dmat2x3) 353 | TYPENAME(dmat2x4) 354 | TYPENAME(dmat3x2) 355 | TYPENAME(dmat3x3) 356 | TYPENAME(dmat3x4) 357 | TYPENAME(dmat4x2) 358 | TYPENAME(dmat4x3) 359 | TYPENAME(dmat4x4) 360 | TYPENAME(sampler1D) 361 | TYPENAME(image1D) 362 | TYPENAME(sampler2D) 363 | TYPENAME(image2D) 364 | TYPENAME(sampler3D) 365 | TYPENAME(image3D) 366 | TYPENAME(samplerCube) 367 | TYPENAME(imageCube) 368 | TYPENAME(sampler2DRect) 369 | TYPENAME(image2DRect) 370 | TYPENAME(sampler1DArray) 371 | TYPENAME(image1DArray) 372 | TYPENAME(sampler2DArray) 373 | TYPENAME(image2DArray) 374 | TYPENAME(samplerBuffer) 375 | TYPENAME(imageBuffer) 376 | TYPENAME(sampler2DMS) 377 | TYPENAME(image2DMS) 378 | TYPENAME(sampler2DMSArray) 379 | TYPENAME(image2DMSArray) 380 | TYPENAME(samplerCubeArray) 381 | TYPENAME(imageCubeArray) 382 | TYPENAME(sampler1DShadow) 383 | TYPENAME(sampler2DShadow) 384 | TYPENAME(sampler2DRectShadow) 385 | TYPENAME(sampler1DArrayShadow) 386 | TYPENAME(sampler2DArrayShadow) 387 | TYPENAME(samplerCubeShadow) 388 | TYPENAME(samplerCubeArrayShadow) 389 | TYPENAME(isampler1D) 390 | TYPENAME(iimage1D) 391 | TYPENAME(isampler2D) 392 | TYPENAME(iimage2D) 393 | TYPENAME(isampler3D) 394 | TYPENAME(iimage3D) 395 | TYPENAME(isamplerCube) 396 | TYPENAME(iimageCube) 397 | TYPENAME(isampler2DRect) 398 | TYPENAME(iimage2DRect) 399 | TYPENAME(isampler1DArray) 400 | TYPENAME(iimage1DArray) 401 | TYPENAME(isampler2DArray) 402 | TYPENAME(iimage2DArray) 403 | TYPENAME(isamplerBuffer) 404 | TYPENAME(iimageBuffer) 405 | TYPENAME(isampler2DMS) 406 | TYPENAME(iimage2DMS) 407 | TYPENAME(isampler2DMSArray) 408 | TYPENAME(iimage2DMSArray) 409 | TYPENAME(isamplerCubeArray) 410 | TYPENAME(iimageCubeArray) 411 | TYPENAME(atomic_uint) 412 | TYPENAME(usampler1D) 413 | TYPENAME(uimage1D) 414 | TYPENAME(usampler2D) 415 | TYPENAME(uimage2D) 416 | TYPENAME(usampler3D) 417 | TYPENAME(uimage3D) 418 | TYPENAME(usamplerCube) 419 | TYPENAME(uimageCube) 420 | TYPENAME(usampler2DRect) 421 | TYPENAME(uimage2DRect) 422 | TYPENAME(usampler1DArray) 423 | TYPENAME(uimage1DArray) 424 | TYPENAME(usampler2DArray) 425 | TYPENAME(uimage2DArray) 426 | TYPENAME(usamplerBuffer) 427 | TYPENAME(uimageBuffer) 428 | TYPENAME(usampler2DMS) 429 | TYPENAME(uimage2DMS) 430 | TYPENAME(usampler2DMSArray) 431 | TYPENAME(uimage2DMSArray) 432 | TYPENAME(usamplerCubeArray) 433 | TYPENAME(uimageCubeArray) 434 | -------------------------------------------------------------------------------- /lexer.cpp: -------------------------------------------------------------------------------- 1 | #include // memcpy, strlen 2 | #include // malloc, free 3 | #include // INT_MAX, UINT_MAX 4 | 5 | #include "lexer.h" 6 | 7 | namespace glsl { 8 | 9 | // Lookup table of keywords 10 | #undef KEYWORD 11 | #define KEYWORD(X) { #X, kKeyword_##X }, 12 | static const keywordInfo kKeywords[] = { 13 | #include "lexemes.h" 14 | }; 15 | #undef KEYWORD 16 | #define KEYWORD(...) 17 | 18 | // Lookup table of operators 19 | #undef OPERATOR 20 | #define OPERATOR(X, S, PREC) { #X, S, PREC }, 21 | static const operatorInfo kOperators[] = { 22 | #include "lexemes.h" 23 | }; 24 | #undef OPERATOR 25 | #define OPERATOR(...) 26 | 27 | token::token() 28 | : m_type(0) 29 | { 30 | asDouble = 0.0; 31 | } 32 | 33 | int token::precedence() const { 34 | if (m_type == kType_operator) 35 | return kOperators[asOperator].precedence; 36 | return -1; 37 | } 38 | 39 | /// location 40 | location::location() 41 | : column(1) 42 | , line(1) 43 | , position(0) 44 | { 45 | } 46 | 47 | void location::advanceColumn(size_t count) { 48 | column += count; 49 | position += count; 50 | } 51 | 52 | void location::advanceLine() { 53 | line++; 54 | position++; 55 | column = 1; 56 | } 57 | 58 | static inline bool isDigit(int ch) { 59 | return unsigned(ch) - '0' < 10; 60 | } 61 | 62 | static inline bool isChar(int ch) { 63 | return (unsigned(ch) | 32) - 'a' < 26; 64 | } 65 | 66 | static inline bool isOctal(int ch) { 67 | return unsigned(ch) - '0' < 8; 68 | } 69 | 70 | static inline bool isHex(int ch) { 71 | return (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F') || isDigit(ch); 72 | } 73 | 74 | static inline bool isSpace(int ch) { 75 | return (ch >= '\t' && ch <= '\r') || ch == ' '; 76 | } 77 | 78 | lexer::lexer(const char *string) 79 | : m_data(string) 80 | , m_length(0) 81 | , m_error(0) 82 | { 83 | if (m_data) 84 | m_length = strlen(m_data); 85 | } 86 | 87 | int lexer::at(int offset) const { 88 | if (position() + offset < m_length) 89 | return m_data[position() + offset]; 90 | return 0; 91 | } 92 | 93 | void lexer::skipWhitespace(bool allowNewlines) { 94 | while (position() < m_length && isSpace(at())) { 95 | if (at() == '\n') { 96 | if (allowNewlines) { 97 | m_location.advanceLine(); 98 | } else { 99 | break; 100 | } 101 | } else { 102 | m_location.advanceColumn(); 103 | } 104 | } 105 | } 106 | 107 | void lexer::read(token &out) { 108 | // Any previous identifier must be freed 109 | if (out.m_type == kType_identifier) 110 | free(out.asIdentifier); 111 | else if (out.m_type == kType_directive && out.asDirective.type == directive::kExtension) 112 | free(out.asDirective.asExtension.name); 113 | 114 | // TODO: Line continuation (backslash `\'.) 115 | if (position() == m_length) { 116 | out.m_type = kType_eof; 117 | return; 118 | } 119 | 120 | int ch1 = at(1); 121 | int ch2 = at(2); 122 | 123 | // Lex numerics 124 | if (isDigit(at()) || (at() == '.' && isDigit(ch1))) 125 | { 126 | bool isFloat = false; 127 | bool isDouble = false; 128 | bool isUnsigned = false; 129 | bool isOctalish = false; 130 | bool isHexish = false; 131 | 132 | if (at() == '0') { 133 | if (ch1 && (ch1 == 'x' || ch1 == 'X')) { 134 | isHexish = true; 135 | m_location.advanceColumn(2); 136 | } else { 137 | isOctalish = true; 138 | } 139 | } 140 | 141 | vector numeric = readNumeric(isOctalish, isHexish); 142 | if (position() != m_length && at() == '.') { 143 | isFloat = true; 144 | isOctalish = false; 145 | numeric.push_back('.'); 146 | m_location.advanceColumn(); 147 | vector others = readNumeric(isOctalish, isHexish); 148 | numeric.reserve(numeric.size() + others.size()); 149 | numeric.insert(numeric.end(), others.begin(), others.end()); 150 | } 151 | 152 | if (position() != m_length && (at() == 'e' || at() == 'E')) { 153 | ch1 = at(1); 154 | ch2 = at(2); 155 | if ((ch1 == '+' || ch1 == '-') && (ch2 >= '0' && ch2 <= '9')) { 156 | numeric.push_back(ch1); 157 | numeric.push_back(ch2); 158 | m_location.advanceColumn(2); 159 | vector others = readNumeric(isOctalish, isHexish); 160 | numeric.reserve(numeric.size() + others.size()); 161 | numeric.insert(numeric.end(), others.begin(), others.end()); 162 | isFloat = true; 163 | isOctalish = false; 164 | } else { 165 | m_error = "invalid numeric literal"; 166 | return; 167 | } 168 | } 169 | 170 | if (position() != m_length && isChar(at())) { 171 | ch1 = at(1); 172 | if (at() == 'f' || at() == 'F') { 173 | isFloat = true; 174 | isOctalish = false; 175 | } else if ((at() == 'l' && ch1 == 'f') || (at() == 'L' && ch1 == 'F')) { 176 | isFloat = false; 177 | isDouble = true; 178 | isOctalish = false; 179 | m_location.advanceColumn(); 180 | } else if (at() == 'u' || at() == 'U') { 181 | if (isFloat) { 182 | m_error = "invalid use of suffix on literal"; 183 | return; 184 | } 185 | isUnsigned = true; 186 | } else { 187 | m_error = "invalid numeric literal"; 188 | return; 189 | } 190 | m_location.advanceColumn(); 191 | } 192 | 193 | if (isHexish && (isFloat || isDouble)) { 194 | m_error = "invalid numeric literal"; 195 | return; 196 | } 197 | 198 | numeric.push_back('\0'); 199 | int base = isHexish ? 16 : (isOctalish ? 8 : 10); 200 | char *error; 201 | if (isFloat) { 202 | out.m_type = kType_constant_float; 203 | out.asFloat = strtof(&numeric[0], &error); 204 | if (error == &numeric[0]) { 205 | m_error = "invalid numeric literal"; 206 | return; 207 | } 208 | } else if (isDouble) { 209 | out.m_type = kType_constant_double; 210 | out.asDouble = strtod(&numeric[0], &error); 211 | if (error == &numeric[0]) { 212 | m_error = "invalid numeric literal"; 213 | return; 214 | } 215 | } else if (isUnsigned) { 216 | out.m_type = kType_constant_uint; 217 | unsigned long long value = strtoull(&numeric[0], 0, base); 218 | if (value <= UINT_MAX) { 219 | out.asUnsigned = (unsigned int)value; 220 | } else { 221 | m_error = "literal needs more than 32-bits"; 222 | } 223 | } else { 224 | out.m_type = kType_constant_int; 225 | long long value = strtoll(&numeric[0], 0, base); 226 | if (value <= INT_MAX) { 227 | out.asInt = (int)value; 228 | } else { 229 | m_error = "literal needs more than 32-bits"; 230 | } 231 | } 232 | } else if (isChar(at()) || at() == '_') { 233 | // Identifiers 234 | out.m_type = kType_identifier; 235 | vector identifier; 236 | while (position() != m_length && (isChar(at()) || isDigit(at()) || at() == '_')) { 237 | identifier.push_back(at()); 238 | m_location.advanceColumn(); 239 | } 240 | identifier.push_back('\0'); 241 | out.asIdentifier = (char *)malloc(identifier.size()); 242 | if (!out.asIdentifier) { 243 | m_error = "Out of memory"; 244 | return; 245 | } 246 | memcpy(out.asIdentifier, &identifier[0], identifier.size()); 247 | 248 | // Or is it a keyword? 249 | for (size_t i = 0; i < sizeof(kKeywords)/sizeof(kKeywords[0]); i++) { 250 | if (strcmp(kKeywords[i].name, out.asIdentifier)) 251 | continue; 252 | free(out.asIdentifier); 253 | out.asIdentifier = 0; 254 | out.m_type = kType_keyword; 255 | out.asKeyword = int(i); 256 | break; 257 | } 258 | } else if (at() == '#') { 259 | m_location.advanceColumn(); // Skip '#'. 260 | 261 | vector chars; 262 | while (isChar(at())) { 263 | chars.push_back(at()); 264 | m_location.advanceColumn(); 265 | } 266 | 267 | // Directive should immediately proceed the # token. 268 | if (chars.empty()) { 269 | m_error = "Expected directive"; 270 | return; 271 | } 272 | 273 | if (!strcmp(&chars[0], "version")) { 274 | out.asDirective.type = directive::kVersion; 275 | 276 | // version [0-9]+ (core|compatibility|es)? 277 | skipWhitespace(false); 278 | 279 | vector digits = readNumeric(false, false); 280 | if (digits.empty()) { 281 | m_error = "Expected version number in #version directive"; 282 | return; 283 | } 284 | digits.push_back('\0'); 285 | 286 | long long value = strtoll(&digits[0], 0, 10); 287 | out.asDirective.asVersion.version = value; 288 | out.asDirective.asVersion.type = kCore; 289 | 290 | skipWhitespace(false); 291 | 292 | vector chars; 293 | while (isChar(at())) { 294 | chars.push_back(at()); 295 | m_location.advanceColumn(); 296 | } 297 | 298 | if (!chars.empty()) { 299 | chars.push_back('\0'); 300 | if (!strcmp(&chars[0], "core")) { 301 | // Do nothing, already core. 302 | } else if (!strcmp(&chars[0], "compatibility")) { 303 | out.asDirective.asVersion.type = kCompatibility; 304 | } else if (!strcmp(&chars[0], "es")) { 305 | out.asDirective.asVersion.type = kES; 306 | } else { 307 | m_error = "Invalid profile in #version directive"; 308 | return; 309 | } 310 | } 311 | } else if (!strcmp(&chars[0], "extension")) { 312 | out.asDirective.type = directive::kExtension; 313 | 314 | // extension [a-zA-Z_]+ : (enable|require|warn|disable) 315 | skipWhitespace(false); 316 | 317 | vector extension; 318 | while (isChar(at())) { 319 | extension.push_back(at()); 320 | m_location.advanceColumn(); 321 | } 322 | extension.push_back('\0'); 323 | 324 | if (extension.empty()) { 325 | m_error = "Expected extension name in #extension directive"; 326 | return; 327 | } 328 | 329 | skipWhitespace(false); 330 | 331 | if (at() != ':') { 332 | m_error = "Expected `:' in #extension directive"; 333 | return; 334 | } 335 | 336 | m_location.advanceColumn(); // Skip ':'. 337 | 338 | skipWhitespace(false); 339 | 340 | vector behavior; 341 | while (isChar(at())) { 342 | behavior.push_back(at()); 343 | m_location.advanceColumn(); 344 | } 345 | behavior.push_back('\0'); 346 | 347 | if (behavior.empty()) { 348 | m_error = "Expected behavior in #extension directive"; 349 | return; 350 | } 351 | 352 | if (!strcmp(&behavior[0], "enable")) { 353 | out.asDirective.asExtension.behavior = kEnable; 354 | } else if (!strcmp(&behavior[0], "require")) { 355 | out.asDirective.asExtension.behavior = kRequire; 356 | } else if (!strcmp(&behavior[0], "warn")) { 357 | out.asDirective.asExtension.behavior = kWarn; 358 | } else if (!strcmp(&behavior[0], "disable")) { 359 | out.asDirective.asExtension.behavior = kDisable; 360 | } else { 361 | m_error = "Unexpected behavior in #extension directive"; 362 | return; 363 | } 364 | 365 | // Do this late when nothing can fail so we don't leak memory. 366 | size_t name_len = strlen(&extension[0]); 367 | char *name = (char*)malloc(name_len + 1); 368 | if (!name) { 369 | m_error = "Out of memory"; 370 | return; 371 | } 372 | memcpy(name, &extension[0], name_len + 1); 373 | out.asDirective.asExtension.name = name; 374 | } else { 375 | m_error = "Unsupported directive"; 376 | return; 377 | } 378 | 379 | out.m_type = kType_directive; 380 | } else { 381 | switch (at()) { 382 | // Non operators 383 | case '\n': 384 | case '\t': 385 | case '\f': 386 | case '\v': 387 | case '\r': 388 | case ' ': 389 | skipWhitespace(true); 390 | out.m_type = kType_whitespace; // Whitespace already skipped. 391 | break; 392 | case ';': 393 | out.m_type = kType_semicolon; 394 | m_location.advanceColumn(); 395 | break; 396 | case '{': 397 | out.m_type = kType_scope_begin; 398 | m_location.advanceColumn(); 399 | break; 400 | case '}': 401 | out.m_type = kType_scope_end; 402 | m_location.advanceColumn(); 403 | break; 404 | // Operators 405 | case '.': 406 | out.m_type = kType_operator; 407 | out.asOperator = kOperator_dot; 408 | break; 409 | case '+': 410 | out.m_type = kType_operator; 411 | if (ch1 == '+') 412 | out.asOperator = kOperator_increment; 413 | else if (ch1 == '=') 414 | out.asOperator = kOperator_add_assign; 415 | else 416 | out.asOperator = kOperator_plus; 417 | break; 418 | case '-': 419 | out.m_type = kType_operator; 420 | if (ch1 == '-') 421 | out.asOperator = kOperator_decrement; 422 | else if (ch1 == '=') 423 | out.asOperator = kOperator_sub_assign; 424 | else 425 | out.asOperator = kOperator_minus; 426 | break; 427 | case '/': 428 | if (ch1 == '/') { 429 | // Skip line comments 430 | while (position() != m_length) { 431 | if (at() == '\n') { 432 | m_location.advanceLine(); 433 | break; 434 | } 435 | m_location.advanceColumn(); 436 | } 437 | out.m_type = kType_comment; 438 | } else if (ch1 == '*') { 439 | // Skip block comments 440 | while (position() != m_length) { 441 | if (at() == '\n') { 442 | m_location.advanceLine(); 443 | continue; 444 | } 445 | if (at() == '*' && position() + 1 < m_length && m_data[position() + 1] == '/') { 446 | m_location.advanceColumn(2); 447 | break; 448 | } 449 | m_location.advanceColumn(); 450 | } 451 | out.m_type = kType_comment; 452 | } else if (ch1 == '=') { 453 | out.m_type = kType_operator; 454 | out.asOperator = kOperator_divide_assign; 455 | } else { 456 | out.m_type = kType_operator; 457 | out.asOperator = kOperator_divide; 458 | } 459 | break; 460 | case '*': 461 | out.m_type = kType_operator; 462 | if (ch1 == '=') 463 | out.asOperator = kOperator_multiply_assign; 464 | else 465 | out.asOperator = kOperator_multiply; 466 | break; 467 | case '%': 468 | out.m_type = kType_operator; 469 | if (ch1 == '=') 470 | out.asOperator = kOperator_modulus_assign; 471 | else 472 | out.asOperator = kOperator_modulus; 473 | break; 474 | case '<': 475 | out.m_type = kType_operator; 476 | if (ch1 == '<' && ch2 == '=') 477 | out.asOperator = kOperator_shift_left_assign; 478 | else if (ch1 == '<') 479 | out.asOperator = kOperator_shift_left; 480 | else if (ch1 == '=') 481 | out.asOperator = kOperator_less_equal; 482 | else 483 | out.asOperator = kOperator_less; 484 | break; 485 | case '>': 486 | out.m_type = kType_operator; 487 | if (ch1 == '>' && ch2 == '=') 488 | out.asOperator = kOperator_shift_right_assign; 489 | else if (ch1 == '>') 490 | out.asOperator = kOperator_shift_right; 491 | else if (ch1 == '=') 492 | out.asOperator = kOperator_greater_equal; 493 | else 494 | out.asOperator = kOperator_greater; 495 | break; 496 | case '[': 497 | out.m_type = kType_operator; 498 | out.asOperator = kOperator_bracket_begin; 499 | break; 500 | case ']': 501 | out.m_type = kType_operator; 502 | out.asOperator = kOperator_bracket_end; 503 | break; 504 | case '(': 505 | out.m_type = kType_operator; 506 | out.asOperator = kOperator_paranthesis_begin; 507 | break; 508 | case ')': 509 | out.m_type = kType_operator; 510 | out.asOperator = kOperator_paranthesis_end; 511 | break; 512 | case '^': 513 | out.m_type = kType_operator; 514 | if (ch1 == '^') 515 | out.asOperator = kOperator_logical_xor; 516 | else if (ch1 == '=') 517 | out.asOperator = kOperator_bit_xor_assign; 518 | else 519 | out.asOperator = kOperator_bit_xor; 520 | break; 521 | case '|': 522 | out.m_type = kType_operator; 523 | if (ch1 == '|') 524 | out.asOperator = kOperator_logical_or; 525 | else if (ch1 == '=') 526 | out.asOperator = kOperator_bit_or_assign; 527 | else 528 | out.asOperator = kOperator_bit_or; 529 | break; 530 | case '&': 531 | out.m_type = kType_operator; 532 | if (ch1 == '&') 533 | out.asOperator = kOperator_logical_and; 534 | else if (ch1 == '=') 535 | out.asOperator = kOperator_bit_and_assign; 536 | else 537 | out.asOperator = kOperator_bit_and; 538 | break; 539 | case '~': 540 | out.m_type = kType_operator; 541 | out.asOperator = kOperator_bit_not; 542 | break; 543 | case '=': 544 | out.m_type = kType_operator; 545 | if (ch1 == '=') 546 | out.asOperator = kOperator_equal; 547 | else 548 | out.asOperator = kOperator_assign; 549 | break; 550 | case '!': 551 | out.m_type = kType_operator; 552 | if (ch1 == '=') 553 | out.asOperator = kOperator_not_equal; 554 | else 555 | out.asOperator = kOperator_logical_not; 556 | break; 557 | case ':': 558 | out.m_type = kType_operator; 559 | out.asOperator = kOperator_colon; 560 | break; 561 | case ',': 562 | out.m_type = kType_operator; 563 | out.asOperator = kOperator_comma; 564 | break; 565 | case '?': 566 | out.m_type = kType_operator; 567 | out.asOperator = kOperator_questionmark; 568 | break; 569 | default: 570 | m_error = "invalid character encountered"; 571 | return; 572 | } 573 | // Skip whitespace for operator 574 | if (out.m_type == kType_operator) 575 | m_location.advanceColumn(strlen(kOperators[out.asOperator].string)); 576 | } 577 | } 578 | 579 | vector lexer::readNumeric(bool isOctalish, bool isHexish) { 580 | vector digits; 581 | if (isOctalish) { 582 | while (position() < m_length && isOctal(at())) { 583 | digits.push_back(at()); 584 | m_location.advanceColumn(); 585 | } 586 | } else if (isHexish) { 587 | while (position() < m_length && isHex(at())) { 588 | digits.push_back(at()); 589 | m_location.advanceColumn(); 590 | } 591 | } else { 592 | while (position() < m_length && isDigit(at())) { 593 | digits.push_back(at()); 594 | m_location.advanceColumn(); 595 | } 596 | } 597 | return digits; 598 | } 599 | 600 | token lexer::peek() { 601 | token out; 602 | backup(); 603 | read(out, true); 604 | restore(); 605 | return out; 606 | } 607 | 608 | void lexer::read(token &out, bool) { 609 | do { 610 | read(out); 611 | } while ((out.m_type == kType_whitespace || out.m_type == kType_comment) && !m_error); 612 | } 613 | 614 | const char *lexer::error() const { 615 | return m_error; 616 | } 617 | 618 | void lexer::backup() { 619 | m_backup = m_location; 620 | } 621 | 622 | void lexer::restore() { 623 | m_location = m_backup; 624 | } 625 | 626 | } 627 | -------------------------------------------------------------------------------- /lexer.h: -------------------------------------------------------------------------------- 1 | #ifndef LEXER_HDR 2 | #define LEXER_HDR 3 | #include "util.h" 4 | 5 | namespace glsl { 6 | 7 | #define KEYWORD(...) 8 | #define OPERATOR(...) 9 | #define TYPENAME(...) 10 | 11 | // Types 12 | #define TYPE(X) kType_##X, 13 | enum { 14 | #include "lexemes.h" 15 | }; 16 | #undef TYPE 17 | #define TYPE(...) 18 | 19 | // Keywords 20 | #undef KEYWORD 21 | #define KEYWORD(X) kKeyword_##X, 22 | enum { 23 | #include "lexemes.h" 24 | }; 25 | #undef KEYWORD 26 | #define KEYWORD(...) 27 | 28 | // Operators 29 | #undef OPERATOR 30 | #define OPERATOR(X, ...) kOperator_##X, 31 | enum { 32 | #include "lexemes.h" 33 | }; 34 | #undef OPERATOR 35 | #define OPERATOR(...) 36 | 37 | enum { 38 | kCore, 39 | kCompatibility, 40 | kES 41 | }; 42 | 43 | enum { 44 | kEnable, 45 | kRequire, 46 | kWarn, 47 | kDisable 48 | }; 49 | 50 | struct keywordInfo { 51 | const char *name; 52 | int type; 53 | }; 54 | 55 | struct operatorInfo { 56 | const char *name; 57 | const char *string; 58 | int precedence; 59 | }; 60 | 61 | struct directive { 62 | enum { 63 | kVersion, 64 | kExtension 65 | }; 66 | 67 | int type; // kVersion, kExtension 68 | 69 | union { 70 | struct { 71 | int version; 72 | int type; // kCore, kCompatibility, kES 73 | } asVersion; 74 | struct { 75 | char* name; 76 | int behavior; // kEnable, kRequire, kWarn, kDisable 77 | } asExtension; 78 | }; 79 | }; 80 | 81 | struct token { 82 | int precedence() const; 83 | 84 | private: 85 | token(); 86 | friend struct lexer; 87 | friend struct parser; 88 | int m_type; 89 | union { 90 | char *asIdentifier; 91 | directive asDirective; 92 | int asInt; 93 | int asKeyword; 94 | int asOperator; 95 | unsigned asUnsigned; 96 | float asFloat; 97 | double asDouble; 98 | }; 99 | }; 100 | 101 | struct location { 102 | location(); 103 | size_t column; 104 | size_t line; 105 | size_t position; 106 | private: 107 | friend struct lexer; 108 | void advanceColumn(size_t count = 1); 109 | void advanceLine(); 110 | }; 111 | 112 | struct lexer { 113 | lexer(const char *data); 114 | 115 | token read(); 116 | token peek(); 117 | 118 | const char *error() const; 119 | 120 | void backup(); 121 | void restore(); 122 | 123 | size_t line() const; 124 | size_t column() const; 125 | 126 | protected: 127 | friend struct parser; 128 | 129 | size_t position() const; 130 | 131 | int at(int offset = 0) const; 132 | 133 | void read(token &out); 134 | void read(token &out, bool); 135 | 136 | void skipWhitespace(bool allowNewlines = false); 137 | 138 | vector readNumeric(bool isOctal, bool isHex); 139 | 140 | private: 141 | const char *m_data; 142 | size_t m_length; 143 | const char *m_error; 144 | location m_location; 145 | location m_backup; 146 | }; 147 | 148 | inline size_t lexer::position() const { 149 | return m_location.position; 150 | } 151 | 152 | inline size_t lexer::line() const { 153 | return m_location.line; 154 | } 155 | 156 | inline size_t lexer::column() const { 157 | return m_location.column; 158 | } 159 | 160 | } 161 | 162 | #endif 163 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include // fread, fclose, fprintf, stderr 2 | #include // strcmp, memcpy 3 | 4 | #include "parser.h" 5 | 6 | using namespace glsl; 7 | 8 | #undef KEYWORD 9 | #define KEYWORD(X) #X, 10 | static const char *kTypes[] = { 11 | #include "lexemes.h" 12 | }; 13 | #undef KEYWORD 14 | #define KEYWORD(...) 15 | 16 | #undef OPERATOR 17 | #define OPERATOR(N, S, P) S, 18 | static const char *kOperators[] = { 19 | #include "lexemes.h" 20 | }; 21 | #undef OPERATOR 22 | #define OPERATOR(...) 23 | 24 | #define print(...) \ 25 | do { \ 26 | printf(__VA_ARGS__); \ 27 | } while (0) 28 | 29 | static void printExpression(astExpression *expression); 30 | static void printStatement(astStatement *statement); 31 | 32 | static void printBuiltin(astBuiltin *builtin) { 33 | print("%s", kTypes[builtin->type]); 34 | } 35 | 36 | static void printType(astType *type) { 37 | if (type->builtin) 38 | printBuiltin((astBuiltin*)type); 39 | else 40 | print("%s", ((astStruct*)type)->name); 41 | } 42 | 43 | static void printIntConstant(astIntConstant *expression) { 44 | print("%d", expression->value); 45 | } 46 | 47 | static void printUIntConstant(astUIntConstant *expression) { 48 | print("%du", expression->value); 49 | } 50 | 51 | static void printFloatConstant(astFloatConstant *expression) { 52 | char format[1024]; 53 | snprintf(format, sizeof format, "%g", expression->value); 54 | if (!strchr(format, '.')) 55 | print("%g.0", expression->value); 56 | else 57 | print("%s", format); 58 | } 59 | 60 | static void printDoubleConstant(astDoubleConstant *expression) { 61 | print("%g", expression->value); 62 | } 63 | 64 | static void printBoolConstant(astBoolConstant *expression) { 65 | print("%s", expression->value ? "true" : "false"); 66 | } 67 | 68 | static void printArraySize(const vector &arraySizes) { 69 | for (size_t i = 0; i < arraySizes.size(); i++) { 70 | print("["); 71 | printExpression(arraySizes[i]); 72 | print("]"); 73 | } 74 | } 75 | 76 | static void printVariable(astVariable *variable, bool nameOnly = false) { 77 | if (variable->isPrecise) 78 | print("precise "); 79 | 80 | if (nameOnly) { 81 | print("%s", variable->name); 82 | return; 83 | } 84 | 85 | printType(variable->baseType); 86 | print(" %s", variable->name); 87 | 88 | if (nameOnly) 89 | return; 90 | 91 | if (variable->isArray) 92 | printArraySize(variable->arraySizes); 93 | } 94 | 95 | static void printStorage(int storage) { 96 | switch (storage) { 97 | case kConst: 98 | print("const "); 99 | break; 100 | case kIn: 101 | print("in "); 102 | break; 103 | case kOut: 104 | print("out "); 105 | break; 106 | case kAttribute: 107 | print("attribute "); 108 | break; 109 | case kUniform: 110 | print("uniform "); 111 | break; 112 | case kVarying: 113 | print("varying "); 114 | break; 115 | case kBuffer: 116 | print("buffer "); 117 | break; 118 | case kShared: 119 | print("shared "); 120 | break; 121 | } 122 | } 123 | 124 | static void printAuxiliary(int auxiliary) { 125 | switch (auxiliary) { 126 | case kCentroid: 127 | print("centroid "); 128 | break; 129 | case kSample: 130 | print("sample "); 131 | break; 132 | case kPatch: 133 | print("patch "); 134 | break; 135 | } 136 | } 137 | 138 | static void printMemory(int memory) { 139 | if (memory & kCoherent) print("coherent "); 140 | if (memory & kVolatile) print("volatile "); 141 | if (memory & kRestrict) print("restrict "); 142 | if (memory & kReadOnly) print("readonly "); 143 | if (memory & kWriteOnly) print("writeonly "); 144 | } 145 | 146 | static void printPrecision(int precision) { 147 | switch (precision) { 148 | case kLowp: 149 | printf("lowp "); 150 | break; 151 | case kMediump: 152 | printf("mediump "); 153 | break; 154 | case kHighp: 155 | printf("highp "); 156 | break; 157 | } 158 | } 159 | 160 | static void printGlobalVariable(astGlobalVariable *variable) { 161 | vector &qualifiers = variable->layoutQualifiers; 162 | if (variable->layoutQualifiers.size()) { 163 | print("layout ("); 164 | for (size_t i = 0; i < qualifiers.size(); i++) { 165 | astLayoutQualifier *qualifier = qualifiers[i]; 166 | print("%s", qualifier->name); 167 | if (qualifier->initialValue) { 168 | print(" = "); 169 | printExpression(qualifier->initialValue); 170 | } 171 | if (i != qualifiers.size() - 1) 172 | print(", "); 173 | } 174 | print(") "); 175 | } 176 | 177 | printStorage(variable->storage); 178 | printAuxiliary(variable->auxiliary); 179 | printMemory(variable->memory); 180 | printPrecision(variable->precision); 181 | 182 | if (variable->isInvariant) 183 | print("invariant "); 184 | 185 | switch (variable->interpolation) { 186 | case kSmooth: 187 | print("smooth "); 188 | break; 189 | case kFlat: 190 | print("flat "); 191 | break; 192 | case kNoPerspective: 193 | print("noperspective "); 194 | break; 195 | } 196 | 197 | printVariable((astVariable*)variable); 198 | 199 | if (variable->initialValue) { 200 | print(" = "); 201 | printExpression(variable->initialValue); 202 | } 203 | 204 | print(";\n"); 205 | } 206 | 207 | static void printVariableIdentifier(astVariableIdentifier *expression) { 208 | printVariable(expression->variable, true); 209 | } 210 | 211 | static void printFieldOrSwizzle(astFieldOrSwizzle *expression) { 212 | printExpression(expression->operand); 213 | print(".%s", expression->name); 214 | } 215 | 216 | static void printArraySubscript(astArraySubscript *expression) { 217 | printExpression(expression->operand); 218 | print("["); 219 | printExpression(expression->index); 220 | print("]"); 221 | } 222 | 223 | static void printFunctionCall(astFunctionCall *expression) { 224 | print("%s(", expression->name); 225 | for (size_t i = 0; i < expression->parameters.size(); i++) { 226 | printExpression(expression->parameters[i]); 227 | if (i != expression->parameters.size() - 1) 228 | print(", "); 229 | } 230 | print(")"); 231 | } 232 | 233 | static void printConstructorCall(astConstructorCall *expression) { 234 | printType(expression->type); 235 | print("("); 236 | for (size_t i = 0; i < expression->parameters.size(); i++) { 237 | printExpression(expression->parameters[i]); 238 | if (i != expression->parameters.size() - 1) 239 | print(", "); 240 | } 241 | print(")"); 242 | } 243 | 244 | enum { kSemicolon = 1 << 0, kNewLine = 1 << 1, kDefault = kSemicolon | kNewLine }; 245 | 246 | static void printFunctionVariable(astFunctionVariable *variable, int flags = kDefault ) { 247 | if (variable->isConst) 248 | print("const "); 249 | printVariable((astVariable*)variable); 250 | if (variable->initialValue) { 251 | print(" = "); 252 | printExpression(variable->initialValue); 253 | } 254 | if (flags & kSemicolon) print(";"); 255 | if (flags & kNewLine) print("\n"); 256 | } 257 | 258 | static void printPostIncrement(astPostIncrementExpression *expression) { 259 | printExpression(expression->operand); 260 | print("++"); 261 | } 262 | 263 | static void printPostDecrement(astPostDecrementExpression *expression) { 264 | printExpression(expression->operand); 265 | print("--"); 266 | } 267 | 268 | static void printUnaryMinus(astUnaryMinusExpression *expression) { 269 | print("-"); 270 | printExpression(expression->operand); 271 | } 272 | 273 | static void printUnaryPlus(astUnaryPlusExpression *expression) { 274 | print("+"); 275 | printExpression(expression->operand); 276 | } 277 | 278 | static void printUnaryBitNot(astUnaryBitNotExpression *expression) { 279 | print("~"); 280 | printExpression(expression->operand); 281 | } 282 | 283 | static void printUnaryLogicalNot(astUnaryLogicalNotExpression *expression) { 284 | print("!"); 285 | printExpression(expression->operand); 286 | } 287 | 288 | static void printPrefixIncrement(astPrefixIncrementExpression *expression) { 289 | print("++"); 290 | printExpression(expression->operand); 291 | } 292 | 293 | static void printPrefixDecrement(astPrefixDecrementExpression *expression) { 294 | print("--"); 295 | printExpression(expression->operand); 296 | } 297 | 298 | static void printAssign(astAssignmentExpression *expression) { 299 | printExpression(expression->operand1); 300 | print(" %s ", kOperators[expression->assignment]); 301 | printExpression(expression->operand2); 302 | } 303 | 304 | static void printSequence(astSequenceExpression *expression) { 305 | printf("("); 306 | printExpression(expression->operand1); 307 | printf(", "); 308 | printExpression(expression->operand2); 309 | printf(")"); 310 | } 311 | 312 | static void printOperation(astOperationExpression *expression) { 313 | printf("("); 314 | printExpression(expression->operand1); 315 | printf(" %s ", kOperators[expression->operation]); 316 | printExpression(expression->operand2); 317 | printf(")"); 318 | } 319 | 320 | static void printTernary(astTernaryExpression *expression) { 321 | printf("("); 322 | printExpression(expression->condition); 323 | printf(" ? "); 324 | printExpression(expression->onTrue); 325 | printf(" : "); 326 | printExpression(expression->onFalse); 327 | printf(")"); 328 | } 329 | 330 | static void printExpression(astExpression *expression) { 331 | switch (expression->type) { 332 | case astExpression::kIntConstant: 333 | return printIntConstant((astIntConstant*)expression); 334 | case astExpression::kUIntConstant: 335 | return printUIntConstant((astUIntConstant*)expression); 336 | case astExpression::kFloatConstant: 337 | return printFloatConstant((astFloatConstant*)expression); 338 | case astExpression::kDoubleConstant: 339 | return printDoubleConstant((astDoubleConstant*)expression); 340 | case astExpression::kBoolConstant: 341 | return printBoolConstant((astBoolConstant*)expression); 342 | case astExpression::kVariableIdentifier: 343 | return printVariableIdentifier((astVariableIdentifier*)expression); 344 | case astExpression::kFieldOrSwizzle: 345 | return printFieldOrSwizzle((astFieldOrSwizzle*)expression); 346 | case astExpression::kArraySubscript: 347 | return printArraySubscript((astArraySubscript*)expression); 348 | case astExpression::kFunctionCall: 349 | return printFunctionCall((astFunctionCall*)expression); 350 | case astExpression::kConstructorCall: 351 | return printConstructorCall((astConstructorCall*)expression); 352 | case astExpression::kPostIncrement: 353 | return printPostIncrement((astPostIncrementExpression*)expression); 354 | case astExpression::kPostDecrement: 355 | return printPostDecrement((astPostDecrementExpression*)expression); 356 | case astExpression::kUnaryMinus: 357 | return printUnaryMinus((astUnaryMinusExpression*)expression); 358 | case astExpression::kUnaryPlus: 359 | return printUnaryPlus((astUnaryPlusExpression*)expression); 360 | case astExpression::kBitNot: 361 | return printUnaryBitNot((astUnaryBitNotExpression*)expression); 362 | case astExpression::kLogicalNot: 363 | return printUnaryLogicalNot((astUnaryLogicalNotExpression*)expression); 364 | case astExpression::kPrefixIncrement: 365 | return printPrefixIncrement((astPrefixIncrementExpression*)expression); 366 | case astExpression::kPrefixDecrement: 367 | return printPrefixDecrement((astPrefixDecrementExpression*)expression); 368 | case astExpression::kAssign: 369 | return printAssign((astAssignmentExpression*)expression); 370 | case astExpression::kSequence: 371 | return printSequence((astSequenceExpression*)expression); 372 | case astExpression::kOperation: 373 | return printOperation((astOperationExpression*)expression); 374 | case astExpression::kTernary: 375 | return printTernary((astTernaryExpression*)expression); 376 | } 377 | } 378 | 379 | static void printCompoundStatement(astCompoundStatement *statement) { 380 | print(" {\n"); 381 | for (size_t i = 0; i < statement->statements.size(); i++) 382 | printStatement(statement->statements[i]); 383 | print("}\n"); 384 | } 385 | 386 | static void printEmptyStatement() { 387 | print(";"); 388 | } 389 | 390 | static void printDeclarationStatement(astDeclarationStatement *statement, int flags = kDefault) { 391 | for (size_t i = 0; i < statement->variables.size(); i++) 392 | printFunctionVariable(statement->variables[i], flags); 393 | } 394 | 395 | static void printExpressionStatement(astExpressionStatement *statement, int flags = kDefault) { 396 | printExpression(statement->expression); 397 | if (flags & kSemicolon) print(";"); 398 | if (flags & kNewLine) print("\n"); 399 | } 400 | 401 | static void printIfStetement(astIfStatement *statement) { 402 | print("if("); 403 | printExpression(statement->condition); 404 | print(")"); 405 | printStatement(statement->thenStatement); 406 | if (statement->elseStatement) { 407 | print("else"); 408 | if (statement->elseStatement->type == astStatement::kIf) 409 | print(" "); 410 | printStatement(statement->elseStatement); 411 | } 412 | } 413 | 414 | static void printSwitchStatement(astSwitchStatement *statement) { 415 | print("switch("); 416 | printExpression(statement->expression); 417 | print(") {\n"); 418 | for (size_t i = 0; i < statement->statements.size(); i++) 419 | printStatement(statement->statements[i]); 420 | print("}\n"); 421 | } 422 | 423 | static void printCaseLabelStatement(astCaseLabelStatement *statement) { 424 | if (statement->isDefault) 425 | print("default"); 426 | else { 427 | print("case "); 428 | printExpression(statement->condition); 429 | } 430 | print(":\n"); 431 | } 432 | 433 | static void printWhileStatement(astWhileStatement *statement) { 434 | print("while("); 435 | switch (statement->condition->type) { 436 | case astStatement::kDeclaration: 437 | printDeclarationStatement((astDeclarationStatement*)statement->condition, false); 438 | break; 439 | case astStatement::kExpression: 440 | printExpressionStatement((astExpressionStatement*)statement->condition, false); 441 | break; 442 | } 443 | print(")"); 444 | printStatement(statement->body); 445 | } 446 | 447 | static void printDoStatement(astDoStatement *statement) { 448 | print("do"); 449 | // deal with non compound (i.e scope) in do loops, e.g: do function_call(); while(expr); 450 | if (statement->body->type != astStatement::kCompound) 451 | print(" "); 452 | printStatement(statement->body); 453 | print("while("); 454 | printExpression(statement->condition); 455 | print(");\n"); 456 | } 457 | 458 | static void printForStatement(astForStatement *statement) { 459 | print("for("); 460 | if (statement->init) { 461 | switch (statement->init->type) { 462 | case astStatement::kDeclaration: 463 | printDeclarationStatement((astDeclarationStatement*)statement->init, kSemicolon); 464 | break; 465 | case astStatement::kExpression: 466 | printExpressionStatement((astExpressionStatement*)statement->init, kSemicolon); 467 | break; 468 | } 469 | } else { 470 | print(";"); 471 | } 472 | if (statement->condition) { 473 | print(" "); 474 | printExpression(statement->condition); 475 | } 476 | print(";"); 477 | if (statement->loop) { 478 | print(" "); 479 | printExpression(statement->loop); 480 | } 481 | print(")"); 482 | printStatement(statement->body); 483 | } 484 | 485 | static void printContinueStatement() { 486 | print("continue;\n"); 487 | } 488 | 489 | static void printBreakStatement() { 490 | print("break;\n"); 491 | } 492 | 493 | static void printReturnStatement(astReturnStatement *statement) { 494 | if (statement->expression) { 495 | print("return "); 496 | printExpression(statement->expression); 497 | print(";\n"); 498 | } else { 499 | print("return;\n"); 500 | } 501 | } 502 | 503 | static void printDiscardStatement() { 504 | print("discard;\n"); 505 | } 506 | 507 | static void printStatement(astStatement *statement) { 508 | switch (statement->type) { 509 | case astStatement::kCompound: 510 | return printCompoundStatement((astCompoundStatement*)statement); 511 | case astStatement::kEmpty: 512 | return printEmptyStatement(); 513 | case astStatement::kDeclaration: 514 | return printDeclarationStatement((astDeclarationStatement*)statement); 515 | case astStatement::kExpression: 516 | return printExpressionStatement((astExpressionStatement*)statement); 517 | case astStatement::kIf: 518 | return printIfStetement((astIfStatement*)statement); 519 | case astStatement::kSwitch: 520 | return printSwitchStatement((astSwitchStatement*)statement); 521 | case astStatement::kCaseLabel: 522 | return printCaseLabelStatement((astCaseLabelStatement*)statement); 523 | case astStatement::kWhile: 524 | return printWhileStatement((astWhileStatement*)statement); 525 | case astStatement::kDo: 526 | return printDoStatement((astDoStatement*)statement); 527 | case astStatement::kFor: 528 | return printForStatement((astForStatement*)statement); 529 | case astStatement::kContinue: 530 | return printContinueStatement(); 531 | case astStatement::kBreak: 532 | return printBreakStatement(); 533 | case astStatement::kReturn: 534 | return printReturnStatement((astReturnStatement*)statement); 535 | case astStatement::kDiscard: 536 | return printDiscardStatement(); 537 | } 538 | print("\n"); 539 | } 540 | 541 | static void printFunctionParameter(astFunctionParameter *parameter) { 542 | printStorage(parameter->storage); 543 | printAuxiliary(parameter->auxiliary); 544 | printMemory(parameter->memory); 545 | printPrecision(parameter->precision); 546 | printType(parameter->baseType); 547 | if (parameter->name) 548 | print(" %s", parameter->name); 549 | if (parameter->isArray) 550 | printArraySize(parameter->arraySizes); 551 | } 552 | 553 | static void printFunction(astFunction *function) { 554 | printType(function->returnType); 555 | print(" %s(", function->name); 556 | for (size_t i = 0; i < function->parameters.size(); i++) 557 | printFunctionParameter(function->parameters[i]); 558 | print(")"); 559 | if (function->isPrototype) { 560 | print(";\n"); 561 | return; 562 | } 563 | print(" {\n"); 564 | for (size_t i = 0; i < function->statements.size(); i++) 565 | printStatement(function->statements[i]); 566 | print("}\n"); 567 | } 568 | 569 | static void printStructure(astStruct *structure) { 570 | print("struct "); 571 | if (structure->name) 572 | print("%s ", structure->name); 573 | print("{\n"); 574 | for (size_t i = 0; i < structure->fields.size(); i++) { 575 | printVariable(structure->fields[i]); 576 | print(";\n"); 577 | } 578 | print("};\n"); 579 | } 580 | 581 | static void printInterfaceBlock(astInterfaceBlock *block) { 582 | printStorage(block->storage); 583 | printf("%s ", block->name); 584 | printf("{\n"); 585 | for (size_t i = 0; i < block->fields.size(); i++) { 586 | printVariable(block->fields[i]); 587 | print(";\n"); 588 | } 589 | printf("};\n"); 590 | } 591 | 592 | static void printVersionDirective(astVersionDirective *version) { 593 | printf("#version %d ", version->version); 594 | switch (version->type) { 595 | case kCore: 596 | printf("core\n"); 597 | break; 598 | case kCompatibility: 599 | printf("compatibility\n"); 600 | break; 601 | case kES: 602 | printf("es\n"); 603 | break; 604 | } 605 | } 606 | 607 | static void printExtensionDirective(astExtensionDirective *extension) { 608 | printf("#extension %s : ", extension->name); 609 | switch (extension->behavior) { 610 | case kEnable: 611 | printf("enable\n"); 612 | break; 613 | case kRequire: 614 | printf("require\n"); 615 | break; 616 | case kWarn: 617 | printf("warn\n"); 618 | break; 619 | case kDisable: 620 | printf("disable\n"); 621 | break; 622 | } 623 | } 624 | 625 | static void printTU(astTU *tu) { 626 | if (tu->versionDirective) 627 | printVersionDirective(tu->versionDirective); 628 | for (size_t i = 0; i < tu->extensionDirectives.size(); i++) 629 | printExtensionDirective(tu->extensionDirectives[i]); 630 | for (size_t i = 0; i < tu->structures.size(); i++) 631 | printStructure(tu->structures[i]); 632 | for (size_t i = 0; i < tu->interfaceBlocks.size(); i++) 633 | printInterfaceBlock(tu->interfaceBlocks[i]); 634 | for (size_t i = 0; i < tu->globals.size(); i++) 635 | printGlobalVariable(tu->globals[i]); 636 | for (size_t i = 0; i < tu->functions.size(); i++) 637 | printFunction(tu->functions[i]); 638 | } 639 | 640 | struct sourceFile { 641 | const char *fileName; 642 | FILE *file; 643 | int shaderType; 644 | }; 645 | 646 | int main(int argc, char **argv) { 647 | int shaderType = -1; 648 | vector sources; 649 | while (argc > 1) { 650 | ++argv; 651 | --argc; 652 | if (argv[0][0] == '-' && argv[0][1]) { 653 | const char *what = argv[0] + 1; 654 | if (!strcmp(what, "c")) 655 | shaderType = astTU::kCompute; 656 | else if (!strcmp(what, "v")) 657 | shaderType = astTU::kVertex; 658 | else if (!strcmp(what, "tc")) 659 | shaderType = astTU::kTessControl; 660 | else if (!strcmp(what, "te")) 661 | shaderType = astTU::kTessEvaluation; 662 | else if (!strcmp(what, "g")) 663 | shaderType = astTU::kGeometry; 664 | else if (!strcmp(what, "f")) 665 | shaderType = astTU::kFragment; 666 | else { 667 | fprintf(stderr, "unknown option: `%s'\n", argv[0]); 668 | return 1; 669 | } 670 | } else { 671 | // Treat as fragment shader by default 672 | if (shaderType == -1) 673 | shaderType = astTU::kFragment; 674 | sourceFile source; 675 | if (!strcmp(argv[0], "-")) { 676 | source.fileName = ""; 677 | source.file = stdin; 678 | source.shaderType = shaderType; 679 | sources.push_back(source); 680 | } else { 681 | source.fileName = argv[0]; 682 | if ((source.file = fopen(argv[0], "r"))) { 683 | source.shaderType = shaderType; 684 | sources.push_back(source); 685 | } else { 686 | fprintf(stderr, "failed to read shader file: `%s' (ignoring)\n", argv[0]); 687 | } 688 | } 689 | } 690 | } 691 | 692 | for (size_t i = 0; i < sources.size(); i++) { 693 | vector contents; 694 | // Read contents of file 695 | if (sources[i].file != stdin) { 696 | fseek(sources[i].file, 0, SEEK_END); 697 | contents.resize(ftell(sources[i].file)); 698 | fseek(sources[i].file, 0, SEEK_SET); 699 | fread(&contents[0], 1, contents.size(), sources[i].file); 700 | fclose(sources[i].file); 701 | } else { 702 | char buffer[1024]; 703 | int c; 704 | while ((c = fread(buffer, 1, sizeof(buffer), stdin))) { 705 | contents.reserve(contents.size() + c); 706 | contents.insert(contents.end(), buffer, buffer + c); 707 | } 708 | } 709 | contents.push_back('\0'); 710 | parser p(&contents[0], sources[i].fileName); 711 | astTU *tu = p.parse(sources[i].shaderType); 712 | if (tu) { 713 | printTU(tu); 714 | } else { 715 | fprintf(stderr, "%s\n", p.error()); 716 | } 717 | } 718 | return 0; 719 | } 720 | -------------------------------------------------------------------------------- /parser.cpp: -------------------------------------------------------------------------------- 1 | #include // strcmp, memcpy 2 | 3 | #include "parser.h" 4 | #include "util.h" 5 | 6 | namespace glsl { 7 | 8 | parser::parser(const char *source, const char *fileName) 9 | : m_ast(0) 10 | , m_lexer(source) 11 | , m_fileName(fileName) 12 | { 13 | m_oom = strnew("Out of memory"); 14 | m_error = strnew(""); 15 | } 16 | 17 | parser::~parser() { 18 | delete m_ast; 19 | for (size_t i = 0; i < m_strings.size(); i++) 20 | free(m_strings[i]); 21 | for (size_t i = 0; i < m_memory.size(); i++) 22 | m_memory[i].destroy(); 23 | } 24 | 25 | #define IS_TYPE(TOKEN, TYPE) \ 26 | ((TOKEN).m_type == (TYPE)) 27 | #define IS_KEYWORD(TOKEN, KEYWORD) \ 28 | (IS_TYPE((TOKEN), kType_keyword) && (TOKEN).asKeyword == (KEYWORD)) 29 | #define IS_OPERATOR(TOKEN, OPERATOR) \ 30 | (IS_TYPE((TOKEN), kType_operator) && (TOKEN).asOperator == (OPERATOR)) 31 | 32 | #define GC_NEW(X) new(&m_memory) 33 | 34 | bool parser::isType(int type) const { 35 | return IS_TYPE(m_token, type); 36 | } 37 | 38 | bool parser::isKeyword(int keyword) const { 39 | return IS_KEYWORD(m_token, keyword); 40 | } 41 | 42 | bool parser::isOperator(int oper) const { 43 | return IS_OPERATOR(m_token, oper); 44 | } 45 | 46 | bool parser::isEndCondition(endCondition condition) const { 47 | return ((condition & kEndConditionSemicolon) && isType(kType_semicolon)) 48 | || ((condition & kEndConditionParanthesis) && isOperator(kOperator_paranthesis_end)) 49 | || ((condition & kEndConditionBracket) && isOperator(kOperator_bracket_end)) 50 | || ((condition & kEndConditionColon) && isOperator(kOperator_colon)) 51 | || ((condition & kEndConditionComma) && isOperator(kOperator_comma)); 52 | } 53 | 54 | // Constant expression evaluator 55 | bool parser::isConstant(astExpression *expression) const { 56 | if (isConstantValue(expression)) 57 | return true; 58 | else if (expression->type == astExpression::kVariableIdentifier) { 59 | astVariable *reference = ((astVariableIdentifier*)expression)->variable; 60 | if (reference->type != astVariable::kGlobal) 61 | return false; 62 | astExpression *initialValue = ((astGlobalVariable*)reference)->initialValue; 63 | if (!initialValue) 64 | return false; 65 | return isConstant(initialValue); 66 | } else if (expression->type == astExpression::kUnaryMinus) 67 | return isConstant(((astUnaryExpression*)expression)->operand); 68 | else if (expression->type == astExpression::kUnaryPlus) 69 | return isConstant(((astUnaryExpression*)expression)->operand); 70 | else if (expression->type == astExpression::kOperation) { 71 | astOperationExpression *operation = (astOperationExpression*)expression; 72 | return isConstant(operation->operand1) && isConstant(operation->operand2); 73 | } 74 | return false; 75 | } 76 | 77 | bool parser::isConstantValue(astExpression *expression) const { 78 | return expression->type == astExpression::kIntConstant || 79 | expression->type == astExpression::kUIntConstant || 80 | expression->type == astExpression::kFloatConstant || 81 | expression->type == astExpression::kDoubleConstant || 82 | expression->type == astExpression::kBoolConstant; 83 | } 84 | 85 | #define ICONST(X) ((astIntConstant*)(X)) 86 | #define UCONST(X) ((astUIntConstant*)(X)) 87 | #define FCONST(X) ((astFloatConstant*)(X)) 88 | #define DCONST(X) ((astDoubleConstant*)(X)) 89 | #define BCONST(X) ((astBoolConstant*)(X)) 90 | 91 | #define ICONST_NEW(X) GC_NEW(astConstantExpression) astIntConstant(X) 92 | #define UCONST_NEW(X) GC_NEW(astConstantExpression) astUIntConstant(X) 93 | #define FCONST_NEW(X) GC_NEW(astConstantExpression) astFloatConstant(X) 94 | #define DCONST_NEW(X) GC_NEW(astConstantExpression) astDoubleConstant(X) 95 | #define BCONST_NEW(X) GC_NEW(astConstantExpression) astBoolConstant(X) 96 | 97 | #define IVAL(X) (ICONST(X)->value) 98 | #define UVAL(X) (UCONST(X)->value) 99 | #define FVAL(X) (FCONST(X)->value) 100 | #define DVAL(X) (DCONST(X)->value) 101 | #define BVAL(X) (BCONST(X)->value) 102 | 103 | astConstantExpression *parser::evaluate(astExpression *expression) { 104 | if (!expression) return 0; 105 | else if (isConstantValue(expression)) 106 | return expression; 107 | else if (expression->type == astExpression::kVariableIdentifier) 108 | return evaluate(((astGlobalVariable*)((astVariableIdentifier*)expression)->variable)->initialValue); 109 | else if (expression->type == astExpression::kUnaryMinus) { 110 | astExpression *operand = evaluate(((astUnaryExpression*)expression)->operand); 111 | if (!operand) return 0; 112 | switch (operand->type) { 113 | case astExpression::kIntConstant: return ICONST_NEW(-IVAL(operand)); 114 | case astExpression::kFloatConstant: return FCONST_NEW(-FVAL(operand)); 115 | case astExpression::kDoubleConstant: return DCONST_NEW(-DVAL(operand)); 116 | default: 117 | fatal("invalid operation in constant expression"); 118 | return 0; 119 | } 120 | } else if (expression->type == astExpression::kUnaryPlus) { 121 | astExpression *operand = evaluate(((astUnaryExpression*)expression)->operand); 122 | if (!operand) return 0; 123 | switch (operand->type) { 124 | case astExpression::kIntConstant: 125 | case astExpression::kUIntConstant: 126 | case astExpression::kFloatConstant: 127 | case astExpression::kDoubleConstant: 128 | return operand; 129 | default: 130 | fatal("invalid operation in constant expression"); 131 | return 0; 132 | } 133 | } else if (expression->type == astExpression::kOperation) { 134 | int operation = ((astOperationExpression*)expression)->operation; 135 | astExpression *lhs = evaluate(((astBinaryExpression*)expression)->operand1); 136 | astExpression *rhs = evaluate(((astBinaryExpression*)expression)->operand2); 137 | if (!lhs) return 0; 138 | if (!rhs) return 0; 139 | switch (lhs->type) { 140 | case astExpression::kIntConstant: 141 | switch (operation) { 142 | case kOperator_multiply: return ICONST_NEW(IVAL(lhs) * IVAL(rhs)); 143 | case kOperator_divide: return ICONST_NEW(IVAL(lhs) / IVAL(rhs)); 144 | case kOperator_modulus: return ICONST_NEW(IVAL(lhs) % IVAL(rhs)); 145 | case kOperator_plus: return ICONST_NEW(IVAL(lhs) + IVAL(rhs)); 146 | case kOperator_minus: return ICONST_NEW(IVAL(lhs) - IVAL(rhs)); 147 | case kOperator_shift_left: return ICONST_NEW(IVAL(lhs) << IVAL(rhs)); 148 | case kOperator_shift_right: return ICONST_NEW(IVAL(lhs) >> IVAL(rhs)); 149 | case kOperator_less: return BCONST_NEW(IVAL(lhs) < IVAL(rhs)); 150 | case kOperator_greater: return BCONST_NEW(IVAL(lhs) > IVAL(rhs)); 151 | case kOperator_less_equal: return BCONST_NEW(IVAL(lhs) <= IVAL(rhs)); 152 | case kOperator_greater_equal: return BCONST_NEW(IVAL(lhs) >= IVAL(rhs)); 153 | case kOperator_equal: return BCONST_NEW(IVAL(lhs) == IVAL(rhs)); 154 | case kOperator_not_equal: return BCONST_NEW(IVAL(lhs) != IVAL(rhs)); 155 | case kOperator_bit_and: return ICONST_NEW(IVAL(lhs) & IVAL(rhs)); 156 | case kOperator_bit_xor: return ICONST_NEW(IVAL(lhs) ^ IVAL(rhs)); 157 | case kOperator_logical_and: return BCONST_NEW(IVAL(lhs) && IVAL(rhs)); 158 | case kOperator_logical_xor: return BCONST_NEW(!IVAL(lhs) != !IVAL(rhs)); 159 | case kOperator_logical_or: return BCONST_NEW(IVAL(lhs) || IVAL(rhs)); 160 | default: 161 | fatal("invalid operation in constant expression"); 162 | return 0; 163 | } 164 | break; 165 | case astExpression::kUIntConstant: 166 | switch (operation) { 167 | case kOperator_multiply: return UCONST_NEW(UVAL(lhs) * UVAL(rhs)); 168 | case kOperator_divide: return UCONST_NEW(UVAL(lhs) / UVAL(rhs)); 169 | case kOperator_modulus: return UCONST_NEW(UVAL(lhs) % UVAL(rhs)); 170 | case kOperator_plus: return UCONST_NEW(UVAL(lhs) + UVAL(rhs)); 171 | case kOperator_minus: return UCONST_NEW(UVAL(lhs) - UVAL(rhs)); 172 | case kOperator_shift_left: return UCONST_NEW(UVAL(lhs) << UVAL(rhs)); 173 | case kOperator_shift_right: return UCONST_NEW(UVAL(lhs) >> UVAL(rhs)); 174 | case kOperator_less: return BCONST_NEW(UVAL(lhs) < UVAL(rhs)); 175 | case kOperator_greater: return BCONST_NEW(UVAL(lhs) > UVAL(rhs)); 176 | case kOperator_less_equal: return BCONST_NEW(UVAL(lhs) <= UVAL(rhs)); 177 | case kOperator_greater_equal: return BCONST_NEW(UVAL(lhs) >= UVAL(rhs)); 178 | case kOperator_equal: return BCONST_NEW(UVAL(lhs) == UVAL(rhs)); 179 | case kOperator_not_equal: return BCONST_NEW(UVAL(lhs) != UVAL(rhs)); 180 | case kOperator_bit_and: return UCONST_NEW(UVAL(lhs) & UVAL(rhs)); 181 | case kOperator_bit_xor: return UCONST_NEW(UVAL(lhs) ^ UVAL(rhs)); 182 | case kOperator_logical_and: return BCONST_NEW(UVAL(lhs) && UVAL(rhs)); 183 | case kOperator_logical_xor: return BCONST_NEW(!UVAL(lhs) != !UVAL(rhs)); 184 | case kOperator_logical_or: return BCONST_NEW(UVAL(lhs) || UVAL(rhs)); 185 | default: 186 | fatal("invalid operation in constant expression"); 187 | return 0; 188 | } 189 | break; 190 | case astExpression::kFloatConstant: 191 | switch (operation) { 192 | case kOperator_multiply: return FCONST_NEW(FVAL(lhs) * FVAL(rhs)); 193 | case kOperator_divide: return FCONST_NEW(FVAL(lhs) / FVAL(rhs)); 194 | case kOperator_plus: return FCONST_NEW(FVAL(lhs) + FVAL(rhs)); 195 | case kOperator_minus: return FCONST_NEW(FVAL(lhs) - FVAL(rhs)); 196 | case kOperator_less: return BCONST_NEW(FVAL(lhs) < FVAL(rhs)); 197 | case kOperator_greater: return BCONST_NEW(FVAL(lhs) > FVAL(rhs)); 198 | case kOperator_less_equal: return BCONST_NEW(FVAL(lhs) <= FVAL(rhs)); 199 | case kOperator_greater_equal: return BCONST_NEW(FVAL(lhs) >= FVAL(rhs)); 200 | case kOperator_equal: return BCONST_NEW(FVAL(lhs) == FVAL(rhs)); 201 | case kOperator_not_equal: return BCONST_NEW(FVAL(lhs) != FVAL(rhs)); 202 | case kOperator_logical_and: return BCONST_NEW(FVAL(lhs) && FVAL(rhs)); 203 | case kOperator_logical_xor: return BCONST_NEW(!FVAL(lhs) != !FVAL(rhs)); 204 | case kOperator_logical_or: return BCONST_NEW(FVAL(lhs) || FVAL(rhs)); 205 | default: 206 | fatal("invalid operation in constant expression"); 207 | return 0; 208 | } 209 | break; 210 | case astExpression::kDoubleConstant: 211 | switch (operation) { 212 | case kOperator_multiply: return DCONST_NEW(DVAL(lhs) * DVAL(rhs)); 213 | case kOperator_divide: return DCONST_NEW(DVAL(lhs) / DVAL(rhs)); 214 | case kOperator_plus: return DCONST_NEW(DVAL(lhs) + DVAL(rhs)); 215 | case kOperator_minus: return DCONST_NEW(DVAL(lhs) - DVAL(rhs)); 216 | case kOperator_less: return BCONST_NEW(DVAL(lhs) < DVAL(rhs)); 217 | case kOperator_greater: return BCONST_NEW(DVAL(lhs) > DVAL(rhs)); 218 | case kOperator_less_equal: return BCONST_NEW(DVAL(lhs) <= DVAL(rhs)); 219 | case kOperator_greater_equal: return BCONST_NEW(DVAL(lhs) >= DVAL(rhs)); 220 | case kOperator_equal: return BCONST_NEW(DVAL(lhs) == DVAL(rhs)); 221 | case kOperator_not_equal: return BCONST_NEW(DVAL(lhs) != DVAL(rhs)); 222 | case kOperator_logical_and: return BCONST_NEW(DVAL(lhs) && DVAL(rhs)); 223 | case kOperator_logical_xor: return BCONST_NEW(!DVAL(lhs) != !DVAL(rhs)); 224 | case kOperator_logical_or: return BCONST_NEW(DVAL(lhs) || DVAL(rhs)); 225 | default: 226 | fatal("invalid operation in constant expression"); 227 | return 0; 228 | } 229 | break; 230 | case astExpression::kBoolConstant: 231 | switch (operation) { 232 | case kOperator_equal: return BCONST_NEW(BVAL(lhs) == BVAL(rhs)); 233 | case kOperator_not_equal: return BCONST_NEW(BVAL(lhs) != BVAL(rhs)); 234 | case kOperator_logical_and: return BCONST_NEW(BVAL(lhs) && BVAL(rhs)); 235 | case kOperator_logical_xor: return BCONST_NEW(!BVAL(lhs) != !BVAL(rhs)); 236 | case kOperator_logical_or: return BCONST_NEW(BVAL(lhs) || BVAL(rhs)); 237 | default: 238 | fatal("invalid operation in constant expression"); 239 | return 0; 240 | } 241 | break; 242 | } 243 | } else { 244 | return evaluate(expression); 245 | } 246 | return 0; 247 | } 248 | 249 | void parser::fatal(const char *fmt, ...) { 250 | // Format banner 251 | char *banner = 0; 252 | int bannerLength = allocfmt(&banner, "%s:%zu:%zu: error: ", m_fileName, m_lexer.line(), m_lexer.column()); 253 | if (bannerLength == -1) { 254 | m_error = m_oom; 255 | return; 256 | } 257 | 258 | // Format message 259 | char *message = 0; 260 | va_list va; 261 | va_start(va, fmt); 262 | int messageLength = allocvfmt(&message, fmt, va); 263 | if (messageLength == -1) { 264 | va_end(va); 265 | m_error = m_oom; 266 | return; 267 | } 268 | va_end(va); 269 | 270 | // Concatenate the two things 271 | char *concat = (char *)malloc(bannerLength + messageLength + 1); 272 | if (!concat) { 273 | free(banner); 274 | free(message); 275 | m_error = m_oom; 276 | return; 277 | } 278 | 279 | memcpy(concat, banner, bannerLength); 280 | memcpy(concat + bannerLength, message, messageLength + 1); // +1 for '\0' 281 | free(banner); 282 | free(message); 283 | 284 | m_error = concat; 285 | m_strings.push_back(m_error); 286 | } 287 | 288 | #undef TYPENAME 289 | #define TYPENAME(X) case kKeyword_##X: 290 | bool parser::isBuiltin() const { 291 | if (!isType(kType_keyword)) 292 | return false; 293 | switch (m_token.asKeyword) { 294 | #include "lexemes.h" 295 | return true; 296 | default: 297 | break; 298 | } 299 | return false; 300 | } 301 | #undef TYPENAME 302 | #define TYPENAME(...) 303 | 304 | /// The parser entry point 305 | CHECK_RETURN astTU *parser::parse(int type) { 306 | m_ast = new astTU(type); 307 | m_scopes.push_back(scope()); 308 | for (;;) { 309 | m_lexer.read(m_token, true); 310 | 311 | if (m_lexer.error()) { 312 | fatal("%s", m_lexer.error()); 313 | return 0; 314 | } 315 | 316 | if (isType(kType_eof)) { 317 | break; 318 | } 319 | 320 | if (isType(kType_directive)) { 321 | if (m_token.asDirective.type == directive::kVersion) { 322 | if (m_ast->versionDirective) { 323 | fatal("Multiple version directives not allowed"); 324 | return 0; 325 | } 326 | astVersionDirective *directive = GC_NEW(astVersionDirective) astVersionDirective(); 327 | directive->version = m_token.asDirective.asVersion.version; 328 | directive->type = m_token.asDirective.asVersion.type; 329 | m_ast->versionDirective = directive; 330 | } else if (m_token.asDirective.type == directive::kExtension) { 331 | astExtensionDirective *extension = GC_NEW(astExtensionDirective) astExtensionDirective(); 332 | extension->behavior = m_token.asDirective.asExtension.behavior; 333 | extension->name = strnew(m_token.asDirective.asExtension.name); 334 | m_ast->extensionDirectives.push_back(extension); 335 | } 336 | continue; 337 | } 338 | 339 | vector items; 340 | if (!parseTopLevel(items)) 341 | return 0; 342 | 343 | if (isType(kType_semicolon)) { 344 | for (size_t i = 0; i < items.size(); i++) { 345 | topLevel &parse = items[i]; 346 | astGlobalVariable *global = GC_NEW(astVariable) astGlobalVariable(); 347 | global->storage = parse.storage; 348 | global->auxiliary = parse.auxiliary; 349 | global->memory = parse.memory; 350 | global->precision = parse.precision; 351 | global->interpolation = parse.interpolation; 352 | global->baseType = parse.type; 353 | global->name = strnew(parse.name); 354 | global->isInvariant = parse.isInvariant; 355 | global->isPrecise = parse.isPrecise; 356 | global->layoutQualifiers = parse.layoutQualifiers; 357 | if (parse.initialValue) { 358 | if (!(global->initialValue = evaluate(parse.initialValue))) 359 | return 0; 360 | } 361 | global->isArray = parse.isArray; 362 | global->arraySizes = parse.arraySizes; 363 | m_ast->globals.push_back(global); 364 | m_scopes.back().push_back(global); 365 | } 366 | } else if (isOperator(kOperator_paranthesis_begin)) { 367 | astFunction *function = parseFunction(items.front()); 368 | if (!function) 369 | return 0; 370 | m_ast->functions.push_back(function); 371 | } else if (isType(kType_whitespace)) { 372 | continue; // whitespace tokens will be used later for the preprocessor 373 | } else { 374 | fatal("syntax error at top level %d", m_token.asKeyword); 375 | return 0; 376 | } 377 | } 378 | return m_ast; 379 | } 380 | 381 | CHECK_RETURN bool parser::parseStorage(topLevel ¤t) { 382 | // const, in, out, attribute, uniform, varying, buffer, shared 383 | if (isKeyword(kKeyword_const)) { 384 | current.storage = kConst; 385 | if (!next()) return false; // skip 'const' 386 | } else if (isKeyword(kKeyword_in)) { 387 | current.storage = kIn; 388 | if (!next()) return false; // skip 'in' 389 | } else if (isKeyword(kKeyword_out)) { 390 | current.storage = kOut; 391 | if (!next()) return false; // skip 'out' 392 | } else if (isKeyword(kKeyword_attribute)) { 393 | current.storage = kAttribute; 394 | if (!next()) return false; // skip 'attribute' 395 | } else if (isKeyword(kKeyword_uniform)) { 396 | current.storage = kUniform; 397 | if (!next()) return false; // skip 'uniform' 398 | } else if (isKeyword(kKeyword_varying)) { 399 | current.storage = kVarying; 400 | if (!next()) return false; // skip 'varying' 401 | } else if (isKeyword(kKeyword_buffer)) { 402 | current.storage = kBuffer; 403 | if (!next()) return false; // skip 'buffer' 404 | } else if (isKeyword(kKeyword_shared)) { 405 | current.storage = kShared; 406 | if (!next()) return false; // skip 'shared' 407 | } 408 | return true; 409 | } 410 | 411 | CHECK_RETURN bool parser::parseAuxiliary(topLevel ¤t) { 412 | // centroid, sample, patch 413 | if (isKeyword(kKeyword_centroid)) { 414 | current.auxiliary = kCentroid; 415 | if (!next()) return false; // skip 'centroid' 416 | } else if (isKeyword(kKeyword_sample)) { 417 | current.auxiliary = kSample; 418 | if (!next()) return false; // skip 'sample' 419 | } else if (isKeyword(kKeyword_patch)) { 420 | current.auxiliary = kPatch; 421 | if (!next()) return false; // skip 'patch' 422 | } 423 | return true; 424 | } 425 | 426 | CHECK_RETURN bool parser::parseInterpolation(topLevel ¤t) { 427 | // smooth, flat, noperspective 428 | if (isKeyword(kKeyword_smooth)) { 429 | current.interpolation = kSmooth; 430 | if (!next()) return false; // skip 'smooth' 431 | } else if (isKeyword(kKeyword_flat)) { 432 | current.interpolation = kFlat; 433 | if (!next()) return false; // skip 'flat' 434 | } else if (isKeyword(kKeyword_noperspective)) { 435 | current.interpolation = kNoPerspective; 436 | if (!next()) return false; // skip 'noperspective' 437 | } 438 | return true; 439 | } 440 | 441 | CHECK_RETURN bool parser::parsePrecision(topLevel ¤t) { 442 | // highp, mediump, lowp 443 | if (isKeyword(kKeyword_highp)) { 444 | current.precision = kHighp; 445 | if (!next()) return false; // skip 'highp' 446 | } else if (isKeyword(kKeyword_mediump)) { 447 | current.precision = kMediump; 448 | if (!next()) return false; // skip 'mediump' 449 | } else if (isKeyword(kKeyword_lowp)) { 450 | current.precision = kLowp; 451 | if (!next()) return false; // skip 'lowp' 452 | } 453 | return true; 454 | } 455 | 456 | CHECK_RETURN bool parser::parseInvariant(topLevel ¤t) { 457 | // invariant 458 | if (isKeyword(kKeyword_invariant)) { 459 | current.isInvariant = true; 460 | if (!next()) return false; // skip 'invariant' 461 | } 462 | return true; 463 | } 464 | 465 | CHECK_RETURN bool parser::parsePrecise(topLevel ¤t) { 466 | // precise 467 | if (isKeyword(kKeyword_precise)) { 468 | current.isPrecise = true; 469 | if (!next()) return false; // skip 'precise' 470 | } 471 | return true; 472 | } 473 | 474 | CHECK_RETURN bool parser::parseMemory(topLevel ¤t) { 475 | // coherent, volatile, restrict, readonly, writeonly 476 | if (isKeyword(kKeyword_coherent)) { 477 | current.memory |= kCoherent; 478 | if (!next()) return false; // skip 'coherent' 479 | } else if (isKeyword(kKeyword_volatile)) { 480 | current.memory |= kVolatile; 481 | if (!next()) return false; // skip 'volatile' 482 | } else if (isKeyword(kKeyword_restrict)) { 483 | current.memory |= kRestrict; 484 | if (!next()) return false; // skip 'restrict' 485 | } else if (isKeyword(kKeyword_readonly)) { 486 | current.memory |= kReadOnly; 487 | if (!next()) return false; // skip 'readonly' 488 | } else if (isKeyword(kKeyword_writeonly)) { 489 | current.memory |= kWriteOnly; 490 | if (!next()) return false; // skip 'writeonly; 491 | } 492 | return true; 493 | } 494 | 495 | static struct { 496 | const char *qualifier; 497 | bool isAssign; 498 | } kLayoutQualifiers[] = { 499 | { "shared", false }, 500 | { "packed", false }, 501 | { "std140", false }, 502 | { "row_major", false }, 503 | { "column_major", false }, 504 | { "binding", true }, 505 | { "offset", true }, 506 | { "align", true }, 507 | { "location", true }, 508 | { "component", true }, 509 | { "index", true }, 510 | { "triangles", false }, 511 | { "quads", false }, 512 | { "isolines", false }, 513 | { "equal_spacing", false }, 514 | { "fractional_even_spacing", false }, 515 | { "fractional_odd_spacing", false }, 516 | { "cw", false }, 517 | { "ccw", false }, 518 | { "point_mode", false }, 519 | { "points", false }, 520 | { "lines", false }, 521 | { "lines_adjacency", false }, 522 | { "triangles_adjacency", false }, 523 | { "invocations", true }, 524 | { "origin_upper_left", false }, 525 | { "pixel_center_integer", false }, 526 | { "early_fragment_tests", false }, 527 | { "local_size_x", true }, 528 | { "local_size_y", true }, 529 | { "local_size_z", true }, 530 | { "xfb_buffer", true }, 531 | { "xfb_stride", true }, 532 | { "xfb_offset", true }, 533 | { "vertices", true }, 534 | { "line_strip", false }, 535 | { "triangle_strip", false }, 536 | { "max_vertices", true }, 537 | { "stream", true }, 538 | { "depth_any", false }, 539 | { "depth_greater", false }, 540 | { "depth_less", false }, 541 | { "depth_unchanged", false } 542 | }; 543 | 544 | CHECK_RETURN bool parser::parseLayout(topLevel ¤t) { 545 | vector &qualifiers = current.layoutQualifiers; 546 | if (isKeyword(kKeyword_layout)) { 547 | if (!next()) // skip 'layout' 548 | return false; 549 | if (!isOperator(kOperator_paranthesis_begin)) { 550 | fatal("expected `(' after `layout'"); 551 | return false; 552 | } 553 | if (!next()) // skip '(' 554 | return false; 555 | while (!isOperator(kOperator_paranthesis_end)) { 556 | astLayoutQualifier *qualifier = GC_NEW(astLayoutQualifier) astLayoutQualifier(); 557 | 558 | // "The tokens used for layout-qualifier-name are identifiers, 559 | // not keywords, however, the shared keyword is allowed as a 560 | // layout-qualifier-id." 561 | if (!isType(kType_identifier) && !isKeyword(kKeyword_shared)) 562 | return false; 563 | 564 | int found = -1; 565 | qualifier->name = strnew(isType(kType_identifier) ? m_token.asIdentifier : "shared"); 566 | for (size_t i = 0; i < sizeof(kLayoutQualifiers)/sizeof(kLayoutQualifiers[0]); i++) { 567 | if (strcmp(qualifier->name, kLayoutQualifiers[i].qualifier)) 568 | continue; 569 | found = int(i); 570 | break; 571 | } 572 | 573 | if (found == -1) { 574 | fatal("unknown layout qualifier `%s'", qualifier->name); 575 | return false; 576 | } 577 | 578 | if (!next()) // skip identifier or 'shared' keyword 579 | return false; 580 | 581 | if (isOperator(kOperator_assign)) { 582 | if (!kLayoutQualifiers[found].isAssign) { 583 | fatal("unexpected layout qualifier value on `%s' layout qualifier", qualifier->name); 584 | return false; 585 | } 586 | if (!next()) // skip '=' 587 | return false; 588 | if (!(qualifier->initialValue = parseExpression(kEndConditionComma | kEndConditionParanthesis))) 589 | return false; 590 | if (!isConstant(qualifier->initialValue)) { 591 | // TODO: check integer-constant-expression 592 | fatal("value for layout qualifier `%s' is not a valid constant expression", 593 | qualifier->name); 594 | return false; 595 | } 596 | if (!(qualifier->initialValue = evaluate(qualifier->initialValue))) 597 | return false; 598 | } else if (kLayoutQualifiers[found].isAssign) { 599 | fatal("expected layout qualifier value for `%s' layout qualifier", qualifier->name); 600 | return false; 601 | } 602 | 603 | if (isOperator(kOperator_comma)) { 604 | if (!next()) // skip ',' 605 | return false; 606 | } 607 | qualifiers.push_back(qualifier); 608 | } 609 | if (!next()) // skip ')' 610 | return false; 611 | } 612 | return true; 613 | } 614 | 615 | static bool isInterfaceBlockStorage(int storage) { 616 | return storage == kIn 617 | || storage == kOut 618 | || storage == kUniform 619 | || storage == kBuffer; 620 | } 621 | 622 | static bool isReservedKeyword(int keyword) { 623 | return keyword == kKeyword_common 624 | || keyword == kKeyword_partition 625 | || keyword == kKeyword_active 626 | || keyword == kKeyword_asm 627 | || keyword == kKeyword_class 628 | || keyword == kKeyword_union 629 | || keyword == kKeyword_enum 630 | || keyword == kKeyword_typedef 631 | || keyword == kKeyword_template 632 | || keyword == kKeyword_this 633 | || keyword == kKeyword_resource 634 | || keyword == kKeyword_goto 635 | || keyword == kKeyword_inline 636 | || keyword == kKeyword_noinline 637 | || keyword == kKeyword_public 638 | || keyword == kKeyword_static 639 | || keyword == kKeyword_extern 640 | || keyword == kKeyword_external 641 | || keyword == kKeyword_interface 642 | || keyword == kKeyword_long 643 | || keyword == kKeyword_short 644 | || keyword == kKeyword_half 645 | || keyword == kKeyword_fixed 646 | || keyword == kKeyword_unsigned 647 | || keyword == kKeyword_superp 648 | || keyword == kKeyword_input 649 | || keyword == kKeyword_output 650 | || keyword == kKeyword_hvec2 651 | || keyword == kKeyword_hvec3 652 | || keyword == kKeyword_hvec4 653 | || keyword == kKeyword_fvec2 654 | || keyword == kKeyword_fvec3 655 | || keyword == kKeyword_fvec4 656 | || keyword == kKeyword_sampler3DRect 657 | || keyword == kKeyword_filter 658 | || keyword == kKeyword_sizeof 659 | || keyword == kKeyword_cast 660 | || keyword == kKeyword_namespace 661 | || keyword == kKeyword_using; 662 | } 663 | 664 | CHECK_RETURN bool parser::parseTopLevelItem(topLevel &level, topLevel *continuation) { 665 | vector items; 666 | while (!isBuiltin() && !isType(kType_identifier)) { 667 | // If this is an empty file don't get caught in this loop indefinitely 668 | token peek = m_lexer.peek(); 669 | if (IS_TYPE(peek, kType_eof)) 670 | return false; 671 | 672 | topLevel item; 673 | if (continuation) 674 | item = *continuation; 675 | 676 | if (!parseStorage(item)) return false; 677 | if (!parseAuxiliary(item)) return false; 678 | if (!parseInterpolation(item)) return false; 679 | if (!parsePrecision(item)) return false; 680 | if (!parseInvariant(item)) return false; 681 | if (!parsePrecise(item)) return false; 682 | if (!parseMemory(item)) return false; 683 | if (!parseLayout(item)) return false; 684 | 685 | if (isType(kType_keyword) && isReservedKeyword(m_token.asKeyword)) { 686 | fatal("cannot use a reserved keyword"); 687 | return false; 688 | } 689 | 690 | // Check for interface block. 691 | if (isType(kType_identifier) && isInterfaceBlockStorage(item.storage)) { 692 | // if (!next()) return false; // skip identifier 693 | astInterfaceBlock *unique = parseInterfaceBlock(item.storage); 694 | if (!unique) 695 | return false; 696 | m_ast->interfaceBlocks.push_back(unique); 697 | if (isType(kType_semicolon)) { 698 | return true; 699 | } else { 700 | level.type = unique; 701 | } 702 | } else if (isKeyword(kKeyword_struct)) { 703 | if (!next()) return 0; // skip struct 704 | astStruct *unique = parseStruct(); 705 | if (!unique) 706 | return false; 707 | m_ast->structures.push_back(unique); 708 | if (isType(kType_semicolon)) 709 | { 710 | return true; 711 | } else { 712 | level.type = unique; 713 | } 714 | } else { 715 | items.push_back(item); 716 | } 717 | } 718 | 719 | if (continuation) { 720 | level = *continuation; 721 | // erase anything that is not an array size on the type, e.g 722 | // int[2] a[2], b; should produce: int a[2][2]; int b[2]; 723 | level.arraySizes.erase(level.arraySizes.begin() + level.arrayOnTypeOffset, level.arraySizes.end()); 724 | } 725 | 726 | for (size_t i = 0; i < items.size(); i++) { 727 | topLevel &next = items[i]; 728 | const int storage = level.storage != -1 ? level.storage : next.storage; 729 | if (m_ast->type == astTU::kVertex && storage == kIn) { 730 | // "It's a compile-time error to use any auxiliary or interpolation 731 | // qualifiers on a vertex shader input" 732 | if (level.auxiliary != -1 || next.auxiliary != -1) { 733 | fatal("cannot use auxiliary storage qualifier on vertex shader input"); 734 | return false; 735 | } else if (level.interpolation != -1 || next.interpolation != -1) { 736 | fatal("cannot use interpolation qualifier on vertex shader input"); 737 | return false; 738 | } 739 | } 740 | if (m_ast->type == astTU::kFragment && storage == kOut) { 741 | // "It's a compile-time error to use auxiliary storage qualifiers or 742 | // interpolation qualifiers on an output in a fragment shader." 743 | if (level.auxiliary != -1 || next.auxiliary != -1) { 744 | fatal("cannot use auxiliary storage qualifier on fragment shader output"); 745 | return false; 746 | } else if (level.interpolation != -1 || next.interpolation != -1) { 747 | fatal("cannot use interpolation qualifier on fragment shader output"); 748 | return false; 749 | } 750 | } 751 | if (m_ast->type != astTU::kTessEvaluation && storage == kIn) { 752 | // "Applying the patch qualifier to inputs can only be done in tessellation 753 | // evaluation shaders. It is a compile-time error to use patch with inputs 754 | // in any other stage." 755 | if (level.auxiliary == kPatch || next.auxiliary == kPatch) { 756 | fatal("applying `patch' qualifier to input can only be done in tessellation evaluation shaders"); 757 | return false; 758 | } 759 | } 760 | if (m_ast->type != astTU::kTessControl && storage == kOut) { 761 | // "Applying patch to an output can only be done in a tessellation control 762 | // shader. It is a compile-time errot to use patch on outputs in any 763 | // other stage." 764 | if (level.auxiliary == kPatch || next.auxiliary == kPatch) { 765 | fatal("applying `patch' qualifier to output can only be done in tessellation control shaders"); 766 | return false; 767 | } 768 | } 769 | if (next.storage != -1 && level.storage != -1) { 770 | fatal("multiple storage qualifiers in declaration"); 771 | return false; 772 | } else if (next.auxiliary != -1 && level.auxiliary != -1) { 773 | fatal("multiple auxiliary storage qualifiers in declaration"); 774 | return false; 775 | } else if (next.interpolation != -1 && level.interpolation != -1) { 776 | fatal("multiple interpolation qualifiers in declaration"); 777 | return false; 778 | } if (next.precision != -1 && level.precision != -1) { 779 | fatal("multiple precision qualifiers in declaration"); 780 | return false; 781 | } 782 | level.storage = next.storage; 783 | level.auxiliary = next.auxiliary; 784 | level.interpolation = next.interpolation; 785 | level.precision = next.precision; 786 | level.memory |= next.memory; 787 | 788 | for (size_t i = 0; i < next.layoutQualifiers.size(); i++) { 789 | // "When the same layout-qualifier-name occurs multiple times, in a single declaration, the 790 | // last occurrence overrides the former occurrence(s)" 791 | for (size_t j = 0; i < level.layoutQualifiers.size(); j++) { 792 | if (next.layoutQualifiers[i]->name == level.layoutQualifiers[j]->name) 793 | level.layoutQualifiers.erase(level.layoutQualifiers.begin() + j); 794 | } 795 | level.layoutQualifiers.push_back(next.layoutQualifiers[i]); 796 | } 797 | } 798 | 799 | // "It's a compile-time error to use interpolation qualifiers with patch" 800 | if (level.auxiliary == kPatch && level.interpolation != -1) { 801 | fatal("cannot use interpolation qualifier with auxiliary storage qualifier `patch'"); 802 | return false; 803 | } 804 | 805 | if (!continuation && !level.type) { 806 | if (isType(kType_identifier)) { 807 | level.type = findType(m_token.asIdentifier); 808 | if (!next()) // skip identifier 809 | return false; 810 | } else { 811 | level.type = parseBuiltin(); 812 | if (!next()) // skip typename 813 | return false; 814 | } 815 | 816 | if (level.type) { 817 | // Could be an array 818 | while (isOperator(kOperator_bracket_begin)) { 819 | level.isArray = true; 820 | astConstantExpression *arraySize = parseArraySize(); 821 | if (!arraySize) 822 | return false; 823 | level.arraySizes.insert(level.arraySizes.begin(), arraySize); 824 | level.arrayOnTypeOffset++; 825 | if (!next()) // skip ']' 826 | return false; 827 | } 828 | } 829 | } 830 | 831 | if (!level.type) { 832 | fatal("expected typename"); 833 | return false; 834 | } 835 | 836 | if (isType(kType_identifier)) { 837 | level.name = strnew(m_token.asIdentifier); 838 | if (!next())// skip identifier 839 | return false; 840 | } 841 | 842 | while (isOperator(kOperator_bracket_begin)) { 843 | level.isArray = true; 844 | level.arraySizes.push_back(parseArraySize()); 845 | if (!next()) // skip ']' 846 | return false; 847 | } 848 | 849 | if (level.storage == kConst || level.storage == kUniform) { 850 | // Can have a constant expression assignment 851 | if (isOperator(kOperator_assign)) { 852 | if (!next()) // skip '=' 853 | return false; 854 | if (!(level.initialValue = parseExpression(kEndConditionSemicolon))) 855 | return false; 856 | if (!isConstant(level.initialValue)) { 857 | fatal("not a valid constant expression"); 858 | return false; 859 | } 860 | } else if (level.storage != kUniform) { 861 | fatal("const-qualified variable declared but not initialized"); 862 | return false; 863 | } 864 | } 865 | 866 | // If it isn't a function or prototype than the use of void is not legal 867 | if (!isOperator(kOperator_paranthesis_begin)) { 868 | if (level.type->builtin && ((astBuiltin*)level.type)->type == kKeyword_void) { 869 | fatal("`void' cannot be used in declaration"); 870 | return false; 871 | } 872 | } 873 | 874 | // if it doesn't have a name than it's illegal 875 | if (strnil(level.name)) { 876 | fatal("expected name for declaration"); 877 | return false; 878 | } 879 | 880 | return true; 881 | } 882 | 883 | CHECK_RETURN bool parser::parseTopLevel(vector &items) { 884 | topLevel item; 885 | if (!parseTopLevelItem(item)) 886 | return false; 887 | if (item.type) 888 | items.push_back(item); 889 | while (items.size() && isOperator(kOperator_comma)) { 890 | if (!next()) 891 | return false; // skip ',' 892 | topLevel nextItem; 893 | if (!parseTopLevelItem(nextItem, &items.front())) 894 | return false; 895 | if (nextItem.type) 896 | items.push_back(nextItem); 897 | } 898 | return true; 899 | } 900 | 901 | template 902 | CHECK_RETURN T *parser::parseBlock(const char* type) { 903 | T *unique = GC_NEW(astType) T; 904 | 905 | if (isType(kType_identifier)) { 906 | unique->name = strnew(m_token.asIdentifier); 907 | if (!next()) return 0; // skip identifier 908 | } 909 | 910 | if (!isType(kType_scope_begin)) { 911 | fatal("expected '{' for %s definition", type); 912 | return 0; 913 | } 914 | 915 | if (!next()) return 0; // skip '{' 916 | 917 | vector items; 918 | while (!isType(kType_scope_end)) { 919 | if (!parseTopLevel(items)) 920 | return 0; 921 | if (!next()) 922 | return 0; 923 | } 924 | 925 | for (size_t i = 0; i < items.size(); i++) { 926 | topLevel &parse = items[i]; 927 | astVariable *field = GC_NEW(astVariable) astVariable(astVariable::kField); 928 | field->baseType = parse.type; 929 | field->name = strnew(parse.name); 930 | field->isPrecise = parse.isPrecise; 931 | field->isArray = parse.isArray; 932 | field->arraySizes = parse.arraySizes; 933 | unique->fields.push_back(field); 934 | } 935 | 936 | if (!next()) return 0; // skip '}' 937 | 938 | return unique; 939 | } 940 | 941 | CHECK_RETURN astStruct *parser::parseStruct() { 942 | return parseBlock("structure"); 943 | } 944 | 945 | CHECK_RETURN astInterfaceBlock *parser::parseInterfaceBlock(int storage) { 946 | astInterfaceBlock* unique = 0; 947 | switch (storage) { 948 | case kIn: 949 | unique = parseBlock("input block"); 950 | break; 951 | case kOut: 952 | unique = parseBlock("outout block"); 953 | break; 954 | case kUniform: 955 | unique = parseBlock("uniform block"); 956 | break; 957 | case kBuffer: 958 | unique = parseBlock("buffer block"); 959 | break; 960 | } 961 | 962 | if (!unique) { 963 | return 0; 964 | } 965 | 966 | // When there's no identifier then implicitly declare these as globals 967 | // in their respective places. 968 | if (!isType(kType_identifier)) { 969 | const size_t n_fields = unique->fields.size(); 970 | for (size_t i = 0; i < n_fields; i++) { 971 | // Check if the variable already exists 972 | astVariable *variable = unique->fields[i]; 973 | if (findVariable(variable->name)) { 974 | fatal("'%s` is already declared in this scope", variable->name); 975 | return 0; 976 | } 977 | m_scopes.back().push_back(unique->fields[i]); 978 | } 979 | } 980 | 981 | unique->storage = storage; 982 | return unique; 983 | 984 | return 0; 985 | } 986 | 987 | CHECK_RETURN astExpression *parser::parseBinary(int lhsPrecedence, astExpression *lhs, endCondition end) { 988 | // Precedence climbing 989 | while (!isEndCondition(end)) { 990 | int binaryPrecedence = m_token.precedence(); 991 | if (binaryPrecedence < lhsPrecedence) 992 | break; 993 | 994 | astBinaryExpression *expression = createExpression(); 995 | if (!next()) 996 | return 0; 997 | 998 | astExpression *rhs = parseUnary(end); 999 | if (!rhs) 1000 | return 0; 1001 | if (!next()) 1002 | return 0; 1003 | 1004 | if (((astExpression*)expression)->type == astExpression::kAssign) { 1005 | astExpression *find = lhs; 1006 | while (find->type == astExpression::kArraySubscript 1007 | || find->type == astExpression::kFieldOrSwizzle) 1008 | { 1009 | find = (find->type == astExpression::kArraySubscript) 1010 | ? ((astArraySubscript*)find)->operand 1011 | : ((astFieldOrSwizzle*)find)->operand; 1012 | } 1013 | if (find->type != astExpression::kVariableIdentifier) { 1014 | fatal("not a valid lvalue"); 1015 | return 0; 1016 | } 1017 | astVariable *variable = ((astVariableIdentifier*)lhs)->variable; 1018 | if (variable->type == astVariable::kGlobal) { 1019 | astGlobalVariable *global = (astGlobalVariable*)variable; 1020 | // "It's a compile-time error to write to a variable declared as an input" 1021 | if (global->storage == kIn) { 1022 | fatal("cannot write to a variable declared as input"); 1023 | return 0; 1024 | } 1025 | // "It's a compile-time error to write to a const variable outside of its declaration." 1026 | if (global->storage == kConst) { 1027 | fatal("cannot write to a const variable outside of its declaration"); 1028 | return 0; 1029 | } 1030 | } 1031 | } 1032 | 1033 | int rhsPrecedence = m_token.precedence(); 1034 | 1035 | // climb 1036 | if (binaryPrecedence < rhsPrecedence) { 1037 | if (!(rhs = parseBinary(binaryPrecedence + 1, rhs, end))) 1038 | return 0; 1039 | } 1040 | 1041 | expression->operand1 = lhs; 1042 | expression->operand2 = rhs; 1043 | lhs = expression; 1044 | } 1045 | return lhs; 1046 | } 1047 | 1048 | CHECK_RETURN astExpression *parser::parseUnaryPrefix(endCondition condition) { 1049 | if (isOperator(kOperator_paranthesis_begin)) { 1050 | if (!next()) return 0; // skip '(' 1051 | return parseExpression(kEndConditionParanthesis); 1052 | } else if (isOperator(kOperator_logical_not)) { 1053 | if (!next()) return 0; // skip '!' 1054 | return GC_NEW(astExpression) astUnaryLogicalNotExpression(parseUnary(condition)); 1055 | } else if (isOperator(kOperator_bit_not)) { 1056 | if (!next()) return 0; // skip '~' 1057 | return GC_NEW(astExpression) astUnaryBitNotExpression(parseUnary(condition)); 1058 | } else if (isOperator(kOperator_plus)) { 1059 | if (!next()) return 0; // skip '+' 1060 | return GC_NEW(astExpression) astUnaryPlusExpression(parseUnary(condition)); 1061 | } else if (isOperator(kOperator_minus)) { 1062 | if (!next()) return 0; // skip '-' 1063 | return GC_NEW(astExpression) astUnaryMinusExpression(parseUnary(condition)); 1064 | } else if (isOperator(kOperator_increment)) { 1065 | if (!next()) return 0; // skip '++' 1066 | return GC_NEW(astExpression) astPrefixIncrementExpression(parseUnary(condition)); 1067 | } else if (isOperator(kOperator_decrement)) { 1068 | if (!next()) return 0; // skip '--' 1069 | return GC_NEW(astExpression) astPrefixDecrementExpression(parseUnary(condition)); 1070 | } else if (isBuiltin()) { 1071 | return parseConstructorCall(); 1072 | } else if (isType(kType_identifier)) { 1073 | token peek = m_lexer.peek(); 1074 | if (IS_OPERATOR(peek, kOperator_paranthesis_begin)) { 1075 | astType *type = findType(m_token.asIdentifier); 1076 | if (type) 1077 | return parseConstructorCall(); 1078 | else 1079 | return parseFunctionCall(); 1080 | } else { 1081 | astVariable *find = findVariable(m_token.asIdentifier); 1082 | if (find) 1083 | return GC_NEW(astExpression) astVariableIdentifier(find); 1084 | fatal("`%s' was not declared in this scope", m_token.asIdentifier); 1085 | return 0; 1086 | } 1087 | } else if (isKeyword(kKeyword_true)) { 1088 | return BCONST_NEW(true); 1089 | } else if (isKeyword(kKeyword_false)) { 1090 | return BCONST_NEW(false); 1091 | } else if (isType(kType_constant_int)) { 1092 | return ICONST_NEW(m_token.asInt); 1093 | } else if (isType(kType_constant_uint)) { 1094 | return UCONST_NEW(m_token.asUnsigned); 1095 | } else if (isType(kType_constant_float)) { 1096 | return FCONST_NEW(m_token.asFloat); 1097 | } else if (isType(kType_constant_double)) { 1098 | return DCONST_NEW(m_token.asDouble); 1099 | } else if (condition == kEndConditionBracket) { 1100 | return 0; 1101 | } 1102 | fatal("syntax error during unary prefix"); 1103 | return 0; 1104 | } 1105 | 1106 | astType* parser::getType(astExpression *expression) 1107 | { 1108 | switch (expression->type) 1109 | { 1110 | case astExpression::kVariableIdentifier: 1111 | return ((astVariableIdentifier*)expression)->variable->baseType; 1112 | case astExpression::kFieldOrSwizzle: 1113 | return getType(((astFieldOrSwizzle*)expression)->operand); 1114 | case astExpression::kArraySubscript: 1115 | return getType(((astArraySubscript*)expression)->operand); 1116 | case astExpression::kFunctionCall: 1117 | for (size_t i = 0; i < m_ast->functions.size(); i++) { 1118 | if (strcmp(m_ast->functions[i]->name, ((astFunctionCall*)expression)->name)) 1119 | continue; 1120 | return m_ast->functions[i]->returnType; 1121 | } 1122 | break; 1123 | case astExpression::kConstructorCall: 1124 | return ((astConstructorCall*)expression)->type; 1125 | } 1126 | return 0; 1127 | } 1128 | 1129 | CHECK_RETURN astExpression *parser::parseUnary(endCondition end) { 1130 | astExpression *operand = parseUnaryPrefix(end); 1131 | if (!operand) 1132 | return 0; 1133 | for (;;) { 1134 | token peek = m_lexer.peek(); 1135 | if (IS_OPERATOR(peek, kOperator_dot)) { 1136 | if (!next()) return 0; // skip last 1137 | if (!next()) return 0; // skip '.' 1138 | if (!isType(kType_identifier)) { 1139 | fatal("expected field identifier or swizzle after `.'"); 1140 | return 0; 1141 | } 1142 | astFieldOrSwizzle *expression = GC_NEW(astExpression) astFieldOrSwizzle(); 1143 | 1144 | astType *type = getType(operand); 1145 | if (type && !type->builtin) { 1146 | astVariable *field = 0; 1147 | astStruct *kind = (astStruct*)type; 1148 | for (size_t i = 0; i < kind->fields.size(); i++) { 1149 | if (strcmp(kind->fields[i]->name, m_token.asIdentifier)) 1150 | continue; 1151 | field = kind->fields[i]; 1152 | break; 1153 | } 1154 | if (!field) { 1155 | fatal("field `%s' does not exist in structure `%s'", m_token.asIdentifier, kind->name); 1156 | return 0; 1157 | } 1158 | } 1159 | 1160 | expression->operand = operand; 1161 | expression->name = strnew(m_token.asIdentifier); 1162 | operand = expression; 1163 | } else if (IS_OPERATOR(peek, kOperator_increment)) { 1164 | if (!next()) return 0; // skip last 1165 | operand = GC_NEW(astExpression) astPostIncrementExpression(operand); 1166 | } else if (IS_OPERATOR(peek, kOperator_decrement)) { 1167 | if (!next()) return 0; // skip last 1168 | operand = GC_NEW(astExpression) astPostDecrementExpression(operand); 1169 | } else if (IS_OPERATOR(peek, kOperator_bracket_begin)) { 1170 | if (!next()) return 0; // skip last 1171 | if (!next()) return 0; // skip '[' 1172 | astArraySubscript *expression = GC_NEW(astExpression) astArraySubscript(); 1173 | astExpression *find = operand; 1174 | while (find->type == astExpression::kArraySubscript) 1175 | find = ((astArraySubscript*)find)->operand; 1176 | if (find->type != astExpression::kVariableIdentifier) { 1177 | fatal("cannot be subscripted"); 1178 | return 0; 1179 | } 1180 | expression->operand = operand; 1181 | if (!(expression->index = parseExpression(kEndConditionBracket))) 1182 | return 0; 1183 | if (isConstant(expression->index)) { 1184 | if (!(expression->index = evaluate(expression->index))) 1185 | return 0; 1186 | } 1187 | operand = expression; 1188 | } else if (IS_OPERATOR(peek, kOperator_questionmark)) { 1189 | if (!next()) return 0; // skip last 1190 | if (!next()) return 0; // skip '?' 1191 | astTernaryExpression *expression = GC_NEW(astExpression) astTernaryExpression(); 1192 | expression->condition = operand; 1193 | expression->onTrue = parseExpression(kEndConditionColon); 1194 | if (!isOperator(kOperator_colon)) { 1195 | fatal("expected `:' for else case in ternary statement"); 1196 | return 0; 1197 | } 1198 | if (!next()) return 0; // skip ':' 1199 | if (!(expression->onFalse = parseUnary(end))) { 1200 | fatal("expected expression after `:' in ternary statement"); 1201 | return 0; 1202 | } 1203 | operand = expression; 1204 | } else { 1205 | break; 1206 | } 1207 | } 1208 | return operand; 1209 | } 1210 | 1211 | CHECK_RETURN astExpression *parser::parseExpression(endCondition condition) { 1212 | astExpression *lhs = parseUnary(condition); 1213 | if (!lhs) 1214 | return 0; 1215 | if (!next()) // skip last 1216 | return 0; 1217 | return parseBinary(0, lhs, condition); 1218 | } 1219 | 1220 | CHECK_RETURN astExpressionStatement *parser::parseExpressionStatement(endCondition condition) { 1221 | astExpression *expression = parseExpression(condition); 1222 | return expression ? GC_NEW(astStatement) astExpressionStatement(expression) : 0; 1223 | } 1224 | 1225 | CHECK_RETURN astConstantExpression *parser::parseArraySize() { 1226 | if (!next()) // skip '[' 1227 | return 0; 1228 | return parseExpression(kEndConditionBracket); 1229 | } 1230 | 1231 | CHECK_RETURN astCompoundStatement *parser::parseCompoundStatement() { 1232 | astCompoundStatement *statement = GC_NEW(astStatement) astCompoundStatement(); 1233 | if (!next()) // skip '{' 1234 | return 0; 1235 | while (!isType(kType_scope_end)) { 1236 | astStatement *nextStatement = parseStatement(); 1237 | if (!nextStatement) return 0; 1238 | statement->statements.push_back(nextStatement); 1239 | if (!next()) // skip ';' 1240 | return 0; 1241 | } 1242 | return statement; 1243 | } 1244 | 1245 | CHECK_RETURN astIfStatement *parser::parseIfStatement() { 1246 | astIfStatement *statement = GC_NEW(astStatement) astIfStatement(); 1247 | if (!next()) // skip 'if' 1248 | return 0; 1249 | if (!isOperator(kOperator_paranthesis_begin)) { 1250 | fatal("expected `(' after `if'"); 1251 | return 0; 1252 | } 1253 | if (!next()) // skip '(' 1254 | return 0; 1255 | if (!(statement->condition = parseExpression(kEndConditionParanthesis))) 1256 | return 0; 1257 | if (!next()) // skip ')' 1258 | return 0; 1259 | statement->thenStatement = parseStatement(); 1260 | token peek = m_lexer.peek(); 1261 | if (IS_KEYWORD(peek, kKeyword_else)) { 1262 | if (!next()) // skip ';' or '}' 1263 | return 0; 1264 | if (!next()) // skip 'else' 1265 | return 0; 1266 | if (!(statement->elseStatement = parseStatement())) 1267 | return 0; 1268 | } 1269 | return statement; 1270 | } 1271 | 1272 | CHECK_RETURN astSwitchStatement *parser::parseSwitchStatement() { 1273 | astSwitchStatement *statement = GC_NEW(astStatement) astSwitchStatement(); 1274 | if (!next()) // skip 'switch' 1275 | return 0; 1276 | if (!isOperator(kOperator_paranthesis_begin)) { 1277 | fatal("expected `(' after `switch'"); 1278 | return 0; 1279 | } 1280 | if (!next()) // skip '(' 1281 | return 0; 1282 | if (!(statement->expression = parseExpression(kEndConditionParanthesis))) 1283 | return 0; 1284 | if (!next()) // skip next 1285 | return 0; 1286 | if (!isType(kType_scope_begin)) { 1287 | fatal("expected `{' after `)'"); 1288 | return 0; 1289 | } 1290 | if (!next()) // skip '{' 1291 | return 0; 1292 | 1293 | vector seenInts; 1294 | vector seenUInts; 1295 | bool hadDefault = false; 1296 | while (!isType(kType_scope_end)) { 1297 | astStatement *nextStatement = parseStatement(); 1298 | if (!nextStatement) return 0; 1299 | if (nextStatement->type == astStatement::kCaseLabel) { 1300 | astCaseLabelStatement *caseLabel = (astCaseLabelStatement*)nextStatement; 1301 | if (!caseLabel->isDefault) { 1302 | if (!isConstant(caseLabel->condition)) { 1303 | fatal("case label is not a valid constant expression"); 1304 | return 0; 1305 | } 1306 | astConstantExpression *value = evaluate(caseLabel->condition); 1307 | // "It is a compile-time error to have two case label constant-expression of equal value" 1308 | if (value->type == astExpression::kIntConstant) { 1309 | const int val = IVAL(value); 1310 | if (glsl::find(seenInts.begin(), seenInts.end(), val) != seenInts.end()) { 1311 | fatal("duplicate case label `%d'", val); 1312 | return 0; 1313 | } 1314 | seenInts.push_back(val); 1315 | } else if (value->type == astExpression::kUIntConstant) { 1316 | const unsigned int val = UVAL(value); 1317 | if (glsl::find(seenUInts.begin(), seenUInts.end(), val) != seenUInts.end()) { 1318 | fatal("duplicate case label `%u'", val); 1319 | return 0; 1320 | } 1321 | seenUInts.push_back(val); 1322 | } else { 1323 | fatal("case label must be scalar `int' or `uint'"); 1324 | return 0; 1325 | } 1326 | } else { 1327 | // "It's a compile-time error to have more than one default" 1328 | if (hadDefault) { 1329 | fatal("duplicate `default' case label"); 1330 | return 0; 1331 | } 1332 | hadDefault = true; 1333 | } 1334 | } 1335 | statement->statements.push_back(nextStatement); 1336 | if (!next()) 1337 | return 0; 1338 | } 1339 | 1340 | // TODO: verify scope of where switches are found 1341 | return statement; 1342 | } 1343 | 1344 | CHECK_RETURN astCaseLabelStatement *parser::parseCaseLabelStatement() { 1345 | astCaseLabelStatement *statement = GC_NEW(astStatement) astCaseLabelStatement(); 1346 | if (isKeyword(kKeyword_default)) { 1347 | statement->isDefault = true; 1348 | if (!next()) // skip 'default' 1349 | return 0; 1350 | if (!isOperator(kOperator_colon)) { 1351 | fatal("expected `:' after `default' in case label"); 1352 | return 0; 1353 | } 1354 | } else { 1355 | if (!next()) // skip 'case' 1356 | return 0; 1357 | statement->condition = parseExpression(kEndConditionColon); 1358 | } 1359 | return statement; 1360 | } 1361 | 1362 | CHECK_RETURN astForStatement *parser::parseForStatement() { 1363 | astForStatement *statement = GC_NEW(astStatement) astForStatement(); 1364 | if (!next()) // skip 'for' 1365 | return 0; 1366 | if (!isOperator(kOperator_paranthesis_begin)) { 1367 | fatal("expected `(' after `for'"); 1368 | return 0; 1369 | } 1370 | if (!next()) // skip '(' 1371 | return 0; 1372 | if (!isType(kType_semicolon)) 1373 | if (!(statement->init = parseDeclarationOrExpressionStatement(kEndConditionSemicolon))) 1374 | return 0; 1375 | if (!next()) // skip ';' 1376 | return 0; 1377 | if (!isType(kType_semicolon)) 1378 | if (!(statement->condition = parseExpression(kEndConditionSemicolon))) 1379 | return 0; 1380 | if (!next()) // skip ';' 1381 | return 0; 1382 | if (!isOperator(kOperator_paranthesis_end)) { 1383 | if (!(statement->loop = parseExpression(kEndConditionParanthesis))) 1384 | return 0; 1385 | } 1386 | if (!next()) // skip ')' 1387 | return 0; 1388 | statement->body = parseStatement(); 1389 | return statement; 1390 | } 1391 | 1392 | CHECK_RETURN astContinueStatement *parser::parseContinueStatement() { 1393 | astContinueStatement *statement = GC_NEW(astStatement) astContinueStatement(); 1394 | if (!next()) // skip 'continue' 1395 | return 0; 1396 | return statement; 1397 | } 1398 | 1399 | CHECK_RETURN astBreakStatement *parser::parseBreakStatement() { 1400 | astBreakStatement *statement = GC_NEW(astStatement) astBreakStatement(); 1401 | if (!next()) 1402 | return 0; // skip 'break' 1403 | if (!isType(kType_semicolon)) { 1404 | fatal("expected semicolon after break statement"); 1405 | return 0; 1406 | } 1407 | return statement; 1408 | } 1409 | 1410 | CHECK_RETURN astDiscardStatement *parser::parseDiscardStatement() { 1411 | astDiscardStatement *statement = GC_NEW(astStatement) astDiscardStatement(); 1412 | if (!next()) // skip 'discard' 1413 | return 0; 1414 | if (!isType(kType_semicolon)) { 1415 | fatal("expected semicolon after discard statement"); 1416 | return 0; 1417 | } 1418 | return statement; 1419 | } 1420 | 1421 | CHECK_RETURN astReturnStatement *parser::parseReturnStatement() { 1422 | astReturnStatement *statement = GC_NEW(astStatement) astReturnStatement(); 1423 | if (!next()) // skip 'return' 1424 | return 0; 1425 | if (!isType(kType_semicolon)) { 1426 | if (!(statement->expression = parseExpression(kEndConditionSemicolon))) 1427 | return 0; 1428 | if (!isType(kType_semicolon)) { 1429 | fatal("expected semicolon after return statement"); 1430 | return 0; 1431 | } 1432 | } 1433 | return statement; 1434 | } 1435 | 1436 | CHECK_RETURN astDoStatement *parser::parseDoStatement() { 1437 | astDoStatement *statement = GC_NEW(astStatement) astDoStatement(); 1438 | if (!next()) // skip 'do' 1439 | return 0; 1440 | if (!(statement->body = parseStatement())) 1441 | return 0; 1442 | if (!next()) 1443 | return 0; 1444 | if (!isKeyword(kKeyword_while)) { 1445 | fatal("expected `while' after `do'"); 1446 | return 0; 1447 | } 1448 | if (!next()) // skip 'while' 1449 | return 0; 1450 | if (!isOperator(kOperator_paranthesis_begin)) { 1451 | fatal("expected `(' after `while'"); 1452 | return 0; 1453 | } 1454 | if (!next()) // skip '(' 1455 | return 0; 1456 | if (!(statement->condition = parseExpression(kEndConditionParanthesis))) 1457 | return 0; 1458 | if (!next()) 1459 | return 0; 1460 | return statement; 1461 | } 1462 | 1463 | CHECK_RETURN astWhileStatement *parser::parseWhileStatement() { 1464 | astWhileStatement *statement = GC_NEW(astStatement) astWhileStatement(); 1465 | if (!next()) // skip 'while' 1466 | return 0; 1467 | if (!isOperator(kOperator_paranthesis_begin)) { 1468 | fatal("expected `(' after `while'"); 1469 | return 0; 1470 | } 1471 | if (!next()) // skip '(' 1472 | return 0; 1473 | if (!(statement->condition = parseDeclarationOrExpressionStatement(kEndConditionParanthesis))) 1474 | return 0; 1475 | if (!next()) 1476 | return 0; 1477 | if (!(statement->body = parseStatement())) 1478 | return 0; 1479 | return statement; 1480 | } 1481 | 1482 | CHECK_RETURN astDeclarationStatement *parser::parseDeclarationStatement(endCondition condition) { 1483 | m_lexer.backup(); 1484 | 1485 | bool isConst = false; 1486 | if (isKeyword(kKeyword_const)) { 1487 | isConst = true; 1488 | if (!next()) // skip 'const' 1489 | return 0; 1490 | } 1491 | 1492 | astType *type = 0; 1493 | if (isBuiltin()) { 1494 | type = parseBuiltin(); 1495 | } else if (isType(kType_identifier)) { 1496 | type = findType(m_token.asIdentifier); 1497 | } 1498 | 1499 | if (!type) { 1500 | m_lexer.restore(); 1501 | return 0; 1502 | } 1503 | 1504 | if (!next()) 1505 | return 0; 1506 | 1507 | astDeclarationStatement *statement = GC_NEW(astStatement) astDeclarationStatement(); 1508 | for (;;) { 1509 | size_t paranthesisCount = 0; 1510 | while (isOperator(kOperator_paranthesis_begin)) { 1511 | paranthesisCount++; 1512 | if (!next()) // skip ',' 1513 | return 0; 1514 | } 1515 | if (!isType(kType_identifier)) { 1516 | m_lexer.restore(); 1517 | return 0; 1518 | } 1519 | 1520 | const char *name = strnew(m_token.asIdentifier); 1521 | if (!next()) // skip identifier 1522 | return 0; 1523 | 1524 | for (size_t i = 0; i < paranthesisCount; i++) { 1525 | if (!isOperator(kOperator_paranthesis_end)) { 1526 | m_lexer.restore(); 1527 | return 0; 1528 | } 1529 | if (!next()) 1530 | return 0; 1531 | } 1532 | 1533 | if (statement->variables.empty() && !isOperator(kOperator_assign) 1534 | && !isOperator(kOperator_comma) && !isEndCondition(condition)) 1535 | { 1536 | m_lexer.restore(); 1537 | return 0; 1538 | } 1539 | 1540 | astExpression *initialValue = 0; 1541 | if (isOperator(kOperator_assign)) { 1542 | if (!next()) // skip '=' 1543 | return 0; 1544 | if (!(initialValue = parseExpression(kEndConditionComma | condition))) 1545 | return 0; 1546 | } 1547 | 1548 | astFunctionVariable *variable = GC_NEW(astVariable) astFunctionVariable(); 1549 | variable->isConst = isConst; 1550 | variable->baseType = type; 1551 | variable->name = strnew(name); 1552 | variable->initialValue = initialValue; 1553 | statement->variables.push_back(variable); 1554 | m_scopes.back().push_back(variable); 1555 | 1556 | if (isEndCondition(condition)) { 1557 | break; 1558 | } else if (isOperator(kOperator_comma)) { 1559 | if (!next()) // skip ',' 1560 | return 0; 1561 | } else if (isOperator(kOperator_bracket_begin)) { 1562 | while (isOperator(kOperator_bracket_begin)) { 1563 | variable->isArray = true; 1564 | astConstantExpression *arraySize = parseArraySize(); 1565 | if (!arraySize) 1566 | return 0; 1567 | variable->arraySizes.push_back(arraySize); 1568 | if (!next()) // skip ']' 1569 | return 0; 1570 | } 1571 | } else { 1572 | fatal("syntax error during declaration statement"); 1573 | return 0; 1574 | } 1575 | } 1576 | 1577 | return statement; 1578 | } 1579 | 1580 | CHECK_RETURN astSimpleStatement *parser::parseDeclarationOrExpressionStatement(endCondition condition) { 1581 | astSimpleStatement *declaration = parseDeclarationStatement(condition); 1582 | if (declaration) { 1583 | return declaration; 1584 | } else { 1585 | return parseExpressionStatement(condition); 1586 | } 1587 | } 1588 | 1589 | CHECK_RETURN astStatement *parser::parseStatement() { 1590 | if (isType(kType_scope_begin)) { 1591 | return parseCompoundStatement(); 1592 | } else if (isKeyword(kKeyword_if)) { 1593 | return parseIfStatement(); 1594 | } else if (isKeyword(kKeyword_switch)) { 1595 | return parseSwitchStatement(); 1596 | } else if (isKeyword(kKeyword_case) || isKeyword(kKeyword_default)) { 1597 | return parseCaseLabelStatement(); 1598 | } else if (isKeyword(kKeyword_for)) { 1599 | return parseForStatement(); 1600 | } else if (isKeyword(kKeyword_do)) { 1601 | return parseDoStatement(); 1602 | } else if (isKeyword(kKeyword_while)) { 1603 | return parseWhileStatement(); 1604 | } else if (isKeyword(kKeyword_continue)) { 1605 | return parseContinueStatement(); 1606 | } else if (isKeyword(kKeyword_break)) { 1607 | return parseBreakStatement(); 1608 | } else if (isKeyword(kKeyword_discard)) { 1609 | return parseDiscardStatement(); 1610 | } else if (isKeyword(kKeyword_return)) { 1611 | return parseReturnStatement(); 1612 | } else if (isType(kType_semicolon)) { 1613 | return GC_NEW(astStatement) astEmptyStatement(); 1614 | } else { 1615 | return parseDeclarationOrExpressionStatement(kEndConditionSemicolon); 1616 | } 1617 | } 1618 | 1619 | CHECK_RETURN astFunction *parser::parseFunction(const topLevel &parse) { 1620 | astFunction *function = GC_NEW(astFunction) astFunction(); 1621 | function->returnType = parse.type; 1622 | function->name = strnew(parse.name); 1623 | 1624 | if (!next()) // skip '(' 1625 | return 0; 1626 | while (!isOperator(kOperator_paranthesis_end)) { 1627 | astFunctionParameter *parameter = GC_NEW(astVariable) astFunctionParameter(); 1628 | while (!isOperator(kOperator_comma) && !isOperator(kOperator_paranthesis_end)) { 1629 | if (isKeyword(kKeyword_in)) { 1630 | parameter->storage = kIn; 1631 | } else if (isKeyword(kKeyword_out)) { 1632 | parameter->storage = kOut; 1633 | } else if (isKeyword(kKeyword_inout)) { 1634 | parameter->storage = kInOut; 1635 | } else if (isKeyword(kKeyword_highp)) { 1636 | parameter->precision = kHighp; 1637 | } else if (isKeyword(kKeyword_mediump)) { 1638 | parameter->precision = kMediump; 1639 | } else if (isKeyword(kKeyword_lowp)) { 1640 | parameter->precision = kLowp; 1641 | } else if (isKeyword(kKeyword_coherent)) { 1642 | parameter->memory = kCoherent; 1643 | } else if (isKeyword(kKeyword_volatile)) { 1644 | parameter->memory = kVolatile; 1645 | } else if (isKeyword(kKeyword_restrict)) { 1646 | parameter->memory = kRestrict; 1647 | } else if (isKeyword(kKeyword_readonly)) { 1648 | parameter->memory = kReadOnly; 1649 | } else if (isKeyword(kKeyword_writeonly)) { 1650 | parameter->memory = kWriteOnly; 1651 | } else if (isType(kType_identifier)) { 1652 | // TODO: user defined types 1653 | parameter->name = strnew(m_token.asIdentifier); 1654 | } else if (isOperator(kOperator_bracket_begin)) { 1655 | while (isOperator(kOperator_bracket_begin)) { 1656 | parameter->isArray = true; 1657 | astConstantExpression *arraySize = parseArraySize(); 1658 | if (!arraySize) 1659 | return 0; 1660 | parameter->arraySizes.push_back(arraySize); 1661 | } 1662 | } else { 1663 | parameter->baseType = parseBuiltin(); 1664 | if (parameter->baseType && parameter->baseType->builtin) { 1665 | astBuiltin *builtin = (astBuiltin*)parameter->baseType; 1666 | if (builtin->type == kKeyword_void && !strnil(parameter->name)) { 1667 | fatal("`void' parameter cannot be named"); 1668 | return 0; 1669 | } 1670 | } 1671 | } 1672 | if (!next()) 1673 | return 0; 1674 | } 1675 | 1676 | if (!parameter->baseType) { 1677 | fatal("expected type"); 1678 | return 0; 1679 | } 1680 | function->parameters.push_back(parameter); 1681 | if (isOperator(kOperator_comma)) { 1682 | if (!next())// skip ',' 1683 | return 0; 1684 | } 1685 | } 1686 | if (!next()) // skip ')' 1687 | return 0; 1688 | 1689 | // If there is just one 'void' than silently drop it 1690 | if (function->parameters.size() == 1) { 1691 | if (function->parameters[0]->baseType->builtin) { 1692 | astBuiltin *builtin = (astBuiltin*)function->parameters[0]->baseType; 1693 | if (builtin->type == kKeyword_void) 1694 | function->parameters.pop_back(); 1695 | } 1696 | } 1697 | 1698 | // "It is a compile-time or link-time error to declare or define a function main with any other parameters or 1699 | // return type." 1700 | if (!strcmp(function->name, "main")) { 1701 | if (!function->parameters.empty()) { 1702 | fatal("`main' cannot have parameters"); 1703 | return 0; 1704 | } 1705 | if (!function->returnType->builtin || ((astBuiltin*)function->returnType)->type != kKeyword_void) { 1706 | fatal("`main' must be declared to return void"); 1707 | return 0; 1708 | } 1709 | } 1710 | 1711 | if (isType(kType_scope_begin)) { 1712 | function->isPrototype = false; 1713 | if (!next()) // skip '{' 1714 | return 0; 1715 | 1716 | m_scopes.push_back(scope()); 1717 | for (size_t i = 0; i < function->parameters.size(); i++) 1718 | m_scopes.back().push_back(function->parameters[i]); 1719 | while (!isType(kType_scope_end)) { 1720 | astStatement *statement = parseStatement(); 1721 | if (!statement) 1722 | return 0; 1723 | function->statements.push_back(statement); 1724 | if (!next())// skip ';' 1725 | return 0; 1726 | } 1727 | 1728 | m_scopes.pop_back(); 1729 | } else if (isType(kType_semicolon)) { 1730 | function->isPrototype = true; 1731 | } else { 1732 | fatal("expected `{' or `;'"); 1733 | return 0; 1734 | } 1735 | return function; 1736 | } 1737 | 1738 | // TODO: cleanup 1739 | #undef TYPENAME 1740 | #define TYPENAME(X) case kKeyword_##X: 1741 | astBuiltin *parser::parseBuiltin() { 1742 | if (!isType(kType_keyword)) { 1743 | fatal("expected keyword"); 1744 | return 0; 1745 | } 1746 | 1747 | switch (m_token.asKeyword) { 1748 | #include "lexemes.h" 1749 | for (size_t i = 0; i < m_builtins.size(); i++) { 1750 | if (m_builtins[i]->type == m_token.asKeyword) { 1751 | return m_builtins[i]; 1752 | } 1753 | } 1754 | m_builtins.push_back(GC_NEW(astType) astBuiltin(m_token.asKeyword)); 1755 | return m_builtins.back(); 1756 | break; 1757 | default: 1758 | break; 1759 | } 1760 | fatal("internal compiler error: attempted to parse as builtin type"); 1761 | return 0; 1762 | } 1763 | #undef TYPENAME 1764 | 1765 | CHECK_RETURN astConstructorCall *parser::parseConstructorCall() { 1766 | astConstructorCall *expression = GC_NEW(astExpression) astConstructorCall(); 1767 | if (!(expression->type = parseBuiltin())) 1768 | return 0; 1769 | if (!next()) 1770 | return 0; 1771 | if (!isOperator(kOperator_paranthesis_begin)) { 1772 | fatal("expected `(' for constructor call"); 1773 | return 0; 1774 | } 1775 | if (!next()) // skip '(' 1776 | return 0; 1777 | while (!isOperator(kOperator_paranthesis_end)) { 1778 | astExpression *parameter = parseExpression(kEndConditionComma | kEndConditionParanthesis); 1779 | if (!parameter) 1780 | return 0; 1781 | expression->parameters.push_back(parameter); 1782 | if (isOperator(kOperator_comma)) { 1783 | if (!next()) // skip ',' 1784 | return 0; 1785 | } 1786 | } 1787 | return expression; 1788 | } 1789 | 1790 | CHECK_RETURN astFunctionCall *parser::parseFunctionCall() { 1791 | astFunctionCall *expression = GC_NEW(astExpression) astFunctionCall(); 1792 | expression->name = strnew(m_token.asIdentifier); 1793 | if (!next()) // skip identifier 1794 | return 0; 1795 | if (!isOperator(kOperator_paranthesis_begin)) { 1796 | fatal("expected `(' for function call"); 1797 | return 0; 1798 | } 1799 | if (!next()) return 0; // skip '(' 1800 | while (!isOperator(kOperator_paranthesis_end)) { 1801 | astExpression *parameter = parseExpression(kEndConditionComma | kEndConditionParanthesis); 1802 | if (!parameter) 1803 | return 0; 1804 | expression->parameters.push_back(parameter); 1805 | if (isOperator(kOperator_comma)) { 1806 | if (!next()) // skip ',' 1807 | return 0; 1808 | } 1809 | } 1810 | return expression; 1811 | } 1812 | 1813 | CHECK_RETURN bool parser::next() { 1814 | m_lexer.read(m_token, true); 1815 | if (isType(kType_eof)) { 1816 | fatal("premature end of file"); 1817 | return false; 1818 | } 1819 | if (m_lexer.error()) { 1820 | fatal("%s", m_lexer.error()); 1821 | return false; 1822 | } 1823 | return true; 1824 | } 1825 | 1826 | astBinaryExpression *parser::createExpression() { 1827 | if (!isType(kType_operator)) { 1828 | fatal("internal compiler error: attempted to create binary expression in wrong context"); 1829 | return 0; 1830 | } 1831 | 1832 | switch (m_token.asOperator) { 1833 | case kOperator_multiply: 1834 | case kOperator_divide: 1835 | case kOperator_modulus: 1836 | case kOperator_plus: 1837 | case kOperator_minus: 1838 | case kOperator_shift_left: 1839 | case kOperator_shift_right: 1840 | case kOperator_less: 1841 | case kOperator_greater: 1842 | case kOperator_less_equal: 1843 | case kOperator_greater_equal: 1844 | case kOperator_equal: 1845 | case kOperator_not_equal: 1846 | case kOperator_bit_and: 1847 | case kOperator_bit_xor: 1848 | case kOperator_logical_and: 1849 | case kOperator_logical_xor: 1850 | case kOperator_logical_or: 1851 | return GC_NEW(astExpression) astOperationExpression(m_token.asOperator); 1852 | case kOperator_assign: 1853 | case kOperator_add_assign: 1854 | case kOperator_sub_assign: 1855 | case kOperator_multiply_assign: 1856 | case kOperator_divide_assign: 1857 | case kOperator_modulus_assign: 1858 | case kOperator_shift_left_assign: 1859 | case kOperator_shift_right_assign: 1860 | case kOperator_bit_and_assign: 1861 | case kOperator_bit_xor_assign: 1862 | case kOperator_bit_or_assign: 1863 | return GC_NEW(astExpression) astAssignmentExpression(m_token.asOperator); 1864 | case kOperator_comma: 1865 | return GC_NEW(astExpression) astSequenceExpression(); 1866 | default: 1867 | return 0; 1868 | } 1869 | } 1870 | 1871 | astType *parser::findType(const char *name) { 1872 | for (size_t i = 0; i < m_ast->structures.size(); i++) { 1873 | if (strcmp(m_ast->structures[i]->name, name)) 1874 | continue; 1875 | return (astType*)m_ast->structures[i]; 1876 | } 1877 | return 0; 1878 | } 1879 | 1880 | astVariable *parser::findVariable(const char *identifier) { 1881 | for (size_t scopeIndex = m_scopes.size(); scopeIndex > 0; scopeIndex--) { 1882 | scope &s = m_scopes[scopeIndex - 1]; 1883 | for (size_t variableIndex = 0; variableIndex < s.size(); variableIndex++) { 1884 | if (!strcmp(s[variableIndex]->name, identifier)) 1885 | return s[variableIndex]; 1886 | } 1887 | } 1888 | return 0; 1889 | } 1890 | 1891 | const char *parser::error() const { 1892 | return m_error; 1893 | } 1894 | 1895 | } 1896 | -------------------------------------------------------------------------------- /parser.h: -------------------------------------------------------------------------------- 1 | #ifndef PARSE_HDR 2 | #define PARSE_HDR 3 | #include "lexer.h" 4 | #include "ast.h" 5 | 6 | namespace glsl { 7 | 8 | #if __GNUC__ >= 4 9 | # define CHECK_RETURN __attribute__((warn_unused_result)) 10 | #elif _MSC_VER >= 1700 11 | # define CHECK_RETURN _Check_return_ 12 | #else 13 | # define CHECK_RETURN 14 | #endif 15 | 16 | struct topLevel { 17 | topLevel() 18 | : storage(-1) 19 | , auxiliary(-1) 20 | , memory(0) 21 | , precision(-1) 22 | , interpolation(-1) 23 | , type(0) 24 | , initialValue(0) 25 | , arrayOnTypeOffset(0) 26 | , isInvariant(false) 27 | , isPrecise(false) 28 | , isArray(false) 29 | { 30 | } 31 | 32 | int storage; 33 | int auxiliary; 34 | int memory; 35 | int precision; 36 | int interpolation; 37 | astType *type; 38 | astConstantExpression *initialValue; 39 | vector arraySizes; 40 | size_t arrayOnTypeOffset; 41 | vector layoutQualifiers; 42 | bool isInvariant; 43 | bool isPrecise; 44 | bool isArray; 45 | char *name; 46 | }; 47 | 48 | struct parser { 49 | ~parser(); 50 | parser(const char *source, const char *fileName); 51 | CHECK_RETURN astTU *parse(int type); 52 | 53 | const char *error() const; 54 | 55 | protected: 56 | void cleanup(); 57 | 58 | enum { 59 | kEndConditionSemicolon = 1 << 0, 60 | kEndConditionParanthesis = 1 << 1, 61 | kEndConditionBracket = 1 << 2, 62 | kEndConditionColon = 1 << 3, 63 | kEndConditionComma = 1 << 4 64 | }; 65 | 66 | typedef int endCondition; 67 | 68 | CHECK_RETURN bool next(); 69 | 70 | CHECK_RETURN bool parseStorage(topLevel ¤t); // const, in, out, attribute, uniform, varying, buffer, shared 71 | CHECK_RETURN bool parseAuxiliary(topLevel ¤t); // centroid, sample, patch 72 | CHECK_RETURN bool parseInterpolation(topLevel ¤t); // smooth, flat, noperspective 73 | CHECK_RETURN bool parsePrecision(topLevel ¤t); // highp, mediump, lowp 74 | CHECK_RETURN bool parseInvariant(topLevel ¤t); // invariant 75 | CHECK_RETURN bool parsePrecise(topLevel ¤t); // precise 76 | CHECK_RETURN bool parseMemory(topLevel ¤t); // coherent, volatile, restrict, readonly, writeonly 77 | CHECK_RETURN bool parseLayout(topLevel ¤t); 78 | 79 | CHECK_RETURN bool parseTopLevelItem(topLevel &level, topLevel *continuation = 0); 80 | CHECK_RETURN bool parseTopLevel(vector &top); 81 | 82 | CHECK_RETURN bool isType(int type) const; 83 | CHECK_RETURN bool isKeyword(int keyword) const; 84 | CHECK_RETURN bool isOperator(int oper) const; 85 | CHECK_RETURN bool isEndCondition(endCondition condition) const; 86 | CHECK_RETURN bool isBuiltin() const; 87 | 88 | CHECK_RETURN bool isConstantValue(astExpression *expression) const; 89 | CHECK_RETURN bool isConstant(astExpression *expression) const; 90 | 91 | void fatal(const char *fmt, ...); 92 | 93 | CHECK_RETURN astConstantExpression *evaluate(astExpression *expression); 94 | 95 | // Type parsers 96 | astBuiltin *parseBuiltin(); 97 | astStruct *parseStruct(); 98 | astInterfaceBlock *parseInterfaceBlock(int storage); 99 | 100 | CHECK_RETURN astFunction *parseFunction(const topLevel &parse); 101 | 102 | // Call parsers 103 | CHECK_RETURN astConstructorCall *parseConstructorCall(); 104 | CHECK_RETURN astFunctionCall *parseFunctionCall(); 105 | 106 | // Expression parsers 107 | CHECK_RETURN astExpression *parseExpression(endCondition end); 108 | CHECK_RETURN astExpression *parseUnary(endCondition end); 109 | CHECK_RETURN astExpression *parseBinary(int lhsPrecedence, astExpression *lhs, endCondition condition); 110 | CHECK_RETURN astExpression *parseUnaryPrefix(endCondition end); 111 | CHECK_RETURN astConstantExpression *parseArraySize(); 112 | 113 | // Statement parsers 114 | CHECK_RETURN astStatement *parseStatement(); 115 | CHECK_RETURN astSwitchStatement *parseSwitchStatement(); 116 | CHECK_RETURN astCaseLabelStatement *parseCaseLabelStatement(); 117 | CHECK_RETURN astForStatement *parseForStatement(); 118 | CHECK_RETURN astCompoundStatement *parseCompoundStatement(); 119 | CHECK_RETURN astIfStatement *parseIfStatement(); 120 | CHECK_RETURN astSimpleStatement *parseDeclarationOrExpressionStatement(endCondition condition); 121 | CHECK_RETURN astDeclarationStatement *parseDeclarationStatement(endCondition condition); 122 | CHECK_RETURN astExpressionStatement *parseExpressionStatement(endCondition condition); 123 | CHECK_RETURN astContinueStatement *parseContinueStatement(); 124 | CHECK_RETURN astBreakStatement *parseBreakStatement(); 125 | CHECK_RETURN astDiscardStatement *parseDiscardStatement(); 126 | CHECK_RETURN astReturnStatement *parseReturnStatement(); 127 | CHECK_RETURN astDoStatement *parseDoStatement(); 128 | CHECK_RETURN astWhileStatement *parseWhileStatement(); 129 | 130 | astBinaryExpression *createExpression(); 131 | 132 | astType *findType(const char *identifier); 133 | astVariable *findVariable(const char *identifier); 134 | astType* getType(astExpression *expression); 135 | private: 136 | typedef vector scope; 137 | 138 | // Specialized in .cpp 139 | template 140 | CHECK_RETURN T *parseBlock(const char* type); 141 | 142 | astTU *m_ast; 143 | lexer m_lexer; 144 | token m_token; 145 | vector m_scopes; 146 | vector m_builtins; 147 | char *m_error; 148 | char *m_oom; 149 | const char *m_fileName; 150 | 151 | void strdel(char **what) { 152 | if (!*what) 153 | return; 154 | free(*what); 155 | *what = 0; 156 | } 157 | 158 | char *strnew(const char *what) { 159 | if (!what) 160 | return 0; 161 | size_t length = strlen(what) + 1; 162 | char *copy = (char*)malloc(length); 163 | memcpy(copy, what, length); 164 | m_strings.push_back(copy); 165 | return copy; 166 | } 167 | 168 | bool strnil(const char *what) { 169 | return !what || !*what; 170 | } 171 | 172 | vector m_memory; // Memory of AST held here 173 | vector m_strings; // Memory of strings held here 174 | }; 175 | 176 | } 177 | 178 | #endif 179 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | 3 | from glob import glob 4 | import os 5 | import subprocess 6 | from itertools import zip_longest 7 | 8 | def main(): 9 | test_dir_name = 'tests' 10 | repo_dir = os.path.dirname(os.path.realpath(__file__)) 11 | test_dir = os.path.join(repo_dir, test_dir_name) 12 | parser = os.path.join(repo_dir, 'glsl-parser') 13 | 14 | for name in sorted(glob(os.path.join(test_dir, '*.glsl'))): 15 | base = os.path.splitext(name)[0] 16 | 17 | if not os.path.isfile(base + '.glsl'): 18 | print('failed to find source file for `%s\'' % name) 19 | continue 20 | if not os.path.isfile(base + '.test') and not os.path.islink(base + '.test'): 21 | print('failed to find test file for `%s\'' % name) 22 | continue 23 | 24 | with open(base + '.test') as test: 25 | errors = [] 26 | # Run the parser from the root directory with a relative 27 | # input path to the GLSL file to ensure that error output 28 | # paths match the expected results. 29 | input_path = os.path.join(test_dir_name, os.path.basename(name)) 30 | process = subprocess.Popen([parser, input_path], 31 | stdout=subprocess.PIPE, 32 | stderr=subprocess.STDOUT, 33 | cwd=repo_dir) 34 | 35 | for line1, line2 in zip_longest(test, process.stdout): 36 | line1 = line1.strip() if line1 else '' 37 | line2 = line2.decode('utf-8').strip() if line2 else '' 38 | expect = line1 if line1 else '' 39 | got = line2 if line2 else '' 40 | if expect != got: 41 | errors.append("expected `%s' got `%s'" % (expect, got)) 42 | print('%s: %s' % (name, 'failed' if len(errors) else 'passed')) 43 | for error in errors: 44 | print(' %s' % error) 45 | 46 | 47 | if __name__ == "__main__": 48 | main() 49 | -------------------------------------------------------------------------------- /tests/arrays.glsl: -------------------------------------------------------------------------------- 1 | float a[1]; 2 | float b[1][2]; 3 | float c[1][2][3]; 4 | float d[1][2][3][4]; 5 | float[2] e[3]; // float[2][3] 6 | float[3][2] f; // float[2][3] 7 | // structure array! 8 | struct foo1 { float a; }; 9 | foo1 bar1[1][2]; 10 | foo1[1] bar2[2]; 11 | foo1[1] aa[1], bb; 12 | -------------------------------------------------------------------------------- /tests/arrays.test: -------------------------------------------------------------------------------- 1 | struct foo1 { 2 | float a; 3 | }; 4 | float a[1]; 5 | float b[1][2]; 6 | float c[1][2][3]; 7 | float d[1][2][3][4]; 8 | float e[2][3]; 9 | float f[2][3]; 10 | foo1 bar1[1][2]; 11 | foo1 bar2[1][2]; 12 | foo1 aa[1][1]; 13 | foo1 bb[1]; 14 | -------------------------------------------------------------------------------- /tests/booleans.glsl: -------------------------------------------------------------------------------- 1 | void test() { 2 | bool test_uninitialized; 3 | bool test_true_initialized = true; 4 | bool test_false_initialized = false; 5 | bool test_assign; 6 | test_assign = test_true_initialized; 7 | test_assign = test_false_initialized; 8 | test_assign = true; 9 | test_assign = false; 10 | } 11 | -------------------------------------------------------------------------------- /tests/booleans.test: -------------------------------------------------------------------------------- 1 | void test() { 2 | bool test_uninitialized; 3 | bool test_true_initialized = true; 4 | bool test_false_initialized = false; 5 | bool test_assign; 6 | test_assign = test_true_initialized; 7 | test_assign = test_false_initialized; 8 | test_assign = true; 9 | test_assign = false; 10 | } 11 | -------------------------------------------------------------------------------- /tests/builtin_types.glsl: -------------------------------------------------------------------------------- 1 | bool test_bool; 2 | int test_int; 3 | uint test_uint; 4 | float test_float; 5 | double test_double; 6 | vec2 test_vec2; 7 | vec3 test_vec3; 8 | vec4 test_vec4; 9 | dvec2 test_dvec2; 10 | dvec3 test_dvec3; 11 | dvec4 test_dvec4; 12 | bvec2 test_bvec2; 13 | bvec3 test_bvec3; 14 | bvec4 test_bvec4; 15 | ivec2 test_ivec2; 16 | ivec3 test_ivec3; 17 | ivec4 test_ivec4; 18 | uvec2 test_uvec2; 19 | uvec3 test_uvec3; 20 | uvec4 test_uvec4; 21 | mat2 test_mat2; 22 | mat3 test_mat3; 23 | mat4 test_mat4; 24 | mat2x2 test_mat2x2; 25 | mat2x3 test_mat2x3; 26 | mat2x4 test_mat2x4; 27 | mat3x2 test_mat3x2; 28 | mat3x3 test_mat3x3; 29 | mat3x4 test_mat3x4; 30 | mat4x2 test_mat4x2; 31 | mat4x3 test_mat4x3; 32 | mat4x4 test_mat4x4; 33 | dmat2 test_dmat2; 34 | dmat3 test_dmat3; 35 | dmat4 test_dmat4; 36 | dmat2x2 test_dmat2x2; 37 | dmat2x3 test_dmat2x3; 38 | dmat2x4 test_dmat2x4; 39 | dmat3x2 test_dmat3x2; 40 | dmat3x3 test_dmat3x3; 41 | dmat3x4 test_dmat3x4; 42 | dmat4x2 test_dmat4x2; 43 | dmat4x3 test_dmat4x3; 44 | dmat4x4 test_dmat4x4; 45 | sampler1D test_sampler1D; 46 | image1D test_image1D; 47 | sampler2D test_sampler2D; 48 | image2D test_image2D; 49 | sampler3D test_sampler3D; 50 | image3D test_image3D; 51 | samplerCube test_samplerCube; 52 | imageCube test_imageCube; 53 | sampler2DRect test_sampler2DRect; 54 | image2DRect test_image2DRect; 55 | sampler1DArray test_sampler1DArray; 56 | image1DArray test_image1DArray; 57 | sampler2DArray test_sampler2DArray; 58 | image2DArray test_image2DArray; 59 | samplerBuffer test_samplerBuffer; 60 | imageBuffer test_imageBuffer; 61 | sampler2DMS test_sampler2DMS; 62 | image2DMS test_image2DMS; 63 | sampler2DMSArray test_sampler2DMSArray; 64 | image2DMSArray test_image2DMSArray; 65 | samplerCubeArray test_samplerCubeArray; 66 | imageCubeArray test_imageCubeArray; 67 | sampler1DShadow test_sampler1DShadow; 68 | sampler2DShadow test_sampler2DShadow; 69 | sampler2DRectShadow test_sampler2DRectShadow; 70 | sampler1DArrayShadow test_sampler1DArrayShadow; 71 | sampler2DArrayShadow test_sampler2DArrayShadow; 72 | samplerCubeShadow test_samplerCubeShadow; 73 | samplerCubeArrayShadow test_samplerCubeArrayShadow; 74 | isampler1D test_isampler1D; 75 | iimage1D test_iimage1D; 76 | isampler2D test_isampler2D; 77 | iimage2D test_iimage2D; 78 | isampler3D test_isampler3D; 79 | iimage3D test_iimage3D; 80 | isamplerCube test_isamplerCube; 81 | iimageCube test_iimageCube; 82 | isampler2DRect test_isampler2DRect; 83 | iimage2DRect test_iimage2DRect; 84 | isampler1DArray test_isampler1DArray; 85 | iimage1DArray test_iimage1DArray; 86 | isampler2DArray test_isampler2DArray; 87 | iimage2DArray test_iimage2DArray; 88 | isamplerBuffer test_isamplerBuffer; 89 | iimageBuffer test_iimageBuffer; 90 | isampler2DMS test_isampler2DMS; 91 | iimage2DMS test_iimage2DMS; 92 | isampler2DMSArray test_isampler2DMSArray; 93 | iimage2DMSArray test_iimage2DMSArray; 94 | isamplerCubeArray test_isamplerCubeArray; 95 | iimageCubeArray test_iimageCubeArray; 96 | atomic_uint test_atomic_uint; 97 | usampler1D test_usampler1D; 98 | uimage1D test_uimage1D; 99 | usampler2D test_usampler2D; 100 | uimage2D test_uimage2D; 101 | usampler3D test_usampler3D; 102 | uimage3D test_uimage3D; 103 | usamplerCube test_usamplerCube; 104 | uimageCube test_uimageCube; 105 | usampler2DRect test_usampler2DRect; 106 | uimage2DRect test_uimage2DRect; 107 | usampler1DArray test_usampler1DArray; 108 | uimage1DArray test_uimage1DArray; 109 | usampler2DArray test_usampler2DArray; 110 | uimage2DArray test_uimage2DArray; 111 | usamplerBuffer test_usamplerBuffer; 112 | uimageBuffer test_uimageBuffer; 113 | usampler2DMS test_usampler2DMS; 114 | uimage2DMS test_uimage2DMS; 115 | usampler2DMSArray test_usampler2DMSArray; 116 | uimage2DMSArray test_uimage2DMSArray; 117 | usamplerCubeArray test_usamplerCubeArray; 118 | uimageCubeArray test_uimageCubeArray; 119 | -------------------------------------------------------------------------------- /tests/builtin_types.test: -------------------------------------------------------------------------------- 1 | bool test_bool; 2 | int test_int; 3 | uint test_uint; 4 | float test_float; 5 | double test_double; 6 | vec2 test_vec2; 7 | vec3 test_vec3; 8 | vec4 test_vec4; 9 | dvec2 test_dvec2; 10 | dvec3 test_dvec3; 11 | dvec4 test_dvec4; 12 | bvec2 test_bvec2; 13 | bvec3 test_bvec3; 14 | bvec4 test_bvec4; 15 | ivec2 test_ivec2; 16 | ivec3 test_ivec3; 17 | ivec4 test_ivec4; 18 | uvec2 test_uvec2; 19 | uvec3 test_uvec3; 20 | uvec4 test_uvec4; 21 | mat2 test_mat2; 22 | mat3 test_mat3; 23 | mat4 test_mat4; 24 | mat2x2 test_mat2x2; 25 | mat2x3 test_mat2x3; 26 | mat2x4 test_mat2x4; 27 | mat3x2 test_mat3x2; 28 | mat3x3 test_mat3x3; 29 | mat3x4 test_mat3x4; 30 | mat4x2 test_mat4x2; 31 | mat4x3 test_mat4x3; 32 | mat4x4 test_mat4x4; 33 | dmat2 test_dmat2; 34 | dmat3 test_dmat3; 35 | dmat4 test_dmat4; 36 | dmat2x2 test_dmat2x2; 37 | dmat2x3 test_dmat2x3; 38 | dmat2x4 test_dmat2x4; 39 | dmat3x2 test_dmat3x2; 40 | dmat3x3 test_dmat3x3; 41 | dmat3x4 test_dmat3x4; 42 | dmat4x2 test_dmat4x2; 43 | dmat4x3 test_dmat4x3; 44 | dmat4x4 test_dmat4x4; 45 | sampler1D test_sampler1D; 46 | image1D test_image1D; 47 | sampler2D test_sampler2D; 48 | image2D test_image2D; 49 | sampler3D test_sampler3D; 50 | image3D test_image3D; 51 | samplerCube test_samplerCube; 52 | imageCube test_imageCube; 53 | sampler2DRect test_sampler2DRect; 54 | image2DRect test_image2DRect; 55 | sampler1DArray test_sampler1DArray; 56 | image1DArray test_image1DArray; 57 | sampler2DArray test_sampler2DArray; 58 | image2DArray test_image2DArray; 59 | samplerBuffer test_samplerBuffer; 60 | imageBuffer test_imageBuffer; 61 | sampler2DMS test_sampler2DMS; 62 | image2DMS test_image2DMS; 63 | sampler2DMSArray test_sampler2DMSArray; 64 | image2DMSArray test_image2DMSArray; 65 | samplerCubeArray test_samplerCubeArray; 66 | imageCubeArray test_imageCubeArray; 67 | sampler1DShadow test_sampler1DShadow; 68 | sampler2DShadow test_sampler2DShadow; 69 | sampler2DRectShadow test_sampler2DRectShadow; 70 | sampler1DArrayShadow test_sampler1DArrayShadow; 71 | sampler2DArrayShadow test_sampler2DArrayShadow; 72 | samplerCubeShadow test_samplerCubeShadow; 73 | samplerCubeArrayShadow test_samplerCubeArrayShadow; 74 | isampler1D test_isampler1D; 75 | iimage1D test_iimage1D; 76 | isampler2D test_isampler2D; 77 | iimage2D test_iimage2D; 78 | isampler3D test_isampler3D; 79 | iimage3D test_iimage3D; 80 | isamplerCube test_isamplerCube; 81 | iimageCube test_iimageCube; 82 | isampler2DRect test_isampler2DRect; 83 | iimage2DRect test_iimage2DRect; 84 | isampler1DArray test_isampler1DArray; 85 | iimage1DArray test_iimage1DArray; 86 | isampler2DArray test_isampler2DArray; 87 | iimage2DArray test_iimage2DArray; 88 | isamplerBuffer test_isamplerBuffer; 89 | iimageBuffer test_iimageBuffer; 90 | isampler2DMS test_isampler2DMS; 91 | iimage2DMS test_iimage2DMS; 92 | isampler2DMSArray test_isampler2DMSArray; 93 | iimage2DMSArray test_iimage2DMSArray; 94 | isamplerCubeArray test_isamplerCubeArray; 95 | iimageCubeArray test_iimageCubeArray; 96 | atomic_uint test_atomic_uint; 97 | usampler1D test_usampler1D; 98 | uimage1D test_uimage1D; 99 | usampler2D test_usampler2D; 100 | uimage2D test_uimage2D; 101 | usampler3D test_usampler3D; 102 | uimage3D test_uimage3D; 103 | usamplerCube test_usamplerCube; 104 | uimageCube test_uimageCube; 105 | usampler2DRect test_usampler2DRect; 106 | uimage2DRect test_uimage2DRect; 107 | usampler1DArray test_usampler1DArray; 108 | uimage1DArray test_uimage1DArray; 109 | usampler2DArray test_usampler2DArray; 110 | uimage2DArray test_uimage2DArray; 111 | usamplerBuffer test_usamplerBuffer; 112 | uimageBuffer test_uimageBuffer; 113 | usampler2DMS test_usampler2DMS; 114 | uimage2DMS test_uimage2DMS; 115 | usampler2DMSArray test_usampler2DMSArray; 116 | uimage2DMSArray test_uimage2DMSArray; 117 | usamplerCubeArray test_usamplerCubeArray; 118 | uimageCubeArray test_uimageCubeArray; 119 | -------------------------------------------------------------------------------- /tests/comments.glsl: -------------------------------------------------------------------------------- 1 | // Single line line-comment 2 | 3 | /* Single line block-comment */ 4 | 5 | /* Multiline 6 | * block-comment 7 | */ 8 | 9 | ; 10 | -------------------------------------------------------------------------------- /tests/comments.test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/graphitemaster/glsl-parser/8fd08ed39973b268953cb4a7100097613e0134a0/tests/comments.test -------------------------------------------------------------------------------- /tests/constants.glsl: -------------------------------------------------------------------------------- 1 | const float test = 1; 2 | const float test_neg = -1; 3 | const float test_pos_two_sub = test - test_neg; 4 | const float test_neg_two_sub = test_neg - test; 5 | const float test_zero_add = test_neg + test; 6 | -------------------------------------------------------------------------------- /tests/constants.test: -------------------------------------------------------------------------------- 1 | const float test = 1; 2 | const float test_neg = -1; 3 | const float test_pos_two_sub = 2; 4 | const float test_neg_two_sub = -2; 5 | const float test_zero_add = 0; 6 | -------------------------------------------------------------------------------- /tests/continuations.glsl: -------------------------------------------------------------------------------- 1 | mat4 model, view, projection; 2 | struct foo { float x; } a, b, c, d; 3 | -------------------------------------------------------------------------------- /tests/continuations.test: -------------------------------------------------------------------------------- 1 | struct foo { 2 | float x; 3 | }; 4 | mat4 model; 5 | mat4 view; 6 | mat4 projection; 7 | foo a; 8 | foo b; 9 | foo c; 10 | foo d; 11 | -------------------------------------------------------------------------------- /tests/directives.glsl: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | #extension all : enable 3 | -------------------------------------------------------------------------------- /tests/directives.test: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | #extension all : enable 3 | -------------------------------------------------------------------------------- /tests/do_statement.glsl: -------------------------------------------------------------------------------- 1 | void test() { 2 | do a(); while (true); 3 | do { } while (true); 4 | } 5 | -------------------------------------------------------------------------------- /tests/do_statement.test: -------------------------------------------------------------------------------- 1 | void test() { 2 | do a(); 3 | while(true); 4 | do { 5 | } 6 | while(true); 7 | } 8 | -------------------------------------------------------------------------------- /tests/first_character_invalid.glsl: -------------------------------------------------------------------------------- 1 | ` 2 | -------------------------------------------------------------------------------- /tests/first_character_invalid.test: -------------------------------------------------------------------------------- 1 | tests/first_character_invalid.glsl:1:1: error: invalid character encountered 2 | -------------------------------------------------------------------------------- /tests/floating_point_literals.glsl: -------------------------------------------------------------------------------- 1 | void test() { 2 | float test_float_uninitialized; 3 | float test_float_initialized = 1.5; 4 | float test_float_f_lower = 1.5f; 5 | float test_float_f_upper = 1.5F; 6 | double test_double_uininitialized; 7 | double test_double_initialized = 1.5; 8 | double test_double_lf_lower = 1.5lf; 9 | double test_double_lf_upper = 1.5LF; 10 | float test_float_f_zero = 1.0f; 11 | } 12 | -------------------------------------------------------------------------------- /tests/floating_point_literals.test: -------------------------------------------------------------------------------- 1 | void test() { 2 | float test_float_uninitialized; 3 | float test_float_initialized = 1.5; 4 | float test_float_f_lower = 1.5; 5 | float test_float_f_upper = 1.5; 6 | double test_double_uininitialized; 7 | double test_double_initialized = 1.5; 8 | double test_double_lf_lower = 1.5; 9 | double test_double_lf_upper = 1.5; 10 | float test_float_f_zero = 1.0; 11 | } 12 | -------------------------------------------------------------------------------- /tests/for_statement.glsl: -------------------------------------------------------------------------------- 1 | void main() { 2 | int i = 0; 3 | for(;;) { } 4 | for(i = 0;; ) { } 5 | for(int i = 0; i < 10;) { } 6 | for(int i = 0; i < 10; i++) { } 7 | } 8 | -------------------------------------------------------------------------------- /tests/for_statement.test: -------------------------------------------------------------------------------- 1 | void main() { 2 | int i = 0; 3 | for(;;) { 4 | } 5 | for(i = 0;;) { 6 | } 7 | for(int i = 0; (i < 10);) { 8 | } 9 | for(int i = 0; (i < 10); i++) { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/integer_literals.glsl: -------------------------------------------------------------------------------- 1 | void test() { 2 | int test_uninitialized_int; 3 | int test_initialized_int = 42; 4 | uint test_uninitialized_uint; 5 | uint test_initialized_uint_no_suffix = 42; 6 | uint test_initialized_uint_suffix = 42u; 7 | uint test_hex_no_suffix_upper = 0xFF; 8 | uint test_hex_suffix_upper = 0xFFu; 9 | uint test_hex_no_suffix_lower = 0xff; 10 | uint test_hex_suffix_lower = 0xffu; 11 | uint test_hex_no_suffix_mixed = 0xFf; 12 | uint test_hex_suffix_mixed = 0xFfU; 13 | int test_negative = -1; 14 | uint test_octal = 0777; 15 | } 16 | -------------------------------------------------------------------------------- /tests/integer_literals.test: -------------------------------------------------------------------------------- 1 | void test() { 2 | int test_uninitialized_int; 3 | int test_initialized_int = 42; 4 | uint test_uninitialized_uint; 5 | uint test_initialized_uint_no_suffix = 42; 6 | uint test_initialized_uint_suffix = 42u; 7 | uint test_hex_no_suffix_upper = 255; 8 | uint test_hex_suffix_upper = 255u; 9 | uint test_hex_no_suffix_lower = 255; 10 | uint test_hex_suffix_lower = 255u; 11 | uint test_hex_no_suffix_mixed = 255; 12 | uint test_hex_suffix_mixed = 255u; 13 | int test_negative = -1; 14 | uint test_octal = 511; 15 | } 16 | -------------------------------------------------------------------------------- /tests/interface_blocks.glsl: -------------------------------------------------------------------------------- 1 | uniform uniform_block { float x; }; 2 | in input_block { float y; }; 3 | out output_block { float z; }; 4 | buffer buffer_block { float w; }; 5 | 6 | // same thing with instance names 7 | uniform uniform_block { float x; } uniform_data; 8 | in input_block { float y; } input_data; 9 | out output_block { float z; } output_data; 10 | buffer buffer_block { float w; } buffer_data; -------------------------------------------------------------------------------- /tests/interface_blocks.test: -------------------------------------------------------------------------------- 1 | uniform uniform_block { 2 | float x; 3 | }; 4 | in input_block { 5 | float y; 6 | }; 7 | out output_block { 8 | float z; 9 | }; 10 | buffer buffer_block { 11 | float w; 12 | }; 13 | uniform uniform_block { 14 | float x; 15 | }; 16 | in input_block { 17 | float y; 18 | }; 19 | out output_block { 20 | float z; 21 | }; 22 | buffer buffer_block { 23 | float w; 24 | }; 25 | uniform_block uniform_data; 26 | input_block input_data; 27 | output_block output_data; 28 | buffer_block buffer_data; -------------------------------------------------------------------------------- /tests/sequence.glsl: -------------------------------------------------------------------------------- 1 | void test() { 2 | 1, 2, 3, 4; 3 | 1, 2, (3, 4); 4 | 1, (2, 3, 4); 5 | (1, 2), 3, 4; 6 | (1, 2, 3), 4; 7 | (1, 2, (3, 4)); 8 | (1, (2, 3, 4)); 9 | ((1, 2), 3, 4); 10 | ((1, 2, 3), 4); 11 | } 12 | -------------------------------------------------------------------------------- /tests/sequence.test: -------------------------------------------------------------------------------- 1 | void test() { 2 | (((1, 2), 3), 4); 3 | ((1, 2), (3, 4)); 4 | (1, ((2, 3), 4)); 5 | (((1, 2), 3), 4); 6 | (((1, 2), 3), 4); 7 | ((1, 2), (3, 4)); 8 | (1, ((2, 3), 4)); 9 | (((1, 2), 3), 4); 10 | (((1, 2), 3), 4); 11 | } 12 | -------------------------------------------------------------------------------- /tests/structures.glsl: -------------------------------------------------------------------------------- 1 | struct foo 2 | { 3 | vec3 a; 4 | vec2 b; 5 | float c[100]; 6 | }; 7 | 8 | struct bar 9 | { 10 | foo a, b, c; 11 | } a, b, c; 12 | 13 | void main( ) 14 | { 15 | bar a, b, c; 16 | } 17 | -------------------------------------------------------------------------------- /tests/structures.test: -------------------------------------------------------------------------------- 1 | struct foo { 2 | vec3 a; 3 | vec2 b; 4 | float c[100]; 5 | }; 6 | struct bar { 7 | foo a; 8 | foo b; 9 | foo c; 10 | }; 11 | bar a; 12 | bar b; 13 | bar c; 14 | void main() { 15 | bar a; 16 | bar b; 17 | bar c; 18 | } 19 | -------------------------------------------------------------------------------- /tests/switch.glsl: -------------------------------------------------------------------------------- 1 | void test() { 2 | // simple test 3 | int i = 10; 4 | switch (i) { 5 | case 0: break; 6 | default: break; 7 | } 8 | // nested 9 | switch (i) { 10 | case 0: 11 | switch (1) { 12 | case 1: 13 | break; 14 | default: 15 | break; 16 | } 17 | break; 18 | default: 19 | break; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/switch.test: -------------------------------------------------------------------------------- 1 | void test() { 2 | int i = 10; 3 | switch(i) { 4 | case 0: 5 | break; 6 | default: 7 | break; 8 | } 9 | switch(i) { 10 | case 0: 11 | switch(1) { 12 | case 1: 13 | break; 14 | default: 15 | break; 16 | } 17 | break; 18 | default: 19 | break; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/ternary.glsl: -------------------------------------------------------------------------------- 1 | void main() { 2 | float a = 0, b = 0, c = 0, d = 0; 3 | float w = (a ? a,b : b,c); 4 | float z = a ? b ? c : d : w; 5 | } 6 | -------------------------------------------------------------------------------- /tests/ternary.test: -------------------------------------------------------------------------------- 1 | void main() { 2 | float a = 0; 3 | float b = 0; 4 | float c = 0; 5 | float d = 0; 6 | float w = ((a ? (a, b) : b), c); 7 | float z = (a ? (b ? c : d) : w); 8 | } 9 | -------------------------------------------------------------------------------- /tests/uniforms.glsl: -------------------------------------------------------------------------------- 1 | uniform float float1; 2 | uniform float float2 = 10.0f; 3 | -------------------------------------------------------------------------------- /tests/uniforms.test: -------------------------------------------------------------------------------- 1 | uniform float float1; 2 | uniform float float2 = 10.0; 3 | -------------------------------------------------------------------------------- /tests/while_statement.glsl: -------------------------------------------------------------------------------- 1 | void test() { 2 | int i = 0; 3 | while (true) { } 4 | while (i < 10) { } 5 | } 6 | -------------------------------------------------------------------------------- /tests/while_statement.test: -------------------------------------------------------------------------------- 1 | void test() { 2 | int i = 0; 3 | while(true) { 4 | } 5 | while((i < 10)) { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /util.cpp: -------------------------------------------------------------------------------- 1 | #include // va_list, va_copy, va_start, va_end 2 | #include // malloc 3 | #include // vsnprintf 4 | 5 | namespace glsl { 6 | 7 | // An implementation of vasprintf 8 | int allocvfmt(char **str, const char *fmt, va_list vp) { 9 | int size = 0; 10 | va_list va; 11 | va_copy(va, vp); 12 | size = vsnprintf(0, size, fmt, va); 13 | va_end(va); 14 | 15 | if (size < 0) 16 | return -1; 17 | *str = (char *)malloc(size + 1); 18 | if (!*str) 19 | return -1; 20 | return vsprintf(*str, fmt, vp); 21 | } 22 | 23 | // An implementation of vsprintf 24 | int allocfmt(char **str, const char *fmt, ...) { 25 | va_list va; 26 | va_start(va, fmt); 27 | int size = allocvfmt(str, fmt, va); 28 | va_end(va); 29 | return size; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | #include // va_list 4 | #include 5 | 6 | namespace glsl { 7 | 8 | // An implementation of std::find 9 | template 10 | static inline I find(I first, I last, const T &value) { 11 | for (; first != last; ++first) 12 | if (*first == value) 13 | return first; 14 | return last; 15 | } 16 | 17 | // An implementation of vasprintf 18 | int allocvfmt(char **str, const char *fmt, va_list vp); 19 | 20 | // An implementation of vsprintf 21 | int allocfmt(char **str, const char *fmt, ...); 22 | 23 | // a tiny wrapper around std::vector so you can provide your own 24 | template 25 | struct vector { 26 | size_t size() const { return m_data.size(); } 27 | bool empty() const { return m_data.empty(); } 28 | const T& operator[](size_t index) const { return m_data[index]; } 29 | T& operator[](size_t index) { return m_data[index]; } 30 | T* begin() { return &m_data[0]; } 31 | T* end() { return &m_data[size()]; } 32 | const T* begin() const { return &m_data[0]; } 33 | const T* end() const { return &m_data[size()]; } 34 | void insert(T *at, const T& value = T()) { m_data.insert(m_data.begin() + size_t(at - begin()), value); } 35 | void insert(T *at, const T *beg, const T *end) { m_data.insert(m_data.begin() + size_t(at - begin()), beg, end); } 36 | void push_back(const T &value) { m_data.push_back(value); } 37 | void reserve(size_t size) { m_data.reserve(size); } 38 | T* erase(T *position) { return &*m_data.erase(m_data.begin() + size_t(position - begin())); } 39 | T* erase(T *first, T *last) { return &*m_data.erase(m_data.begin() + size_t(first - begin()), m_data.begin() + size_t(last - begin())); } 40 | void pop_back() { m_data.pop_back(); } 41 | T &front() { return *begin(); } 42 | const T &front() const { return *begin(); } 43 | T &back() { return *(end() - 1); } 44 | const T& back() const { return *(end() - 1); } 45 | void resize(size_t size) { m_data.resize(size); } 46 | private: 47 | std::vector m_data; 48 | }; 49 | 50 | } 51 | 52 | #endif 53 | --------------------------------------------------------------------------------