TopologicalSort() public method

public TopologicalSort ( ) : List
return List
        public void Check( BinaryFileSchema schema )
        {
            foreach (IBfsDataBlock block in schema.DatablockList)
            {
                if (!(block is IBfsStructType))
                    continue;

                //Clear before each run as nodes will otherwise be seen as visited in the next data block.
                topoDictionary.Clear();

                IBfsStructType structType = block as IBfsStructType;
                BfsTopologicalSorting topological = new BfsTopologicalSorting();
                BfsTopologicalNode prevField = null;

                foreach ( BfsStructField field in structType.StructFieldList)
                {
                    BfsTopologicalNode node = GetTopoNode(field);
                    topological.Nodes.Add(node);

                    //Make each struct field dependent on the previous field.
                    if (prevField != null)
                        node.Nodes.Add(prevField);
                    else
                        prevField = node;

                    if (field.Conditional != null)
                        foreach (BfsExpressionVariable expVar in field.Conditional.DependantVariables)
                            node.Nodes.Add(GetTopoNode(expVar.LastField));

                    if (field.PrimitiveType.ArrayExtension != null && field.PrimitiveType.ArrayExtension is BfsKnownArray)
                    {
                        BfsKnownArray knownArray = field.PrimitiveType.ArrayExtension as BfsKnownArray;
                        foreach (BfsExpressionVariable expVar in knownArray.Expression.DependantVariables)
                            node.Nodes.Add(GetTopoNode(expVar.LastField));
                    }
                }

                //Add all the structure field as well as their dependancies
                foreach (BfsLocalField local in structType.LocalFieldList)
                {
                    BfsTopologicalNode node = GetTopoNode(local);
                    if(local.AssignmentExpression != null)
                        foreach (BfsExpressionVariable expVar in local.AssignmentExpression.DependantVariables)
                            node.Nodes.Add(GetTopoNode(expVar.LastField));
                    topological.Nodes.Add(node);
                }

                //Find the execution/parse order of the struct fields and local fields by performing a topological sort.
                structType.ParseOrder = topological.TopologicalSort();

            }

            foreach (IBfsDataBlock block in schema.DatablockList)
            {
                //Check that local-fields aren't used in their own intialization expression.
                foreach (BfsLocalField local in block.LocalFieldList)
                    if (local.AssignmentExpression != null)
                        foreach (BfsExpressionVariable expvar in local.AssignmentExpression.DependantVariables)
                            if (expvar.NameHierarchy[0] == local)
                                BfsCompiler.ReportError(local.SourceRange,
                                    "Cannot use local variable in it's own initilization expression");

                if (block is IBfsStructType)
                {
                    bool foundEOFcase = false;
                    BfsStructField eofCase = null;
                    IBfsStructType structType = (IBfsStructType)block;
                    HashSet<string> namesSeenSoFar = new HashSet<string>(structType.LocalFields.Keys);

                    foreach (BfsStructField field in structType.StructFields.Values)
                    {
                        if (foundEOFcase)
                            BfsCompiler.ReportError(field.SourceRange,
                                "Array '"+eofCase.Name+"' cannot have an EOF case because there are remaining fields in the struct.");

                        //Check that no variables in conditional expressions or array length expressions aren't read from the file yet.
                        //Check that struct-fields aren't used in their conditional expression.
                        if (field.Conditional != null)
                            foreach (BfsExpressionVariable var in field.Conditional.DependantVariables)
                                if (!namesSeenSoFar.Contains(var.NameHierarchy[0].Name) && !(var.NameHierarchy[0] is BfsEnumAliasExp))
                                    BfsCompiler.ReportError(var.SourceRange,
                                        " The variable '" + var.ToString() + "' cannot be used before it is read from the file.");

                        if (field.FieldType.ArrayExtension != null && field.FieldType.ArrayExtension is BfsKnownArray)
                        {
                            BfsKnownArray knownArray = field.FieldType.ArrayExtension as BfsKnownArray;
                            foreach (BfsExpressionVariable var in knownArray.Expression.DependantVariables)
                                if (!namesSeenSoFar.Contains(var.NameHierarchy[0].Name) && !(var.NameHierarchy[0] is BfsEnumAliasExp))
                                    BfsCompiler.ReportError(var.SourceRange,
                                        " The variable '" + var.ToString() + "' cannot be used before it is read from the file.");
                        }
                        namesSeenSoFar.Add(field.Name);

                        //Check that no struct fields come after an unknown array extension only terminating at EOF
                        //Check that no stopcases comes after an EOF
                        if (field.FieldType.ArrayExtension is BfsUnknownArray)
                        {
                            BfsUnknownArray extension = field.FieldType.ArrayExtension as BfsUnknownArray;
                            bool stopcaseafter = false;
                            foreach (IBfsStopCase stopcase in extension.StopCases)
                            {
                                if (stopcaseafter)
                                    BfsCompiler.ReportWarning(stopcase.SourceRange,
                                        "Stopcase after an EOF will never be triggered. Move the EOF to the end of the list.");

                                if (stopcase is BfsStopCaseEndOfFile)
                                {
                                    stopcaseafter = true;
                                    foundEOFcase = true;
                                    eofCase = field;
                                }
                            }
                        }
                    }
                }
            }
        }