示例#1
0
        public bool MatchString(Runtime runtime, string str, int pos,
                                bool allow_zero, ref RxResult oldState)
        {
            int st = pos >= 0 ? pos : 0;

            for (int i = st; i <= str.Length; ++i)
            {
                var match = regex.Match(str, i);

                if (match.Success)
                {
                    RxResult res;

                    if (pos >= 0 && pos == match.Index + match.Length && !allow_zero)
                    {
                        res.Matched = false;
                        continue;
                    }

                    res.Matched = match.Success;
                    res.Start = match.Index;
                    res.End = match.Index + match.Length;

                    if (match.Groups.Count > 1)
                    {
                        res.Captures = new RxCapture[match.Groups.Count - 1];
                        res.StringCaptures = new string[match.Groups.Count - 1];

                        for (int j = 0; j < res.Captures.Length; ++j)
                        {
                            var capt = match.Groups[j + 1];

                            if (capt.Success)
                            {
                                res.Captures[j].Start = capt.Index;
                                res.Captures[j].End = capt.Index + capt.Length;
                                res.StringCaptures[j] = str.Substring(capt.Index, capt.Length);
                            }
                            else
                            {
                                res.Captures[j].Start = -1;
                                res.Captures[j].End = -1;
                                res.StringCaptures[j] = null;
                            }
                        }
                    }
                    else
                    {
                        res.Captures = null;
                        res.StringCaptures = null;
                    }

                    oldState = runtime.LastMatch;
                    runtime.LastMatch = res;

                    return res.Matched;
                }
            }

            return false;
        }
示例#2
0
 public IP5Any MatchGlobal(Runtime runtime, IP5Any value, int flags,
                           Opcode.ContextValues cxt, ref RxResult oldState)
 {
     return P5Regex.MatchGlobalHelper(this, runtime, value, flags,
                                      cxt, ref oldState);
 }
