public static string Interpret(string regex) { RegexBuffer buffer = new RegexBuffer(regex); RegexExpression expression = new RegexExpression(buffer); return(expression.ToString(0)); }
public RegexQuantifier(RegexBuffer buffer) { int startLocation = buffer.Offset; buffer.MoveNext(); Match match = new Regex(@"(?<n>\d+)(?<Comma>,?)(?<m>\d*)\}").Match(buffer.String); if (match.Success) { if (match.Groups["m"].Length != 0) { this.description = string.Format("At least {0}, but not more than {1} times", match.Groups["n"], match.Groups["m"]); } else if (match.Groups["Comma"].Length != 0) { this.description = string.Format("At least {0} times", match.Groups["n"]); } else { this.description = string.Format("Exactly {0} times", match.Groups["n"]); } buffer.Offset += match.Groups[0].Length; if (!buffer.AtEnd && (buffer.Current == '?')) { this.description = this.description + " (non-greedy)"; buffer.MoveNext(); } } else { this.description = "missing '}' in quantifier"; } buffer.AddLookup(this, startLocation, buffer.Offset - 1); }
private bool CheckLookahead(RegexBuffer buffer) { Match match = new Regex("\r\n\t\t\t\t ^ # anchor to start of string\r\n\t\t\t\t\t\t\\?\r\n\t\t\t\t\t\t(?<Assertion><=|<!|=|!) # assertion char\r\n\t\t\t\t\t\t(?<Rest>.+) # The rest of the expression\r\n\t\t\t\t\t\t", RegexOptions.IgnorePatternWhitespace).Match(buffer.String); if (!match.Success) { return(false); } switch (match.Groups["Assertion"].Value) { case "=": this.description = "zero-width positive lookahead"; break; case "!": this.description = "zero-width negative lookahead"; break; case "<=": this.description = "zero-width positive lookbehind"; break; case "<!": this.description = "zero-width negative lookbehind"; break; } buffer.Offset += match.Groups["Rest"].Index; this.expression = new RegexExpression(buffer); this.CheckClosingParen(buffer); return(true); }
public RegexCharClass(RegexBuffer buffer) { int startLocation = buffer.Offset; buffer.MoveNext(); Match match = new Regex(@"(?<Negated>\^?)(?<Class>.+?)\]").Match(buffer.String); if (match.Success) { if (match.Groups["Negated"].ToString() == "^") { this.description = string.Format("Any character not in \"{0}\"", match.Groups["Class"]); } else { this.description = string.Format("Any character in \"{0}\"", match.Groups["Class"]); } buffer.Offset += match.Groups[0].Length; } else { this.description = "missing ']' in character class"; } buffer.AddLookup(this, startLocation, buffer.Offset - 1); }
private void EatComment(RegexBuffer buffer) { while (buffer.Current != '\r') { buffer.MoveNext(); } }
public RegexConditional(RegexBuffer buffer) { this.startLocation = buffer.Offset; this.expression = new RegexExpression(buffer); this.CheckClosingParen(buffer); this.yesNo = new RegexExpression(buffer); this.CheckClosingParen(buffer); buffer.AddLookup(this, this.startLocation, buffer.Offset - 1); }
private bool HandlePlainOldCapture(RegexBuffer buffer) { if (buffer.ExplicitCapture) { this.description = string.Format("Non-capturing Group", new object[0]); } this.expression = new RegexExpression(buffer); this.CheckClosingParen(buffer); return(true); }
private bool CheckConditional(RegexBuffer buffer) { Match match = new Regex("\r\n\t\t\t\t ^ # anchor to start of string\r\n\t\t\t\t\t\t\\?\\(\r\n\t\t\t\t\t\t(?<Rest>.+) # The rest of the expression\r\n\t\t\t\t\t\t", RegexOptions.IgnorePatternWhitespace).Match(buffer.String); if (match.Success) { this.description = string.Format("Conditional Subexpression", new object[0]); buffer.Offset += match.Groups["Rest"].Index; this.expression = new RegexConditional(buffer); return(true); } return(false); }
private bool CheckBackReference(RegexBuffer buffer) { Match match = new Regex("\r\n\t\t\t\t\t\tk\\<(?<Name>.+?)\\>\r\n\t\t\t\t\t\t", RegexOptions.IgnorePatternWhitespace).Match(buffer.String); if (match.Success) { this.special = true; this.character = string.Format("Backreference to match: {0}", match.Groups["Name"]); buffer.Offset += match.Groups[0].Length; return(true); } return(false); }
private void DecodeEscape(RegexBuffer buffer) { buffer.MoveNext(); this.character = (string)escaped[buffer.Current]; if (this.character == null) { if (!this.CheckBackReference(buffer)) { switch (buffer.Current) { case 'u': { buffer.MoveNext(); string text = buffer.String.Substring(0, 4); this.character = "Unicode " + text; buffer.Offset += 4; return; } case 'x': { buffer.MoveNext(); string text2 = buffer.String.Substring(0, 2); this.character = "Hex " + text2; buffer.Offset += 2; return; } case ' ': this.character = "' ' (space)"; this.special = false; buffer.MoveNext(); return; case 'c': buffer.MoveNext(); this.character = "CTRL-" + buffer.Current; buffer.MoveNext(); return; } this.character = new string(buffer.Current, 1); this.special = false; buffer.MoveNext(); } } else { this.special = true; buffer.MoveNext(); } }
private bool CheckOptions(RegexBuffer buffer) { Match match = new Regex("\r\n\t\t\t\t ^ # anchor to start of string\r\n\t\t\t\t\t\t\\?(?<Options>[imnsx-]+):\r\n\t\t\t\t\t\t", RegexOptions.IgnorePatternWhitespace).Match(buffer.String); if (match.Success) { string text = match.Groups["Options"].Value; this.description = string.Format("Set options to {0}", optionNames[text]); this.expression = null; buffer.Offset += match.Groups[0].Length; return(true); } return(false); }
private bool CheckNamed(RegexBuffer buffer) { Match match = new Regex("\r\n\t\t\t\t ^ # anchor to start of string\r\n\t\t\t\t\t\t\\?(\\<|') # ?< or ?'\r\n\t\t\t\t\t\t(?<Name>[a-zA-Z0-9]+?) # Capture name\r\n\t\t\t\t\t\t(\\>|') # ?> or ?'\r\n\t\t\t\t\t\t(?<Rest>.+) # The rest of the string\r\n\t\t\t\t\t\t", RegexOptions.IgnorePatternWhitespace).Match(buffer.String); if (match.Success) { this.description = string.Format("Capture to <{0}>", match.Groups["Name"]); buffer.Offset += match.Groups["Rest"].Index; this.expression = new RegexExpression(buffer); this.CheckClosingParen(buffer); return(true); } return(false); }
private bool CheckNonCapturing(RegexBuffer buffer) { Match match = new Regex("\r\n\t\t\t\t ^ # anchor to start of string\r\n\t\t\t\t\t\t\\?:\r\n\t\t\t\t\t\t(?<Rest>.+) # The rest of the expression\r\n\t\t\t\t\t\t", RegexOptions.IgnorePatternWhitespace).Match(buffer.String); if (match.Success) { this.description = string.Format("Non-capturing Group", new object[0]); buffer.Offset += match.Groups["Rest"].Index; this.expression = new RegexExpression(buffer); this.CheckClosingParen(buffer); return(true); } return(false); }
private bool CheckBalancedGroup(RegexBuffer buffer) { Match match = new Regex("\r\n\t\t\t\t ^ # anchor to start of string\r\n\t\t\t\t\t\t\\?[\\<|'] # ?< or ?'\r\n\t\t\t\t\t\t(?<Name1>[a-zA-Z]+?) # Capture name1\r\n\t\t\t\t\t\t-\r\n\t\t\t\t\t\t(?<Name2>[a-zA-Z]+?) # Capture name2\r\n\t\t\t\t\t\t[\\>|'] # ?> or ?'\r\n\t\t\t\t\t\t(?<Rest>.+) # The rest of the expression\r\n\t\t\t\t\t\t", RegexOptions.IgnorePatternWhitespace).Match(buffer.String); if (match.Success) { this.description = string.Format("Balancing Group <{0}>-<{1}>", match.Groups["Name1"], match.Groups["Name2"]); buffer.Offset += match.Groups["Rest"].Index; this.expression = new RegexExpression(buffer); this.CheckClosingParen(buffer); return(true); } return(false); }
private void CheckClosingParen(RegexBuffer buffer) { char current = ' '; try { current = buffer.Current; } catch (Exception exception) { buffer.ErrorLocation = this.startLocation; buffer.ErrorLength = 1; throw new Exception(string.Format("Missing closing ')' in capture", new object[0]), exception); } if (current != ')') { throw new Exception(string.Format("Unterminated closure at offset {0}", buffer.Offset)); } buffer.Offset++; }
public RegexCapture(RegexBuffer buffer) { this.startLocation = buffer.Offset; buffer.MoveNext(); buffer.ClearInSeries(); if (buffer.Current == '?') { bool flag = this.CheckNamed(buffer); if (!flag) { flag = this.CheckBalancedGroup(buffer); } if (!flag) { flag = this.CheckNonCapturing(buffer); } if (!flag) { flag = this.CheckOptions(buffer); } if (!flag) { flag = this.CheckLookahead(buffer); } if (!flag) { flag = this.CheckNonBacktracking(buffer); } if (!flag) { flag = this.CheckConditional(buffer); } } else if (!this.HandlePlainOldCapture(buffer)) { throw new Exception(string.Format("Unrecognized capture: {0}", buffer.String)); } buffer.AddLookup(this, this.startLocation, buffer.Offset - 1); }
public RegexAlternate(RegexBuffer buffer) { buffer.AddLookup(this, buffer.Offset, buffer.Offset); buffer.MoveNext(); }
public RegexCharacter(RegexBuffer buffer) { int startLocation = buffer.Offset; bool flag = false; switch (buffer.Current) { case ' ': this.character = "' ' (space)"; buffer.MoveNext(); break; case '$': this.character = "$ (anchor to end of string)"; buffer.MoveNext(); break; case '*': this.character = "* (zero or more times)"; buffer.MoveNext(); this.special = true; flag = true; break; case '+': this.character = "+ (one or more times)"; buffer.MoveNext(); this.special = true; flag = true; break; case '.': this.character = ". (any character)"; buffer.MoveNext(); this.special = true; break; case '?': this.character = "? (zero or one time)"; buffer.MoveNext(); this.special = true; flag = true; break; case '\\': this.DecodeEscape(buffer); break; case '^': this.character = "^ (anchor to start of string)"; buffer.MoveNext(); break; default: this.character = buffer.Current.ToString(); buffer.MoveNext(); this.special = false; break; } if ((flag && !buffer.AtEnd) && (buffer.Current == '?')) { this.character = this.character + " (non-greedy)"; buffer.MoveNext(); } buffer.AddLookup(this, startLocation, buffer.Offset - 1, this.character.Length == 1); }
public RegexExpression(RegexBuffer buffer) { this.Parse(buffer); }
private void Parse(RegexBuffer buffer) { while (!buffer.AtEnd) { if (buffer.IgnorePatternWhitespace && (((buffer.Current == ' ') || (buffer.Current == '\r')) || ((buffer.Current == '\n') || (buffer.Current == '\t')))) { buffer.MoveNext(); } else { switch (buffer.Current) { case '(': { this.items.Add(new RegexCapture(buffer)); continue; } case ')': return; case '#': { if (buffer.IgnorePatternWhitespace) { this.EatComment(buffer); } else { this.items.Add(new RegexCharacter(buffer)); } continue; } case '[': { this.items.Add(new TeamAgile.RegexKit.Common.RegexParser.RegexCharClass(buffer)); continue; } case '\\': { this.items.Add(new RegexCharacter(buffer)); continue; } case '{': { this.items.Add(new RegexQuantifier(buffer)); continue; } case '|': { this.items.Add(new RegexAlternate(buffer)); continue; } } this.items.Add(new RegexCharacter(buffer)); } } }