Procházet zdrojové kódy

BansheeSL: Parser retrieves semantic values
Leak-proof memory allocation

Marko Pintera před 10 roky
rodič
revize
1d40932a65

+ 2 - 0
BansheeSL/BansheeSL.vcxproj

@@ -264,6 +264,7 @@
     <ClInclude Include="BsLexerFX.h" />
     <ClInclude Include="BsParserFX.h" />
     <ClInclude Include="Include\BsASTFX.h" />
+    <ClInclude Include="Include\BsMMAlloc.h" />
     <ClInclude Include="Include\BsSLPrerequisites.h" />
   </ItemGroup>
   <ItemGroup>
@@ -280,6 +281,7 @@
       <CompileAs Condition="'$(Configuration)|$(Platform)'=='DebugRelease|x64'">Default</CompileAs>
     </ClCompile>
     <ClCompile Include="Source\BsASTFX.c" />
+    <ClCompile Include="Source\BSMMAlloc.c" />
     <ClCompile Include="Source\BsSLPlugin.cpp" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+ 6 - 0
BansheeSL/BansheeSL.vcxproj.filters

@@ -27,6 +27,9 @@
     <ClInclude Include="Include\BsASTFX.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsMMAlloc.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="BsLexerFX.l" />
@@ -45,5 +48,8 @@
     <ClCompile Include="Source\BsASTFX.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BSMMAlloc.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 108 - 105
BansheeSL/BsLexerFX.c

@@ -434,8 +434,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
 	yyg->yy_c_buf_p = yy_cp;
 
 /* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */
-#define YY_NUM_RULES 20
-#define YY_END_OF_BUFFER 21
+#define YY_NUM_RULES 21
+#define YY_END_OF_BUFFER 22
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -443,20 +443,20 @@ struct yy_trans_info
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static yyconst flex_int16_t yy_accept[109] =
+static yyconst flex_int16_t yy_accept[110] =
     {   0,
-        1,    1,   21,   19,    1,    1,   19,    2,   19,   19,
-       19,   19,   19,   19,   19,   19,   19,   19,    6,    7,
-        1,    0,    5,    0,    2,    0,    0,    0,    0,    0,
+        1,    1,   22,   20,    1,    1,   20,    2,   20,   20,
+       20,   20,   20,   20,   20,   20,   20,   20,    7,    8,
+        1,    0,    4,    0,    2,    0,    0,    0,    0,    0,
         0,    0,    0,    0,    0,    0,    3,    0,    0,    0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        3,    0,   12,    0,   11,    0,    0,    0,    0,    0,
-        0,    0,    4,    0,    3,    0,    0,    0,    0,    9,
-        0,    0,    0,   18,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,   16,    0,    0,    0,
-        0,   10,    0,    0,   13,   15,    0,    0,    8,    0,
+        3,    0,   13,    0,   12,    0,    0,    0,    0,    0,
+        0,    0,    5,    0,    3,    0,    0,    0,    0,   10,
+        0,    0,    0,    6,   19,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,   17,    0,    0,
+        0,    0,   11,    0,    0,   14,   16,    0,    0,    9,
 
-        0,   17,    0,    0,    0,    0,   14,    0
+        0,    0,   18,    0,    0,    0,    0,   15,    0
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -499,7 +499,7 @@ static yyconst flex_int32_t yy_meta[39] =
         1,    1,    1,    1,    1,    1,    1,    1
     } ;
 
-static yyconst flex_int16_t yy_base[110] =
+static yyconst flex_int16_t yy_base[111] =
     {   0,
         0,    0,  142,  143,   37,   39,  137,   37,  132,  104,
       115,  111,  101,  103,   99,   24,  114,  100,  143,  143,
@@ -508,27 +508,27 @@ static yyconst flex_int16_t yy_base[110] =
        89,   81,   84,   78,   85,   78,   91,   76,   85,   49,
       143,   78,  143,   81,  143,   79,   72,   80,   79,   68,
        68,   76,  143,   91,   48,   74,   50,   63,   69,  143,
-       72,   63,   73,  143,   65,   63,   70,   54,   76,   54,
-       65,   65,   57,   54,   45,   57,  143,   52,   45,   46,
-       45,  143,   44,   51,  143,  143,   46,   37,  143,   47,
+       72,   63,   73,  143,  143,   65,   63,   70,   54,   76,
+       54,   65,   65,   57,   54,   45,   57,  143,   52,   45,
+       46,   45,  143,   44,   51,  143,  143,   46,   37,  143,
 
-       42,  143,   57,   39,   45,   30,  143,  143,   61
+       47,   42,  143,   57,   39,   45,   30,  143,  143,   61
     } ;
 
-static yyconst flex_int16_t yy_def[110] =
+static yyconst flex_int16_t yy_def[111] =
     {   0,
-      108,    1,  108,  108,  108,  108,  109,  108,  108,  108,
-      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
-      108,  109,  108,  108,  108,  108,  108,  108,  108,  108,
-      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
-      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
-      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
-      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
-      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
-      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
-      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
-
-      108,  108,  108,  108,  108,  108,  108,    0,  108
+      109,    1,  109,  109,  109,  109,  110,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  110,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+
+      109,  109,  109,  109,  109,  109,  109,  109,    0,  109
     } ;
 
 static yyconst flex_int16_t yy_nxt[182] =
@@ -538,21 +538,21 @@ static yyconst flex_int16_t yy_nxt[182] =
         4,    4,    4,   17,    4,    4,    4,    4,    4,    4,
         4,    4,    4,   18,    4,    4,   19,   20,   21,   21,
        21,   21,   24,   25,   33,   45,   34,   21,   21,   24,
-       25,   37,   46,   64,   65,   65,   50,   51,   75,   76,
-       51,   22,  107,  106,  105,  104,  103,   50,   51,  102,
-      101,   51,  100,   99,   98,   97,   96,   95,   94,   93,
-       92,   91,   90,   89,   88,   87,   86,   85,   84,   83,
-       82,   81,   80,   79,   78,   77,   74,   65,   63,   73,
+       25,   37,   46,   64,   65,   65,   50,   51,   76,   77,
+       51,   22,  108,  107,  106,  105,  104,   50,   51,  103,
+      102,   51,  101,  100,   99,   98,   97,   96,   95,   94,
+       93,   92,   91,   90,   89,   88,   87,   86,   85,   84,
+       83,   82,   81,   80,   79,   78,   75,   65,   74,   73,
 
        72,   71,   70,   69,   68,   67,   66,   63,   62,   61,
        60,   59,   58,   57,   56,   55,   54,   53,   52,   49,
        48,   47,   44,   43,   42,   41,   40,   39,   38,   37,
        23,   36,   35,   32,   31,   30,   29,   28,   27,   26,
-       23,  108,    3,  108,  108,  108,  108,  108,  108,  108,
-      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
-      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
-      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
-      108
+       23,  109,    3,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109
     } ;
 
 static yyconst flex_int16_t yy_chk[182] =
@@ -563,26 +563,26 @@ static yyconst flex_int16_t yy_chk[182] =
         1,    1,    1,    1,    1,    1,    1,    1,    5,    5,
         6,    6,    8,    8,   16,   33,   16,   21,   21,   25,
        25,   37,   33,   50,   65,   50,   37,   37,   67,   67,
