/// <inheritdoc/> public override object VisitTemplateDefinition([NotNull] LGFileParser.TemplateDefinitionContext context) { var startLine = context.Start.Line; var stopLine = context.Stop.Line; var templateNameLine = context.templateNameLine().TEMPLATE_NAME_LINE().GetText(); var(templateName, parameters) = ExtractTemplateNameLine(templateNameLine); if (_templates.Any(u => u.Name == templateName)) { var diagnostic = BuildTemplatesDiagnostic(TemplateErrors.DuplicatedTemplateInSameTemplate(templateName), context.templateNameLine()); _templates.Diagnostics.Add(diagnostic); } else { var templateBody = context.templateBody().GetText(); var sourceRange = new SourceRange(context, _templates.Source); var template = new Template(templateName, parameters, templateBody, sourceRange); CheckTemplateName(templateName, context.templateNameLine()); CheckTemplateParameters(parameters, context.templateNameLine()); CheckTemplateBody(template, context.templateBody(), startLine); _templates.Add(template); } return(null); }
public override List <Diagnostic> VisitStructuredTemplateBody([NotNull] LGTemplateParser.StructuredTemplateBodyContext context) { var result = new List <Diagnostic>(); var errorName = context.structuredBodyNameLine().errorStructuredName(); if (errorName != null) { result.Add(BuildLGDiagnostic(TemplateErrors.InvalidStrucName(errorName.GetText()), context: context.structuredBodyNameLine())); } if (context.structuredBodyEndLine() == null) { result.Add(BuildLGDiagnostic(TemplateErrors.MissingStrucEnd, context: context)); } var errors = context.errorStructureLine(); if (errors != null && errors.Length > 0) { foreach (var error in errors) { result.Add(BuildLGDiagnostic(TemplateErrors.InvalidStrucBody(error.GetText()), context: error)); } } else { var bodys = context.structuredBodyContentLine(); if (bodys == null || bodys.Length == 0) { result.Add(BuildLGDiagnostic(TemplateErrors.EmptyStrucContent, context: context)); } else { foreach (var body in bodys) { if (body.expressionInStructure() != null) { result.AddRange(CheckExpression(body.expressionInStructure())); } else { // KeyValueStructuredLine var structureValues = body.keyValueStructureLine().keyValueStructureValue(); var errorPrefix = "Property '" + body.keyValueStructureLine().STRUCTURE_IDENTIFIER().GetText() + "':"; foreach (var structureValue in structureValues) { foreach (var expression in structureValue.expressionInStructure()) { result.AddRange(CheckExpression(expression, errorPrefix)); } } } } } } return(result); }
/// <summary> /// Analyzer a template to get the static analyzer results. /// </summary> /// <param name="templateName">Template name.</param> /// <returns>Analyze result including variables and template references.</returns> public AnalyzerResult AnalyzeTemplate(string templateName) { if (!templateMap.ContainsKey(templateName)) { throw new Exception(TemplateErrors.TemplateNotExist(templateName)); } if (evaluationTargetStack.Any(e => e.TemplateName == templateName)) { throw new Exception($"{TemplateErrors.LoopDetected} {string.Join(" => ", evaluationTargetStack.Reverse().Select(e => e.TemplateName))} => {templateName}"); } // Using a stack to track the evaluation trace evaluationTargetStack.Push(new EvaluationTarget(templateName, null)); // we don't exclude parameters any more // because given we don't track down for templates have parameters // the only scenario that we are still analyzing an parameterized template is // this template is root template to analyze, in this we also don't have exclude parameters var dependencies = Visit(templateMap[templateName].TemplateBodyParseTree); evaluationTargetStack.Pop(); return(dependencies); }
/// <summary> /// Add a new template and return LG File. /// </summary> /// <param name="templateName">New template name.</param> /// <param name="parameters">New params.</param> /// <param name="templateBody">New template body.</param> /// <returns>Updated LG file.</returns> public Templates AddTemplate(string templateName, List<string> parameters, string templateBody) { var template = this.FirstOrDefault(u => u.Name == templateName); if (template != null) { throw new Exception(TemplateErrors.TemplateExist(templateName)); } ClearDiagnostics(); var templateNameLine = BuildTemplateNameLine(templateName, parameters); var newTemplateBody = ConvertTemplateBody(templateBody); var content = $"{templateNameLine}{newLine}{newTemplateBody}"; var originStartLine = GetLinesOfText(this.Content).Length; // update content this.Content = $"{Content}{newLine}{templateNameLine}{newLine}{newTemplateBody}"; var newTemplates = new Templates(content: string.Empty, id: Id, importResolver: ImportResolver, expressionParser: ExpressionParser); newTemplates = new TemplatesTransformer(newTemplates).Transform(AntlrParseTemplates(content, Id)); AppendDiagnosticsWithOffset(newTemplates.Diagnostics, originStartLine); var newTemplate = newTemplates.FirstOrDefault(); if (newTemplate != null) { AdjustRangeForAddTemplate(newTemplate, originStartLine); this.Add(newTemplate); new StaticChecker(this).Check().ForEach(u => this.Diagnostics.Add(u)); } return this; }
private List <Diagnostic> CheckExpression(ParserRuleContext expressionContext, string prefix = "") { var exp = expressionContext.GetText(); var result = new List <Diagnostic>(); if (!exp.EndsWith("}", StringComparison.Ordinal)) { result.Add(BuildLGDiagnostic(TemplateErrors.NoCloseBracket, context: expressionContext)); } else { exp = exp.TrimExpression(); try { ExpressionParser.Parse(exp); } #pragma warning disable CA1031 // Do not catch general exception types (catch any exception and return it in the result) catch (Exception e) #pragma warning restore CA1031 // Do not catch general exception types { var suffixErrorMsg = Evaluator.ConcatErrorMsg(TemplateErrors.ExpressionParseError(exp), e.Message); var errorMsg = Evaluator.ConcatErrorMsg(prefix, suffixErrorMsg); result.Add(BuildLGDiagnostic(errorMsg, context: expressionContext)); return(result); } } return(result); }
/// <summary> /// Expand the results of a template with given name and scope. /// Throws errors if certain errors detected <see cref="TemplateErrors"/>. /// </summary> /// <param name="templateName">Given template name.</param> /// <param name="scope">Given scope.</param> /// <returns>All possiable results.</returns> public List <object> ExpandTemplate(string templateName, object scope) { var memory = scope is CustomizedMemory scopeMemory ? scopeMemory : new CustomizedMemory(scope); if (!TemplateMap.ContainsKey(templateName)) { throw new ArgumentException(TemplateErrors.TemplateNotExist(templateName)); } var templateTarget = new EvaluationTarget(templateName, memory); var currentEvaluateId = templateTarget.GetId(); if (_evaluationTargetStack.Any(e => e.GetId() == currentEvaluateId)) { throw new InvalidOperationException($"{TemplateErrors.LoopDetected} {string.Join(" => ", _evaluationTargetStack.Reverse().Select(e => e.TemplateName))} => {templateName}"); } // Using a stack to track the evaluation trace _evaluationTargetStack.Push(templateTarget); var expanderResult = Visit(TemplateMap[templateName].TemplateBodyParseTree); _evaluationTargetStack.Pop(); var result = new List <object>(); expanderResult.ForEach(u => { result.Add(u); }); return(result); }
public object ConstructScope(string inputTemplateName, List <object> args) { var templateName = ParseTemplateName(inputTemplateName).pureTemplateName; if (!TemplateMap.ContainsKey(templateName)) { throw new Exception(TemplateErrors.TemplateNotExist(templateName)); } var parameters = TemplateMap[templateName].Parameters; var currentScope = CurrentTarget().Scope; if (args.Count == 0) { // no args to construct, inherit from current scope return(currentScope); } var newScope = parameters.Zip(args, (k, v) => new { k, v }) .ToDictionary(x => x.k, x => x.v); var memory = currentScope as CustomizedMemory; if (memory == null) { throw new Exception(TemplateErrors.InvalidMemory); } // inherit current memory's global scope return(new CustomizedMemory(memory.GlobalMemory, new SimpleObjectMemory(newScope))); }
/// <summary> /// Expand the results of a template with given name and scope. /// </summary> /// <param name="templateName">Given template name.</param> /// <param name="scope">Given scope.</param> /// <returns>All possiable results.</returns> public List <string> ExpandTemplate(string templateName, object scope) { if (!(scope is CustomizedMemory)) { scope = new CustomizedMemory(scope); } if (!TemplateMap.ContainsKey(templateName)) { throw new Exception(TemplateErrors.TemplateNotExist(templateName)); } if (evaluationTargetStack.Any(e => e.TemplateName == templateName)) { throw new Exception($"{TemplateErrors.LoopDetected} {string.Join(" => ", evaluationTargetStack.Reverse().Select(e => e.TemplateName))} => {templateName}"); } // Using a stack to track the evaluation trace evaluationTargetStack.Push(new EvaluationTarget(templateName, scope)); var result = Visit(TemplateMap[templateName].ParseTree); evaluationTargetStack.Pop(); return(result); }
private LGTemplateParser.BodyContext CheckTemplateBody(Template template, LGFileParser.TemplateBodyContext context, int startLine) { if (string.IsNullOrWhiteSpace(template.Body)) { var diagnostic = BuildTemplatesDiagnostic(TemplateErrors.NoTemplateBody(template.Name), context, DiagnosticSeverity.Warning); _templates.Diagnostics.Add(diagnostic); } else { try { var templateBodyContext = AntlrParseTemplate(template.Body, startLine); if (templateBodyContext != null) { template.TemplateBodyParseTree = templateBodyContext; new TemplateBodyTransformer(template).Transform(); } } catch (TemplateException e) { e.Diagnostics.ToList().ForEach(u => _templates.Diagnostics.Add(u)); } } return(null); }
private List <Diagnostic> CheckExpression(ParserRuleContext expressionContext, string prefix = "") { var exp = expressionContext.GetText(); var result = new List <Diagnostic>(); if (!exp.EndsWith("}")) { result.Add(BuildLGDiagnostic(TemplateErrors.NoCloseBracket, context: expressionContext)); } else { exp = exp.TrimExpression(); try { ExpressionParser.Parse(exp); } catch (Exception e) { var suffixErrorMsg = Evaluator.ConcatErrorMsg(TemplateErrors.ExpressionParseError(exp), e.Message); var errorMsg = Evaluator.ConcatErrorMsg(prefix, suffixErrorMsg); result.Add(BuildLGDiagnostic(errorMsg, context: expressionContext)); return(result); } } return(result); }
private List <Diagnostic> CheckExpression(string exp, ParserRuleContext context, string prefix = "") { var result = new List <Diagnostic>(); if (!exp.EndsWith("}")) { result.Add(BuildLGDiagnostic(TemplateErrors.NoCloseBracket, context: context)); } else { exp = exp.TrimExpression(); try { ExpressionParser.Parse(exp); } catch (Exception e) { var errorMsg = prefix + TemplateErrors.ExpressionParseError(exp) + e.Message; result.Add(BuildLGDiagnostic(errorMsg, context: context)); return(result); } } return(result); }
private void CheckTemplateParameters(List <string> parameters, LGFileParser.TemplateNameLineContext context) { foreach (var parameter in parameters) { if (!IdentifierRegex.IsMatch(parameter)) { var diagnostic = BuildTemplatesDiagnostic(TemplateErrors.InvalidParameter(parameter), context); _templates.Diagnostics.Add(diagnostic); } } }
/// <inheritdoc/> public override object VisitErrorDefinition([NotNull] LGFileParser.ErrorDefinitionContext context) { var lineContent = context.INVALID_LINE().GetText(); if (!string.IsNullOrWhiteSpace(lineContent)) { _templates.Diagnostics.Add(BuildTemplatesDiagnostic(TemplateErrors.SyntaxError($"Unexpected content: '{lineContent}'"), context)); } return(null); }
public override void SyntaxError([NotNull] IRecognizer recognizer, [Nullable] IToken offendingSymbol, int line, int charPositionInLine, [NotNull] string msg, [Nullable] RecognitionException e) { var startPosition = new Position(lineOffset + line, charPositionInLine); var stopPosition = new Position(lineOffset + line, charPositionInLine + offendingSymbol.StopIndex - offendingSymbol.StartIndex + 1); var range = new Range(startPosition, stopPosition); var diagnostic = new Diagnostic(range, TemplateErrors.SyntaxError(msg), DiagnosticSeverity.Error, source); throw new TemplateException(diagnostic.ToString(), new List <Diagnostic>() { diagnostic }); }
/// <summary> /// Evaluate a template with given name and scope. /// </summary> /// <param name="inputTemplateName">Template name.</param> /// <param name="scope">Scope.</param> /// <returns>Evaluate result.</returns> public object EvaluateTemplate(string inputTemplateName, object scope) { if (!(scope is CustomizedMemory)) { scope = new CustomizedMemory(scope); } (var reExecute, var templateName) = ParseTemplateName(inputTemplateName); if (!TemplateMap.ContainsKey(templateName)) { throw new Exception(TemplateErrors.TemplateNotExist(templateName)); } if (evaluationTargetStack.Any(e => e.TemplateName == templateName)) { throw new Exception($"{TemplateErrors.LoopDetected} {string.Join(" => ", evaluationTargetStack.Reverse().Select(e => e.TemplateName))} => {templateName}"); } var templateTarget = new EvaluationTarget(templateName, scope); var currentEvaluateId = templateTarget.GetId(); EvaluationTarget previousEvaluateTarget = null; if (evaluationTargetStack.Count != 0) { previousEvaluateTarget = evaluationTargetStack.Peek(); if (!reExecute && previousEvaluateTarget.EvaluatedChildren.ContainsKey(currentEvaluateId)) { return(previousEvaluateTarget.EvaluatedChildren[currentEvaluateId]); } } // Using a stack to track the evaluation trace evaluationTargetStack.Push(templateTarget); var result = Visit(TemplateMap[templateName].TemplateBodyParseTree); if (previousEvaluateTarget != null) { previousEvaluateTarget.EvaluatedChildren[currentEvaluateId] = result; } evaluationTargetStack.Pop(); if (lgOptions.LineBreakStyle == LGLineBreakStyle.Markdown && result is string str) { result = NewLineRegex.Replace(str, "$1$1"); } return(result); }
private void CheckTemplateName(string templateName, ParserRuleContext context) { var functionNameSplitDot = templateName.Split('.'); foreach (var id in functionNameSplitDot) { if (!TemplateNamePartRegex.IsMatch(id)) { var diagnostic = BuildTemplatesDiagnostic(TemplateErrors.InvalidTemplateName(templateName), context); _templates.Diagnostics.Add(diagnostic); break; } } }
public override List <Diagnostic> VisitTemplateDefinition([NotNull] LGFileParser.TemplateDefinitionContext context) { var result = new List <Diagnostic>(); var templateNameLine = context.templateNameLine(); var errorTemplateName = templateNameLine.errorTemplateName(); if (errorTemplateName != null) { result.Add(BuildLGDiagnostic(TemplateErrors.InvalidTemplateName, context: errorTemplateName, includeTemplateNameInfo: false)); } else { var templateName = context.templateNameLine().templateName().GetText(); if (visitedTemplateNames.Contains(templateName)) { result.Add(BuildLGDiagnostic(TemplateErrors.DuplicatedTemplateInSameTemplate(templateName), context: templateNameLine)); } else { visitedTemplateNames.Add(templateName); foreach (var reference in templates.References) { var sameTemplates = reference.Where(u => u.Name == templateName); foreach (var sameTemplate in sameTemplates) { result.Add(BuildLGDiagnostic(TemplateErrors.DuplicatedTemplateInDiffTemplate(sameTemplate.Name, sameTemplate.Source), context: templateNameLine)); } } if (result.Count > 0) { return(result); } else { if (context.templateBody() == null) { result.Add(BuildLGDiagnostic(TemplateErrors.NoTemplateBody(templateName), DiagnosticSeverity.Warning, context.templateNameLine())); } else { result.AddRange(Visit(context.templateBody())); } } } } return(result); }
private void CheckTemplateReference(string templateName, IEnumerable <Expression> children) { if (!this.TemplateMap.ContainsKey(templateName)) { throw new Exception(TemplateErrors.TemplateNotExist(templateName)); } var expectedArgsCount = this.TemplateMap[templateName].Parameters.Count(); var actualArgsCount = children.Count(); if (actualArgsCount != 0 && expectedArgsCount != actualArgsCount) { throw new Exception(TemplateErrors.ArgumentMismatch(templateName, expectedArgsCount, actualArgsCount)); } }
private List <string> EvalExpression(string exp, ParserRuleContext context, string errorPrefix = "") { exp = exp.TrimExpression(); var(result, error) = EvalByAdaptiveExpression(exp, CurrentTarget().Scope); if (error != null || (result == null && strictMode)) { var errorMsg = string.Empty; var childErrorMsg = string.Empty; if (error != null) { childErrorMsg += error; } else if (result == null) { childErrorMsg += TemplateErrors.NullExpression(exp); } if (context != null) { errorMsg += TemplateErrors.ErrorExpression(context.GetText(), CurrentTarget().TemplateName, errorPrefix); } if (evaluationTargetStack.Count > 0) { evaluationTargetStack.Pop(); } throw new Exception(childErrorMsg + errorMsg); } else if (result == null && !strictMode) { result = "null"; } if (result is IList && result.GetType().IsGenericType&& result.GetType().GetGenericTypeDefinition().IsAssignableFrom(typeof(List <>))) { return((List <string>)result); } return(new List <string>() { result.ToString() }); }
private void ValidTemplateReference(Expression expression) { var templateName = expression.Type; if (!this.TemplateMap.ContainsKey(templateName)) { throw new Exception(TemplateErrors.TemplateNotExist(templateName)); } var expectedArgsCount = this.TemplateMap[templateName].Parameters.Count(); var actualArgsCount = expression.Children.Length; if (expectedArgsCount != actualArgsCount) { throw new Exception(TemplateErrors.ArgumentMismatch(templateName, expectedArgsCount, actualArgsCount)); } }
/// <summary> /// Add a new template and return LG File. /// </summary> /// <param name="templateName">New template name.</param> /// <param name="parameters">New params.</param> /// <param name="templateBody">New template body.</param> /// <returns>Updated LG file.</returns> public Templates AddTemplate(string templateName, List <string> parameters, string templateBody) { var template = this.FirstOrDefault(u => u.Name == templateName); if (template != null) { throw new Exception(TemplateErrors.TemplateExist(templateName)); } var templateNameLine = BuildTemplateNameLine(templateName, parameters); var newTemplateBody = ConvertTemplateBody(templateBody); var newContent = $"{Content}{newLine}{templateNameLine}{newLine}{newTemplateBody}"; Initialize(ParseText(newContent, Id, ImportResolver)); return(this); }
/// <summary> /// Evaluate a template with given name and scope. /// Throws errors if certain errors detected <see cref="TemplateErrors"/>. /// </summary> /// <param name="inputTemplateName">Template name.</param> /// <param name="scope">Scope.</param> /// <returns>Evaluate result.</returns> public object EvaluateTemplate(string inputTemplateName, object scope) { var memory = scope is CustomizedMemory scopeMemory ? scopeMemory : new CustomizedMemory(scope); (var reExecute, var templateName) = ParseTemplateName(inputTemplateName); if (!TemplateMap.ContainsKey(templateName)) { throw new Exception(TemplateErrors.TemplateNotExist(templateName)); } var templateTarget = new EvaluationTarget(templateName, memory); var currentEvaluateId = templateTarget.GetId(); if (_evaluationTargetStack.Any(e => e.GetId() == currentEvaluateId)) { throw new Exception($"{TemplateErrors.LoopDetected} {string.Join(" => ", _evaluationTargetStack.Reverse().Select(e => e.TemplateName))} => {templateName}"); } EvaluationTarget previousEvaluateTarget = null; if (_evaluationTargetStack.Count != 0) { previousEvaluateTarget = _evaluationTargetStack.Peek(); if (!reExecute && previousEvaluateTarget.EvaluatedChildren.ContainsKey(currentEvaluateId)) { return(previousEvaluateTarget.EvaluatedChildren[currentEvaluateId]); } } // Using a stack to track the evaluation trace _evaluationTargetStack.Push(templateTarget); var result = Visit(TemplateMap[templateName].TemplateBodyParseTree); if (previousEvaluateTarget != null) { previousEvaluateTarget.EvaluatedChildren[currentEvaluateId] = result; } _evaluationTargetStack.Pop(); return(result); }
// Validator for template(...) private void ValidateTemplateFunction(Expression expression) { ExpressionFunctions.ValidateAtLeastOne(expression); var children0 = expression.Children[0]; if (children0.ReturnType != ReturnType.Object && children0.ReturnType != ReturnType.String) { throw new Exception(TemplateErrors.ErrorTemplateNameformat(children0.ToString())); } // Validate more if the name is string constant if (children0.Type == ExpressionType.Constant) { var templateName = (children0 as Constant).Value.ToString(); CheckTemplateReference(templateName, expression.Children.Skip(1)); } }
private bool EvalExpressionInCondition(string exp, ParserRuleContext context = null, string errorPrefix = "") { exp = exp.TrimExpression(); var(result, error) = EvalByAdaptiveExpression(exp, CurrentTarget().Scope); if (strictMode && (error != null || result == null)) { var errorMsg = string.Empty; var childErrorMsg = string.Empty; if (error != null) { childErrorMsg += error; } else if (result == null) { childErrorMsg += TemplateErrors.NullExpression(exp); } if (context != null) { errorMsg += TemplateErrors.ErrorExpression(context.GetText(), CurrentTarget().TemplateName, errorPrefix); } if (evaluationTargetStack.Count > 0) { evaluationTargetStack.Pop(); } throw new Exception(childErrorMsg + errorMsg); } else if (error != null || result == null || (result is bool r1 && r1 == false) || (result is int r2 && r2 == 0)) { return(false); } return(true); }
private LGTemplateParser.BodyContext CheckTemplateBody(string templateName, string templateBody, LGFileParser.TemplateBodyContext context, int startLine) { if (string.IsNullOrWhiteSpace(templateBody)) { var diagnostic = BuildTemplatesDiagnostic(TemplateErrors.NoTemplateBody(templateName), context, DiagnosticSeverity.Warning); _templates.Diagnostics.Add(diagnostic); } else { try { return(AntlrParseTemplate(templateBody, startLine)); } catch (TemplateException e) { e.Diagnostics.ToList().ForEach(u => _templates.Diagnostics.Add(u)); } } return(null); }
internal static void CheckExpressionResult(string exp, string error, object result, string templateName, ParserRuleContext context = null, string errorPrefix = "") { var errorMsg = string.Empty; var childErrorMsg = string.Empty; if (error != null) { childErrorMsg = ConcatErrorMsg(childErrorMsg, error); } else if (result == null) { childErrorMsg = ConcatErrorMsg(childErrorMsg, TemplateErrors.NullExpression(exp)); } if (context != null) { errorMsg = ConcatErrorMsg(errorMsg, TemplateErrors.ErrorExpression(context.GetText(), templateName, errorPrefix)); } throw new Exception(ConcatErrorMsg(childErrorMsg, errorMsg)); }
/// <summary> /// Returns a list of Diagnostic instances. /// </summary> /// <returns>Report result.</returns> public List <Diagnostic> Check() { var result = new List <Diagnostic>(); if (_templates.AllTemplates.Count == 0) { var diagnostic = new Diagnostic(Range.DefaultRange, TemplateErrors.NoTemplate, DiagnosticSeverity.Warning, _templates.Id); result.Add(diagnostic); return(result); } foreach (var template in _templates) { _currentTemplate = template; var templateDiagnostics = new List <Diagnostic>(); // checker duplicated in different files foreach (var reference in _templates.References) { var sameTemplates = reference.Where(u => u.Name == template.Name); foreach (var sameTemplate in sameTemplates) { var startLine = template.SourceRange.Range.Start.Line; var range = new Range(startLine, 0, startLine, template.Name.Length + 1); var diagnostic = new Diagnostic(range, TemplateErrors.DuplicatedTemplateInDiffTemplate(sameTemplate.Name, sameTemplate.SourceRange.Source), source: _templates.Id); templateDiagnostics.Add(diagnostic); } } if (templateDiagnostics.Count == 0 && template.TemplateBodyParseTree != null) { templateDiagnostics.AddRange(Visit(template.TemplateBodyParseTree)); } result.AddRange(templateDiagnostics); } return(result); }
internal static void CheckExpressionResult(string exp, string error, object result, string templateName, string lineContent = "", string errorPrefix = "") { var errorMsg = string.Empty; var childErrorMsg = string.Empty; if (error != null) { childErrorMsg = ConcatErrorMsg(childErrorMsg, error); } else if (result == null) { childErrorMsg = ConcatErrorMsg(childErrorMsg, TemplateErrors.NullExpression(exp)); } if (!string.IsNullOrWhiteSpace(lineContent)) { errorMsg = ConcatErrorMsg(errorMsg, TemplateErrors.ErrorExpression(lineContent, templateName, errorPrefix)); } throw new Exception(ConcatErrorMsg(childErrorMsg, errorMsg)); }
private object EvalExpression(string exp, ParserRuleContext context = null, string errorPrefix = "") { exp = exp.TrimExpression(); var(result, error) = EvalByAdaptiveExpression(exp, CurrentTarget().Scope); if (error != null || (result == null && strictMode)) { var errorMsg = string.Empty; var childErrorMsg = string.Empty; if (error != null) { childErrorMsg += error; } else if (result == null) { childErrorMsg += TemplateErrors.NullExpression(exp); } if (context != null) { errorMsg += TemplateErrors.ErrorExpression(context.GetText(), CurrentTarget().TemplateName, errorPrefix); } if (evaluationTargetStack.Count > 0) { evaluationTargetStack.Pop(); } throw new Exception(childErrorMsg + errorMsg); } else if (result == null && !strictMode) { result = "null"; } return(result); }
/// <summary> /// Expand the results of a template with given name and scope. /// </summary> /// <param name="templateName">Given template name.</param> /// <param name="scope">Given scope.</param> /// <returns>All possiable results.</returns> public List <object> ExpandTemplate(string templateName, object scope) { if (!(scope is CustomizedMemory)) { scope = new CustomizedMemory(scope); } if (!TemplateMap.ContainsKey(templateName)) { throw new Exception(TemplateErrors.TemplateNotExist(templateName)); } if (evaluationTargetStack.Any(e => e.TemplateName == templateName)) { throw new Exception($"{TemplateErrors.LoopDetected} {string.Join(" => ", evaluationTargetStack.Reverse().Select(e => e.TemplateName))} => {templateName}"); } // Using a stack to track the evaluation trace evaluationTargetStack.Push(new EvaluationTarget(templateName, scope)); var expanderResult = Visit(TemplateMap[templateName].TemplateBodyParseTree); evaluationTargetStack.Pop(); var result = new List <object>(); expanderResult.ForEach(u => { if (lgOptions.LineBreakStyle == LGLineBreakStyle.Markdown && u is string str) { result.Add(Evaluator.NewLineRegex.Replace(str, "$1$1")); } else { result.Add(u); } }); return(result); }