Click here to Skip to main content
15,885,435 members
Articles / Programming Languages / C#

Resolving Symbolic References in a CodeDOM (Part 7)

Rate me:
Please Sign up or sign in to vote.
4.75/5 (6 votes)
2 Dec 2012CDDL12 min read 19.4K   509   14  
Resolving symbolic references in a CodeDOM.
// The Nova Project by Ken Beckett.
// Copyright (C) 2007-2012 Inevitable Software, all rights reserved.
// Released under the Common Development and Distribution License, CDDL-1.0: http://opensource.org/licenses/cddl1.php

using System.Collections.Generic;

using Nova.CodeDOM;

namespace Nova.Parsing
{
    /// <summary>
    /// The general type of a <see cref="Token"/>.
    /// </summary>
    public enum TokenType : byte { None, Identifier, Symbol, VerbatimString, String, Char, Numeric, Comment,
        DocCommentStart, DocCommentTag, DocCommentSymbol, DocCommentString, CompilerDirective }

    /// <summary>
    /// Represents a discreet unit of text parsed from the input stream, along with location
    /// and formatting information, and any trailing comments.
    /// </summary>
    public class Token : ParsedObject
    {
        #region /* FIELDS */

        /// <summary>
        /// The text of the <see cref="Token"/>.
        /// </summary>
        public string Text;

        /// <summary>
        /// The <see cref="TokenType"/> of the <see cref="Token"/>.
        /// </summary>
        public TokenType TokenType;

        /// <summary>
        /// True if the <see cref="Token"/> was escaped.
        /// </summary>
        public bool WasEscaped;

        /// <summary>
        /// True if inside a documentation comment.
        /// </summary>
        protected bool _inDocComment;

        /// <summary>
        /// The line number of the <see cref="Token"/> (1 to N).
        /// </summary>
        public int LineNumber;

        /// <summary>
        /// The column number of the <see cref="Token"/> (1 to N).
        /// </summary>
        public ushort ColumnNumber;

        /// <summary>
        /// The number of new lines preceeding the <see cref="Token"/>.
        /// </summary>
        public ushort NewLines;

        /// <summary>
        /// Any leading whitespace on the <see cref="Token"/>.  Will be empty if none (not null).
        /// </summary>
        public string LeadingWhitespace;

        /// <summary>
        /// Any trailing comments on the <see cref="Token"/>.
        /// </summary>
        public List<CommentBase> TrailingComments;

#if DEBUG
        /// <summary>
        /// The parent <see cref="CodeUnit"/> (used in Debug mode to track lost comments).
        /// </summary>
        public CodeUnit CodeUnit;
#endif

        #endregion

        #region /* CONSTRUCTORS */

#if DEBUG
        /// <summary>
        /// Create a <see cref="Token"/>.
        /// </summary>
        public Token(string text, TokenType tokenType, bool wasEscaped, bool inDocComment, int lineNumber, int columnNumber, int newLines, string leadingWhitespace, CodeUnit codeUnit)
#else
        public Token(string text, TokenType tokenType, bool wasEscaped, bool inDocComment, int lineNumber, int columnNumber, int newLines, string leadingWhitespace)
#endif
        {
            Text = text;
            TokenType = tokenType;
            WasEscaped = wasEscaped;
            _inDocComment = inDocComment;
            LineNumber = lineNumber;
            ColumnNumber = (ushort)columnNumber;
            NewLines = (ushort)newLines;
            LeadingWhitespace = leadingWhitespace;
#if DEBUG
            CodeUnit = codeUnit;
#endif
        }

#if DEBUG
        /// <summary>
        /// Enable this finalizer to trace lost comments
        /// </summary>
        ~Token()
        {
            if (TrailingComments != null && TrailingComments.Count > 0)
            {
                string error;
                CommentBase comment = TrailingComments[0];
                if (Text != null)
                    error = "Line# " + LineNumber + ": LOST COMMENTS on token '" + Text + "'";
                else
                    error = "Line# " + comment.LineNumber + ": LOST COMMENTS";
                error += ": \"" + comment.AsString().Split('\n')[0] + "\"";
                CodeUnit.LogAndAttachMessage(error, MessageSeverity.Error, MessageSource.Parse);
            }
        }
#endif

        #endregion

        #region /* PROPERTIES */

        /// <summary>
        /// Get the non-verbatim version of the text (without the '@' prefix, if any).
        /// </summary>
        public string NonVerbatimText
        {
            get { return (Text[0] == '@' ? Text.Substring(1) : Text); }
        }

        /// <summary>
        /// True if the <see cref="Token"/> is the first one on the current line.
        /// </summary>
        public bool IsFirstOnLine
        {
            get { return (NewLines > 0); }
        }

        /// <summary>
        /// True if the <see cref="Token"/> is an identifier.
        /// </summary>
        public bool IsIdentifier
        {
            get { return (TokenType == TokenType.Identifier); }
        }

        /// <summary>
        /// True if the <see cref="Token"/> is a symbol.
        /// </summary>
        public bool IsSymbol
        {
            get { return (TokenType == TokenType.Symbol); }
        }

        /// <summary>
        /// True if the <see cref="Token"/> is numeric.
        /// </summary>
        public bool IsNumeric
        {
            get { return (TokenType == TokenType.Numeric); }
        }

        /// <summary>
        /// True if the <see cref="Token"/> is a comment.
        /// </summary>
        public bool IsComment
        {
            get { return (TokenType == TokenType.Comment); }
        }

        /// <summary>
        /// True if the <see cref="Token"/> is the start of a documentation comment.
        /// </summary>
        public bool IsDocCommentStart
        {
            get { return (TokenType == TokenType.DocCommentStart); }
        }

        /// <summary>
        /// True if the <see cref="Token"/> is a documentation comment XML tag name.
        /// </summary>
        public bool IsDocCommentTag
        {
            get { return (TokenType == TokenType.DocCommentTag); }
        }

        /// <summary>
        /// True if inside a documentation comment.
        /// </summary>
        public override bool InDocComment
        {
            get { return _inDocComment; }
        }

        /// <summary>
        /// True if there are any trailing comments.
        /// </summary>
        public override bool HasTrailingComments
        {
            get { return (TrailingComments != null && TrailingComments.Count > 0); }
        }

        #endregion

        #region /* METHODS */

        /// <summary>
        /// Return this <see cref="Token"/>.
        /// </summary>
        public override Token AsToken()
        {
            return this;
        }

        /// <summary>
        /// Get this token as a string.
        /// </summary>
        public override string ToString()
        {
            return Text;
        }

        #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 Common Development and Distribution License (CDDL)


Written By
Software Developer (Senior)
United States United States
I've been writing software since the late 70's, currently focusing mainly on C#.NET. I also like to travel around the world, and I own a Chocolate Factory (sadly, none of my employees are oompa loompas).

Comments and Discussions