syntax.cs :  » 2.6.4-mono-.net-core » System.Text » System » Text » RegularExpressions » Syntax » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » 2.6.4 mono .net core » System.Text 
System.Text » System » Text » RegularExpressions » Syntax » syntax.cs
//
// assembly:  System
// namespace:  System.Text.RegularExpressions
// file:  syntax.cs
//
// author:  Dan Lewis (dlewis@gmx.co.uk)
//    (c) 2002

//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

using System;
using System.Collections;

namespace System.Text.RegularExpressions.Syntax{
  // collection classes

  class ExpressionCollection : CollectionBase {
    public void Add (Expression e) {
      List.Add (e);
    }

    public Expression this[int i] {
      get { return (Expression)List[i]; }
      set { List[i] = value; }
    }

    protected override void OnValidate (object o) {
      // allow null elements
    }
  }

  // abstract classes

  abstract class Expression {
    public abstract void Compile (ICompiler cmp, bool reverse);
    public abstract void GetWidth (out int min, out int max);

    public int GetFixedWidth () {
      int min, max;
      GetWidth (out min, out max);

      if (min == max)
        return min;

      return -1;
    }

    public virtual AnchorInfo GetAnchorInfo (bool reverse) {
      return new AnchorInfo (this, GetFixedWidth ());
    }

    public abstract bool IsComplex ();
  }

  // composite expressions

  abstract class CompositeExpression : Expression {
    public CompositeExpression () {
      expressions = new ExpressionCollection ();
    }

    protected ExpressionCollection Expressions {
      get { return expressions; }
    }

    protected void GetWidth (out int min, out int max, int count) {
      min = Int32.MaxValue;
      max = 0;
      bool empty = true;

      for (int i = 0; i < count; ++ i) {
        Expression e = Expressions[i];
        if (e == null)
          continue;

        empty = false;
        int a, b;
        e.GetWidth (out a, out b);
        if (a < min) min = a;
        if (b > max) max = b;
      }

      if (empty)
        min = max = 0;
    }


    public override bool IsComplex ()
    {
      foreach (Expression e in Expressions) {
        if (e.IsComplex ())
          return true;
      }
      return GetFixedWidth () <= 0;
    }

    private ExpressionCollection expressions;
  }

  // groups

  class Group : CompositeExpression {
    public Group () {
    }

    public Expression Expression {
      get { return Expressions[0]; }
      set { Expressions[0] = value; }
    }

    public void AppendExpression (Expression e) {
      Expressions.Add (e);
    }

    public override void Compile (ICompiler cmp, bool reverse) {
      int count = Expressions.Count;
      for (int i = 0; i < count; ++ i) {
        Expression e;
        if (reverse)
          e = Expressions[count - i - 1];
        else
          e = Expressions[i];

        e.Compile (cmp, reverse);
      }
    }

    public override void GetWidth (out int min, out int max) {
      min = 0;
      max = 0;

      foreach (Expression e in Expressions) {
        int a, b;
        e.GetWidth (out a, out b);
        min += a;
        if (max == Int32.MaxValue || b == Int32.MaxValue)
          max = Int32.MaxValue;
        else
          max += b;
      }
    }

    public override AnchorInfo GetAnchorInfo (bool reverse)
    {
      int ptr;
      int width = GetFixedWidth ();

      ArrayList infos = new ArrayList ();
      IntervalCollection segments = new IntervalCollection ();

      // accumulate segments
      ptr = 0;
      int count = Expressions.Count;
      for (int i = 0; i < count; ++ i) {
        Expression e;
        if (reverse)
          e = Expressions [count - i - 1];
        else
          e = Expressions [i];

        AnchorInfo info = e.GetAnchorInfo (reverse);
        infos.Add (info);

        if (info.IsPosition)
          return new AnchorInfo (this, ptr + info.Offset, width, info.Position);

        if (info.IsSubstring)
          segments.Add (info.GetInterval (ptr));

        if (info.IsUnknownWidth)
          break;

        ptr += info.Width;
      }

      // normalize and find the longest segment
      segments.Normalize ();

      Interval longest = Interval.Empty;
      foreach (Interval segment in segments) {
        if (segment.Size > longest.Size)
          longest = segment;
      }

      if (longest.IsEmpty)
        return new AnchorInfo (this, width);

      // now chain the substrings that made this segment together
      bool ignore = false;
      int n_strings = 0;

      ptr = 0;
      for (int i = 0; i < infos.Count; ++i) {
        AnchorInfo info = (AnchorInfo) infos [i];

        if (info.IsSubstring && longest.Contains (info.GetInterval (ptr))) {
          ignore |= info.IgnoreCase;
          infos [n_strings ++] = info;
        }

        if (info.IsUnknownWidth)
          break;

        ptr += info.Width;
      }

      StringBuilder sb = new StringBuilder ();
      for (int i = 0; i < n_strings; ++i) {
        AnchorInfo info;
        if (reverse)
          info = (AnchorInfo) infos [n_strings - i - 1];
        else
          info = (AnchorInfo) infos [i];
        sb.Append (info.Substring);
      }

      if (sb.Length == longest.Size)
        return new AnchorInfo (this, longest.low, width, sb.ToString (), ignore);
      // were the string segments overlapping?
      if (sb.Length > longest.Size) {
        Console.Error.WriteLine ("overlapping?");
        return new AnchorInfo (this, width);
      }
      throw new SystemException ("Shouldn't happen");
    }
  }

