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);
        }
Exemplo n.º 2
0
        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>());
        }
Exemplo n.º 3
0
        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>());;
        }
Exemplo n.º 4
0
        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);
        }
Exemplo n.º 5
0
        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);
        }
Exemplo n.º 7
0
        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);
        }
Exemplo n.º 12
0
        // 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);
        }
Exemplo n.º 14
0
        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>());
        }
Exemplo n.º 15
0
        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);
        }
Exemplo n.º 16
0
        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>());
        }
Exemplo n.º 17
0
 // 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);
        }
Exemplo n.º 20
0
        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);
        }
Exemplo n.º 22
0
        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);
        }