// 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); } }