Пример #1
0
 private RegularExpression(PartialExpression part)
 {
     input       = part.ToString();
     parsedInput = part;
     TagInput();
     CountTags();
 }
Пример #2
0
        /// <summary>
        /// Copy constructor. Constructs a complete copy of all subexpressions.
        /// </summary>
        /// <param name="origin">original partial expression</param>
        public PartialExpression(PartialExpression origin)
        {
            if (origin == null)
            {
                throw new ArgumentNullException("origin");
            }

            role = origin.role;
            root = origin.root;

            _value    = origin._value;
            _operator = origin._operator;

            if (role == PartialExpressionRole.Union || role == PartialExpressionRole.Concatenation)
            {
                if (origin.parts.Count >= 2)
                {
                    parts = new List <PartialExpression>(new PartialExpression[origin.parts.Count]);
                    Parallel.For(0, origin.parts.Count, (int n) =>
                    {
                        parts[n]      = new PartialExpression(origin.parts[n]);
                        parts[n].root = this;
                    });
                }
                else if (origin.parts.Count == 1)
                {
                    parts = new List <PartialExpression>(1);
                    var partCopy = new PartialExpression(origin.parts[0]);
                    partCopy.root = this;
                    parts.Add(partCopy);
                }
            }
        }
Пример #3
0
 private RegularExpression(RegularExpression origin)
 {
     input       = origin.input;
     alphabet    = new List <string>(origin.alphabet);
     taggedInput = new List <KeyValuePair <string, InputSymbolTag> >(origin.taggedInput);
     tagCount    = new Dictionary <InputSymbolTag, uint>(origin.tagCount);
     parsedInput = new PartialExpression(origin.parsedInput);
 }
Пример #4
0
        /// <summary>
        /// Derives a new expression by removing a given letter from the beginning
        /// of this regular expression.
        /// </summary>
        /// <param name="removedLetter">a one-letter string, it must belong to the alphabet of the input</param>
        /// <returns>a derived expression, or null if no valid expression could be derived</returns>
        public RegularExpression Derive(string removedLetter)
        {
            if (removedLetter == null)
            {
                throw new ArgumentNullException("removedLetter", "cannot remove non-existing letter");
            }
            if (removedLetter.Length != 1)
            {
                throw new ArgumentException("a single letter must be given", "removedLetter");
            }

            RegularExpression regexp = null;

            lock (derivationCacheLock)
            {
                Dictionary <char, RegularExpression> regexpList;
                if (derivationCache.TryGetValue(this, out regexpList))
                {
                    if (regexpList.TryGetValue(removedLetter[0], out regexp))
                    {
                        return(regexp);
                    }
                }
            }

            if (alphabet.Contains(removedLetter))
            {
                var parseTreeCopy = new PartialExpression(parsedInput);
                parseTreeCopy.Derive(removedLetter);
                parseTreeCopy.Optimize();
                if (parseTreeCopy.Role.Equals(PartialExpressionRole.Invalid))
                {
                    return(null);
                }

                regexp = new RegularExpression(parseTreeCopy);
            }

            lock (derivationCacheLock)
            {
                Dictionary <char, RegularExpression> regexpList;
                if (derivationCache.TryGetValue(this, out regexpList))
                {
                    if (!regexpList.ContainsKey(removedLetter[0]))
                    {
                        regexpList.Add(removedLetter[0], regexp);
                    }
                }
                else
                {
                    regexpList = new Dictionary <char, RegularExpression>();
                    regexpList.Add(removedLetter[0], regexp);
                    derivationCache.Add(this, regexpList);
                }
            }

            return(regexp);
        }
Пример #5
0
        public WindowSimpleCanvas(PartialExpression parseTree)
        {
            this.parseTree = parseTree;

            DataContext = this;
            InitializeComponent();

            ParseTreeDrawing.Draw(ParseTreeCanvas, parseTree);
        }
