// System stuff using System; using System.IO; using System.Reflection; // ANTLR stuff using TokenStreamException = antlr.TokenStreamException; using Antlr.Runtime; using Antlr.Runtime.Tree; using Antlr.StringTemplate; // C# CodeGen Stuff using Compiler = System.CodeDom.Compiler; using Microsoft.CSharp; namespace LolSharp { class LolCompiler { //the command line looks like: [--interpret] //the --interpret flag causes immediate execution in lieu of generating an executable static void Main(string[] args) { string filename = args[0]; string programName = filename.Substring(0, filename.LastIndexOf('.')); //TODO - use a more robust command line argument mechanism bool inMemory = (args.Length > 1) && ("--interpret".StartsWith(args[1], StringComparison.OrdinalIgnoreCase)); try { //CSharpTarget.stg contains string templates used for targeting C# TextReader stgReader = new StreamReader(File.Open("CSharpTarget.stg", FileMode.Open)); StringTemplateGroup stg = new StringTemplateGroup(stgReader); //lex ICharStream input = new ANTLRFileStream(filename); LolSharpLexer lex = new LolSharpLexer(input); //parse LolSharpParser parse = new LolSharpParser(new CommonTokenStream(lex)); LolSharpParser.program_return parseRet = parse.program(); //generate C# ITreeNodeStream nodeStream = new CommonTreeNodeStream(parseRet.Tree); LolSharpGen gen = new LolSharpGen(nodeStream); gen.TemplateLib = stg; LolSharpGen.program_return ret = gen.program(); //compile to executable and optionally run Assembly assembly = Generate(ret.Template.ToString(), programName, inMemory); if (inMemory) { assembly.EntryPoint.Invoke(null, new object[] { new string[] { } }); } } catch (TokenStreamException e) { Console.Error.WriteLine("exception: " + e); } catch (RecognitionException e) { Console.Error.WriteLine("exception: " + e); } } static Assembly Generate(string code, string name, bool inMemory) { //TODO - allow specification of output dir string outputDir = Directory.GetCurrentDirectory(); //dump the generated code using (FileStream fs = File.OpenWrite(Path.Combine(outputDir, name + ".lol.cs"))) { StreamWriter writer = new StreamWriter(fs); writer.Write(code); writer.Flush(); writer.Close(); } Compiler.CompilerParameters compilerParams = new Compiler.CompilerParameters(); compilerParams.GenerateInMemory = inMemory; if (!inMemory) { compilerParams.OutputAssembly = Path.Combine(outputDir, name + ".exe"); } compilerParams.TreatWarningsAsErrors = false; compilerParams.CompilerOptions = "/optimize"; compilerParams.MainClass = "LolSharpProgram"; compilerParams.GenerateExecutable = true; CSharpCodeProvider provider = new CSharpCodeProvider(); Compiler.CompilerResults results = provider.CompileAssemblyFromSource(compilerParams, code); if (results.Errors.HasErrors) { throw new Exception("Internal compiler error."); //this means a bug in our compiler, not the user's code } return results.CompiledAssembly; } } }