  class RegularExpression : Group {
    public RegularExpression () {
      group_count = 0;
    }

    public int GroupCount {
      get { return group_count; }
      set { group_count = value; }
    }

    public override void Compile (ICompiler cmp, bool reverse) {
      // info block

      int min, max;
      GetWidth (out min, out max);
      cmp.EmitInfo (group_count, min, max);

      // anchoring expression

      AnchorInfo info = GetAnchorInfo (reverse);
      //if (reverse)
      //  info = new AnchorInfo (this, GetFixedWidth ());  // FIXME

      LinkRef pattern = cmp.NewLink ();
      cmp.EmitAnchor (reverse, info.Offset, pattern);

      if (info.IsPosition)
        cmp.EmitPosition (info.Position);
      else if (info.IsSubstring)
        cmp.EmitString (info.Substring, info.IgnoreCase, reverse);

      cmp.EmitTrue ();

      // pattern

      cmp.ResolveLink (pattern);
      base.Compile (cmp, reverse);
      cmp.EmitTrue ();
    }

    private int group_count;
  }

  class CapturingGroup : Group, IComparable {
    public CapturingGroup () {
      this.gid = 0;
      this.name = null;
    }

    public int Index {
      get { return gid; }
      set { gid = value; }
    }

    public string Name {
      get { return name; }
      set { name = value; }
    }

    public bool IsNamed {
      get { return name != null; }
    }

    public override void Compile (ICompiler cmp, bool reverse) {
      cmp.EmitOpen (gid);
      base.Compile (cmp, reverse);
      cmp.EmitClose (gid);
    }

    public override bool IsComplex () {
      return true;
    }

    public int CompareTo (object other)
    {
      return gid - ((CapturingGroup) other).gid;
    }

    private int gid;
    private string name;
  }

  class BalancingGroup : CapturingGroup {
    public BalancingGroup () {
      this.balance = null;
    }

    public CapturingGroup Balance {
      get { return balance; }
      set { balance = value; }
    }

    public override void Compile (ICompiler cmp, bool reverse) {
      // can't invoke Group.Compile from here :(
      // so I'll just repeat the code

      LinkRef tail = cmp.NewLink ();

      cmp.EmitBalanceStart (this.Index, balance.Index, this.IsNamed,  tail);

      int count = Expressions.Count;
      for (int i = 0; i < count; ++ i) {
        Expression e;
        if (reverse)
          e = Expressions[count - i - 1];
        else
          e = Expressions[i];

        e.Compile (cmp, reverse);
      }

      cmp.EmitBalance ();
      cmp.ResolveLink(tail);
    }

    private CapturingGroup balance;
  }

  class NonBacktrackingGroup : Group {
    public NonBacktrackingGroup () {
    }

    public override void Compile (ICompiler cmp, bool reverse) {
      LinkRef tail = cmp.NewLink ();

      cmp.EmitSub (tail);
      base.Compile (cmp, reverse);
      cmp.EmitTrue ();
      cmp.ResolveLink (tail);
    }

    public override bool IsComplex () {
      return true;
    }
  }

  // repetition

  class Repetition : CompositeExpression {
    public Repetition (int min, int max, bool lazy) {
      Expressions.Add (null);

      this.min = min;
      this.max = max;
      this.lazy = lazy;
    }

    public Expression Expression {
      get { return Expressions[0]; }
      set { Expressions[0] = value; }
    }

    public int Minimum {
      get { return min; }
      set { min = value; }
    }

    public int Maximum {
      get { return max; }
      set { max = value; }
    }