Пример #6
0
        /// <summary>
        /// Constructs a new regular expression part.
        /// </summary>
        /// <param name="role"></param>
        /// <param name="root"></param>
        public PartialExpression(PartialExpressionRole role, PartialExpression root)
        {
            this.role = role;
            this.root = root;

            this.parts     = null;
            this._value    = null;
            this._operator = UnaryOperator.None;
        }
Пример #7
0
        private void ParseInput()
        {
            int lastSymbol;

            parsedInput = ParseSubExpression(0, out lastSymbol);
            if (lastSymbol < taggedInput.Count - 1)
            {
                throw new ArgumentException("parsing is incomplete");
            }
        }
Пример #8
0
 /// <summary>
 /// Inserts a new part to list of sub-parts that are concatenated with each other.
 /// </summary>
 /// <param name="index"></param>
 /// <param name="exp"></param>
 public void InsertToConcatenation(int index, PartialExpression exp)
 {
     if (exp == null)
     {
         throw new ArgumentNullException("exp");
     }
     if (role != PartialExpressionRole.Concatenation)
     {
         throw new ArgumentException("cannot concatenate symbol with a partial expression that does not store concatenation");
     }
     if (parts == null)
     {
         parts = new List <PartialExpression>();
     }
     parts.Insert(index, exp);
     exp.root = this;
 }
Пример #9
0
        //public PartialExpression(PartialExpression root)
        //	: this()
        //{
        //	this.root = root;
        //}

        //public PartialExpression(PartialExpression root, string value)
        //	: this(root)
        //{
        //	this._value = value;
        //}

        /// <summary>
        /// Adds a new part to list of sub-parts that are in alternative with each other.
        /// </summary>
        /// <param name="exp"></param>
        public void AddToUnion(PartialExpression exp)
        {
            if (exp == null)
            {
                throw new ArgumentNullException("exp");
            }
            if (role != PartialExpressionRole.Union)
            {
                throw new ArgumentException("cannot add symbol to a partial expression that does not store union");
            }
            if (parts == null)
            {
                parts = new List <PartialExpression>();
            }
            parts.Add(exp);
            exp.root = this;
        }
Пример #10
0
        private PartialExpression(PartialExpression origin, bool skipFirstPart)
        {
            role = origin.role;
            root = origin.root;

            _value    = origin._value;
            _operator = origin._operator;

            if (role == PartialExpressionRole.Union || role == PartialExpressionRole.Concatenation)
            {
                parts = new List <PartialExpression>();
                int i = 0;
                if (skipFirstPart)
                {
                    ++i;
                }
                for (; i < origin.parts.Count; ++i)
                {
                    var part = new PartialExpression(origin.parts[i]);
                    parts.Add(part);
                    part.root = this;
                }
            }
        }
Пример #11
0
        /// <summary>
        /// Checks for equality between this PartialExpression and another object.
        /// </summary>
        /// <param name="part"></param>
        /// <param name="compareOperators"></param>
        /// <returns></returns>
        public bool ContentEquals(PartialExpression part, bool compareOperators)
        {
            if (part == null)
            {
                return(false);
            }

            if (this == part)
            {
                return(true);
            }

            if (role != part.role)
            {
                return(false);
            }

            if (compareOperators)
            {
                if (_operator != part._operator)
                {
                    return(false);
                }
            }

            switch (role)
            {
            case PartialExpressionRole.EmptyWord:
                return(true);

            case PartialExpressionRole.Letter:
                return(_value.Equals(part._value));

            case PartialExpressionRole.Concatenation:
            {
                if (parts.Count != part.parts.Count)
                {
                    return(false);
                }

                for (int i = 0; i < parts.Count; ++i)
                {
                    if (!parts[i].Equals(part.parts[i]))
                    {
                        return(false);
                    }
                }

                return(true);
            }

            case PartialExpressionRole.Union:
            {
                foreach (var p in parts)
                {
                    if (part.parts.Count(x => x.Equals(p)) == 0)
                    {
                        return(false);
                    }
                }
                foreach (var p in part.parts)
                {
                    if (parts.Count(x => x.Equals(p)) == 0)
                    {
                        return(false);
                    }
                }

                return(true);
            }

            case PartialExpressionRole.Undetermined:
            case PartialExpressionRole.Invalid:
            default:
                return(true);
            }
            // return base.Equals(obj);
        }
