2009-01-19 23:19:33 +00:00
#region = = = = = = = = = = = = = = = = = = Copyright ( c ) 2007 Pascal vd Heiden
/ *
* Copyright ( c ) 2007 Pascal vd Heiden , www . codeimp . com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* /
#endregion
#region = = = = = = = = = = = = = = = = = = Namespaces
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.Globalization ;
using System.Text ;
using CodeImp.DoomBuilder.IO ;
using CodeImp.DoomBuilder.Data ;
using System.IO ;
using System.Diagnostics ;
using CodeImp.DoomBuilder.Compilers ;
#endregion
2009-02-12 18:00:15 +00:00
namespace CodeImp.DoomBuilder.ZDoom
2009-01-19 23:19:33 +00:00
{
2009-02-12 19:08:01 +00:00
public sealed class DecorateParser : ZDTextParser
2009-01-19 23:19:33 +00:00
{
2009-01-21 16:18:30 +00:00
#region = = = = = = = = = = = = = = = = = = Delegates
2009-01-21 23:09:25 +00:00
public delegate void IncludeDelegate ( DecorateParser parser , string includefile ) ;
2009-01-21 16:18:30 +00:00
public IncludeDelegate OnInclude ;
#endregion
2009-01-20 16:18:25 +00:00
2009-01-21 16:18:30 +00:00
#region = = = = = = = = = = = = = = = = = = Constants
2009-01-22 15:10:41 +00:00
2009-01-19 23:19:33 +00:00
#endregion
2009-01-20 16:18:25 +00:00
2009-01-19 23:19:33 +00:00
#region = = = = = = = = = = = = = = = = = = Variables
2009-01-20 16:18:25 +00:00
2009-01-22 15:10:41 +00:00
// These are actors we want to keep
private Dictionary < string , ActorStructure > actors ;
// These are all parsed actors, also those from other games
private Dictionary < string , ActorStructure > archivedactors ;
2009-01-20 16:18:25 +00:00
2009-01-19 23:19:33 +00:00
#endregion
2009-01-20 16:18:25 +00:00
2009-01-19 23:19:33 +00:00
#region = = = = = = = = = = = = = = = = = = Properties
2009-01-20 16:18:25 +00:00
2009-01-22 15:10:41 +00:00
public ICollection < ActorStructure > Actors { get { return actors . Values ; } }
2009-01-20 16:18:25 +00:00
2009-01-19 23:19:33 +00:00
#endregion
2009-01-20 16:18:25 +00:00
2009-01-19 23:19:33 +00:00
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
2009-01-20 16:18:25 +00:00
2009-01-19 23:19:33 +00:00
// Constructor
2009-01-20 16:18:25 +00:00
public DecorateParser ( )
2009-01-19 23:19:33 +00:00
{
2009-02-12 21:34:11 +00:00
// Syntax
whitespace = "\n \t\r" ;
specialtokens = ":{}+-\n;" ;
2009-01-20 16:18:25 +00:00
// Initialize
2009-01-22 15:10:41 +00:00
actors = new Dictionary < string , ActorStructure > ( ) ;
archivedactors = new Dictionary < string , ActorStructure > ( ) ;
2009-01-19 23:19:33 +00:00
}
2009-01-20 16:18:25 +00:00
2009-01-19 23:19:33 +00:00
#endregion
2009-01-22 15:10:41 +00:00
#region = = = = = = = = = = = = = = = = = = Parsing
2009-01-20 16:18:25 +00:00
// This parses the given decorate stream
// Returns false on errors
2009-02-12 19:08:01 +00:00
public override bool Parse ( Stream stream , string sourcefilename )
2009-01-20 16:18:25 +00:00
{
2009-02-12 19:08:01 +00:00
base . Parse ( stream , sourcefilename ) ;
// Keep local data
Stream localstream = datastream ;
string localsourcename = sourcename ;
BinaryReader localreader = datareader ;
2009-01-20 16:18:25 +00:00
// Continue until at the end of the stream
while ( SkipWhitespace ( true ) )
{
// Read a token
string objdeclaration = ReadToken ( ) ;
if ( objdeclaration ! = null )
{
objdeclaration = objdeclaration . ToLowerInvariant ( ) ;
if ( objdeclaration = = "actor" )
{
// Read actor structure
ActorStructure actor = new ActorStructure ( this ) ;
if ( this . HasError ) break ;
2009-01-22 15:10:41 +00:00
// Add the actor
archivedactors [ actor . ClassName . ToLowerInvariant ( ) ] = actor ;
if ( actor . CheckActorSupported ( ) )
actors [ actor . ClassName . ToLowerInvariant ( ) ] = actor ;
// Replace an actor?
if ( actor . ReplacesClass ! = null )
{
if ( GetArchivedActorByName ( actor . ReplacesClass ) ! = null )
archivedactors [ actor . ReplacesClass . ToLowerInvariant ( ) ] = actor ;
else
2009-02-26 23:27:46 +00:00
General . ErrorLogger . Add ( ErrorType . Warning , "Unable to find the DECORATE class '" + actor . ReplacesClass + "' to replace, while parsing '" + actor . ClassName + "'" ) ;
2009-01-22 15:10:41 +00:00
if ( actor . CheckActorSupported ( ) )
{
if ( GetActorByName ( actor . ReplacesClass ) ! = null )
actors [ actor . ReplacesClass . ToLowerInvariant ( ) ] = actor ;
}
}
2009-01-20 16:18:25 +00:00
}
2009-01-21 16:18:30 +00:00
else if ( objdeclaration = = "#include" )
{
// Include a file
SkipWhitespace ( true ) ;
string filename = ReadToken ( ) ;
if ( ! string . IsNullOrEmpty ( filename ) )
{
2009-01-21 23:09:25 +00:00
// Strip the quotes
filename = filename . Replace ( "\"" , "" ) ;
// Callback to parse this file now
if ( OnInclude ! = null ) OnInclude ( this , filename ) ;
// Set our buffers back to continue parsing
2009-01-21 16:18:30 +00:00
datastream = localstream ;
datareader = localreader ;
2009-01-21 23:09:25 +00:00
sourcename = localsourcename ;
2009-01-21 16:18:30 +00:00
if ( HasError ) break ;
}
else
{
ReportError ( "Expected file name to include" ) ;
break ;
}
}
2009-01-22 15:10:41 +00:00
else if ( ( objdeclaration = = "const" ) | | ( objdeclaration = = "native" ) )
{
// We don't need this, ignore up to the first next ;
while ( SkipWhitespace ( true ) )
{
string t = ReadToken ( ) ;
if ( ( t = = ";" ) | | ( t = = null ) ) break ;
}
}
2009-01-20 16:18:25 +00:00
else
{
// Unknown structure!
2009-01-22 15:10:41 +00:00
// Best we can do now is just find the first { and then
// follow the scopes until the matching } is found
2009-01-21 23:09:25 +00:00
string token2 ;
do
{
2009-01-22 15:10:41 +00:00
if ( ! SkipWhitespace ( true ) ) break ;
2009-01-21 23:09:25 +00:00
token2 = ReadToken ( ) ;
2009-01-22 15:10:41 +00:00
if ( token2 = = null ) break ;
2009-01-21 23:09:25 +00:00
}
while ( token2 ! = "{" ) ;
int scopelevel = 1 ;
do
{
2009-01-22 15:10:41 +00:00
if ( ! SkipWhitespace ( true ) ) break ;
2009-01-21 23:09:25 +00:00
token2 = ReadToken ( ) ;
2009-01-22 15:10:41 +00:00
if ( token2 = = null ) break ;
2009-01-21 23:09:25 +00:00
if ( token2 = = "{" ) scopelevel + + ;
if ( token2 = = "}" ) scopelevel - - ;
}
while ( scopelevel > 0 ) ;
2009-01-20 16:18:25 +00:00
}
}
}
// Return true when no errors occurred
2009-02-12 19:08:01 +00:00
return ( ErrorDescription = = null ) ;
2009-01-20 16:18:25 +00:00
}
2009-01-19 23:19:33 +00:00
#endregion
2009-01-22 15:10:41 +00:00
#region = = = = = = = = = = = = = = = = = = Methods
// This returns an actor by name
// Returns null when actor cannot be found
public ActorStructure GetActorByName ( string name )
{
name = name . ToLowerInvariant ( ) ;
if ( actors . ContainsKey ( name ) )
return actors [ name ] ;
else
return null ;
}
// This returns an actor by name
// Returns null when actor cannot be found
internal ActorStructure GetArchivedActorByName ( string name )
{
name = name . ToLowerInvariant ( ) ;
if ( archivedactors . ContainsKey ( name ) )
return archivedactors [ name ] ;
else
return null ;
}
#endregion
2009-01-19 23:19:33 +00:00
}
}