    public bool Lazy {
      get { return lazy; }
      set { lazy = value; }
    }

    public override void Compile (ICompiler cmp, bool reverse) {
      if (Expression.IsComplex ()) {
        LinkRef until = cmp.NewLink ();

        cmp.EmitRepeat (min, max, lazy, until);
        Expression.Compile (cmp, reverse);
        cmp.EmitUntil (until);
      }
      else {
        LinkRef tail = cmp.NewLink ();

        cmp.EmitFastRepeat (min, max, lazy, tail);
        Expression.Compile (cmp, reverse);
        cmp.EmitTrue ();
        cmp.ResolveLink (tail);
      }
    }

    public override void GetWidth (out int min, out int max) {
      Expression.GetWidth (out min, out max);
      min = min * this.min;
      if (max == Int32.MaxValue || this.max == 0xffff)
        max = Int32.MaxValue;
      else
        max = max * this.max;
    }

    public override AnchorInfo GetAnchorInfo (bool reverse) {
      int width = GetFixedWidth ();
      if (Minimum == 0)
        return new AnchorInfo (this, width);

      AnchorInfo info = Expression.GetAnchorInfo (reverse);
      if (info.IsPosition)
        return new AnchorInfo (this, info.Offset, width, info.Position);

      if (info.IsSubstring) {
        if (info.IsComplete) {
          // Minimum > 0
          string str = info.Substring;
          StringBuilder sb = new StringBuilder (str);
          for (int i = 1; i < Minimum; ++ i)
            sb.Append (str);

          return new AnchorInfo (this, 0, width, sb.ToString (), info.IgnoreCase);
        }

        return new AnchorInfo (this, info.Offset, width, info.Substring, info.IgnoreCase);
      }

      return new AnchorInfo (this, width);
    }

    private int min, max;
    private bool lazy;
  }

  // assertions

  abstract class Assertion : CompositeExpression {
    public Assertion () {
      Expressions.Add (null);    // true expression
      Expressions.Add (null);    // false expression
    }

    public Expression TrueExpression {
      get { return Expressions[0]; }
      set { Expressions[0] = value; }
    }

    public Expression FalseExpression {
      get { return Expressions[1]; }
      set { Expressions[1] = value; }
    }

    public override void GetWidth (out int min, out int max) {
      GetWidth (out min, out max, 2);

      if (TrueExpression == null || FalseExpression == null)
        min = 0;
    }
  }

  class CaptureAssertion : Assertion {
    public CaptureAssertion (Literal l) {
      literal = l;
    }

    public CapturingGroup CapturingGroup {
      get { return group; }
      set { group = value; }
    }

    public override void Compile (ICompiler cmp, bool reverse) {
      if (group == null) {
        Alternate.Compile (cmp, reverse);
        return;
      }

      int gid = group.Index;
      LinkRef tail = cmp.NewLink ();

      if (FalseExpression == null) {
        //    IfDefined :1
        //      <yes_exp>
        // 1: <tail>

        cmp.EmitIfDefined (gid, tail);
        TrueExpression.Compile (cmp, reverse);
      }
      else {
        //    IfDefined :1
        //      <yes_expr>
        //      Jump :2
        // 1:   <no_expr>
        // 2: <tail>

        LinkRef false_expr = cmp.NewLink ();
        cmp.EmitIfDefined (gid, false_expr);
        TrueExpression.Compile (cmp, reverse);
        cmp.EmitJump (tail);
        cmp.ResolveLink (false_expr);
        FalseExpression.Compile (cmp, reverse);
      }

      cmp.ResolveLink (tail);
    }

    public override bool IsComplex () {
      if (group == null)
        return Alternate.IsComplex ();
      if (TrueExpression != null && TrueExpression.IsComplex ())
        return true;
      if (FalseExpression != null && FalseExpression.IsComplex ())
        return true;
      return GetFixedWidth () <= 0;
    }

    ExpressionAssertion Alternate {
      get {
        if (alternate == null) {
          alternate = new ExpressionAssertion ();
          alternate.TrueExpression = TrueExpression;
          alternate.FalseExpression = FalseExpression;
          alternate.TestExpression = literal;
        }
        return alternate;
      }
    }

    private ExpressionAssertion alternate;
    private CapturingGroup group;
    private Literal literal;
  }

  class ExpressionAssertion : Assertion {
    public ExpressionAssertion () {
      Expressions.Add (null);    // test expression
    }

    public bool Reverse {
      get { return reverse; }
      set { reverse = value; }
    }

