blob: d6b08b350081ee2d110a8e9ffb42903a2864f157 [file] [log] [blame]
John Bauman66b8ab22014-05-06 15:57:45 -04001//
2// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6#ifndef _PARSER_HELPER_INCLUDED_
7#define _PARSER_HELPER_INCLUDED_
8
Nicolas Capenscc863da2015-01-21 15:50:55 -05009#include "Diagnostics.h"
10#include "DirectiveHandler.h"
11#include "localintermediate.h"
12#include "preprocessor/Preprocessor.h"
Nicolas Capensd8cbf392015-02-10 15:35:11 -050013#include "Compiler.h"
Nicolas Capenscc863da2015-01-21 15:50:55 -050014#include "SymbolTable.h"
John Bauman66b8ab22014-05-06 15:57:45 -040015
16struct TMatrixFields {
17 bool wholeRow;
18 bool wholeCol;
19 int row;
20 int col;
21};
22
23//
24// The following are extra variables needed during parsing, grouped together so
25// they can be passed to the parser without needing a global.
26//
Alexis Hetu0a655842015-06-22 16:52:11 -040027class TParseContext {
28public:
Nicolas Capens08ca3c62015-02-13 16:06:45 -050029 TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, GLenum type, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) :
John Bauman66b8ab22014-05-06 15:57:45 -040030 intermediate(interm),
31 symbolTable(symt),
John Bauman66b8ab22014-05-06 15:57:45 -040032 compileOptions(options),
33 sourcePath(sourcePath),
John Bauman66b8ab22014-05-06 15:57:45 -040034 lexAfterType(false),
John Bauman66b8ab22014-05-06 15:57:45 -040035 inTypeParen(false),
Alexis Hetu0a655842015-06-22 16:52:11 -040036 AfterEOF(false),
Alexis Hetu407813b2016-02-24 16:46:13 -050037 mDeferredSingleDeclarationErrorCheck(false),
Alexis Hetu0a655842015-06-22 16:52:11 -040038 mShaderType(type),
39 mShaderVersion(100),
40 mTreeRoot(0),
41 mLoopNestingLevel(0),
42 mSwitchNestingLevel(0),
43 mStructNestingLevel(0),
44 mCurrentFunctionType(NULL),
45 mFunctionReturnsValue(false),
Alexis Hetu407813b2016-02-24 16:46:13 -050046 mChecksPrecisionErrors(checksPrecErrors),
Alexis Hetu0a655842015-06-22 16:52:11 -040047 mDefaultMatrixPacking(EmpColumnMajor),
Alexis Hetu407813b2016-02-24 16:46:13 -050048 mDefaultBlockStorage(EbsShared),
Alexis Hetu0a655842015-06-22 16:52:11 -040049 mDiagnostics(is),
50 mDirectiveHandler(ext, mDiagnostics, mShaderVersion),
51 mPreprocessor(&mDiagnostics, &mDirectiveHandler),
Alexis Hetu407813b2016-02-24 16:46:13 -050052 mScanner(NULL),
Alexis Hetudd7ff7a2015-06-11 08:25:30 -040053 mUsesFragData(false),
54 mUsesFragColor(false) { }
John Bauman66b8ab22014-05-06 15:57:45 -040055 TIntermediate& intermediate; // to hold and build a parse tree
56 TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed
John Bauman66b8ab22014-05-06 15:57:45 -040057 int compileOptions;
58 const char* sourcePath; // Path of source file or NULL.
John Bauman66b8ab22014-05-06 15:57:45 -040059 bool lexAfterType; // true if we've recognized a type, so can only be looking for an identifier
John Bauman66b8ab22014-05-06 15:57:45 -040060 bool inTypeParen; // true if in parentheses, looking only for an identifier
John Bauman66b8ab22014-05-06 15:57:45 -040061 bool AfterEOF;
John Bauman66b8ab22014-05-06 15:57:45 -040062
Alexis Hetu407813b2016-02-24 16:46:13 -050063 const pp::Preprocessor &getPreprocessor() const { return mPreprocessor; }
64 pp::Preprocessor &getPreprocessor() { return mPreprocessor; }
65 void *getScanner() const { return mScanner; }
66 void setScanner(void *scanner) { mScanner = scanner; }
67 int getShaderVersion() const { return mShaderVersion; }
68 GLenum getShaderType() const { return mShaderType; }
69 int numErrors() const { return mDiagnostics.numErrors(); }
Alexis Hetu0a655842015-06-22 16:52:11 -040070 TInfoSink &infoSink() { return mDiagnostics.infoSink(); }
Alexis Hetufe1269e2015-06-16 12:43:32 -040071 void error(const TSourceLoc &loc, const char *reason, const char* token,
John Bauman66b8ab22014-05-06 15:57:45 -040072 const char* extraInfo="");
Alexis Hetufe1269e2015-06-16 12:43:32 -040073 void warning(const TSourceLoc &loc, const char* reason, const char* token,
John Bauman66b8ab22014-05-06 15:57:45 -040074 const char* extraInfo="");
75 void trace(const char* str);
76 void recover();
Alexis Hetu407813b2016-02-24 16:46:13 -050077 TIntermNode *getTreeRoot() const { return mTreeRoot; }
78 void setTreeRoot(TIntermNode *treeRoot) { mTreeRoot = treeRoot; }
79
80 bool getFunctionReturnsValue() const { return mFunctionReturnsValue; }
81 void setFunctionReturnsValue(bool functionReturnsValue)
82 {
83 mFunctionReturnsValue = functionReturnsValue;
84 }
85
86 void setLoopNestingLevel(int loopNestintLevel)
87 {
88 mLoopNestingLevel = loopNestintLevel;
89 }
90
91 const TType *getCurrentFunctionType() const { return mCurrentFunctionType; }
92 void setCurrentFunctionType(const TType *currentFunctionType)
93 {
94 mCurrentFunctionType = currentFunctionType;
95 }
96
97 void incrLoopNestingLevel() { ++mLoopNestingLevel; }
98 void decrLoopNestingLevel() { --mLoopNestingLevel; }
99
100 void incrSwitchNestingLevel() { ++mSwitchNestingLevel; }
Alexis Hetu0a655842015-06-22 16:52:11 -0400101 void decrSwitchNestingLevel() { --mSwitchNestingLevel; }
Alexis Hetu76a343a2015-06-04 17:21:22 -0400102
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400103 // This method is guaranteed to succeed, even if no variable with 'name' exists.
104 const TVariable *getNamedVariable(const TSourceLoc &location, const TString *name, const TSymbol *symbol);
105
Alexis Hetufe1269e2015-06-16 12:43:32 -0400106 bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc &line);
107 bool parseMatrixFields(const TString&, int matCols, int matRows, TMatrixFields&, const TSourceLoc &line);
John Bauman66b8ab22014-05-06 15:57:45 -0400108
Alexis Hetufe1269e2015-06-16 12:43:32 -0400109 bool reservedErrorCheck(const TSourceLoc &line, const TString& identifier);
110 void assignError(const TSourceLoc &line, const char* op, TString left, TString right);
111 void unaryOpError(const TSourceLoc &line, const char* op, TString operand);
112 void binaryOpError(const TSourceLoc &line, const char* op, TString left, TString right);
113 bool precisionErrorCheck(const TSourceLoc &line, TPrecision precision, TBasicType type);
114 bool lValueErrorCheck(const TSourceLoc &line, const char* op, TIntermTyped*);
John Bauman66b8ab22014-05-06 15:57:45 -0400115 bool constErrorCheck(TIntermTyped* node);
116 bool integerErrorCheck(TIntermTyped* node, const char* token);
Alexis Hetufe1269e2015-06-16 12:43:32 -0400117 bool globalErrorCheck(const TSourceLoc &line, bool global, const char* token);
118 bool constructorErrorCheck(const TSourceLoc &line, TIntermNode*, TFunction&, TOperator, TType*);
119 bool arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped* expr, int& size);
120 bool arrayQualifierErrorCheck(const TSourceLoc &line, TPublicType type);
121 bool arrayTypeErrorCheck(const TSourceLoc &line, TPublicType type);
Alexis Hetufe1269e2015-06-16 12:43:32 -0400122 bool voidErrorCheck(const TSourceLoc&, const TString&, const TBasicType&);
123 bool boolErrorCheck(const TSourceLoc&, const TIntermTyped*);
124 bool boolErrorCheck(const TSourceLoc&, const TPublicType&);
125 bool samplerErrorCheck(const TSourceLoc &line, const TPublicType& pType, const char* reason);
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400126 bool locationDeclaratorListCheck(const TSourceLoc &line, const TPublicType &pType);
Alexis Hetufe1269e2015-06-16 12:43:32 -0400127 bool structQualifierErrorCheck(const TSourceLoc &line, const TPublicType& pType);
128 bool parameterSamplerErrorCheck(const TSourceLoc &line, TQualifier qualifier, const TType& type);
129 bool nonInitConstErrorCheck(const TSourceLoc &line, TString& identifier, TPublicType& type, bool array);
130 bool nonInitErrorCheck(const TSourceLoc &line, const TString& identifier, TPublicType& type);
131 bool paramErrorCheck(const TSourceLoc &line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
132 bool extensionErrorCheck(const TSourceLoc &line, const TString&);
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400133 bool singleDeclarationErrorCheck(const TPublicType &publicType, const TSourceLoc &identifierLocation);
Alexis Hetuad6b8752015-06-09 16:15:30 -0400134 bool layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier);
135 bool functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *);
Alexis Hetuad527752015-07-07 13:31:44 -0400136 void es3InvariantErrorCheck(const TQualifier qualifier, const TSourceLoc &invariantLocation);
John Bauman66b8ab22014-05-06 15:57:45 -0400137
Alexis Hetu0a655842015-06-22 16:52:11 -0400138 const TExtensionBehavior& extensionBehavior() const { return mDirectiveHandler.extensionBehavior(); }
John Bauman66b8ab22014-05-06 15:57:45 -0400139 bool supportsExtension(const char* extension);
Alexis Hetufe1269e2015-06-16 12:43:32 -0400140 void handleExtensionDirective(const TSourceLoc &line, const char* extName, const char* behavior);
John Bauman66b8ab22014-05-06 15:57:45 -0400141
Alexis Hetu0a655842015-06-22 16:52:11 -0400142 const TPragma& pragma() const { return mDirectiveHandler.pragma(); }
Alexis Hetufe1269e2015-06-16 12:43:32 -0400143 void handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value);
John Bauman66b8ab22014-05-06 15:57:45 -0400144
145 bool containsSampler(TType& type);
Alexis Hetufe1269e2015-06-16 12:43:32 -0400146 const TFunction* findFunction(const TSourceLoc &line, TFunction* pfnCall, bool *builtIn = 0);
Alexis Hetue5246692015-06-18 12:34:52 -0400147 bool executeInitializer(const TSourceLoc &line, const TString &identifier, const TPublicType &pType,
148 TIntermTyped *initializer, TIntermNode **intermNode);
Alexis Hetu42ff6b12015-06-03 16:03:48 -0400149
150 TPublicType addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier);
Alexis Hetufe1269e2015-06-16 12:43:32 -0400151 bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, const TSourceLoc&);
John Bauman66b8ab22014-05-06 15:57:45 -0400152
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400153 TIntermAggregate *parseSingleDeclaration(TPublicType &publicType, const TSourceLoc &identifierOrTypeLocation, const TString &identifier);
154 TIntermAggregate *parseSingleArrayDeclaration(TPublicType &publicType, const TSourceLoc &identifierLocation, const TString &identifier,
155 const TSourceLoc &indexLocation, TIntermTyped *indexExpression);
156 TIntermAggregate *parseSingleInitDeclaration(const TPublicType &publicType, const TSourceLoc &identifierLocation, const TString &identifier,
157 const TSourceLoc &initLocation, TIntermTyped *initializer);
158
159 // Parse a declaration like "type a[n] = initializer"
160 // Note that this does not apply to declarations like "type[n] a = initializer"
161 TIntermAggregate *parseSingleArrayInitDeclaration(TPublicType &publicType, const TSourceLoc &identifierLocation, const TString &identifier,
162 const TSourceLoc &indexLocation, TIntermTyped *indexExpression,
163 const TSourceLoc &initLocation, TIntermTyped *initializer);
164
165 TIntermAggregate *parseInvariantDeclaration(const TSourceLoc &invariantLoc, const TSourceLoc &identifierLoc, const TString *identifier,
166 const TSymbol *symbol);
167
168 TIntermAggregate *parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation,
169 const TString &identifier);
170 TIntermAggregate *parseArrayDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation,
171 const TString &identifier, const TSourceLoc &arrayLocation, TIntermTyped *indexExpression);
172 TIntermAggregate *parseInitDeclarator(const TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation,
173 const TString &identifier, const TSourceLoc &initLocation, TIntermTyped *initializer);
174
175 // Parse a declarator like "a[n] = initializer"
176 TIntermAggregate *parseArrayInitDeclarator(const TPublicType &publicType, TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation,
177 const TString &identifier, const TSourceLoc &indexLocation, TIntermTyped *indexExpression,
178 const TSourceLoc &initLocation, TIntermTyped *initializer);
179
Alexis Hetua35d8232015-06-11 17:11:06 -0400180 void parseGlobalLayoutQualifier(const TPublicType &typeQualifier);
Alexis Hetu407813b2016-02-24 16:46:13 -0500181 TIntermAggregate *addFunctionPrototypeDeclaration(const TFunction &function, const TSourceLoc &location);
182 TIntermAggregate *addFunctionDefinition(const TFunction &function, TIntermAggregate *functionPrototype, TIntermAggregate *functionBody, const TSourceLoc &location);
183 void parseFunctionPrototype(const TSourceLoc &location, TFunction *function, TIntermAggregate **aggregateOut);
184 TFunction *parseFunctionDeclarator(const TSourceLoc &location, TFunction *function);
Alexis Hetue5246692015-06-18 12:34:52 -0400185 TFunction *addConstructorFunc(const TPublicType &publicType);
Alexis Hetufe1269e2015-06-16 12:43:32 -0400186 TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&);
John Bauman66b8ab22014-05-06 15:57:45 -0400187 TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type);
Alexis Hetufe1269e2015-06-16 12:43:32 -0400188 TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&);
189 TIntermTyped* addConstMatrixNode(int, TIntermTyped*, const TSourceLoc&);
190 TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc &line);
191 TIntermTyped* addConstStruct(const TString&, TIntermTyped*, const TSourceLoc&);
Alexis Hetuad6b8752015-06-09 16:15:30 -0400192 TIntermTyped *addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression);
193 TIntermTyped* addFieldSelectionExpression(TIntermTyped *baseExpression, const TSourceLoc &dotLocation, const TString &fieldString, const TSourceLoc &fieldLocation);
194
195 TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList);
196 TPublicType addStructure(const TSourceLoc &structLine, const TSourceLoc &nameLine, const TString *structName, TFieldList *fieldList);
John Bauman66b8ab22014-05-06 15:57:45 -0400197
Alexis Hetua35d8232015-06-11 17:11:06 -0400198 TIntermAggregate* addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList,
199 const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine);
200
Nicolas Capens7d626792015-02-17 17:58:31 -0500201 TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine);
202 TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc& intValueLine);
203 TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier);
Alexis Hetu55a2cbc2015-04-16 10:49:45 -0400204 TPublicType joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier, const TSourceLoc &storageLoc, TQualifier storageQualifier);
Nicolas Capens7d626792015-02-17 17:58:31 -0500205
John Bauman66b8ab22014-05-06 15:57:45 -0400206 // Performs an error check for embedded struct declarations.
207 // Returns true if an error was raised due to the declaration of
208 // this struct.
Alexis Hetufe1269e2015-06-16 12:43:32 -0400209 bool enterStructDeclaration(const TSourceLoc &line, const TString& identifier);
John Bauman66b8ab22014-05-06 15:57:45 -0400210 void exitStructDeclaration();
211
Alexis Hetuad6b8752015-06-09 16:15:30 -0400212 bool structNestingErrorCheck(const TSourceLoc &line, const TField &field);
213
Alexis Hetu76a343a2015-06-04 17:21:22 -0400214 TIntermSwitch *addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc);
215 TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc);
216 TIntermCase *addDefault(const TSourceLoc &loc);
217
Alexis Hetuad6b8752015-06-09 16:15:30 -0400218 TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
219 TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
Alexis Hetub4769582015-06-16 12:19:50 -0400220 TIntermTyped *addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
221 TIntermTyped *addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
Alexis Hetuad6b8752015-06-09 16:15:30 -0400222
Alexis Hetue5246692015-06-18 12:34:52 -0400223 TIntermTyped *addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
224
Alexis Hetu76a343a2015-06-04 17:21:22 -0400225 TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc);
226 TIntermBranch *addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc);
227
Alexis Hetub3ff42c2015-07-03 18:19:57 -0400228 TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *paramNode, TIntermNode *thisNode, const TSourceLoc &loc, bool *fatalError);
229
Alexis Hetueee212e2015-07-07 17:13:30 -0400230 TIntermTyped *addTernarySelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &line);
231
Alexis Hetuad6b8752015-06-09 16:15:30 -0400232private:
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400233 bool declareVariable(const TSourceLoc &line, const TString &identifier, const TType &type, TVariable **variable);
234
Alexis Hetub4769582015-06-16 12:19:50 -0400235 TIntermTyped *addBinaryMathInternal(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
Alexis Hetue5246692015-06-18 12:34:52 -0400236 TIntermTyped *createAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
Alexis Hetub4769582015-06-16 12:19:50 -0400237
Alexis Hetuad6b8752015-06-09 16:15:30 -0400238 // The funcReturnType parameter is expected to be non-null when the operation is a built-in function.
239 // It is expected to be null for other unary operators.
240 TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc, const TType *funcReturnType);
241
242 // Return true if the checks pass
243 bool binaryOpCommonCheck(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400244
Alexis Hetu407813b2016-02-24 16:46:13 -0500245 // Set to true when the last/current declarator list was started with an empty declaration.
246 bool mDeferredSingleDeclarationErrorCheck;
247
248 GLenum mShaderType; // vertex or fragment language (future: pack or unpack)
249 int mShaderVersion;
250 TIntermNode *mTreeRoot; // root of parse tree being created
251 int mLoopNestingLevel; // 0 if outside all loops
252 int mSwitchNestingLevel; // 0 if outside all switch statements
253 int mStructNestingLevel; // incremented while parsing a struct declaration
254 const TType *mCurrentFunctionType; // the return type of the function that's currently being parsed
255 bool mFunctionReturnsValue; // true if a non-void function has a return
256 bool mChecksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit.
257
258 TLayoutMatrixPacking mDefaultMatrixPacking;
259 TLayoutBlockStorage mDefaultBlockStorage;
260 TDiagnostics mDiagnostics;
261 TDirectiveHandler mDirectiveHandler;
262 pp::Preprocessor mPreprocessor;
263 void *mScanner;
264 bool mUsesFragData; // track if we are using both gl_FragData and gl_FragColor
Alexis Hetudd7ff7a2015-06-11 08:25:30 -0400265 bool mUsesFragColor;
John Bauman66b8ab22014-05-06 15:57:45 -0400266};
267
268int PaParseStrings(int count, const char* const string[], const int length[],
269 TParseContext* context);
270
271#endif // _PARSER_HELPER_INCLUDED_