-       65,  109,  106,  105,  104,  103,  101,   37,   37,  100,
-       98,   65,   97,   94,   93,   91,   90,   89,   88,   86,
-       85,   84,   83,   82,   81,   80,   79,   78,   77,   76,
-       75,   73,   72,   71,   69,   68,   66,   64,   62,   61,
+       65,  110,  107,  106,  105,  104,  102,   37,   37,  101,
+       99,   65,   98,   95,   94,   92,   91,   90,   89,   87,
+       86,   85,   84,   83,   82,   81,   80,   79,   78,   77,
+       76,   73,   72,   71,   69,   68,   66,   64,   62,   61,
 
        60,   59,   58,   57,   56,   54,   52,   49,   48,   47,
        46,   45,   44,   43,   42,   41,   40,   39,   38,   36,
        35,   34,   32,   31,   30,   29,   28,   27,   26,   24,
        22,   18,   17,   15,   14,   13,   12,   11,   10,    9,
-        7,    3,  108,  108,  108,  108,  108,  108,  108,  108,
-      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
-      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
-      108,  108,  108,  108,  108,  108,  108,  108,  108,  108,
-      108
+        7,    3,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109
     } ;
 
-static yyconst flex_int16_t yy_rule_linenum[20] =
+static yyconst flex_int16_t yy_rule_linenum[21] =
     {   0,
-       26,   27,   28,   29,   30,   32,   33,   36,   37,   38,
-       41,   42,   43,   44,   45,   46,   47,   48,   50
+       21,   22,   23,   24,   25,   26,   28,   29,   32,   33,
+       34,   37,   38,   39,   40,   41,   42,   43,   44,   46
     } ;
 
 /* The intent behind this definition is that it'll catch
@@ -605,9 +605,7 @@ static yyconst flex_int16_t yy_rule_linenum[20] =
 #define isatty _isatty
 #define fileno _fileno
     
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
+#define YY_EXTRA_TYPE struct tagParseState *
 
 /* %if-c-only Reentrant structure and macros (non-C++). */
 /* %if-reentrant */
@@ -891,10 +889,10 @@ YY_DECL
     struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
 
 /* %% [7.0] user's declarations go here */
-#line 24 "BsLexerFX.l"
+#line 19 "BsLexerFX.l"
 
 
-#line 898 "BsLexerFX.c"
+#line 896 "BsLexerFX.c"
 
     yylval = yylval_param;
 
@@ -959,13 +957,13 @@ yy_match:
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 109 )
+				if ( yy_current_state >= 110 )
 					yy_c = yy_meta[(unsigned int) yy_c];
 				}
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
 			++yy_cp;
 			}
-		while ( yy_current_state != 108 );
+		while ( yy_current_state != 109 );
 		yy_cp = yyg->yy_last_accepting_cpos;
 		yy_current_state = yyg->yy_last_accepting_state;
 
@@ -984,13 +982,13 @@ do_action:	/* This label is used only to access EOF actions. */
 			{
 			if ( yy_act == 0 )
 				fprintf( stderr, "--scanner backing up\n" );
-			else if ( yy_act < 20 )
+			else if ( yy_act < 21 )
 				fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n",
 				         (long)yy_rule_linenum[yy_act], yytext );
-			else if ( yy_act == 20 )
+			else if ( yy_act == 21 )
 				fprintf( stderr, "--accepting default rule (\"%s\")\n",
 				         yytext );
-			else if ( yy_act == 21 )
+			else if ( yy_act == 22 )
 				fprintf( stderr, "--(end of buffer or a NUL)\n" );
 			else
 				fprintf( stderr, "--EOF (start condition %d)\n", YY_START );
@@ -1009,107 +1007,112 @@ do_action:	/* This label is used only to access EOF actions. */
 case 1:
 /* rule 1 can match eol */
 YY_RULE_SETUP
-#line 26 "BsLexerFX.l"
+#line 21 "BsLexerFX.l"
 { /* Skip blank */ }
 	YY_BREAK
 case 2:
 YY_RULE_SETUP
-#line 27 "BsLexerFX.l"
-{ return TOKEN_INTEGER; }
+#line 22 "BsLexerFX.l"
+{ yylval->intValue = atoi(yytext); return TOKEN_INTEGER; }
 	YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 28 "BsLexerFX.l"
-{ return TOKEN_FLOAT; }
+#line 23 "BsLexerFX.l"
+{ yylval->floatValue = (float)atof(yytext); return TOKEN_FLOAT; }
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 29 "BsLexerFX.l"
-{ return TOKEN_BOOLEAN; }
+#line 24 "BsLexerFX.l"
+{ yylval->strValue = mmalloc_strdup(yyextra->memContext, yytext); return TOKEN_STRING; }
 	YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 30 "BsLexerFX.l"
-{ return TOKEN_STRING; }
+#line 25 "BsLexerFX.l"
+{ yylval->intValue = 1; return TOKEN_BOOLEAN; }
 	YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 32 "BsLexerFX.l"
-{ return TOKEN_LBRACKET; }
+#line 26 "BsLexerFX.l"
+{ yylval->intValue = 0; return TOKEN_BOOLEAN; }
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 33 "BsLexerFX.l"
+#line 28 "BsLexerFX.l"
+{ return TOKEN_LBRACKET; }
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 29 "BsLexerFX.l"
 { return TOKEN_RBRACKET; }
 	YY_BREAK
 /* Shader keywords */
-case 8:
+case 9:
 YY_RULE_SETUP
-#line 36 "BsLexerFX.l"
+#line 32 "BsLexerFX.l"
 { return TOKEN_SEPARABLE; }
 	YY_BREAK
-case 9:
+case 10:
 YY_RULE_SETUP
-#line 37 "BsLexerFX.l"
+#line 33 "BsLexerFX.l"
 { return TOKEN_QUEUE; }
 	YY_BREAK
-case 10:
+case 11:
 YY_RULE_SETUP
-#line 38 "BsLexerFX.l"
+#line 34 "BsLexerFX.l"
 { return TOKEN_PRIORITY; }
 	YY_BREAK
 /* Rasterizer state keywords */
-case 11:
+case 12:
 YY_RULE_SETUP
-#line 41 "BsLexerFX.l"
+#line 37 "BsLexerFX.l"
 { return TOKEN_FILLMODE; }
 	YY_BREAK
-case 12:
+case 13:
 YY_RULE_SETUP
-#line 42 "BsLexerFX.l"
+#line 38 "BsLexerFX.l"
 { return TOKEN_CULLMODE; }
 	YY_BREAK
-case 13:
+case 14:
 YY_RULE_SETUP
-#line 43 "BsLexerFX.l"
+#line 39 "BsLexerFX.l"
 { return TOKEN_DEPTHBIAS; }
 	YY_BREAK
-case 14:
+case 15:
 YY_RULE_SETUP
-#line 44 "BsLexerFX.l"
+#line 40 "BsLexerFX.l"
 { return TOKEN_SDEPTHBIAS; }
 	YY_BREAK
-case 15:
+case 16:
 YY_RULE_SETUP
-#line 45 "BsLexerFX.l"
+#line 41 "BsLexerFX.l"
 { return TOKEN_DEPTHCLIP; }
 	YY_BREAK
-case 16:
+case 17:
 YY_RULE_SETUP
-#line 46 "BsLexerFX.l"
+#line 42 "BsLexerFX.l"
 { return TOKEN_SCISSOR; }
 	YY_BREAK
-case 17:
+case 18:
 YY_RULE_SETUP
-#line 47 "BsLexerFX.l"
+#line 43 "BsLexerFX.l"
 { return TOKEN_MULTISAMPLE; }
 	YY_BREAK
-case 18:
+case 19:
 YY_RULE_SETUP
-#line 48 "BsLexerFX.l"
+#line 44 "BsLexerFX.l"
 { return TOKEN_AALINE; }
 	YY_BREAK
-case 19:
+case 20:
 YY_RULE_SETUP
-#line 50 "BsLexerFX.l"
+#line 46 "BsLexerFX.l"
 { return yytext[0]; }
 	YY_BREAK
-case 20:
+case 21:
 YY_RULE_SETUP
