Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Implement an Autoplay Handler

, 18 Sep 2006
Implementing an Autoplay handler in C#.
autoplaydemo_demo.zip
autoplaydemo_src.zip
AutoPlayDemo
Autoplay.ico
AutoPlayDemo.csproj.user
bin
Properties
Settings.settings
Resources
AutoPlayListener
Autoplay.ico
AutoPlayListener.snk
bin
Properties
Resources
Autoplay.ico
RegistryScript
Almdal.RegistryScript.snk
bin
Properties
SharedPipies
Almdal.SharedPipes.snk
bin
Properties
/********************************************************8
 *	Author: Andrew Deren
 *	Date: July, 2004
 *	http://www.adersoftware.com
 * 
 *	StringTokenizer class. You can use this class in any way you want
 * as long as this header remains in this file.
 * 
 *  Changed by Tim Almdal to use the generic IEnumarable
 * 
 **********************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Almdal.RegistryScript {
    /// <summary>
    /// StringTokenizer tokenized string (or stream) into tokens.
    /// </summary>
    public class StringTokenizer : IEnumerable<Token>, IEnumerator<Token> {
        const char EOF = (char)0;

        int line;
        int column;
        int pos;	// position within data

        string data;

        bool ignoreWhiteSpace;
        char[] symbolChars;

        int saveLine;
        int saveCol;
        int savePos;

        public StringTokenizer(TextReader reader) {
            if (reader == null)
                throw new ArgumentNullException("reader");

            data = reader.ReadToEnd();

            Reset();
        }

        public StringTokenizer(string data) {
            if (data == null)
                throw new ArgumentNullException("data");

            this.data = data;

            Reset();
        }

        /// <summary>
        /// gets or sets which characters are part of TokenKind.Symbol
        /// </summary>
        public char[] SymbolChars {
            get { return this.symbolChars; }
            set { this.symbolChars = value; }
        }

        /// <summary>
        /// if set to true, white space characters will be ignored,
        /// but EOL and whitespace inside of string will still be tokenized
        /// </summary>
        public bool IgnoreWhiteSpace {
            get { return this.ignoreWhiteSpace; }
            set { this.ignoreWhiteSpace = value; }
        }

        //private void Reset() {
        //    this.ignoreWhiteSpace = false;
        //    this.symbolChars = new char[] { '=', '+', '-', '/', ',', '.', '*', '~', '!', '@', '#', '$', '%', '^', '&', '(', ')', '{', '}', '[', ']', ':', ';', '<', '>', '?', '|', '\\' };

        //    line = 1;
        //    column = 1;
        //    pos = 0;
        //}

        protected char Peek(int count) {
            if (pos + count >= data.Length)
                return EOF;
            else
                return data[pos + count];
        }

        protected char Consume() {
            char ret = data[pos];
            pos++;
            column++;

            return ret;
        }

        protected Token CreateToken(TokenKind kind, string value) {
            return new Token(kind, value, line, column);
        }

        protected Token CreateToken(TokenKind kind) {
            string tokenData = data.Substring(savePos, pos - savePos);
            return new Token(kind, tokenData, saveLine, saveCol);
        }

        protected Token Next() {                        //  TNA - removed the dastardly goto
            while (true) {
                char ch = Peek(0);
                switch (ch) {
                    case EOF:
                        return CreateToken(TokenKind.EOF, string.Empty);

                    case ' ':
                    case '\t': {
                            if (this.ignoreWhiteSpace) {
                                Consume();
                                break;                  //  start again
                            }
                            else
                                return ReadWhitespace();
                        }
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9':
                        return ReadNumber();

                    case '\r': {
                            StartRead();
                            Consume();
                            if (Peek(0) == '\n')
                                Consume();	// on DOS/Windows we have \r\n for new line

                            line++;
                            column = 1;

                            return CreateToken(TokenKind.EOL);
                        }
                    case '\n': {
                            StartRead();
                            Consume();
                            line++;
                            column = 1;

                            return CreateToken(TokenKind.EOL);
                        }

                    case '\'': 
                    case '"':
                        return ReadString(ch);

                    case '%': 
                        return ReadVariable();

                    default: {
                            if (Char.IsLetter(ch) || ch == '_')
                                return ReadWord();
                            else if (IsSymbol(ch)) {
                                StartRead();
                                Consume();
                                return CreateToken(TokenKind.Symbol);
                            }
                            else {
                                StartRead();
                                Consume();
                                return CreateToken(TokenKind.Unknown);
                            }
                        }
                }
            }
        }

        /// <summary>
        /// save read point positions so that CreateToken can use those
        /// </summary>
        private void StartRead() {
            saveLine = line;
            saveCol = column;
            savePos = pos;
        }

        #region Read Token Methods
        /// <summary>
        /// reads all whitespace characters (does not include newline)
        /// </summary>
        /// <returns></returns>
        protected Token ReadWhitespace() {
            StartRead();

            Consume(); // consume the looked-ahead whitespace char

            while (true) {
                char ch = Peek(0);
                if (ch == '\t' || ch == ' ')
                    Consume();
                else
                    break;
            }

            return CreateToken(TokenKind.WhiteSpace);

        }

        /// <summary>
        /// reads number. Number is: DIGIT+ ("." DIGIT*)?
        /// </summary>
        /// <returns></returns>
        protected Token ReadNumber() {
            StartRead();

            bool hadDot = false;

            Consume(); // read first digit

            while (true) {
                char ch = Peek(0);
                if (Char.IsDigit(ch))
                    Consume();
                else if (ch == '.' && !hadDot) {
                    hadDot = true;
                    Consume();
                }
                else
                    break;
            }

            return CreateToken(TokenKind.Number);
        }

        /// <summary>
        /// reads word. Word contains any alpha character or _
        /// </summary>
        protected Token ReadWord() {
            StartRead();

            Consume(); // consume first character of the word

            while (true) {
                char ch = Peek(0);
                if (Char.IsLetter(ch) || ch == '_')
                    Consume();
                else
                    break;
            }

            return CreateToken(TokenKind.Word);
        }

        /// <summary>
        /// Read a variable of the format %name%
        /// </summary>
        /// <returns></returns>
        protected Token ReadVariable() {

            Consume();              // consume first character which is $

            StartRead();            // this marks the position of the beginning of the token

            while (true) {
                char ch = Peek(0);    // look at next available character
            if (ch == '%') break;   //  found seconf % then
                Consume();
            }

            Token tkn = CreateToken(TokenKind.Variable);

            StartRead();                //  read the closing %
            Consume();

            if ((tkn.Value.Length > 0)) {
                return tkn;
            }

            return CreateToken(TokenKind.Symbol);
        }
        
        /// <summary>
        /// reads all characters until next " is found.
        /// If "" (2 quotes) are found, then they are consumed as
        /// part of the string
        /// </summary>
        /// <returns></returns>
        protected Token ReadString(char EOS) {
            StartRead();

            Consume(); // read "

            while (true) {
                char ch = Peek(0);
                if (ch == EOF)
                    break;
                else if (ch == '\r')	// handle CR in strings
				{
                    Consume();
                    if (Peek(0) == '\n')	// for DOS & windows
                        Consume();

                    line++;
                    column = 1;
                }
                else if (ch == '\n')	// new line in quoted string
				{
                    Consume();

                    line++;
                    column = 1;
                }
                else if (ch == EOS) {
                    Consume();
                    if (Peek(0) != EOS)
                        break;	// done reading, and this quotes does not have escape character
                    else
                        Consume(); // consume second ", because first was just an escape
                }
                else
                    Consume();
            }
            return CreateToken(TokenKind.QuotedString);
        }

        /// <summary>
        /// checks whether c is a symbol character.
        /// </summary>
        protected bool IsSymbol(char c) {
            for (int i = 0; i < symbolChars.Length; i++)
                if (symbolChars[i] == c)
                    return true;

            return false;
        }
        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
            return ((IEnumerator<Token>)this);
        }

        #endregion

        #region IEnumerable<Token> Members

        IEnumerator<Token> IEnumerable<Token>.GetEnumerator() {
            bool eos = false;
            while (!eos) {
                Token tkn = Next();
                eos = tkn.Kind == TokenKind.EOF;
                yield return tkn;
            }
        }

        #endregion

        #region IEnumerator<Token> Members

        public Token Current {
            get { throw new Exception("The method or operation is not implemented."); }
        }

        #endregion

        #region IDisposable Members

        public void Dispose() {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion

        #region IEnumerator<Token> Members

        Token System.Collections.Generic.IEnumerator<Token>.Current {
            get { throw new Exception("The method or operation is not implemented."); }
        }
        #endregion

        #region IEnumerator Members

        object System.Collections.IEnumerator.Current {
            get { throw new Exception("The method or operation is not implemented."); }
        }

        public bool MoveNext() {
            throw new Exception("The method or operation is not implemented.");
        }

        public void Reset() {
            this.symbolChars = new char[] { '=', '+', '-', '/', ',', '.', '*', '~', '!', '@', '#', '$', '%', '^', '&', '(', ')', '{', '}', '[', ']', ':', ';', '<', '>', '?', '|', '\\' };

            line = 1;
            column = 1;
            pos = 0;
        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Tim Almdal

Canada Canada
No Biography provided

| Advertise | Privacy | Mobile
Web01 | 2.8.140827.1 | Last Updated 18 Sep 2006
Article Copyright 2006 by Tim Almdal
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid