/// <summary> /// AND /// </summary> /// <param name="left"></param> /// <param name="tbl"></param> /// <returns></returns> public static int and(Node[] nodes, Dictionary<string, int> row = null, Dictionary<string, int>[] tbl = null) { foreach (var node in nodes) { if (Node.Compute(node, row, tbl) == 0) return 0; } return 1; }
public void parse_関数_1項_1() { var node = new Node("SUM(2)"); node.Parse(); { Assert.True(node.Left.Expression == "2"); } Assert.True(node.Expression == "SUM"); Assert.True(node.Right == null); return; }
public void parse_関数_1項_2() { var node = new Node("SUM(-2)"); node.Parse(); Assert.True(node.Expression == "SUM"); Assert.True(node.Type == NodeType.Function); Assert.True(node.Left.Expression == "-"); { Assert.True(node.Left.Left == null); Assert.True(node.Left.Right.Expression == "2"); } Assert.True(node.Right == null); }
public void parse_2項変数() { var node = new Node("2+abc"); node.Parse(); Assert.True(node.Left.Expression == "2"); Assert.True(node.Left.Type == NodeType.Constant); Assert.True(node.Expression == "+"); Assert.True(node.Type == NodeType.Operator); Assert.True(node.Right.Expression == "abc"); Assert.True(node.Right.Type == NodeType.Item); return; }
public void parse_4項カッコあり() { var node = new Node("(2+3+4)+5"); node.Parse(); { Assert.True(node.Left.Left.Expression == "2"); Assert.True(node.Left.Expression == "+"); { Assert.True(node.Left.Right.Left.Expression == "3"); Assert.True(node.Left.Right.Expression == "+"); Assert.True(node.Left.Right.Right.Expression == "4"); } } Assert.True(node.Expression == "+"); Assert.True(node.Right.Expression == "5"); return; }
public int 計算_カラム(string expression) { var row = new Dictionary<string, int>() { { "A", 1 }, { "B", 2 } }; var tbl = new[] { new Dictionary<string, int>() {{"A", 1}}, new Dictionary<string, int>() {{"A", 2}}, new Dictionary<string, int>() {{"A", 3}}, }; var node = new Node(expression); node.Parse(); var ans = Node.Compute(node, row, tbl); return ans; }
public int 計算_if(string expression) { var row = new Dictionary<string, int>() { { "X", 4 }, { "Y", 2 } }; var tbl = new[] { new Dictionary<string, int>() {{"A", 1},{"B", 3}}, new Dictionary<string, int>() {{"A", 2},{"B", 6}}, new Dictionary<string, int>() {{"A", 3},{"B", 7}}, }; var node = new Node(expression); node.Parse(); return Node.Compute(node, row, tbl); }
public int 計算(string expression) { var node = new Node(expression); node.Parse(); //var ans = node.Compute(); var ans = Node.Compute(node); return ans; }
public int 条件_less(string expression) { var node = new Node(expression); node.Parse(); return Node.Compute(node); }
public void parse_2項() { var node = new Node("2+3"); node.Parse(); Assert.True(node.Left.Expression == "2"); Assert.True(node.Expression == "+"); Assert.True(node.Type == NodeType.Operator); Assert.True(node.Right.Expression == "3"); return; }
public void parse_3項() { var node = new Node("2+3+4"); node.Parse(); Assert.True(node.Left.Expression == "2"); Assert.True(node.Expression == "+"); Assert.True(node.Right.Left.Expression == "3"); Assert.True(node.Right.Expression == "+"); Assert.True(node.Right.Right.Expression == "4"); return; }
/// <summary> /// ツリー形式になっている関数の引数ノードを配列として返す /// </summary> /// <param name="root"></param> /// <returns></returns> public static Node[] GetArgumentNodes(Node root) { var nodes = new List<Node>(); var node = root; while(true) { // 2回目以降(子要素)が関数型の場合もそれを最後として登録する if (node.Type == NodeType.Constant || node.Type == NodeType.Item || ( node.Type == NodeType.Operator && node.Expression != ",") || ( node.Type == NodeType.Function && node != root) ) { nodes.Add(node); break; } if (node.Left != null) { nodes.Add(node.Left); } node = node.Right; } return nodes.ToArray(); }
public void parse_1項_3() { var node = new Node("-2"); node.Parse(); Assert.True(node.Expression == "-"); Assert.True(node.Right.Expression == "2"); return; }
public void parse_関数引数取得2() { var node = new Node("SUM(2,3+4,-5)"); node.Parse(); var nodes = Node.GetArgumentNodes(node); Assert.True(nodes [ 0 ].Type == NodeType.Constant); Assert.True(nodes [ 0 ].Expression == "2"); Assert.True(nodes [ 1 ].Type == NodeType.Operator); Assert.True(nodes [ 1 ].Expression == "+"); { Assert.True(nodes [ 1 ].Left.Expression == "3"); Assert.True(nodes [ 1 ].Right.Expression == "4"); } Assert.True(nodes [ 2 ].Type == NodeType.Operator); Assert.True(nodes [ 2 ].Expression == "-"); { Assert.True(nodes [ 2 ].Left == null); Assert.True(nodes [ 2 ].Right.Expression == "5"); } }
/// <summary> /// IF /// </summary> /// <param name="left"></param> /// <param name="tbl"></param> /// <returns></returns> public static int iif(Node [] nodes, Dictionary<string, int> row = null, Dictionary<string, int>[] tbl = null) { var condition = Node.Compute(nodes[0], row, tbl); if (condition == 1) { return Node.Compute(nodes[1], row, tbl); } else { return Node.Compute(nodes[2], row, tbl); } }
public void parse_関数_3項() { var node = new Node("SUM(2,3+4,5)"); node.Parse(); Assert.True(node.Expression == "SUM"); Assert.True(node.Type == NodeType.Function); Assert.True(node.Left.Expression == "2"); Assert.True(node.Right.Expression == ","); { Assert.True(node.Right.Left.Expression == "+"); { Assert.True(node.Right.Left.Left.Expression == "3"); Assert.True(node.Right.Left.Right.Expression == "4"); } Assert.True(node.Right.Right.Expression == "5"); } var nodes = Node.GetArgumentNodes(node); }
public void parse_関数_2項() { var node = new Node("SUM(2,3)"); node.Parse(); Assert.True(node.Expression == "SUM"); Assert.True(node.Type == NodeType.Function); Assert.True(node.Left.Expression == "2"); Assert.True(node.Right.Expression == "3"); }
/// <summary> /// 比較「<」 /// </summary> /// <param name="left"></param> /// <param name="tbl"></param> /// <returns></returns> public static int lt(Node left, Node right, Dictionary<string, int> row = null, Dictionary<string, int> [ ] tbl = null) { var leftVal = Node.Compute(left, row, tbl); var rightVal = Node.Compute(right, row, tbl); if (leftVal < rightVal) { return 1; } else { return 0; } }
/// <summary> /// 式解析 /// </summary> /// <remarks>再帰的に呼び出される</remarks> public void Parse() { int pos = GetOperatorPosition((this.Expression)); // 符号として+-が指定されるケース if (pos == 0) { // TODO いきなり+-以外の演算子が出現したら異常 this.Left = null; this.Right = new Node(this.Expression.Substring(pos + 1)); this.Right.Parse(); this.Expression = this.Expression[pos].ToString(); this.Type = NodeType.Operator; } // 「項 演算子 項」のケース else if (pos > 0) { this.Left = new Node(this.Expression.Substring(0, pos)); this.Left.Parse(); this.Right = new Node(this.Expression.Substring(pos+1)); this.Right.Parse(); this.Expression = this.Expression [ pos ].ToString(); this.Type = NodeType.Operator; } // 関数「Func(項・・・)」のケース else if (IsFunction(this.Expression) == true) { // 関数名だけをExpressionとして保存する。本当は属性を何か持ちたい var functionName = ( new Regex(@"^"+functionMatcher) ).Match(this.Expression).ToString(); if (functionDictionary.ContainsKey(functionName) == false) { throw new Exception("サポートされていない関数名が指定されています("+functionName+")"); } else { // 一旦オペランド部を解析する var operandNode = new Node(Regex.Replace(Expression, @"^(" + functionMatcher +@")\((.+)\)$", "$2")); operandNode.Parse(); // 多項の引数の場合 if (operandNode.Expression == ",") { this.Left = operandNode.Left; this.Right = operandNode.Right; } // 1項の引数の場合 else { this.Left = operandNode; this.Right = null; } this.Expression = functionName; this.Type = NodeType.Function; } } // 式を含まないケース else { if((new Regex(@".*[^0-9].*")).IsMatch(this.Expression) ) { this.Type = NodeType.Item; }else{ this.Type = NodeType.Constant; } } return; }
/// <summary> /// 集合関数>累計 /// </summary> /// <param name="item"></param> /// <param name="dic"></param> /// <returns></returns> public static int sum(Node left, Dictionary<string, int>[] tbl) { return (from n in tbl select Node.Compute(left, n)).Sum(); }
public void parse_1項_1() { var node = new Node("2"); node.Parse(); Assert.True(node.Expression == "2"); Assert.True(node.Type == NodeType.Constant); return; }
/// <summary> /// 評価 /// </summary> /// <param name="node"></param> /// <param name="row">親テーブルの一行</param> /// <param name="tbl">テーブル</param> /// <returns></returns> public static int Compute(Node node, Dictionary<string, int> row = null, Dictionary<string, int> [] tbl = null) { var ans = 0; // 無効ノード if (node.Expression == null || node.Type == NodeType.None) { return ans; } #region 特殊ケース // 関数処理 if (node.Type == NodeType.Function) { if (node.Expression == "SUM") { return Node.sum(node.Left, tbl); } else if (node.Expression == "lt") { return Node.lt(node.Left, node.Right, row, tbl); } else if (node.Expression == "eq") { return Node.eq(node.Left, node.Right, row, tbl); } else if (node.Expression == "gt") { return Node.gt(node.Left, node.Right, row, tbl); } else if (node.Expression == "if") { var nodes = GetArgumentNodes(node); return Node.iif( nodes, row, tbl); } else if (node.Expression == "and") { var nodes = GetArgumentNodes(node); return Node.and( nodes, row, tbl); } else if (node.Expression == "or") { var nodes = GetArgumentNodes(node); return Node.or( nodes, row, tbl); } else { throw new Exception("この関数は実装されていません("+node.Expression+")"); } } // 行中のカラム指定 if (node.Type == NodeType.Item) { return row[node.Expression]; } #endregion // 左要素の評価 if (node.Left != null) { ans = Compute(node.Left, row); } // 演算子に応じて評価 if (node.Expression == "-") { ans -= Compute(node.Right, row); } else if (node.Expression == "+") { ans += Compute(node.Right, row); } else if (node.Expression == "/") { if (node.Right == null) { throw new Exception("除算ですが項が不足しています"); } ans /= Compute(node.Right, row); } else if (node.Expression == "*") { if (node.Right == null) { throw new Exception("乗算ですが項が不足しています"); } ans *= Compute(node.Right, row); } else { ans = int.Parse(node.Expression); } return ans; }