-#line 51 "BsLexerFX.l"
+#line 47 "BsLexerFX.l"
 YY_FATAL_ERROR( "flex scanner jammed" );
 	YY_BREAK
-#line 1113 "BsLexerFX.c"
+#line 1116 "BsLexerFX.c"
 case YY_STATE_EOF(INITIAL):
 	yyterminate();
 
@@ -1425,7 +1428,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 109 )
+			if ( yy_current_state >= 110 )
 				yy_c = yy_meta[(unsigned int) yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1459,11 +1462,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 109 )
+		if ( yy_current_state >= 110 )
 			yy_c = yy_meta[(unsigned int) yy_c];
 		}
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 108);
+	yy_is_jam = (yy_current_state == 109);
 
 	(void)yyg;
 	return yy_is_jam ? 0 : yy_current_state;
@@ -2408,4 +2411,4 @@ void yyfree (void * ptr , yyscan_t yyscanner)
 
 /* %ok-for-header */
 
-#line 50 "BsLexerFX.l"
+#line 46 "BsLexerFX.l"

+ 3 - 5
BansheeSL/BsLexerFX.h

@@ -296,9 +296,7 @@ void yyfree (void * ,yyscan_t yyscanner );
 #define isatty _isatty
 #define fileno _fileno
     
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
+#define YY_EXTRA_TYPE struct tagParseState *
 
 /* %if-c-only Reentrant structure and macros (non-C++). */
 /* %if-reentrant */
@@ -449,8 +447,8 @@ extern int yylex \
 #undef YY_DECL
 #endif
 
-#line 50 "BsLexerFX.l"
+#line 46 "BsLexerFX.l"
 
-#line 455 "BsLexerFX.h"
+#line 453 "BsLexerFX.h"
 #undef yyIN_HEADER
 #endif /* yyHEADER_H */

+ 8 - 12
BansheeSL/BsLexerFX.l

@@ -2,33 +2,29 @@
 #include "BsParserFX.h"
 %}
  
-%option reentrant noyywrap
-%option nounistd
-%option never-interactive
+%option reentrant noyywrap nounistd never-interactive warn nodefault bison-bridge
 %option outfile="BsLexerFX.c" header-file="BsLexerFX.h"
-%option warn nodefault
+%option extra-type="struct tagParseState *"
 %option debug
 
-%option bison-bridge
- 
 LBRACKET		"{"
 RBRACKET		"}"
  
 INTEGER		[0-9][0-9]*
 INTEGER_BIN	0x[0-9][0-9]*
 FLOAT		[0-9]+\.[0-9]+([eE][+-]?[0-9]+)?[fF]?
-BOOLEAN		(true|false)
 STRING		\"[^"\n]*\"
 WS			[ \r\n\t]*
 
 %%
 
 {WS}			{ /* Skip blank */ }
-{INTEGER}       { return TOKEN_INTEGER; }
-{FLOAT}			{ return TOKEN_FLOAT; }
-{BOOLEAN}		{ return TOKEN_BOOLEAN; }
-{STRING}		{ return TOKEN_STRING; }
- 
+{INTEGER}       { yylval->intValue = atoi(yytext); return TOKEN_INTEGER; }
+{FLOAT}			{ yylval->floatValue = (float)atof(yytext); return TOKEN_FLOAT; }
+{STRING}		{ yylval->strValue = mmalloc_strdup(yyextra->memContext, yytext); return TOKEN_STRING; }
+true			{ yylval->intValue = 1; return TOKEN_BOOLEAN; }
+false			{ yylval->intValue = 0; return TOKEN_BOOLEAN; }
+
 {LBRACKET}      { return TOKEN_LBRACKET; }
 {RBRACKET}      { return TOKEN_RBRACKET; }
 

+ 76 - 76
BansheeSL/BsParserFX.c

@@ -57,7 +57,7 @@
 #include "BsLexerFX.h"
 #define inline
 
-	void yyerror(ASTFXNode* root_node, yyscan_t scanner, const char *msg) 
+	void yyerror(ParseState* parse_state, yyscan_t scanner, const char *msg) 
 	{ 
 		fprintf (stderr, "%s\n", msg);
 	}
