예제 #1
0
        public RegularExpression(List<Expression>/*!*/ pattern, RubyRegexOptions options, bool isCondition, SourceSpan location)
            : base(location) {
            Assert.NotNull(pattern);

            _pattern = pattern;
            _options = options;
        }
예제 #2
0
 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();
 }
예제 #3
0
 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;
 }
예제 #4
0
 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;
 }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        //[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);
            }
        }
예제 #8
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);
        }
예제 #9
0
 internal protected BinaryRegex(byte[]/*!*/ pattern, RubyRegexOptions options)
     : base(options) {
     Assert.NotNull(pattern);
     _pattern = ArrayUtils.Copy(pattern);
 }
예제 #10
0
        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);
            }
        }
예제 #11
0
 internal void SetRegexOptions(RubyRegexOptions value) {
     Integer1 = (int)value;
 }
예제 #12
0
 private RegexpTransformer(string/*!*/ rubyPattern, RubyRegexOptions options) {
     _rubyPattern = rubyPattern;
     _options = options;
 }
예제 #13
0
        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));
 }
예제 #15
0
 public RegularExpression(List<Expression>/*!*/ pattern, RubyRegexOptions options, SourceSpan location) 
     : this(pattern, options, false, location) {
 }
예제 #16
0
 public static RubyRegex/*!*/ CreateRegexE(string/*!*/ str1, int codepage, RubyRegexOptions options) {
     return new RubyRegex(str1, options);
 }
예제 #17
0
 public static RubyRegex/*!*/ CreateRegexU(string/*!*/ str1, RubyRegexOptions options) {
     return new RubyRegex(str1, options);
 }
예제 #18
0
 public static RubyRegex/*!*/ CreateRegexN(object[]/*!*/ strings, int codepage, RubyRegexOptions options) {
     return new RubyRegex(ConcatenateStrings(strings), options);
 }
예제 #19
0
 public static RubyRegex/*!*/ CreateRegexME(MutableString str1, string/*!*/ str2, int codepage, RubyRegexOptions options) {
     return new RubyRegex(MutableString.CreateInternal(str1).Append(str2), options);
 }
예제 #20
0
 public static RubyRegex/*!*/ CreateRegexUM(string/*!*/ str1, MutableString str2, RubyRegexOptions options) {
     return new RubyRegex(MutableString.Create(str1).Append(str2), options);
 }
예제 #21
0
 public RubyRegex(MutableString /*!*/ pattern, RubyRegexOptions options)
 {
     ContractUtils.RequiresNotNull(pattern, "pattern");
     _regex = pattern.ToRegularExpression(options);
 }
예제 #22
0
 public RubyRegex()
 {
     _pattern = MutableString.CreateEmpty();
     _options = RubyRegexOptions.NONE;
 }
예제 #23
0
파일: TokenValue.cs 프로젝트: ltwlf/IronSP
 internal void SetRegexOptions(RubyRegexOptions value)
 {
     Integer1 = (int)value;
 }
예제 #24
0
 public static RubyRegex/*!*/ CreateRegexM(MutableString str1, RubyRegexOptions options) {
     return new RubyRegex(MutableString.CreateInternal(str1), options);
 }
예제 #25
0
 internal static string/*!*/ TransformPattern(string/*!*/ pattern, RubyRegexOptions options) {
     return RegexpTransformer.Transform(pattern, options);
 }
예제 #26
0
 //[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);
     }
 }
예제 #27
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);
 }
예제 #28
0
 public abstract GenericRegex/*!*/ ToRegularExpression(RubyRegexOptions options);
예제 #29
0
 public RegularExpression(List <Expression> /*!*/ pattern, RubyRegexOptions options, SourceSpan location)
     : this(pattern, options, false, location)
 {
 }
예제 #30
0
        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;
            }
        }
예제 #31
0
        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
        }
예제 #32
0
 internal void SetRegexOptions(RubyRegexOptions value)
 {
     Integer = (int)value;
     _type   = TokenValueType.RegexOptions;
 }
 public override GenericRegex/*!*/ ToRegularExpression(RubyRegexOptions options) {
     return new StringRegex(_data, options);
 }
예제 #34
0
 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);
 }
예제 #35
0
 //[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);
 }
예제 #36
0
 protected GenericRegex(RubyRegexOptions options) {
     ContractUtils.Requires(RubyRegex.GetPersistedOptions(options) == options);
     _options = options;
 }
예제 #37
0
 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));
 }
예제 #39
0
        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;
        }
예제 #40
0
 public RubyRegex(string /*!*/ pattern, RubyRegexOptions options)
 {
     ContractUtils.RequiresNotNull(pattern, "pattern");
     _regex = new StringRegex(pattern, options);
 }
예제 #41
0
 internal void SetRegexOptions(RubyRegexOptions value) {
     Integer = (int)value;
     _type = TokenValueType.RegexOptions;
 }
예제 #42
0
 public AssertTokenizer/*!*/ Read(RubyRegexOptions expected) {
     Next();
     _tests.Assert(_actualToken == Tokens.RegexpEnd);
     _tests.Assert(expected == _actualValue.RegExOptions);
     return this;
 }
예제 #43
0
 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);            
 }
예제 #44
0
        // 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());
        }
예제 #45
0
 public RubyRegex(MutableString /*!*/ pattern, RubyRegexOptions options)
 {
     Set(pattern, options);
 }
예제 #46
0
 protected GenericRegex(RubyRegexOptions options)
 {
     _options = options;
 }
예제 #47
0
 public abstract GenericRegex /*!*/ ToRegularExpression(RubyRegexOptions options);
예제 #48
0
 internal protected BinaryRegex(byte[] /*!*/ pattern, RubyRegexOptions options)
     : base(options)
 {
     Assert.NotNull(pattern);
     _pattern = ArrayUtils.Copy(pattern);
 }
예제 #49
0
 public GenericRegex /*!*/ ToRegularExpression(RubyRegexOptions options)
 {
     return(_content.ToRegularExpression(options));
 }
예제 #50
0
 public void Set(MutableString /*!*/ pattern, RubyRegexOptions options)
 {
     _regex = pattern.ToRegularExpression(options);
 }