private static int CountCommas(LexList list, int rank, bool arrayIndexActualsAllowed) { Stack <string> stack = new Stack <string>(); if (arrayIndexActualsAllowed) { int saveIndex = list.Index - 1; bool finished = false; while (!list.AtEnd() && !finished) { switch (list.Str) { case ",": if (stack.Count == 0) { rank++; } break; case "(": stack.Push(")"); break; case "{": stack.Push("}"); break; case "[": stack.Push("]"); break; case ")": case "}": if (stack.Pop() != list.Str) { list.ThrowException("Unbalanced brackets in array initialiser"); } break; case "]": if (stack.Count == 0) { list.Prev(); finished = true; } else { if (stack.Pop() != list.Str) { list.ThrowException("Unbalanced brackets in array initialiser"); } } break; } list.Next(); } list.Index = saveIndex; } else { while (list.Str == ",") { list.Next(); rank++; } } return(rank); }
private void CompileNextFieldDefinition(LexList theLexList, Type varType) { string varId = theLexList.GetIdentifier("Expected the name of the field here."); MostRecentNameAdded = varId; theLexList.CheckStr(";", "Expected a ; here"); if (MadeFieldsDict.ContainsKey(varId)) { theLexList.ThrowException("This field already defined."); } if (CompileMethodsDict.ContainsKey(varId)) { theLexList.ThrowException("This field name already used as a method name."); } MadeFieldsDict.Add(varId, new MadeField() { VarName = varId, VarType = varType, Index = MadeFieldsDict.Count }); FieldInfo fi = ClassType.GetField("Fields", BindingFlags.Public | BindingFlags.Instance); if (fi == null) { theLexList.ThrowException("Can only add fields to a class that has a 'List<Object> Fields' field."); } if (fi.FieldType != typeof(List <object>)) { theLexList.ThrowException("Can only add fields to a class where its Fields field is of type List<object>."); } theLexList.Next(); }
// ClassVisibility = ( 'partial' 'class' | 'class' 'partial' ) . private void DoClassVisibility() { if (InputList.AtEnd()) { InputList.ThrowException("Unexpected end of text."); } if (InputList.Str == "partial") { InputList.Next(); InputList.CheckStrAndAdvance("class", "Expected a 'class' after the 'partial'."); } else if (InputList.Str == "class") { InputList.Next(); InputList.CheckStrAndAdvance("partial", "Expected a 'partial' after the 'class'."); } else { InputList.ThrowException("Expected either a 'partial class' or a 'class partial' here."); } }
private Type ParseArrayTypeModifier(LexList list, Type returnType, bool arrayIndexActualsAllowed) { if (list.Str == "[") { list.Next(); if (list.Kind == LexKind.End) { list.ThrowException("Unexpected end of input."); } if (!arrayIndexActualsAllowed) { if (list.Str != "]") { list.ThrowException("Expected a ']' here."); } list.Next(); } Type arrayType = returnType.MakeArrayType(); while (list.Str == "[") { list.Next(); arrayType = arrayType.MakeArrayType(); if (list.Str != "]") { list.ThrowException("Expected a ']' here"); } list.Next(); } if (arrayIndexActualsAllowed) { list.Prev(); } return(arrayType); } else { return(returnType); } }
private Type[] ParseGenericTypeModifier(LexList list, out bool pendingCloseAngle, BindingFlags visibility) { list.Next(); pendingCloseAngle = false; List <Type> types = new List <Type>(); bool pending = false; while (true) { types.Add(Parse(list, true, false, out pending, visibility)); if (pending) { break; } else if (list.Kind == LexKind.End) { list.ThrowException("Unexpected end of input."); } else if (list.Str == ",") { list.Next(); } else if (list.Str == ">") { list.Next(); break; } else if (list.Str == ">>") { list.Next(); pendingCloseAngle = true; break; } } return(types.ToArray()); }
// Each method declaration starts with a 'private' or a 'public' and then continues as per a method processed in MakeMethod.cs private CompileMethod DoOneMethod(LexList theLexList) { BindingFlags vis = BindingFlags.Public; if (theLexList.Str == "public") { vis = BindingFlags.Public; } else if (theLexList.Str == "private") { vis = BindingFlags.NonPublic; } else { theLexList.ThrowException("Expected this method to be marked either public or private."); } theLexList.Next(); CompileMethod cm = new CompileMethod(Parser, theLexList, ClassType, vis); theLexList.CheckStrAndAdvance("}", "Expected a closing } at the end of the method."); return(cm); }
// Syntax: // Type = TypeNonArray [ TypeArrayPart ] . // TypeNonArray = TypeIdAndGenerics *( '.' TypeIdAndGenerics ) . // TypeIdAndGenerics = TypeIdentifier [ Generics ] . // Generics = '<' Type *( ',' Type ) '>' . // TypeArrayPart = '[' ']' *( '[' ']' ) . public Type Parse(LexList list, bool typeOnly, bool arrayIndexActualsAllowed, out bool pendingCloseAngle, BindingFlags visibility) { string id = ""; Type returnType = null; int checkPoint = list.Index; pendingCloseAngle = false; while (true) { if (list.Kind == LexKind.Type) { returnType = list.CurrentToken().ActualObject as Type; list.Next(); return(returnType); } if (list.Kind != LexKind.Identifier) { if (typeOnly) { list.ThrowException("Unable to convert this to a type."); } return(returnType); } if (id != "") { id += "."; } id += list.GetIdentifier(); Type ty = null; if (list.Str != "<" || !IsGenericSpec(list)) { ty = FindTypeFromDottedIds(returnType, id, visibility); } if (ty != null) { id = ""; returnType = ty; checkPoint = list.Index; if (list.Kind == LexKind.End) { return(returnType); } if (list.Str != ".") { return(ParseArrayTypeModifier(list, returnType, arrayIndexActualsAllowed)); } } else if (ty == null && list.Str == "<" && IsGenericSpec(list)) { // The test for the GenericSpec is needed to separate out comparision '<' or shift '<' from generic brackets. int save = list.Index; Type[] types = ParseGenericTypeModifier(list, out pendingCloseAngle, visibility); id += "`" + types.Length.ToString(); ty = FindTypeFromDottedIds(returnType, id, visibility); if (ty != null) { ty = ty.MakeGenericType(types.ToArray()); } if (ty == null) { if (typeOnly) { list[save].ThrowException("Unable to resolve generic type.", list); } list.Index = checkPoint; return(returnType); } return(ParseArrayTypeModifier(list, ty, arrayIndexActualsAllowed)); } else { if (list.Str != ".") { if (typeOnly) { list.Prev(); list.ThrowException("Unable to convert this to a type."); } list.Index = checkPoint; return(returnType); } } list.Next(); // skips over the '.' } }
public MakeClass AddMethodsAndFields(LexList list, bool overwriteAllowed) { if (InputList != null) { PreviousInputLists.Add(InputList); } InputList = list; Type varType = null; var currentListOfMethods = new List <CompileMethod>(); try { Crosslink(); DoClassVisibility(); DoClassType(); InputList.CheckStrAndAdvance("{", "Expected an { after the class header."); while (true) { if (InputList.Str == "}" && InputList.NextIsAtEnd()) { break; } else if ((InputList.Str == "public" || InputList.Str == "private" || InputList.Str == "[") && !IsAFieldDefinition()) { CompileNextMethodHeader(InputList, overwriteAllowed, currentListOfMethods); } else if ((InputList.Str == "public" || InputList.Str == "private") && IsAFieldDefinition()) { InputList.Next(); varType = IsVarKind(); if (varType == null) { InputList.ThrowException("Unknown field type here"); } CompileNextFieldDefinition(InputList, varType); } else if ((varType = IsVarKind()) != null) { CompileNextFieldDefinition(InputList, varType); } else { InputList.ThrowException("Expected either a 'public' or 'private' keyword (to start a method) or a type (to start a field declaration) here or the closing } of the class."); } } InputList.CheckStrAndAdvance("}", "Expected a closing } here."); if (!InputList.AtEnd()) { InputList.ThrowException("Expected the end of the source text here."); } if (MadeFieldsDict.Count > 0) { MakeFieldInitialiser(currentListOfMethods); } FinishClass(currentListOfMethods); } catch (LexListException lle) { throw lle; } catch (Exception ex) { list.CurrentToken().ThrowException(ex.Message, list); } return(this); }