public SyntacticBlockList Clone( ) { var r = new SyntacticBlockList(); r.AddRange(this); r.IsSelected = IsSelected; return(r); }
public SyntacticBlockList Parse(string s) { var t = s.ToCharArray(); int i = 0; var paths = new SyntacticBlockList(); var rootNode = _gramTree; Parse(ref t, i, rootNode, rootNode, paths); return(paths); }
void Parse( ref char[] chars, int i, TreeNode rootNode, TreeNode node, SyntacticBlockList paths, TreePath currentPath = null, bool returnImmediately = false, int recurseLevel = 0 ) { if (chars.Length == 0 || i == chars.Length) { return; } bool matching = false; bool partialMatching = false; while (i < chars.Length) { bool lastChar = i == chars.Length - 1; var c = chars[i]; var sc = "" + c; matching = false; var beginIndex = i; /*if (recurseLevel==0 && node==null) { * // start by grammar multi roots * foreach ( var kv in rootNode.SubNodes ) * { * _Parse(ref chars,i,rootNode,kv.Value,paths,currentPath,recurseLevel); * } * SelectPaths(ref chars,ref i,ref matching,ref partialMatching,rootNode,ref node); * }*/ if (!node.IsRoot) { if (node.Label == sc) { // exact match - potential matching sequence matching = true; partialMatching = false; } else { if (node.Label == SCF) { matching = c < 32 && c != 27; partialMatching = false; } else if (node.Label == CHAR) { matching = true; partialMatching = false; } else if (node.Label == TEXT) { // @TODO: develop matching = true; partialMatching = true; } else if (node.Label == NUMLIST) { if (char.IsDigit(c) || c == ';') { matching = true; partialMatching = true; } else { matching = !partialMatching; } } else if (node.Label == NUM) { if (char.IsDigit(c)) { matching = true; partialMatching = true; } } else { matching = false; } } i++; } else { matching = true; partialMatching = false; } #region functions void AddRemainingText(ref char[] chars, SyntacticBlock selected) { if (selected.Index > 0) { if (paths.Count > 1) { int holeSize, blockIndex; if (paths.Count > 1) { var previous = paths[^ 2];
void _Parse( ref char[] chars, int i, TreeNode rootNode, TreeNode node, SyntacticBlockList paths, TreePath currentPath = null, bool returnImmediately = false, int recurseLevel = 0 ) { if (chars.Length == 0 || i == chars.Length) { return; } bool matching = false; bool partialMatching = false; while (i < chars.Length) { bool lastChar = i == chars.Length - 1; var c = chars[i]; var sc = "" + c; matching = false; var beginIndex = i; /*if (recurseLevel==0 && node==null) { * // start by grammar multi roots * foreach ( var kv in rootNode.SubNodes ) * { * _Parse(ref chars,i,rootNode,kv.Value,paths,currentPath,recurseLevel); * } * SelectPaths(ref chars,ref i,ref matching,ref partialMatching,rootNode,ref node); * }*/ if (!node.IsRoot) { if (node.Label == sc) { // exact match - potential matching sequence matching = true; partialMatching = false; } else { if (node.Label == SCF) { matching = c < 32 && c != 27; partialMatching = false; } else if (node.Label == CHAR) { matching = true; partialMatching = false; } else if (node.Label == TEXT) { // @TODO: develop matching = true; partialMatching = true; } else if (node.Label == NUMLIST) { if (char.IsDigit(c) || c == ';') { matching = true; partialMatching = true; } else { matching = !partialMatching; } } else if (node.Label == NUM) { if (char.IsDigit(c)) { matching = true; partialMatching = true; } } else { matching = false; } } i++; } else { matching = true; partialMatching = false; } #region functions void AddRemainingText(ref char[] chars, SyntacticBlock selected) { if (selected.Index > 0) { if (paths.Count > 1) { int holeSize, blockIndex; if (paths.Count > 1) { var previous = paths[paths.Count - 2]; holeSize = selected.Index - (previous.Index + previous.Text.Length - 1) - 1; blockIndex = previous.Index + previous.Text.Length; } else { holeSize = selected.Index; blockIndex = 0; } if (holeSize > 0) { var textBlock = new SyntacticBlock( blockIndex, null, new string(chars, blockIndex, holeSize), true, false ); paths.Insert(paths.Count - 1, textBlock); } } else { var textBlock = new SyntacticBlock( 0, null, new string(chars, 0, selected.Index), true, false ); paths.Insert(paths.Count - 1, textBlock); } } } void SelectPaths( ref char[] chars, ref int i, ref bool matching, ref bool partialMatching, TreeNode rootNode, ref TreeNode node ) { // any sub syntax of another syntax is removed // equivalent are selected dependings on rule priority var _paths = paths.Where(x => !x.IsSelected).ToList(); if (_paths.Count == 0) { return; } List <SyntacticBlock> t; if (_paths.Count > 1) { var maxLength = _paths.Max(x => x.Text.Length); var longests = _paths.Where(x => x.Text.Length == maxLength); t = new List <SyntacticBlock>(longests); t.Sort((x, y) => x.SyntacticRule.Rule.ID.CompareTo(y.SyntacticRule.Rule.ID)); } else { t = _paths; } // keep only the right syntax var selected = t.First(); selected.IsSelected = true; matching = false; partialMatching = false; var tmp = new List <SyntacticBlock>(paths); foreach (var p in tmp) { if (!p.IsSelected && p != selected) { paths.Remove(p); } } // add text node if any AddRemainingText(ref chars, selected); // setup parser to go on on next position i += selected.Text.Length - 1; if (rootNode != null) { node = rootNode; } currentPath = null; } #endregion if ( (matching && !partialMatching) || (!matching && partialMatching) ) { if (!partialMatching || !matching) { if (!node.IsRoot) { if (currentPath == null) { currentPath = new TreePath(null, beginIndex); } else { currentPath = new TreePath(currentPath.Rule, currentPath.Index, currentPath); } currentPath.Add(node); } if (node.SubNodes.Count == 0) { // gram path match var sblock = new SyntacticBlock( currentPath.Index, currentPath, new string(chars, currentPath.Index, i - currentPath.Index )); var key = sblock.SyntacticRule.Key; if (_rulesIndex.TryGetValue(key, out var matchingRule)) { sblock.SyntacticRule.Rule = matchingRule; } else { throw new Exception($"a syntactic pattern has been recognized but no corresponding rule can be found (grammar is ambiguous ?) : {sblock}"); } paths.Add(sblock); if (recurseLevel == 0) { SelectPaths(ref chars, ref i, ref matching, ref partialMatching, rootNode, ref node); } else { return; // stop on result } } else { i += (partialMatching)?-1:0; /*ignore last match*/ //var m = matching; //var pm = partialMatching; //matching = partialMatching = false; // explore gram next foreach (var kv in node.SubNodes) { var pathsCount = paths.Count; _Parse( ref chars, i, rootNode, kv.Value, paths, currentPath, node.IsRoot, recurseLevel + 1); var hasNewPath = paths.Count > pathsCount; //if (node.IsRoot) // SelectPaths(ref chars,ref i,ref matching,ref partialMatching,rootNode,ref node); } if (recurseLevel == 0) { SelectPaths(ref chars, ref i, ref matching, ref partialMatching, rootNode, ref node); if (node.IsRoot) { i++; } } else { // stop on result return; } } } else { // else scan next of current pattern } } else { if (!(matching && partialMatching)) { if (currentPath != null) { // path doesn't match currentPath = null; return; // rule not fit at i - stop on result } else { if (returnImmediately) { return; } } } else { // scan next of current pattern ('node' partial matching) } } } // end string #region handle tail if (currentPath != null) { // path match to the end of the string but not ended // incomplete path var sblock = new SyntacticBlock( currentPath.Index, currentPath, new string(chars, currentPath.Index, i - currentPath.Index ), true ); var key = sblock.SyntacticRule.Key; if (_rulesIndex.TryGetValue(key, out var matchingRule)) { sblock.SyntacticRule.Rule = matchingRule; } paths.Add(sblock); } else { // add remaining text int beginIndex = 0; if (paths.Count > 0) { var last = paths.Last(); beginIndex = last.Index + last.Text.Length; } var textBlock = new SyntacticBlock( beginIndex, null, new string(chars, beginIndex, chars.Length - beginIndex), true, false ); paths.Add(textBlock); } #endregion }