Пример #12
0
        private void DeriveConcatenation(string removedLetter)
        {
            var firstPart = parts[0];

            if (firstPart._operator == UnaryOperator.KleeneStar)
            {
                // derivation can split into two variants
                // (a^*)bc becomes (bc)+(a(a^*)bc) and only then it is derived

                var new1 = new PartialExpression(this, true);
                if (new1.parts.Count == 1)
                {
                    new1.Optimize();
                }
                //new1.root = this;

                PartialExpression new2firstPart = new PartialExpression(firstPart);
                new2firstPart._operator = UnaryOperator.None;

                var new2 = new PartialExpression(this);
                new2.InsertToConcatenation(0, new2firstPart);

                parts = null;
                role  = PartialExpressionRole.Union;
                AddToUnion(new1);
                AddToUnion(new2);

                Derive(removedLetter);
            }
            else if (firstPart.role == PartialExpressionRole.Union &&
                     firstPart.parts.Any(x => x.role == PartialExpressionRole.EmptyWord))
            {
                // this union contains an empty word, so the derivation can be split in two variants
                // (a+.)bc becomes (abc)+(bc) and only then it is derived

                PartialExpression new1firstPart = new PartialExpression(firstPart);
                new1firstPart.parts.RemoveAll(x => x.role == PartialExpressionRole.EmptyWord);

                var new1 = new PartialExpression(this);
                new1.parts[0]      = new1firstPart;            // instead
                new1firstPart.root = new1;
                new1.root          = this;

                var new2 = new PartialExpression(this, true);
                if (new2.parts.Count == 1)
                {
                    new2.Optimize();
                }
                new2.root = this;

                role  = PartialExpressionRole.Union;
                parts = new List <PartialExpression> {
                    new1, new2
                };

                Derive(removedLetter);
            }
            else
            {
                parts[0].Derive(removedLetter);
                if (parts[0].role == PartialExpressionRole.Invalid)
                {
                    parts = null;
                    role  = PartialExpressionRole.Invalid;
                }
                else if (parts.Count > 1)
                {
                    if (parts[0].role == PartialExpressionRole.EmptyWord)
                    {
                        parts.RemoveAt(0);
                        Optimize();
                    }
                }
                else if (parts[0].role == PartialExpressionRole.EmptyWord)
                {
                    parts = null;
                    role  = PartialExpressionRole.EmptyWord;
                }
            }
        }
Пример #13
0
        /// <summary>
        /// The derivation is performed in-place, therefore it is good to make a backup of instance
        /// if the original is expected to be of some use later.
        /// </summary>
        /// <param name="removedLetter">string containing a single letter</param>
        public void Derive(string removedLetter)
        {
            // to properly derive expressions with unary operators, they have to be transformed
            switch (_operator)
            {
            case UnaryOperator.KleeneStar:
            {
                // (a)^* becomes .+a(a)^* because those expressions are equivalent

                var extracted = new PartialExpression(this);
                extracted._operator = UnaryOperator.None;

                var remaining = new PartialExpression(this);

                var concat = new PartialExpression(PartialExpressionRole.Concatenation, this);
                concat.AddToConcatenation(extracted);
                concat.AddToConcatenation(remaining);

                parts = null;
                role  = PartialExpressionRole.Union;
                AddToUnion(new PartialExpression(PartialExpressionRole.EmptyWord, this));
                AddToUnion(concat);
                _operator = UnaryOperator.None;
            } break;

            case UnaryOperator.KleenePlus:
            {
                // (a)^+ becomes a(a)^* because those expressions are equivalent

                var extracted = new PartialExpression(this);
                extracted._operator = UnaryOperator.None;

                var remaining = new PartialExpression(this);
                remaining._operator = UnaryOperator.KleeneStar;

                parts = null;
                role  = PartialExpressionRole.Concatenation;
                AddToConcatenation(extracted);
                AddToConcatenation(remaining);
                _operator = UnaryOperator.None;
            } break;
            }


            switch (role)
            {
            case PartialExpressionRole.EmptyWord:
                role = PartialExpressionRole.Invalid;
                break;

            case PartialExpressionRole.Letter:
                if (_value.Equals(removedLetter))
                {
                    role = PartialExpressionRole.EmptyWord;
                }
                else
                {
                    role = PartialExpressionRole.Invalid;
                }
                _value = null;
                break;

            case PartialExpressionRole.Concatenation:
                DeriveConcatenation(removedLetter);
                break;

            case PartialExpressionRole.Union:
                DeriveUnion(removedLetter);
                break;

            default:
                throw new ArgumentException("encountered partial expression with role that is not allowed");
            }
        }
