public RegularExpression(List<Expression>/*!*/ pattern, RubyRegexOptions options, bool isCondition, SourceSpan location) : base(location) { Assert.NotNull(pattern); _pattern = pattern; _options = options; }
internal static string Transform(string/*!*/ rubyPattern, RubyRegexOptions options) { if (rubyPattern == "\\Af(?=[[:xdigit:]]{2}+\\z)") { // pp.rb uses this pattern. The real fix requires cracking the entire regexp and so is left for later return "\\Af(?=(?:[[:xdigit:]]{2})+\\z)"; } RegexpTransformer transformer = new RegexpTransformer(rubyPattern); return transformer.Transform(); }
internal static string Transform(string/*!*/ rubyPattern, RubyRegexOptions options, out bool hasGAnchor) { if (rubyPattern == "\\Af(?=[[:xdigit:]]{2}+\\z)") { // pp.rb uses this pattern. The real fix requires cracking the entire regexp and so is left for later hasGAnchor = false; return "\\Af(?=(?:[[:xdigit:]]{2})+\\z)"; } RegexpTransformer transformer = new RegexpTransformer(rubyPattern); var result = transformer.Transform(); hasGAnchor = transformer._hasGAnchor; return result; }
internal static string Transform(string/*!*/ rubyPattern, RubyRegexOptions options, out bool hasGAnchor) { // TODO: surrogates (REXML uses this pattern) if (rubyPattern == "^[\t\n\r -\uD7FF\uE000-\uFFFD\uD800\uDC00-\uDBFF\uDFFF]*$") { hasGAnchor = false; return "^(?:[\t\n\r -\uD7FF\uE000-\uFFFD]|[\uD800-\uDBFF][\uDC00-\uDFFF])*$"; } RegexpTransformer transformer = new RegexpTransformer(rubyPattern); var result = transformer.Transform(); hasGAnchor = transformer._hasGAnchor; return result; }
public static RegexOptions ToClrOptions(RubyRegexOptions options) { RegexOptions result = RegexOptions.Multiline; if ((options & RubyRegexOptions.IgnoreCase) != 0) { result |= RegexOptions.IgnoreCase; } if ((options & RubyRegexOptions.Extended) != 0) { result |= RegexOptions.IgnorePatternWhitespace; } if ((options & RubyRegexOptions.Multiline) != 0) { result |= RegexOptions.Singleline; } return(result); }
public void Set(MutableString /*!*/ pattern, RubyRegexOptions options) { ContractUtils.RequiresNotNull(pattern, "pattern"); // RubyRegexOptions.Once is only used to determine how the Regexp object should be created and cached. // It is not a property of the final object. /foo/ should compare equal with /foo/o. _options = options & ~RubyRegexOptions.Once; RubyEncoding encoding = RubyEncoding.GetRegexEncoding(options); if (encoding != null) { _pattern = MutableString.CreateBinary(pattern.ToByteArray(), encoding ?? RubyEncoding.Binary).Freeze(); } else { _pattern = pattern.PrepareForCharacterRead().Clone().Freeze(); } TransformPattern(encoding, options & RubyRegexOptions.EncodingMask); }
//[DebuggerHidden] private void TestCorrectPatternTranslation(string /*!*/ pattern, RubyRegexOptions options, string /*!*/ expected, bool expectedGAnchor, IList <string> expectedWarnings) { bool hasGAnchor; List <string> warnings; string actual = RegexpTransformer.Transform(pattern, options, out hasGAnchor, out warnings); AreEqual(expected, actual); new Regex(expected); Assert(hasGAnchor == expectedGAnchor); if (warnings != null) { Assert(expectedWarnings != null); Assert(expectedWarnings.Count == warnings.Count); foreach (var warning in expectedWarnings) { Assert(warnings.IndexOf(warning) >= 0); } } else { Assert(expectedWarnings == null || expectedWarnings.Count == 0); } }
private Regex /*!*/ TransformPattern(RubyEncoding encoding, RubyRegexOptions kc) { // We can reuse cached CLR regex if it was created for the same k-coding: if (_cachedRegex != null && kc == _cachedKCode) { return(_cachedRegex); } string pattern; if (kc != 0 || encoding == RubyEncoding.Binary) { pattern = _pattern.ToString(encoding.Encoding); } else { pattern = _pattern.ConvertToString(); } List <string> warnings; Regex result; try { result = new Regex(RegexpTransformer.Transform(pattern, _options, out _hasGAnchor, out warnings), ToClrOptions(_options)); } catch (Exception e) { throw new RegexpError(e.Message); } // TODO: report //if (warnings != null) { // ... //} _cachedKCode = kc; _cachedRegex = result; return(result); }
internal protected BinaryRegex(byte[]/*!*/ pattern, RubyRegexOptions options) : base(options) { Assert.NotNull(pattern); _pattern = ArrayUtils.Copy(pattern); }
internal protected StringRegex(string/*!*/ pattern, RubyRegexOptions options) : base(options) { Assert.NotNull(pattern); _pattern = pattern; string transformed = RegexpTransformer.Transform(pattern, options); try { _regex = new Regex(transformed, RubyRegex.ToClrOptions(options)); } catch (ArgumentException e) { Utils.Log("-- original ---" + new String('-', 50), "REGEX_ERROR"); Utils.Log(pattern, "REGEX_ERROR"); Utils.Log("-- transformed " + new String('-', 50), "REGEX_ERROR"); Utils.Log(transformed, "REGEX_ERROR"); Utils.Log("---------------" + new String('-', 50), "REGEX_ERROR"); throw new RegexpError(e.Message, e); } }
internal void SetRegexOptions(RubyRegexOptions value) { Integer1 = (int)value; }
private RegexpTransformer(string/*!*/ rubyPattern, RubyRegexOptions options) { _rubyPattern = rubyPattern; _options = options; }
private static RubyRegex/*!*/ CreateRegexWorker( RubyRegexOptions options, StrongBox<RubyRegex> regexpCache, bool isLiteralWithoutSubstitutions, Func<RubyRegex> createRegex) { try { bool once = ((options & RubyRegexOptions.Once) == RubyRegexOptions.Once) || isLiteralWithoutSubstitutions; if (once) { // Note that the user is responsible for thread synchronization if (regexpCache.Value == null) { regexpCache.Value = createRegex(); } return regexpCache.Value; } else { // In the future, we can consider caching the last Regexp. For some regexp literals // with substitution, the substition will be the same most of the time return createRegex(); } } catch (RegexpError e) { if (isLiteralWithoutSubstitutions) { // Ideally, this should be thrown during parsing of the source, even if the // expression happens to be unreachable at runtime. throw new SyntaxError(e.Message); } else { throw; } } }
public override GenericRegex /*!*/ ToRegularExpression(RubyRegexOptions options) { return(new StringRegex(_data, options)); }
public RegularExpression(List<Expression>/*!*/ pattern, RubyRegexOptions options, SourceSpan location) : this(pattern, options, false, location) { }
public static RubyRegex/*!*/ CreateRegexE(string/*!*/ str1, int codepage, RubyRegexOptions options) { return new RubyRegex(str1, options); }
public static RubyRegex/*!*/ CreateRegexU(string/*!*/ str1, RubyRegexOptions options) { return new RubyRegex(str1, options); }
public static RubyRegex/*!*/ CreateRegexN(object[]/*!*/ strings, int codepage, RubyRegexOptions options) { return new RubyRegex(ConcatenateStrings(strings), options); }
public static RubyRegex/*!*/ CreateRegexME(MutableString str1, string/*!*/ str2, int codepage, RubyRegexOptions options) { return new RubyRegex(MutableString.CreateInternal(str1).Append(str2), options); }
public static RubyRegex/*!*/ CreateRegexUM(string/*!*/ str1, MutableString str2, RubyRegexOptions options) { return new RubyRegex(MutableString.Create(str1).Append(str2), options); }
public RubyRegex(MutableString /*!*/ pattern, RubyRegexOptions options) { ContractUtils.RequiresNotNull(pattern, "pattern"); _regex = pattern.ToRegularExpression(options); }
public RubyRegex() { _pattern = MutableString.CreateEmpty(); _options = RubyRegexOptions.NONE; }
public static RubyRegex/*!*/ CreateRegexM(MutableString str1, RubyRegexOptions options) { return new RubyRegex(MutableString.CreateInternal(str1), options); }
internal static string/*!*/ TransformPattern(string/*!*/ pattern, RubyRegexOptions options) { return RegexpTransformer.Transform(pattern, options); }
//[DebuggerHidden] private void TestCorrectPatternTranslation(string/*!*/ pattern, RubyRegexOptions options, string/*!*/ expected, bool expectedGAnchor, IList<string> expectedWarnings) { bool hasGAnchor; List<string> warnings; string actual = RegexpTransformer.Transform(pattern, options, out hasGAnchor, out warnings); AreEqual(expected, actual); new Regex(expected); Assert(hasGAnchor == expectedGAnchor); if (warnings != null) { Assert(expectedWarnings != null); Assert(expectedWarnings.Count == warnings.Count); foreach (var warning in expectedWarnings) { Assert(warnings.IndexOf(warning) >= 0); } } else { Assert(expectedWarnings == null || expectedWarnings.Count == 0); } }
public static RubyRegex/*!*/ CreateRegexN(object[]/*!*/ strings, RubyEncoding/*!*/ encoding, RubyRegexOptions options, StrongBox<RubyRegex> regexpCache) { Func<RubyRegex> createRegex = delegate { return new RubyRegex(CreateMutableStringN(strings, encoding), options); }; return CreateRegexWorker(options, regexpCache, false, createRegex); }
public abstract GenericRegex/*!*/ ToRegularExpression(RubyRegexOptions options);
public RegularExpression(List <Expression> /*!*/ pattern, RubyRegexOptions options, SourceSpan location) : this(pattern, options, false, location) { }
public static RubyEncoding GetRegexEncoding(RubyRegexOptions options) { switch (options & RubyRegexOptions.EncodingMask) { #if !SILVERLIGHT case RubyRegexOptions.EUC: return RubyEncoding.EUC; case RubyRegexOptions.SJIS: return RubyEncoding.SJIS; #endif case RubyRegexOptions.UTF8: return RubyEncoding.UTF8; case RubyRegexOptions.FIXED: return RubyEncoding.Binary; default: return null; } }
public static RubyEncoding GetKCoding(RubyRegexOptions options) { #if SILVERLIGHT return null; #else switch (options & RubyRegexOptions.EncodingMask) { case RubyRegexOptions.EUC: return RubyEncoding.KCodeEUC; case RubyRegexOptions.SJIS: return RubyEncoding.KCodeSJIS; case RubyRegexOptions.UTF8: return RubyEncoding.KCodeUTF8; default: return null; } #endif }
internal void SetRegexOptions(RubyRegexOptions value) { Integer = (int)value; _type = TokenValueType.RegexOptions; }
public override GenericRegex/*!*/ ToRegularExpression(RubyRegexOptions options) { return new StringRegex(_data, options); }
public RubyRegex(byte[] /*!*/ pattern, RubyRegexOptions options) { ContractUtils.RequiresNotNull(pattern, "pattern"); // TODO: _regex = new BinaryRegex(pattern, options); _regex = new StringRegex(BinaryEncoding.Obsolete.GetString(pattern, 0, pattern.Length), options); }
//[DebuggerHidden] private void TestCorrectPatternTranslation(string/*!*/ pattern, RubyRegexOptions options, string/*!*/ expected, bool expectedGAnchor) { bool hasGAnchor; string actual = RegexpTransformer.Transform(pattern, options, out hasGAnchor); AreEqual(expected, actual); new Regex(expected); Assert(hasGAnchor == expectedGAnchor); }
protected GenericRegex(RubyRegexOptions options) { ContractUtils.Requires(RubyRegex.GetPersistedOptions(options) == options); _options = options; }
public override GenericRegex/*!*/ ToRegularExpression(RubyRegexOptions options) { // TODO: Fix BinaryRegex and use instead return new StringRegex(ToString(), options); }
public override GenericRegex /*!*/ ToRegularExpression(RubyRegexOptions options) { // TODO: Fix BinaryRegex and use instead return(new StringRegex(ToString(), options)); }
private static int AppendOptionString(MutableString/*!*/ result, RubyRegexOptions options, bool enabled, bool includeEncoding) { int count = 0; if (((options & RubyRegexOptions.Multiline) != 0) == enabled) { result.Append('m'); count++; } if (((options & RubyRegexOptions.IgnoreCase) != 0) == enabled) { result.Append('i'); count++; } if (((options & RubyRegexOptions.Extended) != 0) == enabled) { result.Append('x'); count++; } if (includeEncoding) { switch (options & RubyRegexOptions.EncodingMask) { case RubyRegexOptions.NONE: break; case RubyRegexOptions.EUC: result.Append('e'); break; case RubyRegexOptions.FIXED: result.Append('n'); break; case RubyRegexOptions.UTF8: result.Append('u'); break; case RubyRegexOptions.SJIS: result.Append('s'); break; default: throw Assert.Unreachable; } } return count; }
public RubyRegex(string /*!*/ pattern, RubyRegexOptions options) { ContractUtils.RequiresNotNull(pattern, "pattern"); _regex = new StringRegex(pattern, options); }
public AssertTokenizer/*!*/ Read(RubyRegexOptions expected) { Next(); _tests.Assert(_actualToken == Tokens.RegexpEnd); _tests.Assert(expected == _actualValue.RegExOptions); return this; }
private static RubyRegex ConstructRubyRegexp(RubyConstructor/*!*/ ctor, Node node) { ScalarNode scalar = node as ScalarNode; if (node == null) { throw RubyExceptions.CreateTypeError("Can only create regex from scalar node"); } Match match = _regexPattern.Match(scalar.Value); if (!match.Success) { throw new ConstructorException("Invalid Regular expression: \"" + scalar.Value + "\""); } RubyRegexOptions options = new RubyRegexOptions(); foreach (char c in match.Groups["opts"].Value) { switch (c) { case 'i': options |= RubyRegexOptions.IgnoreCase; break; case 'x': options |= RubyRegexOptions.Extended; break; case 'm': options |= RubyRegexOptions.Multiline; break; case 'o': break; case 'n': options |= RubyRegexOptions.FIXED; break; case 'e': options |= RubyRegexOptions.EUC; break; case 's': options |= RubyRegexOptions.SJIS; break; case 'u': options |= RubyRegexOptions.UTF8; break; default: throw new ConstructorException("Unknown regular expression option: '" + c + "'"); } } // TODO: encoding (ignore kcode on 1.9, string enc?): return new RubyRegex(MutableString.CreateMutable(match.Groups["expr"].Value, RubyEncoding.UTF8), options); }
// fixes escapes // - unescapes non-special characters // - fixes \xF -> \x0F internal static string /*!*/ TransformPattern(string /*!*/ pattern, RubyRegexOptions options) { int first = 0; int i = SkipWellEscaped(pattern, 0); // trailing backslash is an error in both MRI, .NET if (i == -1) { return(pattern); } StringBuilder result = new StringBuilder(pattern.Length); do { Debug.Assert(i + 1 < pattern.Length); Debug.Assert(pattern[i] == '\\'); result.Append(pattern, first, i - first); i++; char c = pattern[i++]; switch (c) { case 'x': result.Append('\\'); result.Append('x'); // error: if (i == pattern.Length) { break; } // fix single digit: c = pattern[i++]; if (i == pattern.Length || !Tokenizer.IsHexadecimalDigit(pattern[i])) { result.Append('0'); } result.Append(c); break; case 'h': // Oniguruma only: [0-9A-Fa-f] case 'H': // Oniguruma only: [^0-9A-Fa-f] case 'g': // Oniguruma only case 'k': // Oniguruma, .NET: named backreference, MRI not supported // remove backslash default: if (Tokenizer.IsDecimalDigit(c)) { // TODO: // \([1-9][0-9]*) where there is no group of such number (replace by an empty string) result.Append('\\'); } // .NET throws invalid escape exception, remove backslash: result.Append(c); break; } Debug.Assert(i <= pattern.Length); first = i; i = SkipWellEscaped(pattern, i); } while (i >= 0); result.Append(pattern, first, pattern.Length - first); return(result.ToString()); }
public RubyRegex(MutableString /*!*/ pattern, RubyRegexOptions options) { Set(pattern, options); }
protected GenericRegex(RubyRegexOptions options) { _options = options; }
public abstract GenericRegex /*!*/ ToRegularExpression(RubyRegexOptions options);
internal protected BinaryRegex(byte[] /*!*/ pattern, RubyRegexOptions options) : base(options) { Assert.NotNull(pattern); _pattern = ArrayUtils.Copy(pattern); }
public GenericRegex /*!*/ ToRegularExpression(RubyRegexOptions options) { return(_content.ToRegularExpression(options)); }
public void Set(MutableString /*!*/ pattern, RubyRegexOptions options) { _regex = pattern.ToRegularExpression(options); }