using C4IT.F4SD.DisplayFormatting; using F4SD.DocuEngine.DocuEngineDataProvider; using F4SD.DocuEngine.DocuEngineParser.Exceptions; using System; using System.Linq; using System.Text.RegularExpressions; namespace F4SD.DocuEngine.DocuEngineParser.ContentBlock { internal partial class ContentBlock { public string DocuTemplate { get; private set; } public IDocuEngineDataContainer Container { get; private set; } private ParsingContext parsingContext; public ContentBlock(string DocuTemplate, IDocuEngineDataContainer Container) { this.DocuTemplate = DocuTemplate; this.Container = Container; parsingContext = new ParsingContext(); } public string ParseContentBlock(ref int index) { bool isContentBlockFinished = false; try { while (!isContentBlockFinished) { ParseTextBlock(ref index, out var finished); if (finished) { isContentBlockFinished = true; } else { ParseCommandBlock(ref index); } } } catch (DocuEngineParserException parserException) { parsingContext.Append(parserException.CurrentText); parserException.AddToCurrentText(parsingContext.GetFinalText()); throw; } return parsingContext.GetFinalText(); } private void ParseTextBlock(ref int index, out bool isContextBlockFinished) { bool foundTrigger = false; string[] keywords = { "@@", "[[", "]]", "{{", "}}" }; string pattern = string.Join("|", keywords.Select(Regex.Escape)); Regex regex = new Regex(pattern); isContextBlockFinished = false; while (!foundTrigger) { Match match = regex.Match(DocuTemplate, index); if (match.Success) { parsingContext.Append(DocuTemplate.Substring(index, match.Index - index)); index = match.Index; switch (match.Value) { case "@@": if (DocuTemplate.Substring(index, 3).Equals("@@@")) { parsingContext.Append("@@"); index += 3; } else { foundTrigger = true; index += 2; } break; case "[[": if (DocuTemplate.Substring(index, 3).Equals("[[[")) { parsingContext.Append("[["); index += 3; } else { index += 2; SkipWhiteSpace(ref index); string variableName = ParseVariableName(ref index); SkipWhiteSpace(ref index); if (DocuTemplate.ElementAtOrDefault(index).Equals(';')) { index++; SkipWhiteSpace(ref index); string displayTypeString = ParseDisplayType(ref index); RawValueType? displayType = null; if (Enum.TryParse(displayTypeString, true, out RawValueType parseDisplayType)) { displayType = parseDisplayType; } parsingContext.Append(SubstituteVariable(variableName, displayType)); SkipWhiteSpace(ref index); if (DocuTemplate.Substring(index, 2).Equals("]]") && !(DocuTemplate.Substring(index, 3).Equals("]]]"))) { index += 2; continue; } else { throw new SyntaxErrorException("]]", DocuTemplate.Substring(index, 3)); } } else if (DocuTemplate.Substring(index, 2).Equals("]]")) { parsingContext.Append(SubstituteVariable(variableName, null)); index += 2; continue; } else { throw new SyntaxErrorException("]]\" / \";", DocuTemplate.Substring(index, 3)); } } break; case "]]": if (DocuTemplate.Substring(index, 3).Equals("]]]")) { parsingContext.Append("]]"); index += 3; } else { throw new SyntaxErrorException("]]]", "]]"); } break; case "{{": if (DocuTemplate.Substring(index, 3).Equals("{{{")) { parsingContext.Append("{{"); index += 3; } else { throw new SyntaxErrorException("{{{", "{{"); } break; case "}}": if (DocuTemplate.Substring(index, 3).Equals("}}}")) { parsingContext.Append("}}"); index += 3; } else if (DocuTemplate.Substring(index, 3).Equals("}};")) { foundTrigger = true; isContextBlockFinished = true; index += 3; } else { foundTrigger = true; isContextBlockFinished = true; index += 2; } break; } } else { int length = DocuTemplate.Length - index; if (length < 0) { length = 0; } else if (length > 15) { length = 15; } throw new SyntaxErrorException("}};", DocuTemplate.Substring(index, length)); } } } private void ParseCommandBlock(ref int index) { string[] keywords = { "(" }; string pattern = string.Join("|", keywords.Select(Regex.Escape)); Regex regex = new Regex(pattern); Match match = regex.Match(DocuTemplate, index); if (match.Success) { string commandName = ""; commandName = DocuTemplate.Substring(index, match.Index - index); index = match.Index + 1; switch (commandName) { case "if": ParseIfCommand(ref index); break; case "switch": ParseSwitchCommand(ref index); break; case "foreach": ParseForeachCommand(ref index); break; case "include": //TODO break; } } else { int length = DocuTemplate.Length - index; if (length < 0) { length = 0; } else if (length > 15) { length = 15; } throw new SyntaxErrorException("if\" / \"switch\" / \"foreach", DocuTemplate.Substring(index, length)); } } } }