bool ErrorOrReturn(string msgKey, params string[] parameters) { if (ErrorMode == ErrorMode.ErrorFree) { return(true); } throw new BbCodeParsingException( string.IsNullOrEmpty(msgKey) ? string.Empty : MessagesHelper.GetString(msgKey, parameters)); }
public virtual SequenceNode ParseSyntaxTree(string bbCode) { if (bbCode == null) { throw new ArgumentNullException(nameof(bbCode)); } Stack <SyntaxTreeNode> stack = new Stack <SyntaxTreeNode>(); var rootNode = new SequenceNode(); stack.Push(rootNode); int end = 0; while (end < bbCode.Length) { if (MatchTagEnd(bbCode, ref end, stack)) { continue; } if (MatchStartTag(bbCode, ref end, stack)) { continue; } if (MatchTextNode(bbCode, ref end, stack)) { continue; } if (ErrorMode != ErrorMode.ErrorFree) { // there is no possible match at the current position throw new BbCodeParsingException(string.Empty); } // if the error free mode is enabled force interpretation as text if no other match could be made AppendText(bbCode[end].ToString(), stack); end++; } // assert bbCode was matched entirely Debug.Assert(end == bbCode.Length); // close all tags that are still open and can be closed implicitly while (stack.Count > 1) { var node = (TagNode)stack.Pop(); if (node.Tag.RequiresClosingTag && ErrorMode == ErrorMode.Strict) { throw new BbCodeParsingException( MessagesHelper.GetString("TagNotClosed", node.Tag.Name)); } } if (stack.Count != 1) { Debug.Assert(ErrorMode != ErrorMode.ErrorFree); // only the root node may be left throw new BbCodeParsingException(string.Empty); } return(rootNode); }
string ParseText(string input, ref int pos) { int end = pos; bool escapeFound = false; bool anyEscapeFound = false; while (end < input.Length) { if (input[end] == '[' && !escapeFound) { break; } if (input[end] == ']' && !escapeFound) { if (ErrorMode == ErrorMode.Strict) { throw new BbCodeParsingException( MessagesHelper.GetString("NonescapedChar")); } } if (input[end] == '\\' && !escapeFound) { escapeFound = true; anyEscapeFound = true; } else if (escapeFound) { if (!(input[end] == '[' || input[end] == ']' || input[end] == '\\')) { if (ErrorMode == ErrorMode.Strict) { throw new BbCodeParsingException( MessagesHelper.GetString("EscapeChar")); } } escapeFound = false; } end++; } if (escapeFound) { if (ErrorMode == ErrorMode.Strict) { throw new BbCodeParsingException(""); } } var result = input.Substring(pos, end - pos); if (anyEscapeFound) { var result2 = new char[result.Length]; int writePos = 0; bool lastWasEscapeChar = false; for (int i = 0; i < result.Length; i++) { if (!lastWasEscapeChar && result[i] == '\\') { if (i < result.Length - 1) { if (!(result[i + 1] == '[' || result[i + 1] == ']' || result[i + 1] == '\\')) { // the next char was not escapable. write the slash into the output array result2[writePos++] = result[i]; } else { // the next char is meant to be escaped so the backslash is skipped lastWasEscapeChar = true; } } else { // the backslash was the last char in the string. just write it into the output array result2[writePos++] = '\\'; } } else { result2[writePos++] = result[i]; lastWasEscapeChar = false; } } result = new string(result2, 0, writePos); } pos = end; return(result == string.Empty ? null : result); }