@@ -424,13 +424,13 @@ do {                                            \
 
 /*ARGSUSED*/
 static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, ASTFXNode* root_node, yyscan_t scanner)
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, ParseState* parse_state, yyscan_t scanner)
 {
   FILE *yyo = yyoutput;
   YYUSE (yyo);
   if (!yyvaluep)
     return;
-  YYUSE (root_node);
+  YYUSE (parse_state);
   YYUSE (scanner);
 # ifdef YYPRINT
   if (yytype < YYNTOKENS)
@@ -451,14 +451,14 @@ yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvalue
 `--------------------------------*/
 
 static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, ASTFXNode* root_node, yyscan_t scanner)
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, ParseState* parse_state, yyscan_t scanner)
 {
   if (yytype < YYNTOKENS)
     YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
   else
     YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
 
-  yy_symbol_value_print (yyoutput, yytype, yyvaluep, root_node, scanner);
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, parse_state, scanner);
   YYFPRINTF (yyoutput, ")");
 }
 
@@ -467,7 +467,7 @@ do {                                                            \
   if (yydebug)                                                  \
     {                                                           \
       YYFPRINTF (stderr, "%s ", Title);                         \
-      yy_symbol_print (stderr, Type, Value, root_node, scanner);        \
+      yy_symbol_print (stderr, Type, Value, parse_state, scanner);        \
       YYFPRINTF (stderr, "\n");                                 \
     }                                                           \
 } while (YYID (0))
@@ -695,13 +695,13 @@ struct yyGLRStack {
 static void yyexpandGLRStack (yyGLRStack* yystackp);
 #endif
 
-static void yyFail (yyGLRStack* yystackp, ASTFXNode* root_node, yyscan_t scanner, const char* yymsg)
+static void yyFail (yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner, const char* yymsg)
   __attribute__ ((__noreturn__));
 static void
-yyFail (yyGLRStack* yystackp, ASTFXNode* root_node, yyscan_t scanner, const char* yymsg)
+yyFail (yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner, const char* yymsg)
 {
   if (yymsg != YY_NULL)
-    yyerror (root_node, scanner, yymsg);
+    yyerror (parse_state, scanner, yymsg);
   YYLONGJMP (yystackp->yyexception_buffer, 1);
 }
 
@@ -767,12 +767,12 @@ yyfill (yyGLRStackItem *yyvsp, int *yylow, int yylow1, yybool yynormal)
 /*ARGSUSED*/ static YYRESULTTAG
 yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
               yyGLRStack* yystackp,
-              YYSTYPE* yyvalp, ASTFXNode* root_node, yyscan_t scanner)
+              YYSTYPE* yyvalp, ParseState* parse_state, yyscan_t scanner)
 {
   yybool yynormal __attribute__ ((__unused__)) =
     (yystackp->yysplitPoint == YY_NULL);
   int yylow;
-  YYUSE (root_node);
+  YYUSE (parse_state);
   YYUSE (scanner);
 # undef yyerrok
 # define yyerrok (yystackp->yyerrState = 0)
@@ -790,7 +790,7 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
 # define YYFILL(N) yyfill (yyvsp, &yylow, N, yynormal)
 # undef YYBACKUP
 # define YYBACKUP(Token, Value)                                              \
-  return yyerror (root_node, scanner, YY_("syntax error: cannot back up")),     \
+  return yyerror (parse_state, scanner, YY_("syntax error: cannot back up")),     \
          yyerrok, yyerr
 
   yylow = 1;
@@ -809,13 +809,13 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
   case 3:
 /* Line 868 of glr.c  */
 #line 64 "BsParserFX.y"
-    { nodeOptionsAdd(root_node->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
+    { nodeOptionsAdd(parse_state->memContext, parse_state->rootNode->options, &(((yyGLRStackItem const *)yyvsp)[YYFILL ((1) - (2))].yystate.yysemantics.yysval.nodeOption)); }
     break;
 
   case 5:
 /* Line 868 of glr.c  */
 #line 72 "BsParserFX.y"
-    { ((*yyvalp).nodeOption).type = OT_Separable; ((*yyvalp).nodeOption).value.boolValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.boolValue); }
+    { ((*yyvalp).nodeOption).type = OT_Separable; ((*yyvalp).nodeOption).value.intValue = (((yyGLRStackItem const *)yyvsp)[YYFILL ((3) - (4))].yystate.yysemantics.yysval.intValue); }
     break;
 
   case 6:
@@ -868,10 +868,10 @@ yyuserMerge (int yyn, YYSTYPE* yy0, YYSTYPE* yy1)
 
 /*ARGSUSED*/
 static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, ASTFXNode* root_node, yyscan_t scanner)
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, ParseState* parse_state, yyscan_t scanner)
 {
   YYUSE (yyvaluep);
-  YYUSE (root_node);
+  YYUSE (parse_state);
   YYUSE (scanner);
 
   if (!yymsg)
@@ -894,11 +894,11 @@ yyrhsLength (yyRuleNum yyrule)
 }
 
 static void
-yydestroyGLRState (char const *yymsg, yyGLRState *yys, ASTFXNode* root_node, yyscan_t scanner)
+yydestroyGLRState (char const *yymsg, yyGLRState *yys, ParseState* parse_state, yyscan_t scanner)
 {
   if (yys->yyresolved)
     yydestruct (yymsg, yystos[yys->yylrState],
-                &yys->yysemantics.yysval, root_node, scanner);
+                &yys->yysemantics.yysval, parse_state, scanner);
   else
     {
 #if YYDEBUG
@@ -909,7 +909,7 @@ yydestroyGLRState (char const *yymsg, yyGLRState *yys, ASTFXNode* root_node, yys
           else
             YYFPRINTF (stderr, "%s incomplete ", yymsg);
           yy_symbol_print (stderr, yystos[yys->yylrState],
-                           YY_NULL, root_node, scanner);
+                           YY_NULL, parse_state, scanner);
           YYFPRINTF (stderr, "\n");
         }
 #endif
@@ -922,7 +922,7 @@ yydestroyGLRState (char const *yymsg, yyGLRState *yys, ASTFXNode* root_node, yys
           for (yyrh = yyoption->yystate, yyn = yyrhsLength (yyoption->yyrule);
                yyn > 0;
                yyrh = yyrh->yypred, yyn -= 1)
-            yydestroyGLRState (yymsg, yyrh, root_node, scanner);
+            yydestroyGLRState (yymsg, yyrh, parse_state, scanner);
         }
     }
 }
@@ -1287,7 +1287,7 @@ yyglrShiftDefer (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
  *  for userAction.  */
 static inline YYRESULTTAG
 yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
-            YYSTYPE* yyvalp, ASTFXNode* root_node, yyscan_t scanner)
+            YYSTYPE* yyvalp, ParseState* parse_state, yyscan_t scanner)
 {
   int yynrhs = yyrhsLength (yyrule);
 
@@ -1300,7 +1300,7 @@ yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
       yystackp->yyspaceLeft += yynrhs;
       yystackp->yytops.yystates[0] = & yystackp->yynextFree[-1].yystate;
       return yyuserAction (yyrule, yynrhs, rhs, yystackp,
-                           yyvalp, root_node, scanner);
+                           yyvalp, parse_state, scanner);
     }
   else
     {
@@ -1321,7 +1321,7 @@ yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
       yyupdateSplit (yystackp, yys);
       yystackp->yytops.yystates[yyk] = yys;
       return yyuserAction (yyrule, yynrhs, yyrhsVals + YYMAXRHS + YYMAXLEFT - 1,
-                           yystackp, yyvalp, root_node, scanner);
+                           yystackp, yyvalp, parse_state, scanner);
     }
 }
 
@@ -1340,7 +1340,7 @@ do {                                    \
 
 /*ARGSUSED*/ static inline void
 yy_reduce_print (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
-                 YYSTYPE* yyvalp, ASTFXNode* root_node, yyscan_t scanner)
+                 YYSTYPE* yyvalp, ParseState* parse_state, yyscan_t scanner)
 {
   int yynrhs = yyrhsLength (yyrule);
   yybool yynormal __attribute__ ((__unused__)) =
@@ -1349,7 +1349,7 @@ yy_reduce_print (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
   int yylow = 1;
   int yyi;
   YYUSE (yyvalp);
-  YYUSE (root_node);
+  YYUSE (parse_state);
   YYUSE (scanner);
   YYFPRINTF (stderr, "Reducing stack %lu by rule %d (line %lu):\n",
              (unsigned long int) yyk, yyrule - 1,
@@ -1360,7 +1360,7 @@ yy_reduce_print (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
       YYFPRINTF (stderr, "   $%d = ", yyi + 1);
       yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
                        &(((yyGLRStackItem const *)yyvsp)[YYFILL ((yyi + 1) - (yynrhs))].yystate.yysemantics.yysval)
-                                              , root_node, scanner);
+                                              , parse_state, scanner);
       YYFPRINTF (stderr, "\n");
     }
 }
@@ -1379,7 +1379,7 @@ yy_reduce_print (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
  */
 static inline YYRESULTTAG
 yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
-             yybool yyforceEval, ASTFXNode* root_node, yyscan_t scanner)
+             yybool yyforceEval, ParseState* parse_state, yyscan_t scanner)
 {
   size_t yyposn = yystackp->yytops.yystates[yyk]->yyposn;
 
@@ -1387,8 +1387,8 @@ yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
     {
       YYSTYPE yysval;
 
-      YY_REDUCE_PRINT ((yystackp, yyk, yyrule, &yysval, root_node, scanner));
-      YYCHK (yydoAction (yystackp, yyk, yyrule, &yysval, root_node, scanner));
+      YY_REDUCE_PRINT ((yystackp, yyk, yyrule, &yysval, parse_state, scanner));
+      YYCHK (yydoAction (yystackp, yyk, yyrule, &yysval, parse_state, scanner));
       YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyrule], &yysval, &yyloc);
       yyglrShift (yystackp, yyk,
                   yyLRgotoState (yystackp->yytops.yystates[yyk]->yylrState,
@@ -1581,7 +1581,7 @@ yypreference (yySemanticOption* y0, yySemanticOption* y1)
 }
 
 static YYRESULTTAG yyresolveValue (yyGLRState* yys,
-                                   yyGLRStack* yystackp, ASTFXNode* root_node, yyscan_t scanner);
+                                   yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner);
 
 
 /** Resolve the previous N states starting at and including state S.  If result
@@ -1591,14 +1591,14 @@ static YYRESULTTAG yyresolveValue (yyGLRState* yys,
  *  if necessary.  */
 static YYRESULTTAG
 yyresolveStates (yyGLRState* yys, int yyn,
-                 yyGLRStack* yystackp, ASTFXNode* root_node, yyscan_t scanner)
+                 yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner)
 {
   if (0 < yyn)
     {
       YYASSERT (yys->yypred);
-      YYCHK (yyresolveStates (yys->yypred, yyn-1, yystackp, root_node, scanner));
+      YYCHK (yyresolveStates (yys->yypred, yyn-1, yystackp, parse_state, scanner));
       if (! yys->yyresolved)
-        YYCHK (yyresolveValue (yys, yystackp, root_node, scanner));
+        YYCHK (yyresolveValue (yys, yystackp, parse_state, scanner));
     }
   return yyok;
 }
@@ -1609,17 +1609,17 @@ yyresolveStates (yyGLRState* yys, int yyn,
  *  semantic values if invoked).  */
 static YYRESULTTAG
 yyresolveAction (yySemanticOption* yyopt, yyGLRStack* yystackp,
-                 YYSTYPE* yyvalp, ASTFXNode* root_node, yyscan_t scanner)
+                 YYSTYPE* yyvalp, ParseState* parse_state, yyscan_t scanner)
 {
   yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1];
   int yynrhs = yyrhsLength (yyopt->yyrule);
   YYRESULTTAG yyflag =
-    yyresolveStates (yyopt->yystate, yynrhs, yystackp, root_node, scanner);
+    yyresolveStates (yyopt->yystate, yynrhs, yystackp, parse_state, scanner);
   if (yyflag != yyok)
     {
       yyGLRState *yys;
       for (yys = yyopt->yystate; yynrhs > 0; yys = yys->yypred, yynrhs -= 1)
-        yydestroyGLRState ("Cleanup: popping", yys, root_node, scanner);
+        yydestroyGLRState ("Cleanup: popping", yys, parse_state, scanner);
       return yyflag;
     }
 
@@ -1631,7 +1631,7 @@ yyresolveAction (yySemanticOption* yyopt, yyGLRStack* yystackp,
     yylval = yyopt->yyval;
     yyflag = yyuserAction (yyopt->yyrule, yynrhs,
                            yyrhsVals + YYMAXRHS + YYMAXLEFT - 1,
-                           yystackp, yyvalp, root_node, scanner);
+                           yystackp, yyvalp, parse_state, scanner);
     yychar = yychar_current;
     yylval = yylval_current;
   }
@@ -1688,7 +1688,7 @@ yyreportTree (yySemanticOption* yyx, int yyindent)
 
 /*ARGSUSED*/ static YYRESULTTAG
 yyreportAmbiguity (yySemanticOption* yyx0,
-                   yySemanticOption* yyx1, ASTFXNode* root_node, yyscan_t scanner)
+                   yySemanticOption* yyx1, ParseState* parse_state, yyscan_t scanner)
 {
   YYUSE (yyx0);
   YYUSE (yyx1);
@@ -1702,7 +1702,7 @@ yyreportAmbiguity (yySemanticOption* yyx0,
   YYFPRINTF (stderr, "\n");
 #endif
 
-  yyerror (root_node, scanner, YY_("syntax is ambiguous"));
+  yyerror (parse_state, scanner, YY_("syntax is ambiguous"));
   return yyabort;
 }
 
@@ -1713,7 +1713,7 @@ yyreportAmbiguity (yySemanticOption* yyx0,
  *  of whether result = yyok, S has been left with consistent data so that
  *  yydestroyGLRState can be invoked if necessary.  */
 static YYRESULTTAG
-yyresolveValue (yyGLRState* yys, yyGLRStack* yystackp, ASTFXNode* root_node, yyscan_t scanner)
+yyresolveValue (yyGLRState* yys, yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner)
 {
   yySemanticOption* yyoptionList = yys->yysemantics.yyfirstVal;
   yySemanticOption* yybest = yyoptionList;
@@ -1736,7 +1736,7 @@ yyresolveValue (yyGLRState* yys, yyGLRStack* yystackp, ASTFXNode* root_node, yys
           switch (yypreference (yybest, yyp))
             {
             case 0:
-              return yyreportAmbiguity (yybest, yyp, root_node, scanner);
+              return yyreportAmbiguity (yybest, yyp, parse_state, scanner);
               break;
             case 1:
               yymerge = yytrue;
@@ -1761,19 +1761,19 @@ yyresolveValue (yyGLRState* yys, yyGLRStack* yystackp, ASTFXNode* root_node, yys
     {
       yySemanticOption* yyp;
       int yyprec = yydprec[yybest->yyrule];
-      yyflag = yyresolveAction (yybest, yystackp, &yysval, root_node, scanner);
+      yyflag = yyresolveAction (yybest, yystackp, &yysval, parse_state, scanner);
       if (yyflag == yyok)
         for (yyp = yybest->yynext; yyp != YY_NULL; yyp = yyp->yynext)
           {
             if (yyprec == yydprec[yyp->yyrule])
               {
                 YYSTYPE yysval_other;
-                yyflag = yyresolveAction (yyp, yystackp, &yysval_other, root_node, scanner);
+                yyflag = yyresolveAction (yyp, yystackp, &yysval_other, parse_state, scanner);
                 if (yyflag != yyok)
                   {
                     yydestruct ("Cleanup: discarding incompletely merged value for",
                                 yystos[yys->yylrState],
-                                &yysval, root_node, scanner);
+                                &yysval, parse_state, scanner);
                     break;
                   }
                 yyuserMerge (yymerger[yyp->yyrule], &yysval, &yysval_other);
@@ -1781,7 +1781,7 @@ yyresolveValue (yyGLRState* yys, yyGLRStack* yystackp, ASTFXNode* root_node, yys
           }
     }
   else
-    yyflag = yyresolveAction (yybest, yystackp, &yysval, root_node, scanner);
+    yyflag = yyresolveAction (yybest, yystackp, &yysval, parse_state, scanner);
 
   if (yyflag == yyok)
     {
@@ -1794,7 +1794,7 @@ yyresolveValue (yyGLRState* yys, yyGLRStack* yystackp, ASTFXNode* root_node, yys
 }
 
 static YYRESULTTAG
-yyresolveStack (yyGLRStack* yystackp, ASTFXNode* root_node, yyscan_t scanner)
+yyresolveStack (yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner)
 {
   if (yystackp->yysplitPoint != YY_NULL)
     {
@@ -1806,7 +1806,7 @@ yyresolveStack (yyGLRStack* yystackp, ASTFXNode* root_node, yyscan_t scanner)
            yys = yys->yypred, yyn += 1)
         continue;
       YYCHK (yyresolveStates (yystackp->yytops.yystates[0], yyn, yystackp
-                             , root_node, scanner));
+                             , parse_state, scanner));
     }
   return yyok;
 }
@@ -1843,7 +1843,7 @@ yycompressStack (yyGLRStack* yystackp)
 
 static YYRESULTTAG
 yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
-                   size_t yyposn, ASTFXNode* root_node, yyscan_t scanner)
+                   size_t yyposn, ParseState* parse_state, yyscan_t scanner)
 {
   int yyaction;
   const short int* yyconflicts;
@@ -1867,7 +1867,7 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
               yymarkStackDeleted (yystackp, yyk);
               return yyok;
             }
-          YYCHK (yyglrReduce (yystackp, yyk, yyrule, yyfalse, root_node, scanner));
+          YYCHK (yyglrReduce (yystackp, yyk, yyrule, yyfalse, parse_state, scanner));
         }
       else
         {
@@ -1899,9 +1899,9 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
                           (unsigned long int) yynewStack,
                           (unsigned long int) yyk));
               YYCHK (yyglrReduce (yystackp, yynewStack,
-                                  *yyconflicts, yyfalse, root_node, scanner));
+                                  *yyconflicts, yyfalse, parse_state, scanner));
               YYCHK (yyprocessOneStack (yystackp, yynewStack,
-                                        yyposn, root_node, scanner));
+                                        yyposn, parse_state, scanner));
               yyconflicts += 1;
             }
 
@@ -1916,19 +1916,19 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
             }
           else
             YYCHK (yyglrReduce (yystackp, yyk, -yyaction,
-                                yyfalse, root_node, scanner));
+                                yyfalse, parse_state, scanner));
         }
     }
   return yyok;
 }
 
 /*ARGSUSED*/ static void
-yyreportSyntaxError (yyGLRStack* yystackp, ASTFXNode* root_node, yyscan_t scanner)
+yyreportSyntaxError (yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner)
 {
   if (yystackp->yyerrState != 0)
     return;
 #if ! YYERROR_VERBOSE
-  yyerror (root_node, scanner, YY_("syntax error"));
+  yyerror (parse_state, scanner, YY_("syntax error"));
 #else
   {
   yySymbol yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
@@ -2043,12 +2043,12 @@ yyreportSyntaxError (yyGLRStack* yystackp, ASTFXNode* root_node, yyscan_t scanne
               yyformat++;
             }
         }
-      yyerror (root_node, scanner, yymsg);
+      yyerror (parse_state, scanner, yymsg);
       YYFREE (yymsg);
     }
   else
     {
-      yyerror (root_node, scanner, YY_("syntax error"));
+      yyerror (parse_state, scanner, YY_("syntax error"));
       yyMemoryExhausted (yystackp);
     }
   }
@@ -2060,7 +2060,7 @@ yyreportSyntaxError (yyGLRStack* yystackp, ASTFXNode* root_node, yyscan_t scanne
    yylval, and yylloc are the syntactic category, semantic value, and location
    of the lookahead.  */
 /*ARGSUSED*/ static void
-yyrecoverSyntaxError (yyGLRStack* yystackp, ASTFXNode* root_node, yyscan_t scanner)
+yyrecoverSyntaxError (yyGLRStack* yystackp, ParseState* parse_state, yyscan_t scanner)
 {
   size_t yyk;
   int yyj;
@@ -2072,12 +2072,12 @@ yyrecoverSyntaxError (yyGLRStack* yystackp, ASTFXNode* root_node, yyscan_t scann
       {
         yySymbol yytoken;
         if (yychar == YYEOF)
-          yyFail (yystackp, root_node, scanner, YY_NULL);
+          yyFail (yystackp, parse_state, scanner, YY_NULL);
         if (yychar != YYEMPTY)
           {
             yytoken = YYTRANSLATE (yychar);
             yydestruct ("Error: discarding",
-                        yytoken, &yylval, root_node, scanner);
+                        yytoken, &yylval, parse_state, scanner);
           }
         YYDPRINTF ((stderr, "Reading a token: "));
         yychar = YYLEX;
@@ -2109,7 +2109,7 @@ yyrecoverSyntaxError (yyGLRStack* yystackp, ASTFXNode* root_node, yyscan_t scann
     if (yystackp->yytops.yystates[yyk] != YY_NULL)
       break;
   if (yyk >= yystackp->yytops.yysize)
-    yyFail (yystackp, root_node, scanner, YY_NULL);
+    yyFail (yystackp, parse_state, scanner, YY_NULL);
   for (yyk += 1; yyk < yystackp->yytops.yysize; yyk += 1)
     yymarkStackDeleted (yystackp, yyk);
   yyremoveDeletes (yystackp);
@@ -2137,13 +2137,13 @@ yyrecoverSyntaxError (yyGLRStack* yystackp, ASTFXNode* root_node, yyscan_t scann
             }
         }
       if (yys->yypred != YY_NULL)
-        yydestroyGLRState ("Error: popping", yys, root_node, scanner);
+        yydestroyGLRState ("Error: popping", yys, parse_state, scanner);
       yystackp->yytops.yystates[0] = yys->yypred;
       yystackp->yynextFree -= 1;
       yystackp->yyspaceLeft += 1;
     }
   if (yystackp->yytops.yystates[0] == YY_NULL)
-    yyFail (yystackp, root_node, scanner, YY_NULL);
+    yyFail (yystackp, parse_state, scanner, YY_NULL);
 }
 
 #define YYCHK1(YYE)                                                          \
@@ -2168,7 +2168,7 @@ yyrecoverSyntaxError (yyGLRStack* yystackp, ASTFXNode* root_node, yyscan_t scann
 `----------*/
 
 int
-yyparse (ASTFXNode* root_node, yyscan_t scanner)
+yyparse (ParseState* parse_state, yyscan_t scanner)
 {
   int yyresult;
   yyGLRStack yystack;
@@ -2214,10 +2214,10 @@ yyparse (ASTFXNode* root_node, yyscan_t scanner)
               if (yyrule == 0)
                 {
 
-                  yyreportSyntaxError (&yystack, root_node, scanner);
+                  yyreportSyntaxError (&yystack, parse_state, scanner);
                   goto yyuser_error;
                 }
-              YYCHK1 (yyglrReduce (&yystack, 0, yyrule, yytrue, root_node, scanner));
+              YYCHK1 (yyglrReduce (&yystack, 0, yyrule, yytrue, parse_state, scanner));
             }
           else
             {
@@ -2254,11 +2254,11 @@ yyparse (ASTFXNode* root_node, yyscan_t scanner)
               else if (yyisErrorAction (yyaction))
                 {
 
-                  yyreportSyntaxError (&yystack, root_node, scanner);
+                  yyreportSyntaxError (&yystack, parse_state, scanner);
                   goto yyuser_error;
                 }
               else
-                YYCHK1 (yyglrReduce (&yystack, 0, -yyaction, yytrue, root_node, scanner));
+                YYCHK1 (yyglrReduce (&yystack, 0, -yyaction, yytrue, parse_state, scanner));
             }
         }
 
