VariableProperties GetDeclaredVariableInMethodScope(string variableName) { // Get the last node to iterate backwards over the linked list. Note that it is impossible for the linked list to be empty initially var currNode = SymbolTable.MethodScopeLinkedList.Last; // Create variable properties variable for storing the output VariableProperties variableProperties = null; // This loop will ALWAYS end, as it is certain there will exist at least 1 node, and a node will always have an end, aka. previous == null. Should there somehow not exist such a node (for debugging maybe), it will give an error // We need to iterate over all previous scopes and see if the variable is declared as that is not allowed in C# while (true) { // Get the value (aka. dictionary) of the scope var scopeVariables = currNode.Value; // Determine whether the variable exists in the scope // Stop the loop if the variable has been found in the current scope if (scopeVariables.ContainsKey(variableName)) { variableProperties = scopeVariables[variableName]; break; } // If there exists no previous node, stop the loop if (currNode.Previous == null) { break; } currNode = currNode.Previous; } // Simply return, as variable properties may or may not be null return(variableProperties); }
public override int VisitFunction([NotNull] CBluntParser.FunctionContext context) { #if DEBUG Console.WriteLine("VisitFunction"); #endif // Create a new scope to the linked list SymbolTable.MethodScopeLinkedList.AddLast(new Dictionary <string, VariableProperties>()); // Get the method's type var methodType = context.functiontype().GetText(); // Get the method's name var methodName = context.ID(0).GetText(); // Create the actual properties for the method MethodProperties methodProperties = new MethodProperties { // Set the type of the method Type = methodType, // Create the parameter types list for parsing of the method's parameters ParameterTypes = new List <string>() }; // Check whether the method contains parameters. If so, add the parameter types to the methodProperties and add the variables // to the main scope of the method for (int i = 0; i < context.variabletype().Count(); ++i) { // Get the parameter's type var parameterType = context.variabletype(i).GetText(); // Get the parameter's name. This is +1 due to that the first ID is the method's name var parameterName = context.ID(i + 1).GetText(); // Add the parameter type to the list of parameter types methodProperties.ParameterTypes.Add(parameterType); // All parameters are guranteed to be initialized, set the initialized flag var variableProperties = new VariableProperties(parameterType) { Initialized = true }; // Add the variable along with properties to the method scope SymbolTable.MethodScopeLinkedList.Last.Value.Add(parameterName, variableProperties); } SymbolTable.CurrentMethodType = methodType; // Visit the block of the method Visit(context.block()); // After the function has finished, remove the scope SymbolTable.MethodScopeLinkedList.RemoveLast(); return(0); }
VariableProperties GetDeclaredVariableInClassScope(string variableName) { // Create variableproperties var for storing the potential class variable VariableProperties variableProperties = null; if (SymbolTable.ClassScopeVariablesDictionary.ContainsKey(variableName)) { variableProperties = SymbolTable.ClassScopeVariablesDictionary[variableName]; } // Return either null or the variable's properties return(variableProperties); }
/* * Get a declared variable in method scope first, then the class scope */ VariableProperties GetDeclaredVariable(string variableName) { // Get the variable's properties from method scope VariableProperties variableProperties = GetDeclaredVariableInMethodScope(variableName); // If the variable's properties was not found, try the class scope if (variableProperties == null) { variableProperties = GetDeclaredVariableInClassScope(variableName); } // Return the variable return(variableProperties); }
public override int VisitVariableedit([NotNull] CBluntParser.VariableeditContext context) { #if DEBUG Console.WriteLine("VisitVariableedit"); #endif // The name of the variable var variableName = context.ID().GetText(); // The operator type (For example: = += /= so on) var operatorType = context.equals().GetText(); // The assignment value var assignmentValue = context.expression().GetText(); /// TODO: USE UTILITY METHOD // First iterate over the current scope and all previous scopes var currNode = SymbolTable.MethodScopeLinkedList.Last; // The properties of the variable we found VariableProperties variableProperties = null; variableProperties = GetDeclaredVariable(variableName); if (variableProperties == null) { SyntaxError(context, "Variable with name " + variableName + " cannot be assigned a value as it does not exist"); return(1); } // Get the expected assignment value, aka the value we expect the variable to be assigned SymbolTable.ExpressionStoreLinkedList.AddLast(new ExpressionStore()); Visit(context.expression()); // Set assignment type from expression, compare it against operator type var assignmentType = SymbolTable.ExpressionStoreLinkedList.Last.Value.Type; SymbolTable.ExpressionStoreLinkedList.RemoveLast(); switch (operatorType) { // Always allow default assignment case "=": break; case "+=": if (assignmentType != "number") { SyntaxError(context, "Cannot use addition assignment operator on a type " + assignmentType); return(1); } break; case "-=": if (assignmentType != "number") { SyntaxError(context, "Cannot use subtraction assignment operator on a type " + assignmentType); return(1); } break; case "*=": if (assignmentType != "number") { SyntaxError(context, "Cannot use multiplication assignment operator on a type " + assignmentType); return(1); } break; case "/=": if (assignmentType != "number") { SyntaxError(context, "Cannot use division assignment operator on a type " + assignmentType); return(1); } break; } // Now test if this variable's type is the type we are trying to assign if (variableProperties.Type != assignmentType) { SyntaxError(context, "Variable " + variableName + " is of type " + variableProperties.Type + ", cannot assign it a value of type " + assignmentType); return(1); } // If all checks passes, the variable will also be initialized variableProperties.Initialized = true; return(0); }