// IsConstOrVar - Checkes whether a specified word is a constant or a variable
        // Input:  Atom - the name of the atom
        // Output: Returns true if the specified word is a constant or a variable
        private bool IsConstOrVar(string Atom)
        {
            bool bConstOrVar = false;

            // Search constant name space
            for (int i = 0; i < GlobalConstants.Count; i++)
            {
                ForthConstant fc = (ForthConstant)GlobalConstants[i];
                if (fc.Name.ToUpper() == Atom.ToUpper())
                {
                    bConstOrVar = true;
                }
            }
            // Search variable name space
            for (int i = 0; i < GlobalVariables.Count; i++)
            {
                ForthVariable fv = (ForthVariable)GlobalVariables[i];
                if (fv.Name.ToUpper() == Atom.ToUpper())
                {
                    bConstOrVar = true;
                }
            }

            return(bConstOrVar);
        }
        // DoAnalysis - Builds up the word, constant and variable lists
        // Input:  None
        // Output: None (Globally changes GlobalVariables, GlobalConstants, LocalVariables, Words)
        private void DoAnalysis()
        {
            ForthAtom Atom, NextAtom;
            ForthWord WordDef = null;           // Holds the definition of a word
            string    temp;
            int       noIFs    = 0;             // Number of IF statements
            int       noDOs    = 0;             // Number of DO statements
            int       noBEGINs = 0;             // Number of BEGIN statements
            int       noWHILEs = 0;             // Number of WHILE statements
            int       noCASEs  = 0;             // Number of CASE statements
            int       noOFs    = 0;             // Number of OF statements

            // Define enumerator for the source atoms list
            IEnumerator saEnum = SourceAtoms.GetEnumerator();

            while (saEnum.MoveNext())
            {
                Atom = (ForthAtom)saEnum.Current;
                // If the atom does not start with " or ." make the atom upper case
                if (!Atom.Name.StartsWith(".\"") && !Atom.Name.StartsWith("\""))
                {
                    Atom.Name = Atom.Name.ToUpper();
                }
                // Process atoms
                switch (Atom.Name)
                {
                case "EXTERN":                          // Store information after EXTERN for calling methods at runtime
                    if (InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareOutsideWords, Atom);
                    }
                    saEnum.MoveNext();                                  // Advance to next atom
                    NextAtom = ((ForthAtom)saEnum.Current);
                    string ForthWord = NextAtom.Name;                   // Forth word name
                    if (IsReserved(ForthWord))
                    {
                        RaiseException(SyntacticExceptionType._EReservedWord, NextAtom);
                    }
                    if (!IsIdentifier(ForthWord))
                    {
                        RaiseException(SyntacticExceptionType._EInvalidIdentifier, NextAtom);
                    }
                    saEnum.MoveNext();                                  // Advance to next atom
                    NextAtom = ((ForthAtom)saEnum.Current);
                    string FileName = NextAtom.Name;                    // Library name
                    saEnum.MoveNext();                                  // Advance to next atom
                    NextAtom = ((ForthAtom)saEnum.Current);
                    string Callee     = NextAtom.Name;
                    int    DotPos     = Callee.LastIndexOf('.');
                    string ClassName  = Callee.Substring(0, DotPos);
                    string MethodName = Callee.Substring(DotPos + 1);
                    ExternalWords.Add(new ExternalWord {
                        Name = ForthWord, Library = FileName, Class = ClassName, Method = MethodName
                    });
                    break;

                case "LIBRARY":                         // Store next atom as the name of the library
                    if (InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareOutsideWords, Atom);
                    }
                    saEnum.MoveNext();                                  // Advance to next atom
                    NextAtom = ((ForthAtom)saEnum.Current);
                    string libname = NextAtom.Name;
                    if (IsReserved(libname))
                    {
                        RaiseException(SyntacticExceptionType._EReservedWord, NextAtom);
                    }
                    if (!IsIdentifier(libname))
                    {
                        RaiseException(SyntacticExceptionType._EInvalidIdentifier, NextAtom);
                    }
                    LibraryName = libname;
                    break;

                case "CONSTANT":                         // Associate the value on the global stack to the next atom
                    if (InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareOutsideWords, Atom);
                    }
                    saEnum.MoveNext();                                  // Advance to next atom
                    NextAtom = ((ForthAtom)saEnum.Current);
                    if (IsReserved(NextAtom.Name))
                    {
                        RaiseException(SyntacticExceptionType._EReservedWord, NextAtom);
                    }
                    if (!IsIdentifier(NextAtom.Name))
                    {
                        RaiseException(SyntacticExceptionType._EInvalidIdentifier, NextAtom);
                    }
                    if (IsConstOrVar(NextAtom.Name))
                    {
                        RaiseException(SyntacticExceptionType._EDuplicateConst, NextAtom);
                    }
                    if (SourceStack.Count == 0)
                    {
                        RaiseException(SyntacticExceptionType._EUnableToDefineConst, NextAtom);
                    }
                    GlobalConstants.Add(new ForthConstant {
                        Name = NextAtom.Name, Value = SourceStack.Pop()
                    });                                                                                                                  // Add constant definiton to the list
                    break;

                case "VARIABLE":                         // The next atom is the variable name with the initial size of 1
                    saEnum.MoveNext();                   // Advance to next atom
                    NextAtom = ((ForthAtom)saEnum.Current);
                    if (IsReserved(NextAtom.Name))
                    {
                        RaiseException(SyntacticExceptionType._EReservedWord, NextAtom);
                    }
                    if (!IsIdentifier(NextAtom.Name))
                    {
                        RaiseException(SyntacticExceptionType._EInvalidIdentifier, NextAtom);
                    }
                    if (IsConstOrVar(NextAtom.Name))
                    {
                        RaiseException(SyntacticExceptionType._EDuplicateVar, NextAtom);
                    }
                    if (!InWordDefinition)
                    {
                        GlobalVariables.Add(new ForthVariable {
                            Name = NextAtom.Name, Size = 1
                        });
                    }
                    else
                    {
                        LocalVariables.Add(new ForthLocalVariable {
                            Name = NextAtom.Name, WordName = WordDef.Name
                        });
                    }
                    break;

                case "ALLOT":                         // The last number on the stack is the additional size for the last defined variable
                    if (InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareOutsideWords, Atom);
                    }
                    if (SourceStack.Count == 0)
                    {
                        RaiseException(SyntacticExceptionType._EUnableToAllocVar, Atom);
                    }
                    if (SourceStack.Peek().GetType() != typeof(int))
                    {
                        RaiseException(SyntacticExceptionType._EWrongAllotConstType, Atom);
                    }
                    int AllotSize = (int)SourceStack.Pop();                             // Get the ALLOT size
                    // Change the size of the last defined variable
                    int           LastVarPos = GlobalVariables.Count - 1;               // Get the position of the last variable we defined
                    ForthVariable fv         = (ForthVariable)(GlobalVariables[LastVarPos]);
                    fv.Size += AllotSize;
                    GlobalVariables[LastVarPos] = fv;                                   // Update changes in list
                    break;

                case ":":                         // Begin word definition
                    if (InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._ENestedWordsNotAllowed, Atom);
                    }
                    saEnum.MoveNext();                                  // Advance to next atom
                    NextAtom      = ((ForthAtom)saEnum.Current);
                    NextAtom.Name = NextAtom.Name.ToUpper();
                    if (IsReserved(NextAtom.Name))
                    {
                        RaiseException(SyntacticExceptionType._EReservedWord, NextAtom);
                    }
                    if (!IsIdentifier(NextAtom.Name))
                    {
                        RaiseException(SyntacticExceptionType._EInvalidIdentifier, NextAtom);
                    }
                    InWordDefinition = true;                                    // Signal beginning of word definition
                    WordDef          = new ForthWord {
                        Name = NextAtom.Name
                    };                                                                                  // Alloc here the structure, we fill it later
                    if (NextAtom.Name == "MAIN")
                    {
                        MainDefined = true;
                    }
                    break;

                case ";":                         // End word definition
                    if (!InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareInsideWords, Atom);
                    }
                    // All control structures should be terminated by now
                    if ((noIFs > 0) || (noDOs > 0) || (noBEGINs > 0) || (noWHILEs > 0) || (noCASEs > 0))
                    {
                        RaiseException(SyntacticExceptionType._EUnfinishedControlStruct, Atom);
                    }
                    Words.Add(WordDef);                                 // Add word to the list
                    InWordDefinition = false;                           // Signal end of word definition
                    break;

                case "IF":                         // IF statement
                    if (!InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareInsideWords, Atom);
                    }
                    noIFs++;
                    goto default;

                case "ELSE":                         // ELSE statement
                    if (!InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareInsideWords, Atom);
                    }
                    if (noIFs == 0)
                    {
                        RaiseException(SyntacticExceptionType._EMalformedIETStruct, Atom);
                    }
                    goto default;

                case "THEN":                         // THEN statement
                    if (!InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareInsideWords, Atom);
                    }
                    if (noIFs == 0)
                    {
                        RaiseException(SyntacticExceptionType._EMalformedIETStruct, Atom);
                    }
                    noIFs--;
                    goto default;

                case "DO":                         // DO statement
                    if (!InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareInsideWords, Atom);
                    }
                    noDOs++;
                    goto default;

                case "LOOP":                         // LOOP statement
                    if (!InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareInsideWords, Atom);
                    }
                    if (noDOs == 0)
                    {
                        RaiseException(SyntacticExceptionType._EMalformedDLStruct, Atom);
                    }
                    noDOs--;
                    goto default;

                case "+LOOP":                         // +LOOP statement
                    goto case "LOOP";

                case "LEAVE":                         // LEAVE statement
                    if (!InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareInsideWords, Atom);
                    }
                    if (noDOs == 0)
                    {
                        RaiseException(SyntacticExceptionType._EMalformedDLStruct, Atom);
                    }
                    goto default;

                case "BEGIN":                         // BEGIN statement
                    if (!InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareInsideWords, Atom);
                    }
                    noBEGINs++;
                    goto default;

                case "WHILE":                         // WHILE statement
                    if (!InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareInsideWords, Atom);
                    }
                    if (noBEGINs == 0)
                    {
                        RaiseException(SyntacticExceptionType._EMalformedBWRStruct, Atom);
                    }
                    noWHILEs++;
                    goto default;

                case "REPEAT":                         // REPEAT statement
                    if (!InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareInsideWords, Atom);
                    }
                    if ((noBEGINs == 0) || (noWHILEs == 0))
                    {
                        RaiseException(SyntacticExceptionType._EMalformedBWRStruct, Atom);
                    }
                    noBEGINs--;
                    noWHILEs--;
                    goto default;

                case "AGAIN":                         // AGAIN statement
                    if (!InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareInsideWords, Atom);
                    }
                    if (noBEGINs == 0)
                    {
                        RaiseException(SyntacticExceptionType._EMalformedBAStruct, Atom);
                    }
                    noBEGINs--;
                    goto default;

                case "UNTIL":                         // UNTIL statement
                    if (!InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareInsideWords, Atom);
                    }
                    if (noBEGINs == 0)
                    {
                        RaiseException(SyntacticExceptionType._EMalformedBUStruct, Atom);
                    }
                    noBEGINs--;
                    goto default;

                case "CASE":                         // CASE statement
                    if (!InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareInsideWords, Atom);
                    }
                    noCASEs++;
                    goto default;

                case "OF":                         // OF statement
                    if (!InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareInsideWords, Atom);
                    }
                    if (noCASEs == 0)
                    {
                        RaiseException(SyntacticExceptionType._EMalformedCOEStruct, Atom);
                    }
                    noOFs++;
                    goto default;

                case "ENDOF":                         // ENDOF statement
                    if (!InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareInsideWords, Atom);
                    }
                    if (noOFs == 0)
                    {
                        RaiseException(SyntacticExceptionType._EMalformedCOEStruct, Atom);
                    }
                    noOFs--;
                    goto default;

                case "ENDCASE":                         // ENDCASE statement
                    if (!InWordDefinition)
                    {
                        RaiseException(SyntacticExceptionType._EDeclareInsideWords, Atom);
                    }
                    if (noOFs > 0)
                    {
                        RaiseException(SyntacticExceptionType._EMalformedCOEStruct, Atom);
                    }
                    noCASEs--;
                    goto default;

                default:
                    temp = Atom.Name;                                   // Get the atom name
                    if (InWordDefinition)
                    {
                        WordDef.Definition.Add(temp);                                   // Add atom to word definition
                    }
                    else
                    {
                        // The atom should now be a constant previously defined, a number or a string
                        int ConstValue;                                         // Here we hold the value of the constant, in case we find it
                        if (GetConstIntValue(temp, out ConstValue))
                        {
                            SourceStack.Push(ConstValue);
                        }
                        else if (IsNumber(temp))
                        {
                            SourceStack.Push(Convert.ToInt32(temp));
                        }
                        else if (IsString(temp))
                        {
                            SourceStack.Push(temp.Trim(new char[] { '"' }));
                        }
                        else
                        {
                            RaiseException(SyntacticExceptionType._EInvalidIdentifier, Atom);
                        }
                    }
                    break;
                }
            }
            // Check whether word MAIN is defined
            if (MainDefined == false)
            {
                RaiseException(SyntacticExceptionType._EMainNotDefined);
            }
        }