    public bool Negate {
      get { return negate; }
      set { negate = value; }
    }

    public Expression TestExpression {
      get { return Expressions[2]; }
      set { Expressions[2] = value; }
    }

    public override void Compile (ICompiler cmp, bool reverse) {
      LinkRef true_expr = cmp.NewLink ();
      LinkRef false_expr = cmp.NewLink ();

      // test op: positive / negative

      if (!negate)
        cmp.EmitTest (true_expr, false_expr);
      else
        cmp.EmitTest (false_expr, true_expr);

      // test expression: lookahead / lookbehind

      TestExpression.Compile (cmp, this.reverse);
      cmp.EmitTrue ();

      // target expressions

      if (TrueExpression == null) {      // (?= ...)
        //    Test :1, :2
        //      <test_expr>
        // :2   False
        // :1   <tail>

        cmp.ResolveLink (false_expr);
        cmp.EmitFalse ();
        cmp.ResolveLink (true_expr);
      }
      else {
        cmp.ResolveLink (true_expr);
        TrueExpression.Compile (cmp, reverse);

        if (FalseExpression == null) {    // (?(...) ...)
          //    Test :1, :2
          //      <test_expr>
          // :1   <yes_expr>
          // :2   <tail>

          cmp.ResolveLink (false_expr);
        }
        else {          // (?(...) ... | ...)
          //    Test :1, :2
          //      <test_expr>
          // :1   <yes_expr>
          //      Jump :3
          // :2   <no_expr>
          // :3   <tail>

          LinkRef tail = cmp.NewLink ();

          cmp.EmitJump (tail);
          cmp.ResolveLink (false_expr);
          FalseExpression.Compile (cmp, reverse);
          cmp.ResolveLink (tail);
        }
      }
    }

    public override bool IsComplex ()
    {
      return true;
    }

    private bool reverse, negate;
  }

  // alternation

  class Alternation : CompositeExpression {
    public Alternation () {
    }

    public ExpressionCollection Alternatives {
      get { return Expressions; }
    }

    public void AddAlternative (Expression e) {
      Alternatives.Add (e);
    }

    public override void Compile (ICompiler cmp, bool reverse) {
      //      LinkRef next = cmp.NewLink ();
      LinkRef tail = cmp.NewLink ();

      foreach (Expression e in Alternatives) {
        LinkRef next = cmp.NewLink ();
        cmp.EmitBranch (next);
        e.Compile (cmp, reverse);
        cmp.EmitJump (tail);
        cmp.ResolveLink (next);
        cmp.EmitBranchEnd();
      }

      cmp.EmitFalse ();
      cmp.ResolveLink (tail);
      cmp.EmitAlternationEnd();
    }

    public override void GetWidth (out int min, out int max) {
      GetWidth (out min, out max, Alternatives.Count);
    }
  }

  // terminal expressions

  class Literal : Expression {
    public Literal (string str, bool ignore) {
      this.str = str;
      this.ignore = ignore;
    }

    public string String {
      get { return str; }
      set { str = value; }
    }

    public bool IgnoreCase {
      get { return ignore; }
      set { ignore = value; }
    }

    public static void CompileLiteral (string str, ICompiler cmp, bool ignore, bool reverse)
    {
      if (str.Length == 0)
        return;

      if (str.Length == 1)
        cmp.EmitCharacter (str[0], false, ignore, reverse);
      else
        cmp.EmitString (str, ignore, reverse);
    }

    public override void Compile (ICompiler cmp, bool reverse)
    {
      CompileLiteral (str, cmp, ignore, reverse);
    }

    public override void GetWidth (out int min, out int max) {
      min = max = str.Length;
    }

    public override AnchorInfo GetAnchorInfo (bool reverse) {
      return new AnchorInfo (this, 0, str.Length, str, ignore);
    }

    public override bool IsComplex () {
      return false;
    }

    private string str;
    private bool ignore;
  }

  class PositionAssertion : Expression {
    public PositionAssertion (Position pos) {
      this.pos = pos;
    }

    public Position Position {
      get { return pos; }
      set { pos = value; }
    }

    public override void Compile (ICompiler cmp, bool reverse) {
      cmp.EmitPosition (pos);
    }

    public override void GetWidth (out int min, out int max) {
      min = max = 0;
    }

    public override bool IsComplex () {
      return false;
    }

    public override AnchorInfo GetAnchorInfo (bool revers) {
      switch (pos) {
      case Position.StartOfString: case Position.StartOfLine: case Position.StartOfScan:
        return new AnchorInfo (this, 0, 0, pos);

      default:
        return new AnchorInfo (this, 0);
      }
    }

