private RegularExpression(PartialExpression part) { input = part.ToString(); parsedInput = part; TagInput(); CountTags(); }
/// <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); } } }
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); }
/// <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); }
public WindowSimpleCanvas(PartialExpression parseTree) { this.parseTree = parseTree; DataContext = this; InitializeComponent(); ParseTreeDrawing.Draw(ParseTreeCanvas, parseTree); }
/// <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; }
private void ParseInput() { int lastSymbol; parsedInput = ParseSubExpression(0, out lastSymbol); if (lastSymbol < taggedInput.Count - 1) { throw new ArgumentException("parsing is incomplete"); } }
/// <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; }
//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; }
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; } } }
/// <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); }
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; } } }
/// <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"); } }
///// <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; }
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; }
/// <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); }
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); }
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)); }