示例#3
0
        private bool MatchAt(Runtime runtime, string str, int pos,
                             out RxResult res)
        {
            int len = str.Length;

            res.Matched = false;
            res.Start = res.End = -1;
            res.Captures = null;
            res.StringCaptures = null;

            RxContext cxt;

            cxt.Pos = pos;
            cxt.Groups = new List<RxGroup>();
            cxt.States = new List<RxState>();
            cxt.StateBacktrack = new List<int>();
            if (Captures > 0)
                cxt.Captures = new RxCapture[Captures];
            else
                cxt.Captures = null;
            if (Saved > 0)
                cxt.Saved = new int[Saved];
            else
                cxt.Saved = null;
            cxt.LastOpenCapture = cxt.LastClosedCapture = -1;

            for (int index = 0; index >= 0;)
            {
                switch (Ops[index].Number)
                {
                case Opcode.OpNumber.OP_RX_START_MATCH:
                    // do nothing for now
                    ++index;
                    break;
                case Opcode.OpNumber.OP_RX_EXACT:
                case Opcode.OpNumber.OP_RX_EXACT_I:
                {
                    var s = Exact[Ops[index].Index];
                    bool case_insensitive = Ops[index].Number == Opcode.OpNumber.OP_RX_EXACT_I;

                    if (   cxt.Pos + s.Length > len
                        || string.Compare(str, cxt.Pos, s, 0, s.Length,
                                          case_insensitive) != 0)
                        index = Backtrack(ref cxt);
                    else
                    {
                        cxt.Pos += s.Length;
                        ++index;
                    }

                    break;
                }
                case Opcode.OpNumber.OP_RX_SAVE_POS:
                {
                    cxt.Saved[Ops[index].Index] = cxt.Pos;

                    ++index;
                    break;
                }
                case Opcode.OpNumber.OP_RX_RESTORE_POS:
                {
                    cxt.Pos = cxt.Saved[Ops[index].Index];

                    ++index;
                    break;
                }
                case Opcode.OpNumber.OP_RX_ANY_NONEWLINE:
                {
                    if (cxt.Pos == len || str[cxt.Pos] == '\n')
                        index = Backtrack(ref cxt);
                    else
                    {
                        ++cxt.Pos;
                        ++index;
                    }

                    break;
                }
                case Opcode.OpNumber.OP_RX_ANY:
                {
                    if (cxt.Pos == len)
                        index = Backtrack(ref cxt);
                    else
                    {
                        ++cxt.Pos;
                        ++index;
                    }

                    break;
                }
                case Opcode.OpNumber.OP_RX_CLASS:
                {
                    var c = Classes[Ops[index].Index];

                    if (cxt.Pos < len)
                    {
                        char ch = str[cxt.Pos];

                        ++cxt.Pos;
                        ++index;

                        if (c.Exact.IndexOf(ch) >= 0)
                            break;

                        if ((c.Flags & Opcode.RX_CLASS_WORDS) != 0 && IsWord(ch))
                            break;
                        if ((c.Flags & Opcode.RX_CLASS_NOT_WORDS) != 0 && !IsWord(ch))
                            break;
                        if ((c.Flags & Opcode.RX_CLASS_DIGITS) != 0 && char.IsDigit(ch))
                            break;
                        if ((c.Flags & Opcode.RX_CLASS_NOT_DIGITS) != 0 && !char.IsDigit(ch))
                            break;
                        if ((c.Flags & Opcode.RX_CLASS_SPACES) != 0 && char.IsWhiteSpace(ch))
                            break;
                        if ((c.Flags & Opcode.RX_CLASS_NOT_SPACES) != 0 && !char.IsWhiteSpace(ch))
                            break;
                    }

                    index = Backtrack(ref cxt);
                    break;
                }
                case Opcode.OpNumber.OP_RX_BEGINNING:
                {
                    if (cxt.Pos != 0)
                        index = Backtrack(ref cxt);
                    else
                        ++index;

                    break;
                }
                case Opcode.OpNumber.OP_RX_START_GROUP:
                {
                    var grp = new RxGroup(-1);

                    cxt.Groups.Add(grp);
                    cxt.StateBacktrack.Add(cxt.States.Count);

                    index = Targets[Ops[index].Index];
                    break;
                }
                case Opcode.OpNumber.OP_RX_BACKTRACK:
                case Opcode.OpNumber.OP_RX_TRY:
                {
                    var st = new RxState(cxt.Pos, Targets[Ops[index].Index],
                                         cxt.Groups.Count);

                    cxt.States.Add(st);

                    ++index;
                    break;
                }
                case Opcode.OpNumber.OP_RX_POP_STATE:
                {
                    cxt.States.RemoveAt(cxt.States.Count - 1);

                    ++index;
                    break;
                }
                case Opcode.OpNumber.OP_RX_FAIL:
                {
                    index = Backtrack(ref cxt);
                    break;
                }
                case Opcode.OpNumber.OP_RX_QUANTIFIER:
                {
                    var group = cxt.Groups[cxt.Groups.Count - 1];
                    var quant = Quantifiers[Ops[index].Index];
                    int lastMatch = group.LastMatch;

                    ++index;
                    group.Count += 1;
                    group.LastMatch = cxt.Pos;

                    if (group.Count > 0 && quant.Group >= 0)
                        EndCapture(ref cxt, quant.Group);

                    // max repeat count
                    if (group.Count == quant.MaxCount)
                    {
                        cxt.Groups.RemoveAt(cxt.Groups.Count - 1);
                        break;
                    }

                    // zero-length match
                    if (cxt.Pos == lastMatch)
                    {
                        break;
                    }

                    RxSavedGroups gr;
                    if (group.Count == 0 || group.Count >= quant.MinCount)
                        SaveGroups(ref cxt, quant.SubgroupStart, quant.SubgroupEnd,
                                   group.Count == 0,
                                   out gr);
                    else
                        gr = new RxSavedGroups();

                    if (group.Count == 0 && quant.MinCount > 0)
                    {
                        // force failure on backtrack
                        var st = new RxState(cxt.Pos, -1, -1);
                        st.Groups = gr;

                        cxt.States.Add(st);
                    }
                    else if (quant.IsGreedy && group.Count >= quant.MinCount)
                    {
                        var st = new RxState(cxt.Pos, index, cxt.Groups.Count - 1);
                        st.Groups = gr;

                        cxt.States.Add(st);
                    }

                    cxt.Groups[cxt.Groups.Count - 1] = group;

                    // if nongreedy, match at least min
                    if (!quant.IsGreedy && group.Count >= quant.MinCount)
                    {
                        var st = new RxState(cxt.Pos, Targets[quant.To], cxt.Groups.Count);
                        st.Groups = gr;

                        cxt.States.Add(st);
                        break;
                    }

                    if (quant.Group >= 0)
                        StartCapture(ref cxt, quant.Group);

                    index = Targets[quant.To];
                    break;
                }
                case Opcode.OpNumber.OP_RX_CAPTURE_START:
                {
                    StartCapture(ref cxt, Ops[index].Index);

                    ++index;
                    break;
                }
                case Opcode.OpNumber.OP_RX_CAPTURE_END:
                {
                    EndCapture(ref cxt, Ops[index].Index);

                    ++index;
                    break;
                }
                case Opcode.OpNumber.OP_RX_ACCEPT:
                {
                    for (int i = cxt.LastOpenCapture + 1; i < Ops[index].Index; ++i)
                        cxt.Captures[i].Start = cxt.Captures[i].End = -1;

                    if (cxt.Captures != null)
                    {
                        res.StringCaptures = new string[cxt.Captures.Length];
                        for (int i = 0; i < cxt.Captures.Length; ++i)
                            if (cxt.Captures[i].End != -1)
                                res.StringCaptures[i] =
                                    str.Substring(cxt.Captures[i].Start,
                                                  cxt.Captures[i].End - cxt.Captures[i].Start);
                    }

                    res.Start = pos;
                    res.End = cxt.Pos;
                    res.Captures = cxt.Captures;
                    res.Matched = true;

                    index = -1;

                    break;
                }
                case Opcode.OpNumber.OP_JUMP:
                    index = Targets[Ops[index].Index];
                    break;
                default:
                    throw new System.Exception("PANIC: unhandled opcode " + Ops[index].Number);
                }
            }

            return res.Matched;
        }
