public IMatch Clone() { var result = new CharSet() { InverseSet = InverseSet }; result.AddRange(Chars); result.Repeat.Set(Repeat); return(result); }
public static PatternList Parse(string pattern) { var stack = new Stack <PatternList>(); stack.Push(new PatternList() { Patterns = { new Pattern() } }); var last = ""; Repetition repeat; var inCharSet = false; foreach (var token in Tokenizer(pattern)) { if (inCharSet) { if (token.Value == "]" && token.IsOperator) { inCharSet = false; } else { var set = new CharSet(); for (var i = 0; i < token.Value.Length; i++) { if (i < token.Value.Length - 2 && token.Value[i + 1] == '-') { set.AddRange(token.Value[i], token.Value[i + 2]); i += 2; } else { set.Add(token.Value[i]); } } set.InverseSet = last == "[^"; stack.Peek().Patterns.Last().Matches.Add(set); } } else if (token.IsOperator) { switch (token.Value) { case "^": case "$": case @"\A": case @"\b": case @"\B": case @"\G": case @"\Z": case @"\z": stack.Peek().Patterns.Last().Matches.Add(new Anchor(token.Value[token.Value.Length - 1])); break; case "(": var capture = new Capture(); capture.Options.Patterns.Add(new Pattern()); stack.Peek().Patterns.Last().Matches.Add(capture); stack.Push(capture.Options); break; case ")": stack.Pop(); break; case "|": stack.Peek().Patterns.Add(new Pattern()); break; case "{": case "}": // Do nothing break; case "[": case "[^": inCharSet = true; break; case ".": case @"\d": case @"\D": case @"\s": case @"\S": case @"\w": case @"\W": stack.Peek().Patterns.Last().Matches.Add(new CharSet(token.Value[token.Value.Length - 1])); break; case "*": case "*?": repeat = stack.Peek().Patterns.Last().Matches.Last().Repeat; repeat.MinCount = 0; repeat.MaxCount = int.MaxValue; repeat.Greedy = token.Value.Length == 1; break; case "+": case "+?": repeat = stack.Peek().Patterns.Last().Matches.Last().Repeat; repeat.MinCount = 1; repeat.MaxCount = int.MaxValue; repeat.Greedy = token.Value.Length == 1; break; case "?": repeat = stack.Peek().Patterns.Last().Matches.Last().Repeat; if (last == "}") { repeat.Greedy = false; } else { repeat.MinCount = 0; repeat.MaxCount = 1; repeat.Greedy = true; } break; case "??": repeat = stack.Peek().Patterns.Last().Matches.Last().Repeat; repeat.MinCount = 0; repeat.MaxCount = 1; repeat.Greedy = false; break; default: throw new NotSupportedException(); } } else { if (last == "{") { var times = token.Value.Split(',').ToArray(); repeat = stack.Peek().Patterns.Last().Matches.Last().Repeat; repeat.MinCount = int.Parse(times[0]); if (times.Length == 1) { repeat.MaxCount = repeat.MinCount; } else { repeat.MaxCount = string.IsNullOrEmpty(times[1]) ? int.MaxValue : int.Parse(times[1]); } } else { stack.Peek().Patterns.Last().Matches.Add(new StringMatch(token.Value)); } } last = token.Value; } if (stack.Count != 1) { throw new InvalidOperationException(); } var result = stack.Pop(); result.Visit(Simplify); return(result); }
public virtual PatternList Parse(string str) { _pat = new Pattern(); _strMatch = new StringMatch(); Anchor endAnchor = null; if (string.IsNullOrEmpty(str)) { return(new PatternList()); } if (str[0] == this.Pattern_Anything) { str = str.TrimStart(this.Pattern_Anything); } else { _pat.Matches.Add(new Anchor() { Type = AnchorType.Start_Absolute }); } if (!string.IsNullOrEmpty(str) && str[str.Length - 1] == this.Pattern_Anything) { str = str.TrimEnd(this.Pattern_Anything); } else { endAnchor = new Anchor() { Type = AnchorType.End_Absolute }; } var i = 0; bool inRange = false; while (i < str.Length) { if (inRange) { if (str[i] == ']') { inRange = false; _pat.Matches.Add(_set); _set = null; } else if (_set.Chars.Count > 0 && str[i] == this.Pattern_SetRange && (i + 1) < str.Length && str[i + 1] != ']') { _set.AddRange((char)(_set.Chars.Last() + 1), str[i + 1]); i++; } else { _set.Chars.Add(str[i]); } } else if (str[i] == this.Pattern_Anything) { FinishStringMatch(); _set = new CharSet('.'); _set.Repeat.MinCount = 0; _set.Repeat.MaxCount = int.MaxValue; _pat.Matches.Add(_set); _set = null; } else if (str[i] == this.Pattern_SingleChar) { FinishStringMatch(); _set = new CharSet('.'); _set.Repeat.MinCount = 1; _set.Repeat.MaxCount = 1; _pat.Matches.Add(_set); _set = null; } else if (str[i] == this.Pattern_SingleDigit) { FinishStringMatch(); _set = new CharSet('d'); _set.Repeat.MinCount = 1; _set.Repeat.MaxCount = 1; _pat.Matches.Add(_set); _set = null; } else if (str[i] == '[' && !inRange && AllowCharSet) { FinishStringMatch(); inRange = true; _set = new CharSet(); if ((i + 1) < str.Length && str[i + 1] == this.Pattern_InverseSet) { _set.InverseSet = true; i++; } } else if (str[i] == this.Pattern_Escape) { i++; _strMatch.Match.Append(str[i]); } else { _strMatch.Match.Append(str[i]); } i++; } if (_strMatch.Match.Length > 0) { _pat.Matches.Add(_strMatch); } if (endAnchor != null) { _pat.Matches.Add(endAnchor); } var patOpts = new PatternList(); patOpts.Patterns.Add(_pat); patOpts.Visit(RegexParser.Simplify); return(patOpts); }