@@ -2290,17 +2290,17 @@ yyparse (ASTFXNode* root_node, yyscan_t scanner)
              on yylval in the event of memory exhaustion.  */
 
           for (yys = 0; yys < yystack.yytops.yysize; yys += 1)
-            YYCHK1 (yyprocessOneStack (&yystack, yys, yyposn, root_node, scanner));
+            YYCHK1 (yyprocessOneStack (&yystack, yys, yyposn, parse_state, scanner));
           yyremoveDeletes (&yystack);
           if (yystack.yytops.yysize == 0)
             {
               yyundeleteLastStack (&yystack);
               if (yystack.yytops.yysize == 0)
-                yyFail (&yystack, root_node, scanner, YY_("syntax error"));
-              YYCHK1 (yyresolveStack (&yystack, root_node, scanner));
+                yyFail (&yystack, parse_state, scanner, YY_("syntax error"));
+              YYCHK1 (yyresolveStack (&yystack, parse_state, scanner));
               YYDPRINTF ((stderr, "Returning to deterministic operation.\n"));
 
-              yyreportSyntaxError (&yystack, root_node, scanner);
+              yyreportSyntaxError (&yystack, parse_state, scanner);
               goto yyuser_error;
             }
 
@@ -2331,7 +2331,7 @@ yyparse (ASTFXNode* root_node, yyscan_t scanner)
 
           if (yystack.yytops.yysize == 1)
             {
-              YYCHK1 (yyresolveStack (&yystack, root_node, scanner));
+              YYCHK1 (yyresolveStack (&yystack, parse_state, scanner));
               YYDPRINTF ((stderr, "Returning to deterministic operation.\n"));
               yycompressStack (&yystack);
               break;
@@ -2339,7 +2339,7 @@ yyparse (ASTFXNode* root_node, yyscan_t scanner)
         }
       continue;
     yyuser_error:
