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 );
163 lDefine.type = "Parser_Define";
164 lDefine.name = String_Zone( Parser_Token );
166 //Parser_Expect( PARSER_TT_BRACKETCLOSE );
167 // read the rest of the line
168 String_EntityZone( lDefine, value );
169 lOldLine = Parser_LineNumber;
171 if( !Parser_GetToken() )
173 else if( lOldLine != Parser_LineNumber ) {
176 } else if( Parser_Token == "\\" )
179 String_EntitySet( lDefine, value, strcat( lDefine.value, "\"", Parser_Token, "\" " ) );
181 Parser_Print( PARSER_HIGH, strcat( " Name = '", lDefine.name, "' Replacement = '", lDefine.value, "'" ) );
183 lDefine.chain = Parser_DefineChain;
184 Parser_DefineChain = lDefine;
186 Parser_Print( PARSER_HIGH, "Done parsing #define" );
189 void() Parser_ParseUndef =
191 local entity lEntity, lPrevious;
194 Parser_Print( PARSER_HIGH, "Parsing #undef..." );
195 Parser_Expect( PARSER_TT_TOKEN );
197 lPrevious = null_entity;
198 for( lEntity = Parser_DefineChain ; lEntity ; lPrevious = lEntity, lEntity = lEntity.chain )
199 if( lEntity.name == Parser_Token ) {
201 lPrevious.chain = lEntity.chain;
203 Parser_DefineChain = lEntity.chain;
205 Parser_Print( PARSER_INFO, strcat( "#undef: Removed [", Parser_Token, "]" ) );
207 String_Free( lEntity.name );
208 String_Free( lEntity.value );
215 Parser_Print( PARSER_INFO, strcat( "#undef: [", Parser_Token, "] not found!" ) );
218 void() Parser_ProcessDefine =
220 local string lConstant;
221 local entity lDefine;
224 Parser_Expect( PARSER_TT_TOKEN );
225 lConstant = String_Zone( Parser_Token );
227 Parser_Expect( PARSER_TT_BRACKETCLOSE );
229 Parser_Print( PARSER_HIGH, strcat( "Processing [", lConstant, "]..." ) );
231 for( lDefine = Parser_DefineChain ; lDefine ; lDefine = lDefine.chain )
232 if( lDefine.name == lConstant ) {
233 // if you want to have a single token use \" or '
234 Parser_Line = String_Set( Parser_Line, strcat( " ", lDefine.value ) );
235 Parser_Print( PARSER_HIGH, strcat( "Replacing with '", Parser_Line, "'" ) );
236 for( ; Parser_TokenNum < Parser_NumTokens ; Parser_TokenNum++ )
237 Parser_Line = String_Set( Parser_Line, strcat( Parser_Line, " \"", argv( Parser_TokenNum ), "\"" ) );
238 Parser_TokenizeLine();
239 String_Free( lConstant );
243 Parser_Token = String_Set( Parser_Token, String_Normal( lConstant ) );
244 Parser_Print( PARSER_NORMAL, strcat( "#define: Couldn't find constant '", Parser_Token, "'!" ) );
245 Parser_Error( "constant not found" );
250 void( string pNamespace ) Parser_ParseDefinition =
252 local entity lEntity;
254 if( Parser_TokenType == PARSER_TT_ITEM )
255 Parser_ParseItem( pNamespace );
256 else if( Parser_TokenType == PARSER_TT_TEMPLATE ) {
257 lEntity = Parser_ParseItem( pNamespace );
258 lEntity.flag = lEntity.flag | FLAG_TEMPLATE;
259 } else if( Parser_TokenType == PARSER_TT_DEFINE )
260 Parser_ParseDefine();
261 else if( Parser_TokenType == PARSER_TT_DERIVE )
262 Parser_DeriveItem( pNamespace );
263 else if( Parser_TokenType == PARSER_TT_DERIVETEMPLATE ) {
264 lEntity = Parser_DeriveItem( pNamespace );
265 lEntity.flag = lEntity.flag | FLAG_TEMPLATE;
266 } else if( Parser_TokenType == PARSER_TT_UNDEF )
268 else if( Parser_TokenType == PARSER_TT_NAMESPACE )
269 Parser_ParseNamespace( pNamespace );
270 else if( Parser_TokenType == PARSER_TT_INCLUDE )
271 Parser_IncludeFile( pNamespace );
272 else if( Parser_TokenType == PARSER_TT_IGNORE )
273 Parser_ParseIgnore();
275 Parser_Error( "couldn't find type in Parser_ParseDef" );
278 void() Parser_ParseIgnore =
280 local float lBraceCount;
282 Parser_Expect( PARSER_TT_BRACEOPEN );
283 for( lBraceCount = 1 ; lBraceCount > 0 ; )
284 if( !Parser_GetToken() )
286 else if( Parser_TokenType == PARSER_TT_BRACEOPEN )
288 else if( Parser_TokenType == PARSER_TT_BRACECLOSE )
292 entity( string pNamespace ) Parser_ParseItem =
294 local string lNamespace;
295 local string lEntityText;
296 local entity lEntity;
298 Parser_Print( PARSER_HIGH, "Parsing item.." );
301 Parser_Expect( PARSER_TT_TOKEN );
302 lEntityText = String_Zone( strcat( "{ \"type\" \"Item_", Parser_Token,"\" " ) );
304 Parser_Print( PARSER_HIGH, strcat( " Type = '", Parser_Token, "'" ) );
307 Parser_Expect( PARSER_TT_TOKEN );
308 if( pNamespace != "" )
309 lNamespace = String_Zone( strcat( pNamespace, "::", Parser_Token ) );
311 lNamespace = String_Zone( Parser_Token );
313 lEntityText = String_Set( lEntityText, strcat( lEntityText, "\"name\" \"", lNamespace, "\" " ) );
314 lEntityText = String_Set( lEntityText, strcat( lEntityText, "\"parent\" \"", pNamespace, "\" " ) );
316 Parser_Print( PARSER_HIGH, strcat( " Name = '", Parser_Token, "' Parent = '", pNamespace,
317 "' Namespace = '", lNamespace, "'" ) );
319 Parser_Expect( PARSER_TT_BRACEOPEN );
320 lEntityText = Parser_ParseEntity( lNamespace, lEntityText );
322 // parse the entity (builtin)
324 parseentitydata( lEntity, lEntityText );
326 String_Free( lEntityText );
327 String_Free( lNamespace );
329 Parser_Print( PARSER_HIGH, strcat( "Parsing '", lEntity.name, "' finished" ) );
334 void( entity pSource, entity pTarget ) Parser_CloneChildren =
336 // we search for all items that are direct children of pSource and copy them
337 // and adapt their parent and names
341 while ( (lNode = findstring( lNode, parent, pSource.name )) != null_entity ) {
343 local string lModifierString;
346 copyentity( lNode, lClone );
348 if( lClone.flag & FLAG_TEMPLATE )
349 lClone.flag = lClone.flag - FLAG_TEMPLATE;
351 lModifierString = strcat( "{ name \"", pTarget.name,
352 substring( lNode.name, strlen( pSource.name ), 100000 ), "\" parent \"", pTarget.name, "\" }" );
354 parseentitydata( lClone, lModifierString );
356 Parser_CloneChildren( lNode, lClone );
360 entity( string pNamespace ) Parser_DeriveItem =
362 local string lNamespace;
363 local string lEntityText;
365 local string lBaseName;
366 local entity lEntity;
368 Parser_Print( PARSER_HIGH, "Parsing derived item.." );
371 Parser_Expect( PARSER_TT_TOKEN );
373 if( substring( Parser_Token, 0, 2 ) == "::" )
374 lBaseName = String_Zone( substring( Parser_Token, 2, strlen( Parser_Token ) - 2 ) );
375 else if( pNamespace == "" )
376 lBaseName = String_Zone( Parser_Token );
378 lBaseName = String_Zone( strcat( pNamespace, "::", Parser_Token ) );
380 // try the local namespace first, then try to find it in the global
381 if( findstring( null_entity, name, lBaseName ) == null_entity )
382 lBaseName = String_Set( lBaseName, Parser_Token );
385 Parser_Print( PARSER_HIGH, strcat( " Base = '", lBaseName, "'" ) );
387 lBase = findstring( null_entity, name, lBaseName );
388 if( lBase == null_entity )
389 Parser_Error( "couldnt find item" );
392 Parser_Expect( PARSER_TT_TOKEN );
393 if( pNamespace != "" )
394 lNamespace = String_Zone( strcat( pNamespace, "::", Parser_Token ) );
396 lNamespace = String_Zone( Parser_Token );
398 lEntityText = String_Zone( strcat( "{ \"name\" \"", lNamespace, "\" " ) );
399 lEntityText = String_Set( lEntityText, strcat( lEntityText, "\"parent\" \"", pNamespace, "\" " ) );
401 Parser_Print( PARSER_HIGH, strcat( " Name = '", Parser_Token, "' Parent = '", pNamespace,
402 "' Namespace = '", lNamespace, "'" ) );
404 Parser_Expect( PARSER_TT_BRACEOPEN );
405 lEntityText = Parser_ParseEntity( lNamespace, lEntityText );
407 // parse the entity (builtin)
409 copyentity( lBase, lEntity );
410 if( lEntity.flag & FLAG_TEMPLATE )
411 lEntity.flag = lEntity.flag - FLAG_TEMPLATE;
412 parseentitydata( lEntity, lEntityText );
414 String_Free( lEntityText );
415 String_Free( lNamespace );
416 String_Free( lBaseName );
418 // now copy over all children
419 Parser_CloneChildren( lBase, lEntity );
421 Parser_Print( PARSER_HIGH, strcat( "Parsing '", lEntity.name, "' finished" ) );
426 string( string pNamespace, string pEntityText ) Parser_ParseEntity =
428 while( Parser_GetToken() ) {
429 if( Parser_TokenType == PARSER_TT_TOKEN ) {
430 // must be a property...
431 // store the key value
432 pEntityText = String_Set( pEntityText, strcat( pEntityText, "\"", Parser_Token, "\" " ) );
433 Parser_Expect( PARSER_TT_TOKEN );
434 pEntityText = String_Set( pEntityText, strcat( pEntityText, "\"", Parser_Token, "\" " ) );
435 } else if( Parser_TokenType == PARSER_TT_BRACECLOSE )
438 Parser_ParseDefinition( pNamespace );
441 return String_Append( pEntityText, " }" );
444 void( string pNamespace ) Parser_ParseNamespace =
446 local string lNamespace;
448 Parser_Print( PARSER_HIGH, "Parsing Namespace..." );
450 Parser_Expect( PARSER_TT_TOKEN );
451 if( pNamespace != "" )
452 lNamespace = String_Zone( strcat( pNamespace, "::", Parser_Token ) );
454 lNamespace = String_Zone( Parser_Token );
455 Parser_Print( PARSER_HIGH, strcat( " Subnamespace = '", Parser_Token, "' New namespace = '", lNamespace, "'" ) );
457 Parser_Expect( PARSER_TT_BRACEOPEN );
459 while( Parser_GetToken() ) {
460 if( Parser_TokenType == PARSER_TT_BRACECLOSE )
463 Parser_ParseDefinition( lNamespace );
466 Parser_Print( PARSER_HIGH, strcat( "Finished parsing Namespace. Namespace = '", pNamespace, "'" ) );
468 String_Free( lNamespace );
471 void( string pFilename, string pNamespace ) Parser_ParseFile =
473 Parser_Filename = String_Zone( pFilename );
474 Parser_File = fopen( Parser_Filename, FILE_READ );
475 if( Parser_File == -1 ) {
476 print( "Parser: Couldn't open ", Parser_Filename, "\n" );
480 Parser_Line = String_Create();
481 Parser_LineNumber = 0;
482 Parser_NumTokens = Parser_TokenNum = 0;
484 while( Parser_GetToken() )
485 Parser_ParseDefinition( pNamespace );
487 fclose( Parser_File );
488 String_Free( Parser_Filename );
489 String_Free( Parser_Line );
494 Parser_Token = String_Create();
495 Parser_DefineChain = null_entity;
496 Parser_IncludeDepth = 0;
498 Parser_FileList = String_Create();
505 _Parser_Print( PARSER_HIGH, "Deleting #defines:" );
506 while( Parser_DefineChain ) {
507 lNext = Parser_DefineChain.chain;
508 _Parser_Print( PARSER_HIGH, strcat( " [", Parser_DefineChain.name, "]" ) );
510 String_Free( Parser_DefineChain.name );
511 String_Free( Parser_DefineChain.value );
513 remove( Parser_DefineChain );
514 Parser_DefineChain = lNext;
518 String_Free( Parser_Token );
519 String_Free( Parser_FileList );
522 void( string pPluginDir ) Parser_ParsePlugins =
524 local float lSearchHandle;
525 local float lCounter, lCount;
527 lSearchHandle = search_begin( strcat( pPluginDir, "/*.plugin" ), true, true );
528 if( lSearchHandle < 0 ) {
532 lCount = search_getsize( lSearchHandle );
534 for( lCounter = 0 ; lCounter < lCount ; lCounter++ ) {
535 local string pPlugin;
537 Parser_FileList = String_Set( Parser_FileList, "" );
539 pPlugin = String_Zone( search_getfilename( lSearchHandle, lCounter ) );
540 Parser_FileList = Util_AltStringPush( Parser_FileList, pPlugin );
542 Parser_ParseFile( pPlugin, "" );
544 _Parser_Print( PARSER_INFO, strcat( "Plugin '", pPlugin, "': files parsed: ", Parser_FileList ) );
545 String_Free( pPlugin );
548 search_end( lSearchHandle );
551 void( string pMain, string pPluginDir ) Parser_ParseMenu =
555 pMain = String_Zone( pMain );
556 Parser_FileList = Util_AltStringPush( Parser_FileList, pMain );
558 Parser_ParseFile( pMain, "" );
560 _Parser_Print( PARSER_INFO, strcat( "Files parsed: ", Parser_FileList ) );
561 String_Free( pMain );
564 if( pPluginDir != "" ) {
565 Parser_ParsePlugins( pPluginDir );