Пример #14
0
        ///// <summary>
        ///// Constructs a new regular expression part.
        ///// </summary>
        ///// <param name="root"></param>
        ///// <param name="parts"></param>
        ///// <param name="concatenation"></param>
        //private PartialExpression(PartialExpression root, List<PartialExpression> parts, bool concatenation)
        //	: this(concatenation ? PartialExpressionRole.Concatenation : PartialExpressionRole.Union, root)
        //{
        //	this.parts = parts;
        //}

        /// <summary>
        /// Constructs a new regular expression part.
        /// </summary>
        /// <param name="root"></param>
        /// <param name="value"></param>
        public PartialExpression(PartialExpression root, string value)
            : this(PartialExpressionRole.Letter, root)
        {
            this._value = value;
        }
Пример #15
0
        public WindowUserHelp(PhiniteSettings settings, object machineOperationsLock, FiniteStateMachine machine)
        {
            if (machineOperationsLock == null)
            {
                throw new ArgumentNullException("machineOperationsLock");
            }
            if (machine == null)
            {
                throw new ArgumentNullException("machine");
            }

            this.settings = settings;

            fsmLock = machineOperationsLock;
            fsm     = machine;

            //lock (fsmLock)
            {
                states    = fsm.States;
                accepting = fsm.AcceptingStates;

                newExpression = fsm.NextNotLabeledState;

                parseTree = newExpression.ParseTree;

                newExpressionSimilarities = fsm.NextNotLabeledStateSimilarities;
            }

            newExpressionProcessed = false;
            expressionIsSelected   = false;
            selectedExpression     = -1;
            labeledExpressionsData = null;

            DataContext = this;
            InitializeComponent();

            ParseTreeDrawing.Draw(ParseTreeCanvas, parseTree);

            var data = new List <Tuple <RegularExpression, string, string, string> >();
            int i    = 0;

            foreach (var state in states)
            {
                var stateIsAccepting = accepting.Contains(state);

                StringBuilder s = new StringBuilder();
                if (i == 0)
                {
                    s.Append("initial state");
                }
                if (stateIsAccepting)
                {
                    if (i == 0)
                    {
                        s.Append(", ");
                    }
                    s.Append("accepting state");
                }

                //double similarity = newExpression.Similarity(state);

                data.Add(new Tuple <RegularExpression, string, string, string>(state, String.Format("q{0}", i), s.ToString(),
                                                                               String.Format("{0:0.00}%", newExpressionSimilarities[i] * 100)));

                ++i;
            }

            LabeledExpressionsData = data;
        }
Пример #16
0
 /// <summary>
 /// Clears the canvas and draws the parse tree on it.
 /// </summary>
 /// <param name="canvas">the canvas</param>
 /// <param name="parseTree">the parse tree to be drawn</param>
 public static void Draw(Canvas canvas, PartialExpression parseTree)
 {
     DrawParseTree(canvas, parseTree);
 }
