#undef DEBUG /* * TclParse.java -- * * A Class of the following type is filled in by Parser.parseCommand. * It describes a single command parsed from an input string. * * Copyright (c) 1997 by Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * Included in SQLite3 port to C# for use in testharness only; 2008 Noah B Hart * * RCS @(#) $Id: TclParse.java,v 1.2 1999/05/09 01:33:45 dejong Exp $ */ using System; namespace tcl.lang { public class TclParse { // The original command string passed to Parser.parseCommand. public char[] inString; // Index into 'string' that is the character just after the last // one in the command string. public int endIndex; // Index into 'string' that is the # that begins the first of // one or more comments preceding the command. public int commentStart; // Number of bytes in comments (up through newline character // that terminates the last comment). If there were no // comments, this field is 0. public int commentSize; // Index into 'string' that is the first character in first // word of command. public int commandStart; // Number of bytes in command, including first character of // first word, up through the terminating newline, close // bracket, or semicolon. public int commandSize; // Total number of words in command. May be 0. public int numWords; // Stores the tokens that compose the command. public TclToken[] tokenList; // Total number of tokens in command. internal int numTokens; // Total number of tokens available at token. internal int tokensAvailable; /* *---------------------------------------------------------------------- * * The fields below are intended only for the private use of the * parser. They should not be used by procedures that invoke * Tcl_ParseCommand. * *---------------------------------------------------------------------- */ // Interpreter to use for error reporting, or null. internal Interp interp; // Name of file from which script came, or null. Used for error // messages. internal string fileName; // Line number corresponding to first character in string. internal int lineNum; // Points to character in string that terminated most recent token. // Filled in by Parser.parseTokens. If an error occurs, points to // beginning of region where the error occurred (e.g. the open brace // if the close brace is missing). public int termIndex; // This field is set to true by Parser.parseCommand if the command // appears to be incomplete. This information is used by // Parser.commandComplete. internal bool incomplete; // When a TclParse is the return value of a method, result is set to // a standard Tcl result, indicating the return of the method. public TCL.CompletionCode result; // Default size of the tokenList array. private const int INITIAL_NUM_TOKENS = 20; private const int MAX_CACHED_TOKENS = 50; //my tests show 50 is best internal TclParse( Interp interp, char[] inString, int endIndex, string fileName, int lineNum ) { this.interp = interp; this.inString = inString; this.endIndex = endIndex; this.fileName = fileName; this.lineNum = lineNum; this.tokenList = new TclToken[INITIAL_NUM_TOKENS]; this.tokensAvailable = INITIAL_NUM_TOKENS; this.numTokens = 0; this.numWords = 0; this.commentStart = -1; this.commentSize = 0; this.commandStart = -1; this.commandSize = 0; this.incomplete = false; } internal TclToken getToken( int index ) // The index into tokenList. { if ( index >= tokensAvailable ) { expandTokenArray( index ); } if ( tokenList[index] == null ) { tokenList[index] = grabToken(); tokenList[index].script_array = tokenList[0].script_array; } return tokenList[index]; } // Release internal resources that this TclParser object might have allocated internal void release() { for ( int index = 0; index < tokensAvailable; index++ ) { if ( tokenList[index] != null ) { releaseToken( tokenList[index] ); tokenList[index] = null; } } } // Creating an interpreter will cause this init method to be called internal static void init( Interp interp ) { TclToken[] TOKEN_CACHE = new TclToken[MAX_CACHED_TOKENS]; for ( int i = 0; i < MAX_CACHED_TOKENS; i++ ) { TOKEN_CACHE[i] = new TclToken(); } interp.parserTokens = TOKEN_CACHE; interp.parserTokensUsed = 0; } private TclToken grabToken() { if ( interp == null || interp.parserTokensUsed == MAX_CACHED_TOKENS ) { // either we do not have a cache because the interp is null or we have already // used up all the open cache slots, we just allocate a new one in this case return new TclToken(); } else { // the cache has an avaliable slot so grab it return interp.parserTokens[interp.parserTokensUsed++]; } } private void releaseToken( TclToken token ) { if ( interp != null && interp.parserTokensUsed > 0 ) { // if cache is not full put the object back in the cache interp.parserTokensUsed -= 1; interp.parserTokens[interp.parserTokensUsed] = token; } } /* //uncommenting these methods will disable caching static void init(Interp interp) {} private TclToken grabToken() {return new TclToken();} private void releaseToken(TclToken token) {} */ internal void expandTokenArray( int needed ) { // Make sure there is at least enough room for needed tokens while ( needed >= tokensAvailable ) { tokensAvailable *= 2; } TclToken[] newList = new TclToken[tokensAvailable]; Array.Copy( (System.Array)tokenList, 0, (System.Array)newList, 0, tokenList.Length ); tokenList = newList; } public override string ToString() { return ( get().ToString() ); } public TclObject get() { TclObject obj; TclToken token; string typeString; int nextIndex; string cmd; int i; System.Diagnostics.Debug.WriteLine( "Entered TclParse.get()" ); System.Diagnostics.Debug.WriteLine( "numTokens is " + numTokens ); obj = TclList.newInstance(); try { if ( commentSize > 0 ) { TclList.append( interp, obj, TclString.newInstance( new string( inString, commentStart, commentSize ) ) ); } else { TclList.append( interp, obj, TclString.newInstance( "-" ) ); } if ( commandStart >= ( endIndex + 1 ) ) { commandStart = endIndex; } cmd = new string( inString, commandStart, commandSize ); TclList.append( interp, obj, TclString.newInstance( cmd ) ); TclList.append( interp, obj, TclInteger.newInstance( numWords ) ); for ( i = 0; i < numTokens; i++ ) { System.Diagnostics.Debug.WriteLine( "processing token " + i ); token = tokenList[i]; switch ( token.type ) { case Parser.TCL_TOKEN_WORD: typeString = "word"; break; case Parser.TCL_TOKEN_SIMPLE_WORD: typeString = "simple"; break; case Parser.TCL_TOKEN_EXPAND_WORD: typeString = "expand"; break; case Parser.TCL_TOKEN_TEXT: typeString = "text"; break; case Parser.TCL_TOKEN_BS: typeString = "backslash"; break; case Parser.TCL_TOKEN_COMMAND: typeString = "command"; break; case Parser.TCL_TOKEN_VARIABLE: typeString = "variable"; break; default: typeString = "??"; break; } System.Diagnostics.Debug.WriteLine( "typeString is " + typeString ); TclList.append( interp, obj, TclString.newInstance( typeString ) ); TclList.append( interp, obj, TclString.newInstance( token.TokenString ) ); TclList.append( interp, obj, TclInteger.newInstance( token.numComponents ) ); } nextIndex = commandStart + commandSize; TclList.append( interp, obj, TclString.newInstance( new string( inString, nextIndex, ( endIndex - nextIndex ) ) ) ); } catch ( TclException e ) { // Do Nothing. } return obj; } } // end TclParse }