} // end Driver.Main //----------------------------------------------------------------------------- // Parse multiple source files into a single program. // The Parser only understands Lexers (as opposed to filenames), so we can't // give the parser the string array of source files. But we don't want to // create the lexers all at once and pass them to the parser either. // Return null on errors. //----------------------------------------------------------------------------- private static AST.ProgramDecl ParseAllFiles( string [] arstSourceFiles ) { //AST.ProgramDecl root = null; AST.NamespaceDecl [] arFiles = new AST.NamespaceDecl[arstSourceFiles.Length]; bool fHasErrors = false; int iFile = 0; foreach (string stSourceFile in arstSourceFiles) { string stShort = IO.Path.GetFileNameWithoutExtension(stSourceFile); // Get a lexer for this file System.IO.StreamReader reader = null; try{ reader = new System.IO.StreamReader(stSourceFile); } catch (System.Exception e) { reader = null; PrintError_CantFindSourceFile(stSourceFile, e); fHasErrors = true; } if (reader == null) { arFiles[iFile] = null; } else { ILexer lex = new ManualParser.Lexer(stSourceFile, reader, m_defines); // Parse this file IParser p = new ManualParser.Parser(lex); Debug.Assert(p != null); // Return null on errors. Continue to try and parse the other source // files so that we can catch as many errors as possible, but // we won't resolve / codegen anything if it has parse errors. Log.WriteLine(Log.LF.Parser, "Parsing source file:" + stSourceFile); AST.NamespaceDecl nodeFile = p.ParseSourceFile(); if (nodeFile == null) { fHasErrors = true; } // Spit this out even if we have errors; it may be partially helpful. if (s_fGenerateXML) { System.Xml.XmlWriter oParse = new System.Xml.XmlTextWriter(stShort + "_parse.xml", null); AST.Node.DumpTree(nodeFile, oParse); } arFiles[iFile] = nodeFile; } // Add to program iFile++; } if (fHasErrors) { return(null); } return(new AST.ProgramDecl(arFiles)); }
//----------------------------------------------------------------------------- // Primary Worker. This drives the different stages. // Returns the error code for all expected end-user errors. // Unexpected errors (bugs / holes in the compiler) will throw an exception. //----------------------------------------------------------------------------- static int MainWorker(string[] arstSourceFiles) { if (arstSourceFiles == null) { PrintError_NoSourceFiles(); return(1); } // Check if debugging the lexer. Just do first file // @todo - should we do all files? if (ShouldDebugQuit(EStage.cLexer)) { string stDefault = arstSourceFiles[0]; System.IO.StreamReader reader = new System.IO.StreamReader(stDefault); ILexer lex = new ManualParser.Lexer(stDefault, reader); return(TestLexer(lex)); } // // Lex & Parse all source files. // It doesn't matter which order files are parsed in // AST.ProgramDecl root = ParseAllFiles(arstSourceFiles); if (root == null) { return(1); } if (ShouldDebugQuit(EStage.cParser)) { return(0); } // // Symantic checks: // // Must startup codegen so that it can assign clr types m_codegen.BeginOutput(arstSourceFiles); System.Reflection.Assembly [] refs = LoadImportedAssemblies(); if (StdErrorLog.HasErrors()) { return(19); } ICLRtypeProvider provider = m_codegen.GetProvider(refs); ISemanticChecker check = new SymbolEngine.SemanticChecker(); bool fCheckOk = check.DoCheck(root, provider, refs); if (!fCheckOk) { return(2); } // Dump parse tree after resolution if (s_fGenerateXML) { string stOutput = IO.Path.GetFileNameWithoutExtension(arstSourceFiles[0]); System.Xml.XmlWriter oSym = new System.Xml.XmlTextWriter(stOutput + "_sym.xml", null); check.DumpSymbolTable(oSym); System.Xml.XmlWriter oPost = new System.Xml.XmlTextWriter(stOutput + "_post.xml", null); AST.Node.DumpTree(root, oPost); } if (ShouldDebugQuit(EStage.cSymbolResolution)) { return(0); } // // Codegen // m_codegen.DoCodeGen(root); m_codegen.EndOutput(); // If we make it this far, we have no errors. return(0); }