Пример #17
0
        private PartialExpression ParseSubExpression(int startingIndex, out int lastIndex)
        {
            var returned = new PartialExpression(PartialExpressionRole.Undetermined, null);

            lastIndex = startingIndex;

            PartialExpression current = returned;

            for (int i = startingIndex; i < taggedInput.Count; ++i)
            {
                var tagPair = taggedInput[i];

                switch (tagPair.Value)
                {
                case InputSymbolTag.Letter:
                {
                    current.Role = PartialExpressionRole.Concatenation;
                    current.AddToConcatenation(new PartialExpression(current, tagPair.Key));
                } break;

                case InputSymbolTag.EmptyWord:
                {
                    current.Role = PartialExpressionRole.Concatenation;
                    current.AddToConcatenation(new PartialExpression(PartialExpressionRole.EmptyWord, current));
                } break;

                case InputSymbolTag.Union:
                {
                    if (current.Root == null)
                    {
                        var newCurrent = new PartialExpression(PartialExpressionRole.Undetermined, null);
                        //var newRoot = new PartialExpression(null, new List<PartialExpression> { current, newCurrent }, false);
                        var newRoot = new PartialExpression(PartialExpressionRole.Union, null);
                        newRoot.AddToUnion(current);
                        newRoot.AddToUnion(newCurrent);

                        current.Root    = newRoot;
                        newCurrent.Root = newRoot;

                        if (returned == current)
                        {
                            returned = newRoot;
                        }
                        current = newCurrent;
                    }
                    else if (current.Root.Role.Equals(PartialExpressionRole.Union) &&
                             current.Root.Parts.Contains(current))
                    {
                        var newCurrent = new PartialExpression(PartialExpressionRole.Undetermined, current.Root);
                        current.Root.AddToUnion(newCurrent);
                        current = newCurrent;
                    }
                    else
                    {
                        throw new NotImplementedException("more handling code needed");
                    }
                } break;

                case InputSymbolTag.OpeningParenthesis:
                {
                    int last    = 0;
                    var subExpr = ParseSubExpression(i + 1, out last);
                    current.Role = PartialExpressionRole.Concatenation;
                    current.AddToConcatenation(subExpr);
                    subExpr.Root = current;
                    i            = last;
                } break;

                case InputSymbolTag.ClosingParenthesis:
                {
                    lastIndex = i;
                    return(returned);
                }

                case InputSymbolTag.KleeneStar:
                case InputSymbolTag.KleenePlus:
                {
                    current.Parts[current.Parts.Count - 1].Operator = (UnaryOperator)tagPair.Value;
                    //current.LastConcatenatedSymbol.Operator = (UnaryOperator)input.Value;
                } break;

                default:
                {
                    throw new NotImplementedException("more handling code needed");
                }
                }

                lastIndex = i;
            }
            return(returned);
        }
