1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "BsASTFX.h"
4#include "BsMMAlloc.h"
5#include <assert.h>
6
7OptionInfo OPTION_LOOKUP[] =
8{
9 { OT_None, ODT_Int },
10 { OT_Options, ODT_Complex },
11 { OT_Separable, ODT_Bool },
12 { OT_Priority, ODT_Int },
13 { OT_Sort, ODT_Int },
14 { OT_Transparent, ODT_Bool },
15 { OT_Shader, ODT_Complex },
16 { OT_SubShader, ODT_Complex },
17 { OT_Mixin, ODT_String },
18 { OT_Raster, ODT_Complex },
19 { OT_Depth, ODT_Complex },
20 { OT_Stencil, ODT_Complex },
21 { OT_Blend, ODT_Complex },
22 { OT_FeatureSet, ODT_String },
23 { OT_Pass, ODT_Complex },
24 { OT_FillMode, ODT_Int },
25 { OT_CullMode, ODT_Int },
26 { OT_DepthBias, ODT_Float },
27 { OT_SDepthBias, ODT_Float },
28 { OT_DepthClip, ODT_Bool },
29 { OT_Scissor, ODT_Bool },
30 { OT_Multisample, ODT_Bool },
31 { OT_AALine, ODT_Bool },
32 { OT_DepthRead, ODT_Bool },
33 { OT_DepthWrite, ODT_Bool },
34 { OT_CompareFunc, ODT_Int },
35 { OT_StencilReadMask, ODT_Int },
36 { OT_StencilWriteMask, ODT_Int },
37 { OT_StencilOpFront, ODT_Complex },
38 { OT_StencilOpBack, ODT_Complex },
39 { OT_PassOp, ODT_Int },
40 { OT_Fail, ODT_Int },
41 { OT_ZFail, ODT_Int },
42 { OT_AlphaToCoverage, ODT_Bool },
43 { OT_IndependantBlend, ODT_Bool },
44 { OT_Target, ODT_Complex },
45 { OT_Index, ODT_Int },
46 { OT_Enabled, ODT_Bool },
47 { OT_Color, ODT_Complex },
48 { OT_Alpha, ODT_Complex },
49 { OT_WriteMask, ODT_Int },
50 { OT_Source, ODT_Int },
51 { OT_Dest, ODT_Int },
52 { OT_Op, ODT_Int },
53 { OT_Identifier, ODT_String },
54 { OT_Code, ODT_Complex },
55 { OT_StencilRef, ODT_Int },
56 { OT_Tags, ODT_Complex },
57 { OT_TagValue, ODT_String },
58 { OT_Variations, ODT_Complex },
59 { OT_Variation, ODT_Complex },
60 { OT_VariationValue, ODT_Int },
61 { OT_Forward, ODT_Bool },
62 { OT_Attributes, ODT_Complex },
63 { OT_AttrName, ODT_String },
64 { OT_VariationOption, ODT_Complex },
65 { OT_AttrShow, ODT_Int },
66};
67
68NodeOptions* nodeOptionsCreate(void* context)
69{
70 static const int BUFFER_SIZE = 5;
71
72 NodeOptions* options = (NodeOptions*)mmalloc(context, sizeof(NodeOptions));
73 options->count = 0;
74 options->bufferSize = BUFFER_SIZE;
75
76 options->entries = (NodeOption*)mmalloc(context, sizeof(NodeOption) * options->bufferSize);
77 memset(options->entries, 0, sizeof(NodeOption) * options->bufferSize);
78
79 return options;
80}
81
82void nodeOptionDelete(NodeOption* option)
83{
84 if (OPTION_LOOKUP[(int)option->type].dataType == ODT_Complex)
85 {
86 nodeDelete(option->value.nodePtr);
87 option->value.nodePtr = 0;
88 }
89 else if (OPTION_LOOKUP[(int)option->type].dataType == ODT_String)
90 {
91 mmfree((void*)option->value.strValue);
92 option->value.strValue = 0;
93 }
94}
95
96void nodeOptionsDelete(NodeOptions* options)
97{
98 int i = 0;
99
100 for (i = 0; i < options->count; i++)
101 nodeOptionDelete(&options->entries[i]);
102
103 mmfree(options->entries);
104 mmfree(options);
105}
106
107void nodeOptionsResize(void* context, NodeOptions* options, int size)
108{
109 NodeOption* originalEntries = options->entries;
110 int originalSize = options->bufferSize;
111 int elementsToCopy = originalSize;
112 int sizeToCopy = 0;
113
114 options->bufferSize = size;
115 if (options->count > options->bufferSize)
116 options->count = options->bufferSize;
117
118 if (elementsToCopy > size)
119 elementsToCopy = size;
120
121 sizeToCopy = elementsToCopy * sizeof(NodeOption);
122
123 options->entries = (NodeOption*)mmalloc(context, sizeof(NodeOption) * options->bufferSize);
124
125 memcpy(options->entries, originalEntries, sizeToCopy);
126 memset(options->entries + elementsToCopy, 0, sizeof(NodeOption) * options->bufferSize - sizeToCopy);
127
128 mmfree(originalEntries);
129}
130
131void nodeOptionsGrowIfNeeded(void* context, NodeOptions* options)
132{
133 static const int BUFFER_GROW = 10;
134
135 if (options->count == options->bufferSize)
136 nodeOptionsResize(context, options, options->bufferSize + BUFFER_GROW);
137}
138
139void nodeOptionsAdd(void* context, NodeOptions* options, const NodeOption* option)
140{
141 nodeOptionsGrowIfNeeded(context, options);
142
143 options->entries[options->count] = *option;
144 options->count++;
145}
146
147ASTFXNode* nodeCreate(void* context, NodeType type)
148{
149 ASTFXNode* node = (ASTFXNode*)mmalloc(context, sizeof(ASTFXNode));
150 node->options = nodeOptionsCreate(context);
151 node->type = type;
152
153 return node;
154}
155
156void nodeDelete(ASTFXNode* node)
157{
158 nodeOptionsDelete(node->options);
159
160 mmfree(node);
161}
162
163void nodePush(ParseState* parseState, ASTFXNode* node)
164{
165 NodeLink* linkNode = (NodeLink*)mmalloc(parseState->memContext, sizeof(NodeLink));
166 linkNode->next = parseState->nodeStack;
167 linkNode->node = node;
168
169 parseState->nodeStack = linkNode;
170 parseState->topNode = node;
171}
172
173void nodePop(ParseState* parseState)
174{
175 if (!parseState->nodeStack)
176 return;
177
178 NodeLink* toRemove = parseState->nodeStack;
179 parseState->nodeStack = toRemove->next;
180
181 if (parseState->nodeStack)
182 parseState->topNode = parseState->nodeStack->node;
183 else
184 parseState->topNode = 0;
185
186 mmfree(toRemove);
187}
188
189void beginCodeBlock(ParseState* parseState, RawCodeType type)
190{
191 RawCode* rawCodeBlock = (RawCode*)mmalloc(parseState->memContext, sizeof(RawCode));
192 rawCodeBlock->index = parseState->numRawCodeBlocks[type];
193 rawCodeBlock->size = 0;
194 rawCodeBlock->capacity = 4096;
195 rawCodeBlock->code = mmalloc(parseState->memContext, rawCodeBlock->capacity);
196 rawCodeBlock->next = parseState->rawCodeBlock[type];
197
198 parseState->numRawCodeBlocks[type]++;
199 parseState->rawCodeBlock[type] = rawCodeBlock;
200
201 // Insert defines for code-blocks as we don't perform pre-processing within code blocks but we still want outer defines
202 // to be recognized by them (Performing pre-processing for code blocks is problematic because it would require parsing
203 // of all the language syntax in order to properly handle macro replacement).
204 for (int i = 0; i < parseState->numDefines; i++)
205 {
206 const char* define = "#define ";
207
208 appendCodeBlock(parseState, type, define, (int)strlen(define));
209 appendCodeBlock(parseState, type, parseState->defines[i].name, (int)strlen(parseState->defines[i].name));
210
211 if (parseState->defines[i].expr != 0)
212 {
213 appendCodeBlock(parseState, type, " ", 1);
214 appendCodeBlock(parseState, type, parseState->defines[i].expr, (int)strlen(parseState->defines[i].expr));
215 }
216
217 appendCodeBlock(parseState, type, "\n", 1);
218 }
219}
220
221void appendCodeBlock(ParseState* parseState, RawCodeType type, const char* value, int size)
222{
223 RawCode* rawCode = parseState->rawCodeBlock[type];
224
225 if ((rawCode->size + size) > rawCode->capacity)
226 {
227 int newCapacity = rawCode->capacity;
228 do
229 {
230 newCapacity *= 2;
231 } while ((rawCode->size + size) > newCapacity);
232
233 char* newBuffer = mmalloc(parseState->memContext, newCapacity);
234 memcpy(newBuffer, rawCode->code, rawCode->size);
235 mmfree(rawCode->code);
236
237 rawCode->code = newBuffer;
238 rawCode->capacity = newCapacity;
239 }
240
241 memcpy(&rawCode->code[rawCode->size], value, size);
242 rawCode->size += size;
243}
244
245int getCodeBlockIndex(ParseState* parseState, RawCodeType type)
246{
247 return parseState->rawCodeBlock[type]->index;
248}
249
250char* getCurrentFilename(ParseState* parseState)
251{
252 if (!parseState->includeStack)
253 return NULL;
254
255 return parseState->includeStack->data->filename;
256}
257
258void addDefine(ParseState* parseState, const char* value)
259{
260 int defineIdx = parseState->numDefines;
261 parseState->numDefines++;
262
263 if(parseState->numDefines > parseState->defineCapacity)
264 {
265 int newCapacity = parseState->defineCapacity * 2;
266 DefineEntry* newDefines = mmalloc(parseState->memContext, newCapacity * sizeof(DefineEntry));
267
268 memcpy(newDefines, parseState->defines, parseState->defineCapacity * sizeof(DefineEntry));
269
270 mmfree(parseState->defines);
271 parseState->defines = newDefines;
272 parseState->defineCapacity = newCapacity;
273 }
274
275 parseState->defines[defineIdx].name = mmalloc_strdup(parseState->memContext, value);
276 parseState->defines[defineIdx].expr = 0;
277}
278
279void addDefineExpr(ParseState* parseState, const char* value)
280{
281 int defineIdx = parseState->numDefines - 1;
282 if(defineIdx < 0)
283 {
284 assert(0);
285 return;
286 }
287
288 parseState->defines[defineIdx].expr = mmalloc_strdup(parseState->memContext, value);
289}
290
291int hasDefine(ParseState* parseState, const char* value)
292{
293 for (int i = 0; i < parseState->numDefines; i++)
294 {
295 if (strcmp(parseState->defines[i].name, value) == 0)
296 return 1;
297 }
298
299 return 0;
300}
301
302int isDefineEnabled(ParseState* parseState, const char* value)
303{
304 for (int i = 0; i < parseState->numDefines; i++)
305 {
306 if (strcmp(parseState->defines[i].name, value) == 0)
307 {
308 if(parseState->defines[i].expr == 0)
309 return 0;
310
311 int val = atoi(parseState->defines[i].expr);
312 return val != 0;
313 }
314 }
315
316 return 0;
317}
318
319void removeDefine(ParseState* parseState, const char* value)
320{
321 for (int i = 0; i < parseState->numDefines; i++)
322 {
323 if (strcmp(parseState->defines[i].name, value) == 0)
324 {
325 int remaining = parseState->numDefines - (i + 1);
326
327 if(remaining > 0)
328 memcpy(&parseState->defines[i], &parseState->defines[i + 1], remaining * sizeof(DefineEntry));
329
330 parseState->numDefines--;
331 }
332 }
333}
334
335int pushConditionalDef(ParseState* parseState, int state)
336{
337 ConditionalData* conditional = mmalloc(parseState->memContext, sizeof(ConditionalData));
338 conditional->enabled = state && (parseState->conditionalStack == 0 || parseState->conditionalStack->enabled);
339 conditional->selfEnabled = state;
340 conditional->name = NULL;
341 conditional->op = CO_None;
342 conditional->value = NULL;
343 conditional->next = parseState->conditionalStack;
344
345 parseState->conditionalStack = conditional;
346
347 return conditional->enabled;
348}
349
350void pushConditional(ParseState* parseState, const char* name)
351{
352 ConditionalData* conditional = mmalloc(parseState->memContext, sizeof(ConditionalData));
353 conditional->enabled = (parseState->conditionalStack == 0 || parseState->conditionalStack->enabled);
354 conditional->selfEnabled = 0;
355 conditional->op = CO_None;
356 conditional->value = NULL;
357 conditional->name = NULL;
358 conditional->next = parseState->conditionalStack;
359
360 if(name)
361 conditional->name = mmalloc_strdup(parseState->memContext, name);
362
363 parseState->conditionalStack = conditional;
364}
365
366void setConditional(ParseState* parseState, const char* name)
367{
368 assert(parseState->conditionalStack > 0);
369
370 ConditionalData* conditional = parseState->conditionalStack;
371 ConditionalData* parent = conditional->next;
372
373 conditional->name = mmalloc_strdup(parseState->memContext, name);
374 conditional->enabled = (parent == 0 || parent->enabled);
375 conditional->selfEnabled = 0;
376}
377
378void setConditionalOp(ParseState* parseState, ConditionalOp op)
379{
380 assert(parseState->conditionalStack > 0);
381
382 ConditionalData* conditional = parseState->conditionalStack;
383 conditional->op = op;
384}
385
386void setConditionalVal(ParseState* parseState, const char* value)
387{
388 assert(parseState->conditionalStack > 0);
389
390 ConditionalData* conditional = parseState->conditionalStack;
391 conditional->value = mmalloc_strdup(parseState->memContext, value);
392}
393
394int evalConditional(ParseState* parseState)
395{
396 assert(parseState->conditionalStack > 0);
397
398 ConditionalData* conditional = parseState->conditionalStack;
399 if(!conditional->name)
400 {
401 conditional->enabled = 0;
402 return 0;
403 }
404
405 int myVal = 1;
406 if(conditional->value)
407 myVal = atoi(conditional->value);
408
409 for (int i = 0; i < parseState->numDefines; i++)
410 {
411 if (strcmp(parseState->defines[i].name, conditional->name) == 0)
412 {
413 int val = 0;
414 if(parseState->defines[i].expr)
415 val = atoi(parseState->defines[i].expr);
416
417 switch(conditional->op)
418 {
419 default:
420 case CO_None: conditional->selfEnabled = val != 0; break;
421 case CO_Equals: conditional->selfEnabled = myVal == val; break;
422 case CO_NotEquals: conditional->selfEnabled = myVal != val; break;
423 case CO_Lesser: conditional->selfEnabled = val < myVal; break;
424 case CO_Greater: conditional->selfEnabled = val > myVal; break;
425 case CO_LesserEqual: conditional->selfEnabled = val <= myVal; break;
426 case CO_GreaterEqual: conditional->selfEnabled = val >= myVal; break;
427 }
428 }
429 }
430
431 conditional->enabled &= conditional->selfEnabled;
432 return conditional->enabled;
433}
434
435int setConditionalState(ParseState* parseState, int state)
436{
437 if (parseState->conditionalStack == 0)
438 return 1;
439
440 ConditionalData* conditional = parseState->conditionalStack;
441 ConditionalData* parent = conditional->next;
442
443 conditional->enabled = state && (parent == 0 || parent->enabled);
444 conditional->selfEnabled = state;
445
446 return conditional->enabled;
447}
448
449int switchConditional(ParseState* parseState)
450{
451 if (parseState->conditionalStack == 0)
452 return 1;
453
454 ConditionalData* conditional = parseState->conditionalStack;
455 return setConditionalState(parseState, !conditional->selfEnabled);
456}
457
458int popConditional(ParseState* parseState)
459{
460 if (parseState->conditionalStack == 0)
461 return 1;
462
463 ConditionalData* conditional = parseState->conditionalStack;
464 parseState->conditionalStack = conditional->next;
465
466 if(conditional->value)
467 mmfree(conditional->value);
468
469 if(conditional->name)
470 mmfree(conditional->name);
471
472 mmfree(conditional);
473
474 return parseState->conditionalStack == 0 || parseState->conditionalStack->enabled;
475}
476
477ParseState* parseStateCreate()
478{
479 ParseState* parseState = (ParseState*)malloc(sizeof(ParseState));
480 parseState->memContext = mmalloc_new_context();
481 parseState->rootNode = nodeCreate(parseState->memContext, NT_Root);
482 parseState->topNode = 0;
483 parseState->nodeStack = 0;
484 parseState->includeStack = 0;
485 parseState->includes = 0;
486 parseState->rawCodeBlock[0] = 0;
487 parseState->rawCodeBlock[1] = 0;
488 parseState->numRawCodeBlocks[0] = 0;
489 parseState->numRawCodeBlocks[1] = 0;
490 parseState->numOpenBrackets = 0;
491
492 parseState->hasError = 0;
493 parseState->errorLine = 0;
494 parseState->errorColumn = 0;
495 parseState->errorMessage = 0;
496 parseState->errorFile = 0;
497
498 parseState->conditionalStack = 0;
499 parseState->defineCapacity = 10;
500 parseState->numDefines = 0;
501 parseState->defines = mmalloc(parseState->memContext, parseState->defineCapacity * sizeof(DefineEntry));
502
503 nodePush(parseState, parseState->rootNode);
504
505 return parseState;
506}
507
508void parseStateDelete(ParseState* parseState)
509{
510 while (parseState->nodeStack != 0)
511 nodePop(parseState);
512
513 nodeDelete(parseState->rootNode);
514 mmalloc_free_context(parseState->memContext);
515
516 free(parseState);
517}