/// <summary> /// Génère le projet à partir d'un script. /// </summary> /// <param name="script">Script à parser.</param> /// <param name="serverTarget">Langage/Filename dans lequel générer le serveur.</param> /// <param name="clientTargets">Langages/Filenames dans lesquels générer</param> /// <param name="generationLog">Sortie d'erreurs / warnings du parseur de code.</param> /// <returns></returns> public List <OutputFile> Generate(string script, GenerationTarget serverTarget, List <GenerationTarget> clientTargets, out string generationLog) { StringBuilder log = new StringBuilder(); Tools.EventLog.EventLogHandler logHandler = new Tools.EventLog.EventLogHandler((Tools.EventLog.Entry entry) => { log.AppendLine(entry.Type.ToString() + " (" + entry.Source + ") : " + "line " + entry.Line + ". " + entry.Message + ". "); }); var output = Generate(script, serverTarget, clientTargets, logHandler); generationLog = log.ToString(); return(output); }
/// <summary> /// Crée une nouvelle cible de génération à partir d'un string au format: /// Identifier:filename /// </summary> /// <param name="str"></param> /// <returns></returns> public static GenerationTarget FromString(string str) { if (str.Contains(":")) { string[] parts = str.Split(':'); GenerationTarget target = new GenerationTarget(); target.LanguageIdentifier = parts[0]; target.OutputDirectory = parts[1].Replace("\r", "").Replace("\n", "").Trim('"'); return(target); } else { return(new GenerationTarget()); } }
/// <summary> /// Génère le projet à partir d'un script. /// TODO : - préprocesseur (include) /// - Crée une classe de chargement de fichier + interface. /// </summary> /// <param name="processedScript">Script à parser.</param> /// <param name="serverTarget">Langage/Filename dans lequel générer le serveur.</param> /// <param name="clientTargets">Langages/Filenames dans lesquels générer</param> /// <param name="logHandler">Fonction que le parseur va appeler lorsqu'un event /// (erreur / warning / autre) doit être journalisé. /// </param> public List <OutputFile> Generate(string script, GenerationTarget serverTarget, List <GenerationTarget> clientTargets, Tools.EventLog.EventLogHandler logHandler) { List <OutputFile> outputFiles = new List <OutputFile>(); // Lance le pré-processeur sur le script Dictionary <int, Generation.Preprocessor.Preprocessor.LineInfo> lineMapping = new Dictionary <int, Preprocessor.Preprocessor.LineInfo>(); Model.ProjectFile project = null; string processedScript; try { processedScript = Preprocessor.Run(script, ref lineMapping); } catch (Generation.Preprocessor.RessourceNotFoundException e) { logHandler(new Tools.EventLog.Entry(Tools.EventLog.EntryType.Error, "[Preprocessor] La ressource '" + e.Ressource + "' est introuvable", 0, 0, "[unknown]")); return(new List <OutputFile>()); } try { // Crée les jetons d'expression à partir du script. var tokens = Tokenizers.Tokenizer.Parse(processedScript, lineMapping); var exprTokens = Tokenizers.ExpressionParser.Parse(tokens); // Crée la table des types à partir des jetons d'expression. // A ce point de l'exécution, la table ne contient pas les fonctions. Model.Semantic.TypeTable table = new Model.Semantic.TypeTable(); table.OnLog += logHandler; // Initialise le parseur sémantique et le log du parseur sémantique. Model.Semantic.SemanticParser parser = new Model.Semantic.SemanticParser(); parser.Types = table; parser.Log.OnEvent += logHandler; // Project file. project = new Model.ProjectFile() { Types = parser.Types }; project.Log.OnEvent += logHandler; // Parse les différents blocks "main". try { foreach (var tk in exprTokens[0].ListTokens) { if (tk.TkType != Tokenizers.ExpressionToken.ExpressionTokenType.Comment) { var mainBlock = parser.Parse(tk); project.ParseScript(mainBlock); } } } finally { parser.Log.OnEvent -= logHandler; table.OnLog -= logHandler; } // Crée les instructions pour le projet Client et Serveur. List <Model.Language.Instruction> clientDecl = project.GenerateClientProject(); List <Model.Language.Instruction> servDecl = project.GenerateServerProject(); List <string> classes = new List <string>(); StringBuilder builder = new StringBuilder(); StringBuilder servBuilder = new StringBuilder(); // Crée le code du serveur. if (!m_languagesTable.ContainsKey(serverTarget.LanguageIdentifier)) { throw new Exception("Le langage sélectionné pour le serveur '" + serverTarget.LanguageIdentifier + "' n'est pas implémenté"); } Generation.Languages.ILanguageGenerator servGen = m_languagesTable[serverTarget.LanguageIdentifier]; servGen.SetProject(project); outputFiles.AddRange(servGen.GenerateProjectFiles(servDecl, serverTarget.OutputDirectory, true)); // Crée le code pour les clients foreach (GenerationTarget clientTarget in clientTargets) { builder.Clear(); if (!m_languagesTable.ContainsKey(clientTarget.LanguageIdentifier)) { logHandler(new Tools.EventLog.Entry(Tools.EventLog.EntryType.Error, "Le langage sélectionné pour le client '" + clientTarget.LanguageIdentifier + "' n'est pas implémenté. Compilation pour ce langage annulée", 0, 0, "compiler")); continue; } Generation.Languages.ILanguageGenerator clientGen = m_languagesTable[clientTarget.LanguageIdentifier]; clientGen.SetProject(project); outputFiles.AddRange(clientGen.GenerateProjectFiles(clientDecl, clientTarget.OutputDirectory, false)); } } catch (Core.Tokenizers.SyntaxError syntaxError) { logHandler(new Tools.EventLog.Entry(Tools.EventLog.EntryType.Error, "Erreur de syntaxe : " + syntaxError.Message, syntaxError.Line, 0, syntaxError.Source)); outputFiles.Clear(); } catch (Core.Model.Semantic.SemanticError semError) { // Le parseur sémantique utilise déjà le log. outputFiles.Clear(); } finally { if (project != null) { project.Log.OnEvent -= logHandler; } } return(outputFiles); }