-      yyrecoverSyntaxError (&yystack, root_node, scanner);
+      yyrecoverSyntaxError (&yystack, parse_state, scanner);
       yyposn = yystack.yytops.yystates[0]->yyposn;
     }
 
@@ -2356,14 +2356,14 @@ yyparse (ASTFXNode* root_node, yyscan_t scanner)
   goto yyreturn;
 
  yyexhaustedlab:
-  yyerror (root_node, scanner, YY_("memory exhausted"));
+  yyerror (parse_state, scanner, YY_("memory exhausted"));
   yyresult = 2;
   goto yyreturn;
 
  yyreturn:
   if (yychar != YYEMPTY)
     yydestruct ("Cleanup: discarding lookahead",
-                YYTRANSLATE (yychar), &yylval, root_node, scanner);
+                YYTRANSLATE (yychar), &yylval, parse_state, scanner);
 
   /* If the stack is well-formed, pop the stack until it is empty,
      destroying its entries as we go.  But free the stack regardless
@@ -2382,7 +2382,7 @@ yyparse (ASTFXNode* root_node, yyscan_t scanner)
                   {
                     yyGLRState *yys = yystates[yyk];
                   if (yys->yypred != YY_NULL)
-                      yydestroyGLRState ("Cleanup: popping", yys, root_node, scanner);
+                      yydestroyGLRState ("Cleanup: popping", yys, parse_state, scanner);
                     yystates[yyk] = yys->yypred;
                     yystack.yynextFree -= 1;
                     yystack.yyspaceLeft += 1;

+ 4 - 4
BansheeSL/BsParserFX.h

@@ -43,6 +43,7 @@ extern int yydebug;
 /* Line 2579 of glr.c  */
 #line 13 "BsParserFX.y"
 
