4 void() Parser_Define_Spawn = {};
6 void() Parser_TokenizeLine =
8 Parser_NumTokens = tokenize( Parser_Line );
12 bool() Parser_GetToken =
16 if( Parser_TokenNum >= Parser_NumTokens ) { // get a new line
17 lLine = fgets( Parser_File );
20 if( !validstring( lLine ) )
23 return Parser_GetToken();
25 Parser_Line = String_Set( Parser_Line, lLine );
26 Parser_TokenizeLine();
27 return Parser_GetToken();
29 Parser_Token = String_Set( Parser_Token, argv( Parser_TokenNum ) );
33 Parser_Print( PARSER_LOW, strcat( "Read token '", Parser_Token, "'" ) );
35 Parser_TokenType = Parser_GetTokenType();
36 if( Parser_TokenType == PARSER_TT_BRACKETOPEN ) {
37 Parser_ProcessDefine();
38 return Parser_GetToken();
44 float() Parser_GetTokenType =
46 if( Parser_Token == "Item" )
47 return PARSER_TT_ITEM;
48 else if( Parser_Token == "Template" )
49 return PARSER_TT_TEMPLATE;
50 else if( Parser_Token == "Derive" )
51 return PARSER_TT_DERIVE;
52 else if( Parser_Token == "DeriveTemplate" )
53 return PARSER_TT_DERIVETEMPLATE;
54 else if( Parser_Token == "#define" )
55 return PARSER_TT_DEFINE;
56 else if( Parser_Token == "Ignore" )
57 return PARSER_TT_IGNORE;
58 else if( Parser_Token == "#undef" )
59 return PARSER_TT_UNDEF;
60 else if( Parser_Token == "Namespace" )
61 return PARSER_TT_NAMESPACE;
62 else if( Parser_Token == "#include" )
63 return PARSER_TT_INCLUDE;
64 else if( Parser_Token == "}" )
65 return PARSER_TT_BRACECLOSE;
66 else if( Parser_Token == "{" )
67 return PARSER_TT_BRACEOPEN;
68 else if( Parser_Token == "[" )
69 return PARSER_TT_BRACKETOPEN;
70 else if( Parser_Token == "]" )
71 return PARSER_TT_BRACKETCLOSE;
73 return PARSER_TT_TOKEN;
76 void( float pLevel, string pText ) _Parser_Print =
78 if( pLevel == 0 || sys_debug_parser & pLevel )
79 print( "Parser: ", pText, "\n" );
82 void( float pLevel, string pInfo ) Parser_Print =
84 if( pLevel == 0 || sys_debug_parser & pLevel )
85 print( "Parser: ", Parser_Filename, ":", ftos( Parser_LineNumber ), ": ", pInfo, "\n" );
88 void( string pInfo ) Parser_Error =
90 print( "Parser: ", Parser_Filename, ":", ftos( Parser_LineNumber ), ": Error: '");
91 print( Parser_Token, "' not expected (", pInfo, ")!\n" );
92 fclose( Parser_File );
93 error( "Error in the menu parser!" );
96 void( float pType ) Parser_Expect =
98 if( !Parser_GetToken() || ( Parser_TokenType != pType && Parser_TokenType != PARSER_TT_BRACKETOPEN ) )
99 Parser_Error( strcat( "expected ", PARSER_TT_TEXT[ pType - PARSER_TT_ITEM ] ) );
102 void( string pNamespace ) Parser_IncludeFile =
104 local string lFilename, lLine;
105 local float lFile, lLineNumber, lNumTokens, lTokenNum;
108 Parser_Expect( PARSER_TT_TOKEN );
110 Parser_Print( PARSER_INFO, strcat( "#include: Including file '", Parser_Token, "'" ) );
112 Parser_FileList = String_Append( Parser_FileList, strcat( " {'", String_Normal( Util_AltStringPrepare( Parser_Token ) ), "'" ) );
114 lFilename = Parser_Filename;
118 lLineNumber = Parser_LineNumber;
119 lNumTokens = Parser_NumTokens;
120 lTokenNum = Parser_TokenNum;
122 --Parser_IncludeDepth;
123 if( Parser_IncludeDepth > Parser_MaxIncludeDepth )
124 Parser_Print( PARSER_NORMAL, "#include: Maximum depth reached!" );
126 Parser_ParseFile( Parser_Token, pNamespace );
127 --Parser_IncludeDepth;
129 Parser_Filename = lFilename;
133 Parser_LineNumber = lLineNumber;
135 // tokenize the line again, but jump to the old position
136 Parser_TokenizeLine();
137 Parser_NumTokens = lNumTokens;
138 Parser_TokenNum = lTokenNum;
140 Parser_FileList = String_Append( Parser_FileList, "}" );
143 void() Parser_ParseDefine =
145 local entity lDefine;
146 local float lOldLine;
148 Parser_Print( 2, "Parsing #define..." );
150 // #define NAME CONSTANT
151 //Parser_Expect( PARSER_TT_BRACKETOPEN );
152 Parser_Expect( PARSER_TT_TOKEN );
154 // check for double definitions (dont error just print a warning)
155 for( lDefine = Parser_DefineChain ; lDefine ; lDefine = lDefine.chain )
156 if( Parser_Token == lDefine.name ) {
157 Parser_Print( PARSER_INFO, strcat( "#define: [", Parser_Token, "] already defined!" ) );
158 Parser_Expect( PARSER_TT_TOKEN );
164 lDefine.type = "Parser_Define";
165 lDefine.name = String_Zone( Parser_Token );
167 //Parser_Expect( PARSER_TT_BRACKETCLOSE );
168 // read the rest of the line
169 String_EntityZone( lDefine, value );
170 lOldLine = Parser_LineNumber;
172 if( !Parser_GetToken() )
174 else if( lOldLine != Parser_LineNumber ) {
177 } else if( Parser_Token == "\\" )
180 String_EntitySet( lDefine, value, strcat( lDefine.value, "\"", Parser_Token, "\" " ) );
182 Parser_Print( PARSER_HIGH, strcat( " Name = '", lDefine.name, "' Replacement = '", lDefine.value, "'" ) );
184 lDefine.chain = Parser_DefineChain;
185 Parser_DefineChain = lDefine;
187 Parser_Print( PARSER_HIGH, "Done parsing #define" );
190 void() Parser_ParseUndef =
192 local entity lEntity, lPrevious;
195 Parser_Print( PARSER_HIGH, "Parsing #undef..." );
196 Parser_Expect( PARSER_TT_TOKEN );
198 lPrevious = null_entity;
199 for( lEntity = Parser_DefineChain ; lEntity ; lPrevious = lEntity, lEntity = lEntity.chain )
200 if( lEntity.name == Parser_Token ) {
202 lPrevious.chain = lEntity.chain;
204 Parser_DefineChain = lEntity.chain;
206 Parser_Print( PARSER_INFO, strcat( "#undef: Removed [", Parser_Token, "]" ) );
208 String_Free( lEntity.name );
209 String_Free( lEntity.value );
216 Parser_Print( PARSER_INFO, strcat( "#undef: [", Parser_Token, "] not found!" ) );
219 void() Parser_ProcessDefine =
221 local string lConstant;
222 local entity lDefine;
225 Parser_Expect( PARSER_TT_TOKEN );
226 lConstant = String_Zone( Parser_Token );
228 Parser_Expect( PARSER_TT_BRACKETCLOSE );
230 Parser_Print( PARSER_HIGH, strcat( "Processing [", lConstant, "]..." ) );
232 for( lDefine = Parser_DefineChain ; lDefine ; lDefine = lDefine.chain )
233 if( lDefine.name == lConstant ) {
234 // if you want to have a single token use \" or '
235 Parser_Line = String_Set( Parser_Line, strcat( " ", lDefine.value ) );
236 Parser_Print( PARSER_HIGH, strcat( "Replacing with '", Parser_Line, "'" ) );
237 for( ; Parser_TokenNum < Parser_NumTokens ; Parser_TokenNum++ )
238 Parser_Line = String_Set( Parser_Line, strcat( Parser_Line, " \"", argv( Parser_TokenNum ), "\"" ) );
239 Parser_TokenizeLine();
240 String_Free( lConstant );
244 Parser_Token = String_Set( Parser_Token, String_Normal( lConstant ) );
245 Parser_Print( PARSER_NORMAL, strcat( "#define: Couldn't find constant '", Parser_Token, "'!" ) );
246 Parser_Error( "constant not found" );
251 void( string pNamespace ) Parser_ParseDefinition =
253 local entity lEntity;
255 if( Parser_TokenType == PARSER_TT_ITEM )
256 Parser_ParseItem( pNamespace );
257 else if( Parser_TokenType == PARSER_TT_TEMPLATE ) {
258 lEntity = Parser_ParseItem( pNamespace );
259 lEntity.flag = lEntity.flag | FLAG_TEMPLATE;
260 } else if( Parser_TokenType == PARSER_TT_DEFINE )
261 Parser_ParseDefine();
262 else if( Parser_TokenType == PARSER_TT_DERIVE )
263 Parser_DeriveItem( pNamespace );
264 else if( Parser_TokenType == PARSER_TT_DERIVETEMPLATE ) {
265 lEntity = Parser_DeriveItem( pNamespace );
266 lEntity.flag = lEntity.flag | FLAG_TEMPLATE;
267 } else if( Parser_TokenType == PARSER_TT_UNDEF )
269 else if( Parser_TokenType == PARSER_TT_NAMESPACE )
270 Parser_ParseNamespace( pNamespace );
271 else if( Parser_TokenType == PARSER_TT_INCLUDE )
272 Parser_IncludeFile( pNamespace );
273 else if( Parser_TokenType == PARSER_TT_IGNORE )
274 Parser_ParseIgnore();
276 Parser_Error( "couldn't find type in Parser_ParseDef" );
279 void() Parser_ParseIgnore =
281 local float lBraceCount;
283 Parser_Expect( PARSER_TT_BRACEOPEN );
284 for( lBraceCount = 1 ; lBraceCount > 0 ; )
285 if( !Parser_GetToken() )
287 else if( Parser_TokenType == PARSER_TT_BRACEOPEN )
289 else if( Parser_TokenType == PARSER_TT_BRACECLOSE )
293 entity( string pNamespace ) Parser_ParseItem =
295 local string lNamespace;
296 local string lEntityText;
297 local entity lEntity;
299 Parser_Print( PARSER_HIGH, "Parsing item.." );
302 Parser_Expect( PARSER_TT_TOKEN );
303 lEntityText = String_Zone( strcat( "{ \"type\" \"Item_", Parser_Token,"\" " ) );
305 Parser_Print( PARSER_HIGH, strcat( " Type = '", Parser_Token, "'" ) );
308 Parser_Expect( PARSER_TT_TOKEN );
309 if( pNamespace != "" )
310 lNamespace = String_Zone( strcat( pNamespace, "::", Parser_Token ) );
312 lNamespace = String_Zone( Parser_Token );
314 lEntityText = String_Set( lEntityText, strcat( lEntityText, "\"name\" \"", lNamespace, "\" " ) );
315 lEntityText = String_Set( lEntityText, strcat( lEntityText, "\"parent\" \"", pNamespace, "\" " ) );
317 Parser_Print( PARSER_HIGH, strcat( " Name = '", Parser_Token, "' Parent = '", pNamespace,
318 "' Namespace = '", lNamespace, "'" ) );
320 Parser_Expect( PARSER_TT_BRACEOPEN );
321 lEntityText = Parser_ParseEntity( lNamespace, lEntityText );
323 // parse the entity (builtin)
325 parseentitydata( lEntity, lEntityText );
327 String_Free( lEntityText );
328 String_Free( lNamespace );
330 Parser_Print( PARSER_HIGH, strcat( "Parsing '", lEntity.name, "' finished" ) );
335 void( entity pSource, entity pTarget ) Parser_CloneChildren =
337 // we search for all items that are direct children of pSource and copy them
338 // and adapt their parent and names
342 while ( (lNode = findstring( lNode, parent, pSource.name )) != null_entity ) {
344 local string lModifierString;
347 copyentity( lNode, lClone );
349 if( lClone.flag & FLAG_TEMPLATE )
350 lClone.flag = lClone.flag - FLAG_TEMPLATE;
352 lModifierString = strcat( "{ name \"", pTarget.name,
353 substring( lNode.name, strlen( pSource.name ), 100000 ), "\" parent \"", pTarget.name, "\" }" );
355 parseentitydata( lClone, lModifierString );
357 Parser_CloneChildren( lNode, lClone );
361 entity( string pNamespace ) Parser_DeriveItem =
363 local string lNamespace;
364 local string lEntityText;
366 local string lBaseName;
367 local entity lEntity;
369 Parser_Print( PARSER_HIGH, "Parsing derived item.." );
372 Parser_Expect( PARSER_TT_TOKEN );
374 if( substring( Parser_Token, 0, 2 ) == "::" )
375 lBaseName = String_Zone( substring( Parser_Token, 2, strlen( Parser_Token ) - 2 ) );
376 else if( pNamespace == "" )
377 lBaseName = String_Zone( Parser_Token );
379 lBaseName = String_Zone( strcat( pNamespace, "::", Parser_Token ) );
381 // try the local namespace first, then try to find it in the global
382 if( findstring( null_entity, name, lBaseName ) == null_entity )
383 lBaseName = String_Set( lBaseName, Parser_Token );
386 Parser_Print( PARSER_HIGH, strcat( " Base = '", lBaseName, "'" ) );
388 lBase = findstring( null_entity, name, lBaseName );
389 if( lBase == null_entity )
390 Parser_Error( "couldnt find item" );
393 Parser_Expect( PARSER_TT_TOKEN );
394 if( pNamespace != "" )
395 lNamespace = String_Zone( strcat( pNamespace, "::", Parser_Token ) );
397 lNamespace = String_Zone( Parser_Token );
399 lEntityText = String_Zone( strcat( "{ \"name\" \"", lNamespace, "\" " ) );
400 lEntityText = String_Set( lEntityText, strcat( lEntityText, "\"parent\" \"", pNamespace, "\" " ) );
402 Parser_Print( PARSER_HIGH, strcat( " Name = '", Parser_Token, "' Parent = '", pNamespace,
403 "' Namespace = '", lNamespace, "'" ) );
405 Parser_Expect( PARSER_TT_BRACEOPEN );
406 lEntityText = Parser_ParseEntity( lNamespace, lEntityText );
408 // parse the entity (builtin)
410 copyentity( lBase, lEntity );
411 if( lEntity.flag & FLAG_TEMPLATE )
412 lEntity.flag = lEntity.flag - FLAG_TEMPLATE;
413 parseentitydata( lEntity, lEntityText );
415 String_Free( lEntityText );
416 String_Free( lNamespace );
417 String_Free( lBaseName );
419 // now copy over all children
420 Parser_CloneChildren( lBase, lEntity );
422 Parser_Print( PARSER_HIGH, strcat( "Parsing '", lEntity.name, "' finished" ) );
427 string( string pNamespace, string pEntityText ) Parser_ParseEntity =
429 while( Parser_GetToken() ) {
430 if( Parser_TokenType == PARSER_TT_TOKEN ) {
431 // must be a property...
432 // store the key value
433 pEntityText = String_Set( pEntityText, strcat( pEntityText, "\"", Parser_Token, "\" " ) );
434 Parser_Expect( PARSER_TT_TOKEN );
435 pEntityText = String_Set( pEntityText, strcat( pEntityText, "\"", Parser_Token, "\" " ) );
436 } else if( Parser_TokenType == PARSER_TT_BRACECLOSE )
439 Parser_ParseDefinition( pNamespace );
442 return String_Append( pEntityText, " }" );
445 void( string pNamespace ) Parser_ParseNamespace =
447 local string lNamespace;
449 Parser_Print( PARSER_HIGH, "Parsing Namespace..." );
451 Parser_Expect( PARSER_TT_TOKEN );
452 if( pNamespace != "" )
453 lNamespace = String_Zone( strcat( pNamespace, "::", Parser_Token ) );
455 lNamespace = String_Zone( Parser_Token );
456 Parser_Print( PARSER_HIGH, strcat( " Subnamespace = '", Parser_Token, "' New namespace = '", lNamespace, "'" ) );
458 Parser_Expect( PARSER_TT_BRACEOPEN );
460 while( Parser_GetToken() ) {
461 if( Parser_TokenType == PARSER_TT_BRACECLOSE )
464 Parser_ParseDefinition( lNamespace );
467 Parser_Print( PARSER_HIGH, strcat( "Finished parsing Namespace. Namespace = '", pNamespace, "'" ) );
469 String_Free( lNamespace );
472 void( string pFilename, string pNamespace ) Parser_ParseFile =
474 Parser_Filename = String_Zone( pFilename );
475 Parser_File = fopen( Parser_Filename, FILE_READ );
476 if( Parser_File == -1 ) {
477 print( "Parser: Couldn't open ", Parser_Filename, "\n" );
481 Parser_Line = String_Create();
482 Parser_LineNumber = 0;
483 Parser_NumTokens = Parser_TokenNum = 0;
485 while( Parser_GetToken() )
486 Parser_ParseDefinition( pNamespace );
488 fclose( Parser_File );
489 String_Free( Parser_Filename );
490 String_Free( Parser_Line );
495 Parser_Token = String_Create();
496 Parser_DefineChain = null_entity;
497 Parser_IncludeDepth = 0;
499 Parser_FileList = String_Create();
506 _Parser_Print( PARSER_HIGH, "Deleting #defines:" );
507 while( Parser_DefineChain ) {
508 lNext = Parser_DefineChain.chain;
509 _Parser_Print( PARSER_HIGH, strcat( " [", Parser_DefineChain.name, "]" ) );
511 String_Free( Parser_DefineChain.name );
512 String_Free( Parser_DefineChain.value );
514 remove( Parser_DefineChain );
515 Parser_DefineChain = lNext;
519 String_Free( Parser_Token );
520 String_Free( Parser_FileList );
523 void( string pMain ) Parser_ParseMenu =
527 pMain = String_Zone( pMain );
528 Parser_FileList = Util_AltStringPush( Parser_FileList, pMain );
530 Parser_ParseFile( pMain, "" );
532 _Parser_Print( PARSER_INFO, strcat( "Files parsed: ", Parser_FileList ) );
534 String_Free( pMain );