public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { ClassEntry typeClass = null; List <string> errors = new List <string>(); string searchType = lastToken.getSemanticName(); // Check if the type is of int or float if (lastToken.getToken() == Tokens.TokenList.IntRes) { typeClass = intClass; } else if (lastToken.getToken() == Tokens.TokenList.FloatRes) { typeClass = floatClass; } // Check if we are recursively using a type defined in the immediate parent else if (symbolTable.Any() && symbolTable.Peek().getParent() != null && symbolTable.Peek().getParent().getName() == searchType) { errors.Add(string.Format("{0}'s member variable or function parameter cannot refer to its own class at line {1}", searchType, lastToken.getLine())); typeClass = symbolTable.Peek().getParent() as ClassEntry; } else { // Find the type being referenced in the parent scopes foreach (SymbolTable table in symbolTable) { // Look through this table's entry list for a type typeClass = table.GetEntries().FirstOrDefault(x => x.getKind() == EntryKinds.classKind && x.getName() == searchType) as ClassEntry; if (typeClass != null) { break; } } } if (typeClass != null) { semanticRecordTable.Push(new SemanticRecord(typeClass)); } else { errors.Add(string.Format("Type name: {0} does not exist at line {1}", searchType, lastToken.getLine())); semanticRecordTable.Push(new SemanticRecord(new ClassEntry(searchType, 0))); } return(errors); }
public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { string idName = lastToken.getSemanticName(); semanticRecordTable.Push(new SemanticRecord(RecordTypes.IdNameReference, idName)); return(new List <string>()); }
public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { semanticRecordTable.Push(new SemanticRecord(type, value)); return(new List <string>());; }
public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { SemanticRecord top = semanticRecordTable.Pop(); List <string> errors = new List <string>(); LinkedList <ExpressionRecord> expressionParameters = new LinkedList <ExpressionRecord>(); // Collect parameter expressions until we hit the function's name while (top.recordType != RecordTypes.IdNameReference) { if (top.recordType != RecordTypes.ExpressionType) { errors.Add(string.Format("Grammar error at {0}. Migrating a function call should only count parameters, found {1}", lastToken.getLine(), top.recordType.ToString())); } else { expressionParameters.AddFirst((ExpressionRecord)top); } top = semanticRecordTable.Pop(); } // Create the new semantic record semanticRecordTable.Push(new FunctionCallRecord(top.getValue(), expressionParameters)); return(errors); }
public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { List <string> errors = new List <string>(); string idName = lastToken.getSemanticName(); // Check parent scopes to ensure that the id has not already been declared if (symbolTable.Any() && checkParent) { foreach (Entry entry in symbolTable.Peek().GetEntries()) { if (entry.getName() == idName) { errors.Add(string.Format("Identifier {0} at line {1} has already been declared", idName, lastToken.getLine())); break; } } } // Ensure that we don't already have the id on the semantic stack // waiting to be consumed foreach (SemanticRecord record in semanticRecordTable) { if (record.recordType == RecordTypes.Variable && record.getVariable().GetName() == idName) { errors.Add(string.Format("Identifier {0} at line {1} has already been declared", idName, lastToken.getLine())); break; } } // Add the Id to the semantic stack semanticRecordTable.Push(new SemanticRecord(RecordTypes.IdName, idName)); return(errors); }
public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { Variable variable = new Variable(); List <string> errors = new List <string>(); while (semanticRecordTable.Peek().recordType == RecordTypes.IdName || semanticRecordTable.Peek().recordType == RecordTypes.TypeName || semanticRecordTable.Peek().recordType == RecordTypes.Size) { SemanticRecord topRecord = semanticRecordTable.Pop(); switch (topRecord.recordType) { case RecordTypes.Size: variable.AddDimension(int.Parse(topRecord.getValue())); break; case RecordTypes.IdName: variable.SetName(topRecord.getValue()); break; case RecordTypes.TypeName: variable.SetType(topRecord.getType()); // Once we have the type we can create the record SemanticRecord variableRecord = new SemanticRecord(variable); semanticRecordTable.Push(variableRecord); break; default: // This should only occur if the grammar is not valid errors.Add("Grammar error, parsed rule that placed unexpected character on semantic stack"); break; } } return(errors); }
public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { List <string> errors = new List <string>(); string address = string.Empty; if (symbolTable.Any() || symbolTable.Peek().getParent() == null) { address = Entry.MakeAddressForEntry(symbolTable.Peek().getParent(), "const"); } else { errors.Add(string.Format("Cannot evaluate constant at line {0} since it is not in a scope", lastToken.getLine())); } ExpressionRecord expression = new ExpressionRecord(intType ? AddTypeToList.intClass : AddTypeToList.floatClass, address); moonCode.AddGlobal(string.Format("{0} dw {1}", expression.GetAddress(), lastToken.getSemanticName())); semanticRecordTable.Push(expression); return(new List <string>()); }
public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { List <string> errors = new List <string>(); if (!semanticRecordTable.Any()) { errors.Add(string.Format("Grammar error at line {0}, semantic stack empty with creating a put command", lastToken.getLine())); return(errors); } ExpressionRecord expr = semanticRecordTable.Pop() as ExpressionRecord; if (expr == null) { errors.Add(string.Format("Grammar error at line {0}, can only put expressions", lastToken.getLine())); return(errors); } if (!symbolTable.Any() || symbolTable.Peek().getParent() == null) { errors.Add(string.Format("Cannot place put command in empty scope")); return(errors); } moonCode.AddLine(symbolTable.Peek().getParent().getAddress(), string.Format(@" lw r2, {0}(r0) putc r2 ", expr.GetAddress())); return(errors); }
public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { LinkedList <ExpressionRecord> expressions = new LinkedList <ExpressionRecord>(); List <string> errors = new List <string>(); // Accumulate the last two expressions on the semantic stack while (expressions.Count < 2) { if (!semanticRecordTable.Any()) { errors.Add(string.Format("Grammar error: Not enough expressions to validate assignment at line {0}", lastToken.getLine())); return(errors); } SemanticRecord lastRecord = semanticRecordTable.Pop(); if (lastRecord.recordType != RecordTypes.ExpressionType) { errors.Add(string.Format("Grammar error, expression validation at line {0} encountered an illegal record: \"{1}\"", lastToken.getLine(), lastRecord.recordType.ToString())); continue; } expressions.AddLast((ExpressionRecord)lastRecord); } // The first expression is the value we are reading // while the second one is the expression we are writing to ExpressionRecord type1 = expressions.First.Value; ExpressionRecord type2 = expressions.Last.Value; if (type1.GetExpressionType() != type2.GetExpressionType()) { errors.Add(string.Format("Cannot equate at line {0} a value of type {1} to {2}", lastToken.getLine(), type1.GetExpressionType().getName(), type2.GetExpressionType().getName())); } SymbolTable currentScope = symbolTable.Peek(); string outAddress = string.Empty; if (currentScope.getParent() == null) { errors.Add(string.Format("Cannot perform an assignment operation outside of a function")); } else { // Generate the code to read and store the value moonCode.AddLine(currentScope.getParent().getAddress(), string.Format(@" lw r2, {0}(r0) sw {1}(r0), r2 ", type1.GetAddress(), type2.GetAddress())); } return(errors); }
public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { SymbolTable currentTable = symbolTable.Peek(); // Get the last created variable SemanticRecord variableRecord = semanticRecordTable.Pop(); Entry variableEntry = new VarParamEntry(currentTable, variableRecord.getVariable(), EntryKinds.variable); // Only declare variables for functions (not class member variables) //if(currentTable.getParent() is FunctionEntry) { int size = variableRecord.getVariable().GetSize(); string address = variableEntry.getAddress(); if (size <= 0) { moonCode.AddGlobal(string.Format("% {0} res 0", address)); } else if (size == 4) { moonCode.AddGlobal(string.Format("{0} dw 0", address)); } else { moonCode.AddGlobal(string.Format("{0} res {1}{2}align", address, size, Environment.NewLine)); } } return(new List <string>()); }
// The analyze method for the syntactic analyzer takes in a list // of tokens from the lexical analyzer, derives the grammar and handles errors public SyntaxResult analyzeSyntax(List <IToken> lexical) { SymbolTable global = new SymbolTable("Global", null); SyntaxResult results = new SyntaxResult(global); // Remove all errors and comments from the lexical analyzer lexical.RemoveAll(x => x.isError() || x.getToken() == TokenList.BlockComment || x.getToken() == TokenList.LineComment); // Add an end of program token lexical.Add(new SimpleToken(TokenList.EndOfProgram, false)); // The stack for the table parser Stack <IProduceable> parseStack = new Stack <IProduceable>(); parseStack.Push(TokenList.EndOfProgram); parseStack.Push(startProduct); var tokenEnumerator = lexical.GetEnumerator(); // Start enumerating over the list tokenEnumerator.MoveNext(); IToken lastTerminal = null; Stack <SemanticRecord> semanticStack = new Stack <SemanticRecord>(); Stack <SymbolTable> symbolTableStack = new Stack <SymbolTable>(); symbolTableStack.Push(global); MoonCodeResult moonCode = new MoonCodeResult(); // The table driven algorithm as seen in class slides while (parseStack.Peek() != TokenList.EndOfProgram) { var top = parseStack.Peek(); if (top.isTerminal()) { if (top == tokenEnumerator.Current.getToken()) { lastTerminal = tokenEnumerator.Current; parseStack.Pop(); tokenEnumerator.MoveNext(); } else { string resumeMessage = skipErrors(ref tokenEnumerator, parseStack); results.Errors.Add(string.Format("Error Parsing terminal: Expecting {0}, got {1} at token {2}. {3}", top.getProductName(), tokenEnumerator.Current.getToken().getProductName(), tokenEnumerator.Current.getName(), resumeMessage)); } } else if (top is SemanticAction) { // Pop then execute the semantic action parseStack.Pop(); SemanticAction action = (SemanticAction)top; results.SemanticErrors.AddRange(action.ExecuteSemanticAction(semanticStack, symbolTableStack, lastTerminal, moonCode)); } else { Rule rule; Token token = tokenEnumerator.Current.getToken(); var row = table[top]; // consider removing if (table[top].TryGetValue(token, out rule)) { parseStack.Pop(); for (int i = rule.getSymbols().Count - 1; i >= 0; i--) { if (rule.getSymbols()[i] != TokenList.Epsilon) { parseStack.Push(rule.getSymbols()[i]); } } } else // if no entry exists for a symbol token pair, then it is an error { string resumeMessage = skipErrors(ref tokenEnumerator, parseStack); results.Errors.Add(string.Format("Could not find rule for produce {0} to produce {1} at token {2}. {3}", top.getProductName(), token.getProductName(), tokenEnumerator.Current.getName(), resumeMessage)); } } // Add the current state of the stack to the derivation list results.Derivation.Add(new List <IProduceable>(parseStack)); } results.MoonCode = moonCode; return(results); }
// Close a table and move to the parent table in the symbol table tree public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { if (symbolTable.Any()) { symbolTable.Pop(); } return(new List <string>()); }
public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { List <string> errors = new List <string>(); if (!semanticRecordTable.Any()) { errors.Add(string.Format("Cannot verify array index at line {0}", lastToken.getLine())); } else { ExpressionRecord record = semanticRecordTable.Pop() as ExpressionRecord; if (record == null) { errors.Add(string.Format("Array indice at line {0} is not a valid expression", lastToken.getLine())); } else if (record.GetExpressionType() != AddTypeToList.intClass) { errors.Add(string.Format("Array indice at line {0} is not a valid integer", lastToken.getLine())); } else // If the index is valid push a simple record to count this index { semanticRecordTable.Push(new SemanticRecord(RecordTypes.IndiceCount, string.Empty)); } } return(errors); }
public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { semanticRecordTable.Push(new BasicTokenRecord(lastToken.getToken())); return(new List <string>()); }
public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { Token op = null; LinkedList <ExpressionRecord> expressions = new LinkedList <ExpressionRecord>(); List <string> errors = new List <string>(); // Accumulate the two last expressions on the semantic stack while (expressions.Count < 2) { if (!semanticRecordTable.Any()) { errors.Add(string.Format("Grammar error: Not enough expressions to validate arithmetic operation at line {0}", lastToken.getLine())); return(errors); } SemanticRecord record = semanticRecordTable.Pop(); BasicTokenRecord tokenRec = record as BasicTokenRecord; if (tokenRec != null) { // Save the token representing the operation op = tokenRec.getToken(); continue; } if (record is ExpressionRecord) { expressions.AddLast(record as ExpressionRecord); } else { errors.Add(string.Format("Grammar error: record {0} at line {1} is not allowed during an arithmetic expression validation", record.recordType.ToString(), lastToken.getLine())); } } ExpressionRecord type1 = expressions.Last.Value; ExpressionRecord type2 = expressions.First.Value; // Ensure that both expressions are integers if (type1.GetExpressionType() != AddTypeToList.intClass || type2.GetExpressionType() != AddTypeToList.intClass) { errors.Add(string.Format("Cannot perform arithmetic operation at line {0} between factors of type {1} and {2}" , lastToken.getLine(), type1.GetExpressionType().getName(), type2.GetExpressionType().getName())); } SymbolTable currentScope = symbolTable.Peek(); string outAddress = string.Empty; if (currentScope.getParent() == null) { errors.Add(string.Format("Cannot perform an arithemetic operation outside of a function")); } else if (op == TokenList.And || op == TokenList.Or) { // Generate an address for the result of this sub-expression outAddress = Entry.MakeAddressForEntry(currentScope.getParent(), "arithmExpr"); // Get a unique id for the jump label string jumpId = IDGenerator.GetNext(); // Generate the code to perform a logic "and" or "or" instead of bitwise moonCode.AddGlobal(string.Format("{0} dw 0", outAddress)); moonCode.AddLine(currentScope.getParent().getAddress(), string.Format(@" lw r3, {0}(r0) lw r4, {1}(r0) {2} r2, r3, r4 bz r2, zero_{4} addi r2, r0, 1 sw {3}(r0), r2 j endop_{4} zero_{4} sw {3}(r0), r0 endop_{4} ", type1.GetAddress(), type2.GetAddress(), opLists[op], outAddress, jumpId)); } else { // Generate an address for the result of this sub-expression outAddress = Entry.MakeAddressForEntry(currentScope.getParent(), "arithmExpr"); // Generate code for a mathematical or relational expression moonCode.AddGlobal(string.Format("{0} dw 0", outAddress)); moonCode.AddLine(currentScope.getParent().getAddress(), string.Format(@" lw r3, {0}(r0) lw r4, {1}(r0) {2} r2, r3, r4 sw {3}(r0), r2 ", type1.GetAddress(), type2.GetAddress(), opLists[op], outAddress)); } // Place the resulting expression on the semantic stack semanticRecordTable.Push(new ExpressionRecord(AddTypeToList.intClass, outAddress)); return(errors); }
public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { List <string> errors = new List <string>(); if (symbolTable.Any() && symbolTable.Peek().getParent() != null) { moonCode.AddLine(symbolTable.Peek().getParent().getAddress(), line); } else { errors.Add(string.Format("Grammar error: Could not generate the requested code \"{0}\" at line {1}", line, lastToken.getLine())); } return(new List <string>()); }
// This funcion is executed when the symbol is consumed public abstract List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode);
public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { SymbolTable currentTable = symbolTable.Peek(); LinkedList <Variable> foundParameters = new LinkedList <Variable>(); bool entryCreated = false; string funcName = string.Empty; List <string> errors = new List <string>(); // Iterate over the semantic stack and consume records relevant to this function while (!entryCreated) { SemanticRecord topRecord = semanticRecordTable.Pop(); // Handle the record depending on its type switch (topRecord.recordType) { case RecordTypes.Variable: // Encountered paramenters foundParameters.AddFirst(topRecord.getVariable()); break; case RecordTypes.IdName: // The name of this function funcName = topRecord.getValue(); break; case RecordTypes.TypeName: // If we encounter a type we are done collecting and can create the entry FunctionEntry funcEntry = new FunctionEntry(currentTable, funcName, topRecord.getType()); funcEntry.AddParameters(foundParameters); // Push the function's scope to the stack of symbol tables symbolTable.Push(funcEntry.getChild()); entryCreated = true; break; default: // This should only fail if there is an error in the grammar. errors.Add("Grammar error, parsed rule that placed unexpected character on semantic stack"); break; } } return(errors); }
public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { int sizeCount = 0; List <string> errors = new List <string>(); if (!semanticRecordTable.Any()) { errors.Add(string.Format("Grammar error at line {0}: could not migrate variable for emtpy stack", lastToken.getLine())); return(errors); } SemanticRecord top = semanticRecordTable.Pop(); // Accumulate indices until we hit the variable's name while (top.recordType != RecordTypes.IdNameReference) { // Count the number of indices sizeCount++; if (top.recordType != RecordTypes.IndiceCount) { errors.Add(string.Format("Grammar error at {0}. Migrating a variable reference should only count indecies, found {1}", lastToken.getLine(), top.recordType.ToString())); sizeCount--; } if (!semanticRecordTable.Any()) { errors.Add(string.Format("Grammar error at {0}. Could not find Id name for variable", lastToken.getLine())); break; } top = semanticRecordTable.Pop(); } // Create the new semantic record semanticRecordTable.Push(new VariableReferenceRecord(top.getValue(), sizeCount)); return(errors); }
public override List <string> ExecuteSemanticAction(Stack <SemanticRecord> semanticRecordTable, Stack <SymbolTable> symbolTable, IToken lastToken, MoonCodeResult moonCode) { SymbolTable currentTable = symbolTable.Peek(); Entry funcEntry = new FunctionEntry(currentTable, lastToken.getSemanticName(), new ClassEntry("", 0)); symbolTable.Push(funcEntry.getChild()); return(new List <string>()); }
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); }
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); }