示例#4
0
        public bool MatchString(Runtime runtime, string str, int pos,
                                bool allow_zero, ref RxResult oldState)
        {
            int st = pos >= 0 ? pos : 0;

            for (int i = st; i <= str.Length; ++i)
            {
                RxResult res;
                MatchAt(runtime, str, i, out res);

                if (res.Matched)
                {
                    if (pos >= 0 && pos == res.End && !allow_zero)
                    {
                        res.Matched = false;
                        continue;
                    }

                    oldState = runtime.LastMatch;
                    runtime.LastMatch = res;

                    return true;
                }
            }

            return false;
        }
示例#5
0
        public static IP5Any MatchHelper(IP5Regex regex, Runtime runtime, IP5Any value, int flags,
                                   Opcode.ContextValues cxt, ref RxResult oldState)
        {
            bool match = regex.MatchString(runtime, value.AsString(runtime),
                                           -1, false, ref oldState);

            if (cxt != Opcode.ContextValues.LIST)
            {
                return new P5Scalar(runtime, match);
            }
            else if (match && runtime.LastMatch.StringCaptures.Length > 0)
            {
                var res = new IP5Any[runtime.LastMatch.StringCaptures.Length];
                for (int i = 0; i < runtime.LastMatch.StringCaptures.Length; ++i)
                    res[i] = new P5Scalar(runtime, runtime.LastMatch.StringCaptures[i]);

                return new P5List(runtime, res);
            }
            else
            {
                return new P5List(runtime, match);
            }
        }
示例#6
0
        public static IP5Any MatchGlobalHelper(IP5Regex regex, Runtime runtime, IP5Any value, int flags,
                                               Opcode.ContextValues cxt, ref RxResult oldState)
        {
            var scalar = value as P5Scalar;
            bool pos_set;
            int pos = value.GetPos(runtime, out pos_set);
            string str = value.AsString(runtime);
            bool match;
            IP5Any result;

            if (cxt != Opcode.ContextValues.LIST)
            {
                match = regex.MatchString(runtime, str, pos, pos_set,
                                          ref oldState);

                result = new P5Scalar(runtime, match);

                if (scalar != null)
                {
                    if (match)
                        scalar.SetPos(runtime, runtime.LastMatch.End, false);
                    else if ((flags & Opcode.RX_KEEP) == 0)
                        scalar.UnsetPos(runtime);
                }
            }
            else
            {
                var capt = new List<IP5Any>();

                for (;;)
                {
                    match = regex.MatchString(runtime, str,
                                              pos, pos_set, ref oldState);
                    if (match)
                    {
                        if (runtime.LastMatch.StringCaptures != null)
                        {
                            foreach (var s in runtime.LastMatch.StringCaptures)
                                capt.Add(new P5Scalar(runtime, s));
                        }
                        else
                        {
                            string s = str.Substring(runtime.LastMatch.Start,
                                                     runtime.LastMatch.End - runtime.LastMatch.Start);
                            capt.Add(new P5Scalar(runtime, s));
                        }
                    }
                    else
                        break;

                    pos = runtime.LastMatch.End;
                }

                if (scalar != null)
                {
                    if ((flags & Opcode.RX_KEEP) != 0)
                        scalar.SetPos(runtime, pos, false);
                    else
                        scalar.UnsetPos(runtime);
                }

                result = new P5List(runtime, capt);
            }

            return result;
        }