/// <summary> /// Parser to turn lg content into an <see cref="LGFile"/>. /// </summary> /// <param name="content">Text content contains lg templates.</param> /// <param name="id">id is the content identifier. If importResolver is null, id must be a full path string. </param> /// <param name="importResolver">resolver to resolve LG import id to template text.</param> /// <returns>new <see cref="LGFile"/> entity.</returns> public static LGFile ParseText(string content, string id = "", ImportResolverDelegate importResolver = null) { importResolver = importResolver ?? DefaultFileResolver; var lgFile = new LGFile(content: content, id: id, importResolver: importResolver); var diagnostics = new List <Diagnostic>(); try { var(templates, imports, invalidTemplateErrors) = AntlrParse(content, id); lgFile.Templates = templates; lgFile.Imports = imports; diagnostics.AddRange(invalidTemplateErrors); lgFile.References = GetReferences(lgFile, importResolver); var semanticErrors = new StaticChecker(lgFile).Check(); diagnostics.AddRange(semanticErrors); } catch (LGException ex) { diagnostics.AddRange(ex.Diagnostics); } catch (Exception err) { diagnostics.Add(BuildDiagnostic(err.Message, source: id)); } lgFile.Diagnostics = diagnostics; return(lgFile); }
/// <summary> /// Parser to turn lg content into a <see cref="LanguageGeneration.Templates"/>. /// </summary> /// <param name="filePath">Absolute path of a LG file.</param> /// <param name="importResolver">resolver to resolve LG import id to template text.</param> /// <param name="expressionParser">expressionEngine Expression engine for evaluating expressions.</param> /// <returns>new <see cref="LanguageGeneration.Templates"/> entity.</returns> public static Templates ParseFile( string filePath, ImportResolverDelegate importResolver = null, ExpressionParser expressionParser = null) { return(TemplatesParser.ParseFile(filePath, importResolver, expressionParser).InjectToExpressionFunction()); }
/// <summary> /// Parser to turn lg content into an <see cref="LGFile"/>. /// </summary> /// <param name="filePath">LG absolute file path.</param> /// <param name="importResolver">resolver to resolve LG import id to template text.</param> /// <returns>new <see cref="LGFile"/> entity.</returns> public static LGFile ParseFile(string filePath, ImportResolverDelegate importResolver = null) { var fullPath = Path.GetFullPath(filePath.NormalizePath()); var content = File.ReadAllText(fullPath); return(ParseText(content, fullPath, importResolver)); }
/// <summary> /// Parser to turn lg content into a <see cref="Templates"/>. /// </summary> /// <param name="resource">LG resource.</param> /// <param name="importResolver">Resolver to resolve LG import id to template text.</param> /// <param name="expressionParser">Expression parser for parsing expressions.</param> /// <param name="cachedTemplates">Give the file path and templates to avoid parsing and to improve performance.</param> /// <param name="parentTemplates">Parent visited Templates.</param> /// <returns>new <see cref="Templates"/> entity.</returns> private static Templates InnerParseResource( LGResource resource, ImportResolverDelegate importResolver = null, ExpressionParser expressionParser = null, Dictionary <string, Templates> cachedTemplates = null, Stack <Templates> parentTemplates = null) { if (resource == null) { throw new ArgumentNullException(nameof(resource)); } cachedTemplates = cachedTemplates ?? new Dictionary <string, Templates>(); parentTemplates = parentTemplates ?? new Stack <Templates>(); if (cachedTemplates.ContainsKey(resource.Id)) { return(cachedTemplates[resource.Id]); } importResolver = importResolver ?? DefaultFileResolver; var lg = new Templates(content: resource.Content, id: resource.Id, source: resource.FullName, importResolver: importResolver, expressionParser: expressionParser); try { lg = new TemplatesTransformer(lg).Transform(AntlrParseTemplates(resource)); lg.References = GetReferences(lg, cachedTemplates, parentTemplates); new StaticChecker(lg).Check().ForEach(u => lg.Diagnostics.Add(u)); } catch (TemplateException ex) { ex.Diagnostics.ToList().ForEach(u => lg.Diagnostics.Add(u)); } return(lg); }
public Templates( IList <Template> templates = null, IList <TemplateImport> imports = null, IList <Diagnostic> diagnostics = null, IList <Templates> references = null, string content = null, string id = null, ExpressionParser expressionParser = null, ImportResolverDelegate importResolver = null, IList <string> options = null) { if (templates != null) { this.AddRange(templates); } Imports = imports ?? new List <TemplateImport>(); Diagnostics = diagnostics ?? new List <Diagnostic>(); References = references ?? new List <Templates>(); Content = content ?? string.Empty; ImportResolver = importResolver; Id = id ?? string.Empty; ExpressionParser = expressionParser ?? new ExpressionParser(); Options = options ?? new List <string>(); this.InjectToExpressionFunction(); }
/// <summary> /// Parser to turn lg content into a <see cref="Templates"/>. /// </summary> /// <param name="content">Text content contains lg templates.</param> /// <param name="id">Id is the identifier of content. If importResolver is null, id must be a full path string. </param> /// <param name="importResolver">Resolver to resolve LG import id to template text.</param> /// <param name="expressionParser">Expression parser for parsing expressions.</param> /// <param name="cachedTemplates">Give the file path and templates to avoid parsing and to improve performance.</param> /// <returns>new <see cref="Templates"/> entity.</returns> private static Templates InnerParseText( string content, string id = "", ImportResolverDelegate importResolver = null, ExpressionParser expressionParser = null, Dictionary <string, Templates> cachedTemplates = null) { cachedTemplates = cachedTemplates ?? new Dictionary <string, Templates>(); if (cachedTemplates.ContainsKey(id)) { return(cachedTemplates[id]); } importResolver = importResolver ?? DefaultFileResolver; var lg = new Templates(content: content, id: id, importResolver: importResolver, expressionParser: expressionParser); try { lg = new TemplatesTransformer(lg).Transform(AntlrParseTemplates(content, id)); lg.References = GetReferences(lg, cachedTemplates); new StaticChecker(lg).Check().ForEach(u => lg.Diagnostics.Add(u)); } catch (TemplateException ex) { ex.Diagnostics.ToList().ForEach(u => lg.Diagnostics.Add(u)); } return(lg); }
/// <summary> /// Parser to turn lg content into a <see cref="Templates"/>. /// </summary> /// <param name="resource">LG resource.</param> /// <param name="importResolver">Resolver to resolve LG import id to template text.</param> /// <param name="expressionParser">Expression parser for parsing expressions.</param> /// <returns>new <see cref="Templates"/> entity.</returns> public static Templates ParseResource( LGResource resource, ImportResolverDelegate importResolver = null, ExpressionParser expressionParser = null) { return(InnerParseResource(resource, importResolver, expressionParser)); }
/// <summary> /// Parser to turn lg content into a <see cref="Templates"/>. /// </summary> /// <param name="content">Text content contains lg templates.</param> /// <param name="id">Id is the identifier of content. If importResolver is null, id must be a full path string. </param> /// <param name="importResolver">Resolver to resolve LG import id to template text.</param> /// <param name="expressionParser">Expression parser for parsing expressions.</param> /// <returns>New <see cref="Templates"/> entity.</returns> public static Templates ParseText( string content, string id = "", ImportResolverDelegate importResolver = null, ExpressionParser expressionParser = null) { return(InnerParseText(content, id, importResolver, expressionParser)); }
/// <summary> /// Discover all imported lg resources from a start resouce. /// </summary> /// <param name="importResolver">resolver to resolve LG import id to template text.</param> /// <returns>LGResource list of parsed lg content.</returns> public List <LGResource> DiscoverDependencies(ImportResolverDelegate importResolver) { var resourcesFound = new HashSet <LGResource>(); ResolveImportResources(this, importResolver ?? ImportResolver.FileResolver, resourcesFound); return(resourcesFound.ToList()); }
private static IList <LGFile> GetReferences(LGFile file, ImportResolverDelegate importResolver) { var resourcesFound = new HashSet <LGFile>(); ResolveImportResources(file, resourcesFound, importResolver); resourcesFound.Remove(file); return(resourcesFound.ToList()); }
/// <summary> /// Parser to turn lg content into a <see cref="Templates"/>. /// </summary> /// <param name="filePath">Absolut path of a LG file.</param> /// <param name="importResolver">Resolver to resolve LG import id to template text.</param> /// <param name="expressionParser">Expression parser for parsing expressions.</param> /// <returns>new <see cref="Templates"/> entity.</returns> public static Templates ParseFile( string filePath, ImportResolverDelegate importResolver = null, ExpressionParser expressionParser = null) { var fullPath = Path.GetFullPath(filePath.NormalizePath()); var content = File.ReadAllText(fullPath); return(InnerParseText(content, fullPath, importResolver, expressionParser)); }
public static Templates ParseText( string content, string id = "", ImportResolverDelegate importResolver = null, ExpressionParser expressionParser = null) { var resource = new LGResource(id, id, content); return(ParseResource(resource, importResolver, expressionParser)); }
/// <summary> /// Add text as lg file content to template engine. A fullpath id is needed when importResolver is empty, or simply pass in customized importResolver. /// </summary> /// <param name="content">Text content contains lg templates.</param> /// <param name="id">id is the content identifier. If importResolver is null, id must be a full path string. </param> /// <param name="importResolver">resolver to resolve LG import id to template text.</param> /// <returns>Template engine with the parsed content.</returns> public TemplateEngine AddText(string content, string id = "", ImportResolverDelegate importResolver = null) { CheckImportResolver(id, importResolver); var rootResource = LGParser.Parse(content, id); var lgresources = rootResource.DiscoverDependencies(importResolver); Templates.AddRange(lgresources.SelectMany(x => x.Templates)); RunStaticCheck(Templates); return(this); }
/// <summary> /// Parser to turn lg content into a <see cref="Templates"/>. /// </summary> /// <param name="filePath">Absolut path of a LG file.</param> /// <param name="importResolver">Resolver to resolve LG import id to template text.</param> /// <param name="expressionParser">Expression parser for parsing expressions.</param> /// <returns>new <see cref="Templates"/> entity.</returns> public static Templates ParseFile( string filePath, ImportResolverDelegate importResolver = null, ExpressionParser expressionParser = null) { var fullPath = Path.GetFullPath(filePath.NormalizePath()); var content = File.ReadAllText(fullPath); var resource = new LGResource(fullPath, fullPath, content); return(ParseResource(resource, importResolver, expressionParser)); }
private void CheckImportResolver(string id, ImportResolverDelegate importResolver) { // Currently if no resolver is passed into AddText(), // the default fileResolver is used to resolve the imports. // default fileResolver require resource id should be fullPath, // so that it can resolve relative path based on this fullPath. // But we didn't check the id provided with AddText is fullPath or not. // So when id != fullPath, fileResolver won't work. if (importResolver == null) { var importPath = ImportResolver.NormalizePath(id); if (!Path.IsPathRooted(importPath)) { throw new Exception("[Error] id must be full path when importResolver is null"); } } }
public LGFile( IList <LGTemplate> templates = null, IList <LGImport> imports = null, IList <Diagnostic> diagnostics = null, IList <LGFile> references = null, string content = null, string id = null, ExpressionEngine expressionEngine = null, ImportResolverDelegate importResolver = null) { Templates = templates ?? new List <LGTemplate>(); Imports = imports ?? new List <LGImport>(); Diagnostics = diagnostics ?? new List <Diagnostic>(); References = references ?? new List <LGFile>(); Content = content ?? string.Empty; ImportResolver = importResolver; Id = id ?? string.Empty; ExpressionEngine = expressionEngine ?? new ExpressionEngine(); }
/// <summary> /// Parser to turn lg content into a <see cref="Templates"/>. /// </summary> /// <param name="content">Text content contains lg templates.</param> /// <param name="id">id is the identifier of content. If importResolver is null, id must be a full path string. </param> /// <param name="importResolver">resolver to resolve LG import id to template text.</param> /// <param name="expressionParser">expressionEngine parser engine for parsing expressions.</param> /// <param name="cachedTemplates">give the file path and templates to avoid parsing and to improve performance.</param> /// <returns>new <see cref="Templates"/> entity.</returns> private static Templates InnerParseText( string content, string id = "", ImportResolverDelegate importResolver = null, ExpressionParser expressionParser = null, Dictionary <string, Templates> cachedTemplates = null) { cachedTemplates = cachedTemplates ?? new Dictionary <string, Templates>(); if (cachedTemplates.ContainsKey(id)) { return(cachedTemplates[id]); } importResolver = importResolver ?? DefaultFileResolver; var lg = new Templates(content: content, id: id, importResolver: importResolver, expressionParser: expressionParser); var diagnostics = new List <Diagnostic>(); try { var(templates, imports, invalidTemplateErrors, options) = AntlrParse(content, id); lg.AddRange(templates); lg.Imports = imports; lg.Options = options; diagnostics.AddRange(invalidTemplateErrors); lg.References = GetReferences(lg, cachedTemplates); var semanticErrors = new StaticChecker(lg).Check(); diagnostics.AddRange(semanticErrors); } catch (TemplateException ex) { diagnostics.AddRange(ex.Diagnostics); } catch (Exception err) { diagnostics.Add(BuildDiagnostic(err.Message, source: id)); } lg.Diagnostics = diagnostics; return(lg); }
/// <summary> /// Load .lg files into template engine /// You can add one file, or mutlple file as once /// If you have multiple files referencing each other, make sure you add them all at once, /// otherwise static checking won't allow you to add it one by one. /// </summary> /// <param name="filePaths">Paths to .lg files.</param> /// <param name="importResolver">resolver to resolve LG import id to template text.</param> /// <returns>Teamplate engine with parsed files.</returns> public TemplateEngine AddFiles(IEnumerable <string> filePaths, ImportResolverDelegate importResolver = null) { var totalLGResources = new List <LGResource>(); foreach (var filePath in filePaths) { var fullPath = Path.GetFullPath(ImportResolver.NormalizePath(filePath)); var rootResource = LGParser.Parse(File.ReadAllText(fullPath), fullPath); var lgresources = rootResource.DiscoverDependencies(importResolver); totalLGResources.AddRange(lgresources); } // Remove duplicated lg files by id var deduplicatedLGResources = totalLGResources.GroupBy(x => x.Id).Select(x => x.First()).ToList(); Templates.AddRange(deduplicatedLGResources.SelectMany(x => x.Templates)); RunStaticCheck(Templates); return(this); }
public List <Diagnostic> CheckFiles(IEnumerable <string> filePaths, ImportResolverDelegate importResolver = null) { var result = new List <Diagnostic>(); var templates = new List <LGTemplate>(); var isParseSuccess = true; try { var totalLGResources = new List <LGResource>(); foreach (var filePath in filePaths) { // do not use ??=, it will cause issue in the C# < 8.0 importResolver = importResolver ?? ImportResolver.FileResolver; var fullPath = Path.GetFullPath(ImportResolver.NormalizePath(filePath)); var rootResource = LGParser.Parse(File.ReadAllText(fullPath), fullPath); var resources = rootResource.DiscoverDependencies(importResolver); totalLGResources.AddRange(resources); } var deduplicatedLGResources = totalLGResources.GroupBy(x => x.Id).Select(x => x.First()).ToList(); templates = deduplicatedLGResources.SelectMany(x => x.Templates).ToList(); } catch (LGException ex) { result.AddRange(ex.Diagnostics); isParseSuccess = false; } catch (Exception err) { result.Add(new Diagnostic(new Range(new Position(0, 0), new Position(0, 0)), err.Message)); isParseSuccess = false; } if (isParseSuccess) { result.AddRange(CheckTemplates(templates)); } return(result); }
public List <Diagnostic> CheckText(string content, string id = "", ImportResolverDelegate importResolver = null) { if (importResolver == null) { var importPath = ImportResolver.NormalizePath(id); if (!Path.IsPathRooted(importPath)) { throw new Exception("[Error] id must be full path when importResolver is null"); } } var result = new List <Diagnostic>(); var templates = new List <LGTemplate>(); var isParseSuccess = true; try { var rootResource = LGParser.Parse(content, id); var resources = rootResource.DiscoverDependencies(importResolver); templates = resources.SelectMany(x => x.Templates).ToList(); } catch (LGException ex) { result.AddRange(ex.Diagnostics); isParseSuccess = false; } catch (Exception err) { result.Add(new Diagnostic(new Range(new Position(0, 0), new Position(0, 0)), err.Message)); isParseSuccess = false; } if (isParseSuccess) { result.AddRange(CheckTemplates(templates)); } return(result); }
/// <summary> /// Resolve imported LG resources from a start resource. /// All the imports will be visited and resolved to LGResouce list. /// </summary> /// <param name="start">The lg resource from which to start resolving imported resources.</param> /// <param name="importResolver">resolver to resolve LG import id to template text.</param> /// <param name="resourcesFound">Resources that have been found.</param> private void ResolveImportResources(LGResource start, ImportResolverDelegate importResolver, HashSet <LGResource> resourcesFound) { var resourceIds = start.Imports.Select(lg => lg.Id).ToList(); resourcesFound.Add(start); foreach (var id in resourceIds) { try { var(content, path) = importResolver(start.Id, id); var childResource = LGParser.Parse(content, path); if (!resourcesFound.Contains(childResource)) { ResolveImportResources(childResource, importResolver, resourcesFound); } } catch (Exception err) { throw new Exception($"[Error]{id}:{err.Message}", err); } } }
/// <summary> /// Load single .lg file into template engine. /// </summary> /// <param name="filePath">Path to .lg file.</param> /// <param name="importResolver">resolver to resolve LG import id to template text.</param> /// <returns>Teamplate engine with single parsed file.</returns> public TemplateEngine AddFile(string filePath, ImportResolverDelegate importResolver = null) => AddFiles(new List <string> { filePath }, importResolver);
/// <summary> /// Parser to turn lg content into a <see cref="LanguageGeneration.Templates"/>. /// </summary> /// <param name="resource">LG resource.</param> /// <param name="importResolver">Resolver to resolve LG import id to template text.</param> /// <param name="expressionParser">Expression parser engine for parsing expressions.</param> /// <returns>new <see cref="Templates"/> entity.</returns> public static Templates ParseResource( LGResource resource, ImportResolverDelegate importResolver = null, ExpressionParser expressionParser = null) => TemplatesParser.ParseResource(resource, importResolver, expressionParser).InjectToExpressionFunction();
/// <summary> /// Parser to turn lg content into a <see cref="LanguageGeneration.Templates"/>. /// </summary> /// <param name="content">Text content contains lg templates.</param> /// <param name="id">Id is the identifier of content. If importResolver is null, id must be a full path string. </param> /// <param name="importResolver">Resolver to resolve LG import id to template text.</param> /// <param name="expressionParser">Expression parser engine for parsing expressions.</param> /// <returns>new <see cref="Templates"/> entity.</returns> public static Templates ParseText( string content, string id = "", ImportResolverDelegate importResolver = null, ExpressionParser expressionParser = null) => TemplatesParser.ParseText(content, id, importResolver, expressionParser).InjectToExpressionFunction();
/// <summary> /// Parser to turn lg content into a <see cref="LanguageGeneration.Templates"/>. /// </summary> /// <param name="filePath">Absolute path of a LG file.</param> /// <param name="importResolver">resolver to resolve LG import id to template text.</param> /// <param name="expressionParser">expressionEngine Expression engine for evaluating expressions.</param> /// <returns>new <see cref="LanguageGeneration.Templates"/> entity.</returns> public static Templates ParseFile( string filePath, ImportResolverDelegate importResolver = null, ExpressionParser expressionParser = null) => TemplatesParser.ParseFile(filePath, importResolver, expressionParser);
private static void ResolveImportResources(LGFile start, HashSet <LGFile> resourcesFound, ImportResolverDelegate importResolver) { var resourceIds = start.Imports.Select(lg => lg.Id); resourcesFound.Add(start); foreach (var id in resourceIds) { try { var(content, path) = importResolver(start.Id, id); if (resourcesFound.All(u => u.Id != path)) { var childResource = ParseText(content, path, importResolver); ResolveImportResources(childResource, resourcesFound, importResolver); } } catch (LGException err) { throw err; } catch (Exception err) { throw new LGException(err.Message, new List <Diagnostic> { BuildDiagnostic(err.Message, source: start.Id) }); } } }
public List <Diagnostic> CheckFile(string filePath, ImportResolverDelegate importResolver = null) => CheckFiles(new List <string>() { filePath }, importResolver);
/// <summary> /// Initializes a new instance of the <see cref="TemplateEngineLanguageGenerator"/> class. /// </summary> /// <param name="lgText">lg template text.</param> /// <param name="importResolver">template resource loader (id) => templateText.</param> /// <param name="id">optional label for the source of the templates (used for labeling source of template errors).</param> public TemplateEngineLanguageGenerator(string lgText, string id = null, ImportResolverDelegate importResolver = null) { this.Id = id ?? DEFAULTLABEL; this.engine = new TemplateEngine().AddText(lgText ?? string.Empty, this.Id, importResolver: importResolver); }