    private Position pos;
  }

  class Reference : Expression {
    public Reference (bool ignore) {
      this.ignore = ignore;
    }

    public CapturingGroup CapturingGroup {
      get { return group; }
      set { group = value; }
    }

    public bool IgnoreCase {
      get { return ignore; }
      set { ignore = value; }
    }

    public override void Compile (ICompiler cmp, bool reverse) {
      cmp.EmitReference (group.Index, ignore, reverse);
    }

    public override void GetWidth (out int min, out int max) {
      //group.GetWidth (out min, out max);
      // TODO set width to referenced group for non-cyclical references
      min = 0;
      max = Int32.MaxValue;
    }

    public override bool IsComplex () {
      return true;  // FIXME incorporate cyclic check
    }

    private CapturingGroup group;
    private bool ignore;
  }

  class BackslashNumber : Reference {
    string literal;
    bool ecma;

    public BackslashNumber (bool ignore, bool ecma)
      : base (ignore)
    {
      this.ecma = ecma;
    }

    // Precondition: groups [num_str] == null
    public bool ResolveReference (string num_str, Hashtable groups)
    {
      if (ecma) {
        int last_i = 0;
        for (int i = 1; i < num_str.Length; ++i) {
          if (groups [num_str.Substring (0, i)] != null)
            last_i = i;
        }
        if (last_i != 0) {
          CapturingGroup = (CapturingGroup) groups [num_str.Substring (0, last_i)];
          literal = num_str.Substring (last_i);
          return true;
        }
      } else {
        if (num_str.Length == 1)
          return false;
      }

      int ptr = 0;
      int as_octal = Parser.ParseOctal (num_str, ref ptr);
      // Since ParseOctal reads at most 3 digits, as_octal <= octal 0777
      if (as_octal == -1)
        return false;
      if (as_octal > 0xff && ecma) {
        as_octal /= 8;
        --ptr;
      }
      as_octal &= 0xff;
      literal = ((char) as_octal) + num_str.Substring (ptr);
      return true;
    }

    public override void Compile (ICompiler cmp, bool reverse)
    {
      if (CapturingGroup != null)
        base.Compile (cmp, reverse);
      if (literal != null)
        Literal.CompileLiteral (literal, cmp, IgnoreCase, reverse);
    }
  }

  class CharacterClass : Expression {
    public CharacterClass (bool negate, bool ignore) {
      this.negate = negate;
      this.ignore = ignore;

      intervals = new IntervalCollection ();

      // initialize pos/neg category arrays

      int cat_size = (int) Category.LastValue;
      pos_cats = new BitArray (cat_size);
      neg_cats = new BitArray (cat_size);
    }

    public CharacterClass (Category cat, bool negate) : this (false, false) {
      this.AddCategory (cat, negate);
    }

    public bool Negate {
      get { return negate; }
      set { negate = value; }
    }

    public bool IgnoreCase {
      get { return ignore; }
      set { ignore = value; }
    }

    public void AddCategory (Category cat, bool negate) {
      int n = (int)cat;

      if (negate) {
        neg_cats[n] = true;
      } else {
        pos_cats[n] = true;
      }
    }

    public void AddCharacter (char c) {
      // TODO: this is certainly not the most efficient way of doing things
      // TODO: but at least it produces correct results.
      AddRange (c, c);
    }

    public void AddRange (char lo, char hi) {
      Interval new_interval = new Interval (lo, hi);

      // ignore case is on. we must make sure our interval does not
      // use upper case. if it does, we must normalize the upper case
      // characters into lower case.
      if (ignore) {
        if (upper_case_characters.Intersects (new_interval)) {
          Interval partial_new_interval;

          if (new_interval.low < upper_case_characters.low) {
            partial_new_interval = new Interval (upper_case_characters.low + distance_between_upper_and_lower_case,
                         new_interval.high +  distance_between_upper_and_lower_case);
            new_interval.high = upper_case_characters.low - 1;
          }
          else {
            partial_new_interval = new Interval (new_interval.low + distance_between_upper_and_lower_case,
                         upper_case_characters.high + distance_between_upper_and_lower_case);
            new_interval.low = upper_case_characters.high + 1;
          }
          intervals.Add (partial_new_interval);
        }
        else if (upper_case_characters.Contains (new_interval)) {
          new_interval.high += distance_between_upper_and_lower_case;
          new_interval.low += distance_between_upper_and_lower_case;
        }
      }
      intervals.Add (new_interval);
    }