+#include "BsMMAlloc.h"
 #include "BsASTFX.h"
 
 #ifndef YY_TYPEDEF_YY_SCANNER_T
@@ -53,7 +54,7 @@ extern int yydebug;
 
 
 /* Line 2579 of glr.c  */
-#line 57 "BsParserFX.h"
+#line 58 "BsParserFX.h"
 
 /* Tokens.  */
 #ifndef YYTOKENTYPE
@@ -85,11 +86,10 @@ extern int yydebug;
 typedef union YYSTYPE
 {
 /* Line 2579 of glr.c  */
-#line 33 "BsParserFX.y"
+#line 34 "BsParserFX.y"
 
 	int intValue;
 	float floatValue;
-	int boolValue;
 	const char* strValue;
 	ASTFXNode* nodePtr;
 	NodeOption nodeOption;
@@ -104,6 +104,6 @@ typedef union YYSTYPE
 #endif
 
 
-int yyparse (ASTFXNode* root_node, yyscan_t scanner);
+int yyparse (ParseState* parse_state, yyscan_t scanner);
 
 #endif /* !YY_YY_BSPARSERFX_H_INCLUDED  */

+ 6 - 6
BansheeSL/BsParserFX.y

@@ -3,7 +3,7 @@
 #include "BsLexerFX.h"
 #define inline
 
-	void yyerror(ASTFXNode* root_node, yyscan_t scanner, const char *msg) 
+	void yyerror(ParseState* parse_state, yyscan_t scanner, const char *msg) 
 	{ 
 		fprintf (stderr, "%s\n", msg);
 	}
@@ -11,6 +11,7 @@
 %}
 
 %code requires{
+#include "BsMMAlloc.h"
 #include "BsASTFX.h"
 
 #ifndef YY_TYPEDEF_YY_SCANNER_T
@@ -26,14 +27,13 @@
 %define api.pure
 %debug
 %lex-param { yyscan_t scanner }
-%parse-param { ASTFXNode* root_node }
+%parse-param { ParseState* parse_state }
 %parse-param { yyscan_t scanner }
 %glr-parser
 
 %union {
 	int intValue;
 	float floatValue;
-	int boolValue;
 	const char* strValue;
 	ASTFXNode* nodePtr;
 	NodeOption nodeOption;
@@ -47,7 +47,7 @@
 
 %token <intValue>	TOKEN_INTEGER
 %token <floatValue> TOKEN_FLOAT
-%token <boolValue>	TOKEN_BOOLEAN
+%token <intValue>	TOKEN_BOOLEAN
 %token <strValue>	TOKEN_STRING
 
 %token	TOKEN_FILLMODE TOKEN_CULLMODE TOKEN_DEPTHBIAS TOKEN_SDEPTHBIAS
@@ -61,7 +61,7 @@
 
 shader
 	: /* empty */				{ }
-	| shader_statement shader	{ nodeOptionsAdd(root_node->options, &$1); }
+	| shader_statement shader	{ nodeOptionsAdd(parse_state->memContext, parse_state->rootNode->options, &$1); }
 	;
 
 shader_statement
@@ -69,7 +69,7 @@ shader_statement
 	;
 
 shader_option_decl
-	: TOKEN_SEPARABLE '=' TOKEN_BOOLEAN ';'		{ $$.type = OT_Separable; $$.value.boolValue = $3; }
+	: TOKEN_SEPARABLE '=' TOKEN_BOOLEAN ';'		{ $$.type = OT_Separable; $$.value.intValue = $3; }
 	| TOKEN_QUEUE '=' TOKEN_INTEGER ';'			{ $$.type = OT_Queue; $$.value.intValue = $3; }
 	| TOKEN_PRIORITY '=' TOKEN_INTEGER ';'		{ $$.type = OT_Priority; $$.value.intValue = $3; }
 	;

+ 12 - 5
BansheeSL/Include/BsASTFX.h

@@ -7,6 +7,7 @@
 typedef enum tagNodeType NodeType;
 typedef enum tagOptionType OptionType;
 typedef enum tagOptionDataType OptionDataType;
+typedef struct tagParseState ParseState;
 typedef struct tagOptionInfo OptionInfo;
 typedef union tagOptionData OptionData;
 typedef struct tagNodeOptions NodeOptions;
@@ -40,6 +41,12 @@ enum tagOptionDataType
 	ODT_Complex
 };
 
+struct tagParseState
+{
+	ASTFXNode* rootNode;
+	void* memContext;
+};
+
 struct tagOptionInfo
 {
 	OptionType type;
@@ -78,14 +85,14 @@ struct tagASTFXNode
 
 OptionInfo OPTION_LOOKUP[];
 
-NodeOptions* nodeOptionsCreate();
+NodeOptions* nodeOptionsCreate(void* context);
 void nodeOptionDelete(NodeOption* option);
 void nodeOptionsDelete(NodeOptions* options);
-void nodeOptionsResize(NodeOptions* options, int size);
-void nodeOptionsGrowIfNeeded(NodeOptions* options);
-void nodeOptionsAdd(NodeOptions* options, NodeOption* option);
+void nodeOptionsResize(void* context, NodeOptions* options, int size);
+void nodeOptionsGrowIfNeeded(void* context, NodeOptions* options);
+void nodeOptionsAdd(void* context, NodeOptions* options, NodeOption* option);
 
-ASTFXNode* nodeCreate(NodeType type);
+ASTFXNode* nodeCreate(void* context, NodeType type);
 void nodeDelete(ASTFXNode* node);
 
 #endif

+ 10 - 0
BansheeSL/Include/BsMMAlloc.h

@@ -0,0 +1,10 @@
+#ifndef __MMALLOC_H__
+#define __MMALLOC_H__
+
+void* mmalloc_new_context();
+void mmalloc_free_context(void* context);
+void* mmalloc(void* context, int size);
+void mmfree(void* ptr);
+char* mmalloc_strdup(void* context, char* input);
+
+#endif

+ 68 - 0
BansheeSL/Source/BSMMAlloc.c

@@ -0,0 +1,68 @@
+#include "BsMMAlloc.h"
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct tagMMAllocHeader MMAllocHeader;
+
+struct tagMMAllocHeader
+{
+	MMAllocHeader* next;
+	MMAllocHeader* prev;
+};
+
+void* mmalloc_new_context()
+{
+	MMAllocHeader* header = (MMAllocHeader*)malloc(sizeof(MMAllocHeader));
+	header->next = 0;
+	header->prev = 0;
+
+	return header;
+}
+
+void mmalloc_free_context(void* context)
+{
+	MMAllocHeader* header = (MMAllocHeader*)context;
+	while (header->next != 0)
+		mmfree(header->next);
+
+	free(header);
+}
+
+void* mmalloc(void* context, int size)
+{
+	void* buffer = malloc(size + sizeof(MMAllocHeader));
+
+	MMAllocHeader* header = (MMAllocHeader*)buffer;
+	MMAllocHeader* parent = (MMAllocHeader*)context;
+
+	header->next = parent->next;
+	header->prev = parent;
+	parent->next = header;
+
+	return (char*)buffer + sizeof(MMAllocHeader);
+}
+
+void mmfree(void* ptr)
+{
+	void* buffer = (char*)ptr - sizeof(MMAllocHeader);
+	MMAllocHeader* header = (MMAllocHeader*)buffer;
+
+	if (header->prev)
+		header->prev->next = header->next;
+
+	if (header->next)
+		header->next->prev = header->prev;
+
+	free(buffer);
+}
+
+char* mmalloc_strdup(void* context, const char* input)
+{
+	size_t length = strlen(input);
+	char* output = mmalloc(context, sizeof(char) * (length + 1));
+
+	memcpy(output, input, length);
+	output[length] = '\0';
+
+	return output;
+}

+ 19 - 18
BansheeSL/Source/BsASTFX.c

@@ -1,4 +1,5 @@
 #include "BsASTFX.h"
+#include "BsMMAlloc.h"
 
 OptionInfo OPTION_LOOKUP[] =
 {
@@ -8,15 +9,15 @@ OptionInfo OPTION_LOOKUP[] =
 	{ OT_Queue, ODT_Int },
 };
 
-NodeOptions* nodeOptionsCreate()
+NodeOptions* nodeOptionsCreate(void* context)
 {
 	static const int BUFFER_SIZE = 5;
 
-	NodeOptions* options = (NodeOptions*)malloc(sizeof(NodeOptions));
+	NodeOptions* options = (NodeOptions*)mmalloc(context, sizeof(NodeOptions));
 	options->count = 0;
 	options->bufferSize = BUFFER_SIZE;
 
-	options->entries = (NodeOption*)malloc(sizeof(NodeOption) * options->bufferSize);
+	options->entries = (NodeOption*)mmalloc(context, sizeof(NodeOption) * options->bufferSize);
 	memset(options->entries, 0, sizeof(NodeOption) * options->bufferSize);
 
 	return options;
@@ -26,12 +27,12 @@ void nodeOptionDelete(NodeOption* option)
 {
 	if (OPTION_LOOKUP[(int)option->type].dataType == ODT_Complex)
 	{
-		free(option->value.complexValue); // TODO - Maybe this has more complex delete logic? (It probably will have)
+		mmfree(option->value.complexValue); // TODO - Maybe this has more complex delete logic? (It probably will have)
 		option->value.complexValue = 0;
 	}
 	else if (OPTION_LOOKUP[(int)option->type].dataType == ODT_String)
 	{
-		free((void*)option->value.strValue);
+		mmfree((void*)option->value.strValue);
 		option->value.strValue = 0;
 	}
 }
@@ -43,11 +44,11 @@ void nodeOptionsDelete(NodeOptions* options)
 	for (i = 0; i < options->count; i++)
 		nodeOptionDelete(&options->entries[i]);
 
-	free(options->entries);
-	free(options);
+	mmfree(options->entries);
+	mmfree(options);
 }
 
-void nodeOptionsResize(NodeOptions* options, int size)
+void nodeOptionsResize(void* context, NodeOptions* options, int size)
 {
 	NodeOption* originalEntries = options->entries;
 	int originalSize = options->bufferSize;
@@ -65,7 +66,7 @@ void nodeOptionsResize(NodeOptions* options, int size)
 
 	sizeToCopy = elementsToCopy * sizeof(NodeOption);
 
-	options->entries = (NodeOption*)malloc(sizeof(NodeOption) * options->bufferSize);
+	options->entries = (NodeOption*)mmalloc(context, sizeof(NodeOption) * options->bufferSize);
 
 	memcpy(options->entries, originalEntries, sizeToCopy);
 	memset(options->entries + elementsToCopy, 0, sizeof(NodeOption) * options->bufferSize - sizeToCopy);
@@ -73,29 +74,29 @@ void nodeOptionsResize(NodeOptions* options, int size)
 	for (i = 0; i < originalCount; i++)
 		nodeOptionDelete(&originalEntries[i]);
 
-	free(originalEntries);
+	mmfree(originalEntries);
 }
 
-void nodeOptionsGrowIfNeeded(NodeOptions* options)
+void nodeOptionsGrowIfNeeded(void* context, NodeOptions* options)
 {
 	static const int BUFFER_GROW = 10;
 
 	if (options->count == options->bufferSize)
-		nodeOptionsResize(options, options->bufferSize + BUFFER_GROW);
+		nodeOptionsResize(context, options, options->bufferSize + BUFFER_GROW);
 }
 
-void nodeOptionsAdd(NodeOptions* options, NodeOption* option)
+void nodeOptionsAdd(void* context, NodeOptions* options, NodeOption* option)
 {
-	nodeOptionsGrowIfNeeded(options);
+	nodeOptionsGrowIfNeeded(context, options);
 
 	options->entries[options->count] = *option;
 	options->count++;
 }
 
-ASTFXNode* nodeCreate(NodeType type)
+ASTFXNode* nodeCreate(void* context, NodeType type)
 {
-	ASTFXNode* node = (ASTFXNode*)malloc(sizeof(ASTFXNode));
-	node->options = nodeOptionsCreate();
+	ASTFXNode* node = (ASTFXNode*)mmalloc(context, sizeof(ASTFXNode));
+	node->options = nodeOptionsCreate(context);
 	node->type = type;
 
 	return node;
@@ -105,5 +106,5 @@ void nodeDelete(ASTFXNode* node)
 {
 	nodeOptionsDelete(node->options);
 
-	free(node);
+	mmfree(node);
 }

+ 15 - 10
BansheeSL/Source/BsSLPlugin.cpp

@@ -4,6 +4,7 @@
 #include "BsDataStream.h"
 
 extern "C" {
+#include "BsMMAlloc.h"
 #include "BsASTFX.h"
 #include "BsParserFX.h"
 #include "BsLexerFX.h"
@@ -11,29 +12,26 @@ extern "C" {
 
 namespace BansheeEngine
 {
-	ASTFXNode* parseFX(const char* source)
+	void parseFX(ParseState& parseState, const char* source)
 	{
 		yyscan_t scanner;
 		YY_BUFFER_STATE state;
 
-		if (yylex_init(&scanner)) {
+		if (yylex_init_extra(&parseState, &scanner)) {
 			// couldn't initialize
-			return nullptr;
+			return;
 		}
 
 		state = yy_scan_string(source, scanner);
 
-		ASTFXNode* output = nodeCreate(NT_Shader);
-		if (yyparse(output, scanner)) {
+		if (yyparse(&parseState, scanner)) {
 			// error parsing
-			return nullptr;
+			return;
 		}
 
 		yy_delete_buffer(state, scanner);
 
 		yylex_destroy(scanner);
-
-		return output;
 	}
 
 	/**
@@ -57,11 +55,18 @@ namespace BansheeEngine
 		DataStreamPtr file = FileSystem::openFile(exampleFX);
 
 		String contents = file->getAsString();
-		ASTFXNode* node = parseFX(contents.c_str());
+
+		ParseState parseState;
+		parseState.memContext = mmalloc_new_context();
+		parseState.rootNode = nodeCreate(parseState.memContext, NT_Shader);
+
+		parseFX(parseState, contents.c_str());
 
 		int bp = 0;
 
-		nodeDelete(node);
+		nodeDelete(parseState.rootNode);
+		mmalloc_free_context(parseState.memContext);
+
 
 		return nullptr;
 	}