public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { SymbolTable currentTable = symbolTable.Peek(); List <string> errors = new List <string>(); string className = lastToken.getSemanticName(); // Check if the class' name already exists foreach (Entry entry in currentTable.GetEntries()) { if (entry.getName() == className) { errors.Add(string.Format("Identifier {0} at line {1} has already been declared", className, lastToken.getLine())); break; } } // Create a class entry Entry classEntry = new ClassEntry(className, currentTable); symbolTable.Push(classEntry.getChild()); return(errors); }
public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { Stack <SemanticRecord> callChain = new Stack <SemanticRecord>(); List <string> errors = new List <string>(); if (!semanticRecordTable.Any()) { errors.Add(string.Format("Grammar error at line {0}: could not verify factor for emtpy stack", lastToken.getLine())); return(errors); } SemanticRecord lastRecord = semanticRecordTable.Pop(); // Accumulate semantic records until we reach the start of the factor while (lastRecord.recordType != RecordTypes.FactorStart) { callChain.Push(lastRecord); if (!semanticRecordTable.Any()) { errors.Add(string.Format("Grammar error at {0}. Could not find start for a factor", lastToken.getLine())); break; } lastRecord = semanticRecordTable.Pop(); } SemanticRecord currentLink = callChain.Pop(); Entry linkedVariable = null; // The first element in the chain is a reference to a locally accessible variable or function // Go through symbol tables of increasing scope until we find the referenced identifier foreach (SymbolTable table in symbolTable) { linkedVariable = table.GetEntries().FirstOrDefault(x => (x is VarParamEntry || x is FunctionEntry) && x.getName() == currentLink.getValue()); if (linkedVariable != null) { break; } } // Verify the validity of this initial reference bool success = VerifyLink(currentLink, linkedVariable, lastToken, errors); // Go through the call chain and verify each link while (callChain.Any() && success) { currentLink = callChain.Pop(); ClassEntry referredClass = ((VarParamEntry)linkedVariable).getVariable().getClass(); if (referredClass.getChild() == null) { errors.Add(string.Format("Identifier {0} cannot be reached at line {1}", currentLink.getValue(), lastToken.getLine())); return(errors); } // Look in the referred class for the variable or function that is being referred to linkedVariable = referredClass.getChild().GetEntries().FirstOrDefault(x => (x is VarParamEntry || x is FunctionEntry) && x.getName() == currentLink.getValue()); success = VerifyLink(currentLink, linkedVariable, lastToken, errors); } ClassEntry expressionType = new ClassEntry("undefined", 0); // Find the linked variable and create a new expression for it if (linkedVariable is VarParamEntry) { expressionType = ((VarParamEntry)linkedVariable).getVariable().getClass(); } else if (linkedVariable is FunctionEntry) { expressionType = ((FunctionEntry)linkedVariable).GetReturnType(); } if (linkedVariable == null) { errors.Add(string.Format("Grammar error: Could not link variable at line {0}", lastToken.getLine())); } else { semanticRecordTable.Push(new ExpressionRecord(expressionType, linkedVariable.getAddress())); } return(errors); }