    public override void Compile (ICompiler cmp, bool reverse) {
      // create the meta-collection
      IntervalCollection meta =
        intervals.GetMetaCollection (new IntervalCollection.CostDelegate (GetIntervalCost));

      // count ops
      int count = meta.Count;
      for (int i = 0; i < pos_cats.Length; ++ i) {
        if (pos_cats[i] || neg_cats [i])
          ++ count;
      }

      if (count == 0)
        return;

      // emit in op for |meta| > 1
      LinkRef tail = cmp.NewLink ();
      if (count > 1)
        cmp.EmitIn (tail);

      // emit character/range/sets from meta-collection
      // we emit these first so that any 'ignore' flags will be noticed by the evaluator
      foreach (Interval a in meta) {
        if (a.IsDiscontiguous) {      // Set
          BitArray bits = new BitArray (a.Size);
          foreach (Interval b in intervals) {
            if (a.Contains (b)) {
              for (int i = b.low; i <= b.high; ++ i)
                bits[i - a.low] = true;
            }
          }

          cmp.EmitSet ((char)a.low, bits, negate, ignore, reverse);
        }
        else if (a.IsSingleton)        // Character
          cmp.EmitCharacter ((char)a.low, negate, ignore, reverse);
        else            // Range
          cmp.EmitRange ((char)a.low, (char)a.high, negate, ignore, reverse);
      }

      // emit categories
      for (int i = 0; i < pos_cats.Length; ++ i) {
        if (pos_cats[i]) {
          if (neg_cats [i])
            cmp.EmitCategory (Category.AnySingleline, negate, reverse);
          else
            cmp.EmitCategory ((Category)i, negate, reverse);
        } else if (neg_cats[i]) {
          cmp.EmitNotCategory ((Category)i, negate, reverse);
        }
      }

      // finish up
      if (count > 1) {
        if (negate)
          cmp.EmitTrue ();
        else
          cmp.EmitFalse ();

        cmp.ResolveLink (tail);
      }
    }

    public override void GetWidth (out int min, out int max) {
      min = max = 1;
    }

    public override bool IsComplex () {
      return false;
    }

    // private

    private static double GetIntervalCost (Interval i) {
      // use op length as cost metric (=> optimize for space)

      if (i.IsDiscontiguous)
        return 3 + ((i.Size + 0xf) >> 4);    // Set
      else if (i.IsSingleton)
        return 2;          // Character
      else
        return 3;          // Range
    }

    private static Interval upper_case_characters = new Interval ((char)65, (char)90);
    private const int distance_between_upper_and_lower_case = 32;
    private bool negate, ignore;
    private BitArray pos_cats, neg_cats;
    private IntervalCollection intervals;
  }

  class AnchorInfo {
    private Expression expr;

    private Position pos;
    private int offset;

    private string str;
    private int width;
    private bool ignore;

    public AnchorInfo (Expression expr, int width) {
      this.expr = expr;
      this.offset = 0;
      this.width = width;

      this.str = null;
      this.ignore = false;
      this.pos = Position.Any;
    }

    public AnchorInfo (Expression expr, int offset, int width, string str, bool ignore) {
      this.expr = expr;
      this.offset = offset;
      this.width = width;

      this.str = ignore ? str.ToLower () : str;

      this.ignore = ignore;
      this.pos = Position.Any;
    }

    public AnchorInfo (Expression expr, int offset, int width, Position pos) {
      this.expr = expr;
      this.offset = offset;
      this.width = width;

      this.pos = pos;

      this.str = null;
      this.ignore = false;
    }

    public Expression Expression {
      get { return expr; }
    }

    public int Offset {
      get { return offset; }
    }

    public int Width {
      get { return width; }
    }

    public int Length {
      get { return (str != null) ? str.Length : 0; }
    }

    public bool IsUnknownWidth {
      get { return width < 0; }
    }

    public bool IsComplete {
      get { return Length == Width; }
    }

    public string Substring {
      get { return str; }
    }

    public bool IgnoreCase {
      get { return ignore; }
    }

    public Position Position {
      get { return pos; }
    }

    public bool IsSubstring {
      get { return str != null; }
    }

    public bool IsPosition {
      get { return pos != Position.Any; }
    }

    public Interval GetInterval () {
      return GetInterval (0);
    }

    public Interval GetInterval (int start) {
      if (!IsSubstring)
        return Interval.Empty;

      return new Interval (start + Offset, start + Offset + Length - 1);
    }
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.