Пример #18
0
        private static Point DrawParseTree(Canvas canvas, PartialExpression parseTree, double x = 0, double y = 0)
        {
            var canvasContent = canvas.Children;

            bool root = x == 0 && y == 0;

            if (root)
            {
                x = ParseTreeDrawingRootOffset.X;
                y = ParseTreeDrawingRootOffset.Y;
                canvasContent.Clear();
            }

            int    treeWidth = parseTree.CalculateTreeWidth();
            double actualX   = x;
            double actualY   = y;

            if (treeWidth > 1)
            {
                double subtreeDrawingHeight = (treeWidth - 1) * (ParseTreeNodeSize.Height + ParseTreeNodeSpacing.Y);
                actualY += subtreeDrawingHeight / 2;
            }

            #region an indicator

            var indicator = new Ellipse();
            indicator.Fill   = Brushes.DarkViolet;
            indicator.Width  = 6;
            indicator.Height = indicator.Width;

            canvasContent.Add(indicator);
            Canvas.SetLeft(indicator, actualX - indicator.Width / 2);
            Canvas.SetTop(indicator, actualY - indicator.Height / 2);
            Canvas.SetZIndex(indicator, -1000);

            #endregion

            #region border for text block

            var border = new Ellipse();
            border.Stroke          = Brushes.Gray;
            border.Fill            = Brushes.White;
            border.StrokeThickness = 1;
            border.Width           = ParseTreeNodeSize.Width;
            border.Height          = ParseTreeNodeSize.Height;

            canvasContent.Add(border);
            Canvas.SetLeft(border, actualX - ParseTreeNodeSize.Width / 2);
            Canvas.SetTop(border, actualY - ParseTreeNodeSize.Height / 2);

            #endregion

            #region text block

            var elem = new TextBlock();
            elem.TextAlignment = TextAlignment.Center;
            elem.Width         = ParseTreeNodeContentSize.Width;
            elem.Height        = ParseTreeNodeContentSize.Height;

            canvasContent.Add(elem);
            Canvas.SetLeft(elem, actualX - ParseTreeNodeContentSize.Width / 2);
            Canvas.SetTop(elem, actualY - ParseTreeNodeContentSize.Height / 2);

            #endregion

            string text = String.Empty;
            if (parseTree.Role == PartialExpressionRole.EmptyWord)
            {
                text = "epsilon";
            }
            else if (parseTree.Role == PartialExpressionRole.Letter)
            {
                text = parseTree.Value;
            }
            else if ((parseTree.Role & PartialExpressionRole.InternalNode) > 0)
            {
                if (parseTree.Role == PartialExpressionRole.Concatenation)
                {
                    text = "concat";
                }
                else if (parseTree.Role == PartialExpressionRole.Union)
                {
                    text = "union";
                }

                double yy = y;
                foreach (var part in parseTree.Parts)
                {
                    #region edge

                    var edge = new Polyline();
                    edge.Stroke          = Brushes.Gray;
                    edge.StrokeThickness = 2;
                    edge.Points.Add(new Point(EdgeHorizontalMargin, actualY));
                    edge.Points.Add(new Point(ParseTreeNodeSpacing.X - 2 * EdgeHorizontalMargin, yy));

                    canvasContent.Add(edge);
                    Canvas.SetLeft(edge, actualX + ParseTreeNodeSize.Width / 2);
                    //Canvas.SetTop(edge, ParseTreeNodeSize.Height / 2);
                    Canvas.SetZIndex(edge, -500);

                    #endregion

                    var rootPt = DrawParseTree(canvas, part, x + ParseTreeNodeSize.Width + ParseTreeNodeSpacing.X, yy);

                    int partWidth = part.CalculateTreeWidth();

                    if (partWidth > 1)
                    {
                        var pt = edge.Points[1];
                        edge.Points[1] = new Point(pt.X, rootPt.Y);
                    }

                    yy += partWidth * (ParseTreeNodeSize.Height + ParseTreeNodeSpacing.Y);
                }
            }

            if (parseTree.Operator != UnaryOperator.None)
            {
                text += RegularExpression.TagsStrings[(InputSymbolTag)parseTree.Operator];
            }

            elem.Text = text;

            if (root)
            {
                #region start line

                var startLine = new Polyline();
                startLine.Stroke          = Brushes.Gray;
                startLine.StrokeThickness = 2;
                startLine.Points.Add(new Point(0, 0));
                startLine.Points.Add(new Point(RootLineLength, 0));

                canvasContent.Add(startLine);
                Canvas.SetLeft(startLine, actualX - ParseTreeNodeSize.Width / 2 - RootLineLength);
                Canvas.SetTop(startLine, actualY);
                Canvas.SetZIndex(startLine, -500);

                #endregion

                double treeHeight = parseTree.CalculateTreeHeight();
                canvas.Width = (treeHeight - 1) * (ParseTreeNodeSize.Width + ParseTreeNodeSpacing.X)
                               + ParseTreeNodeSize.Width / 2 + ParseTreeDrawingRootOffset.X;
                canvas.Height = (treeWidth - 1) * (ParseTreeNodeSize.Height + ParseTreeNodeSpacing.Y)
                                + ParseTreeNodeSize.Height / 2 + ParseTreeDrawingRootOffset.Y;
            }

            return(new Point(actualX, actualY));
        }