Ejemplo n.º 1
0
        /// <summary>
        /// 逆ポーランド記法表現の文字列から、数式ツリーを復元する。
        /// ただし、演算子品詞のparenthesisDepthは正しく設定されないので注意。
        /// (逆ポーランド記法表現では再現不能。)
        /// </summary>
        /// <param name="rPolish">逆ポーランド記法表現</param>
        /// <returns>復元した数式ツリー。</returns>
        public static MathTree analyzeRPolish(string rPolish)
        {
            string[] separatingStrings = { DIVIDE_CHAR_R_POLISH };
            string[] lexicalStrList    = rPolish.Split(separatingStrings, StringSplitOptions.RemoveEmptyEntries);
            var      tree  = new MathTree();
            var      queue = new Queue <MathTreeNode>();

            foreach (string lexicalStr in lexicalStrList)
            {
                Lexical lexical = LexicalFactory.createFromRPolish(lexicalStr);
                if (lexical is Literal)
                {
                    var node = new MathTreeNode();
                    node.lex    = lexical;
                    node.master = tree;
                    queue.Enqueue(node);
                }
                else if (lexical is UnaryOperator)
                {
                    MathTreeNode operand = queue.Dequeue();
                    var          node    = new MathTreeNode();
                    node.lex    = lexical;
                    node.master = tree;
                    node.right  = operand;
                    queue.Enqueue(node);
                }
                else if (lexical is BinaryOperator)
                {
                    if (queue.Count < 2)
                    {
                        throw new ArgumentException("2つのリテラルを接続していない2項演算子があります。");
                    }
                    MathTreeNode rightOperand = queue.Dequeue();
                    MathTreeNode leftOperand  = queue.Dequeue();
                    var          node         = new MathTreeNode();
                    node.lex    = lexical;
                    node.master = tree;
                    node.left   = leftOperand;
                    node.right  = rightOperand;
                    queue.Enqueue(node);
                }
                else
                {
                    throw new ArgumentException("評価できない品詞が存在します。対象文字列:" + lexicalStr);
                }
            }
            if (queue.Count != 1)
            {
                throw new ArgumentException("最終評価が複数のリテラルとなります。");
            }
            tree.root = queue.Dequeue();
            return(tree);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 数式ツリーのノードの逆ポーランド記法表現を取得する。
        /// </summary>
        /// <param name="node">数式ツリーのノード。</param>
        /// <returns>数式ツリーのノードの逆ポーランド記法表現の文字列。</returns>
        private static string createRPolishNode(MathTreeNode node)
        {
            string rPolish = "";

            if (node.left != null)
            {
                rPolish += createRPolishNode(node.left);
            }
            else if (node.right != null)
            {
                rPolish += createRPolishNode(node.right);
            }
            rPolish += node.lex.getRPolish() + DIVIDE_CHAR_R_POLISH;
            return(rPolish);
        }
Ejemplo n.º 3
0
 private static MathTreeNodeValue evalNode(MathTreeNode node, Dictionary <string, Variable> variableMap, Dictionary <string, Function> functionMap)
 {
     if (node.lex is Literal literal)
     {
         return(literal.eval(variableMap));
     }
     else if (node.lex is UnaryOperator unaryOperator)
     {
         MathTreeNodeValue operand = evalNode(node.right, variableMap, functionMap);
         return(unaryOperator.eval(operand, functionMap));
     }
     else if (node.lex is BinaryOperator binaryOperator)
     {
         MathTreeNodeValue leftOperand  = evalNode(node.left, variableMap, functionMap);
         MathTreeNodeValue rightOperand = evalNode(node.right, variableMap, functionMap);
         return(binaryOperator.eval(leftOperand, rightOperand));
     }
     else
     {
         throw new ApplicationException("リテラル、単項演算子、2項演算子以外の品詞が指定されました。");
     }
 }
Ejemplo n.º 4
0
 /// <summary>
 /// 数式ツリーの1ノードのデータ型を取得する。
 /// </summary>
 /// <param name="node">数式ツリー中のノード。</param>
 /// <param name="variableDataTypeMap">変数のデータ型の連想配列。</param>
 /// <param name="functionDataTypeMap">関数の戻り値のデータ型の連想配列。</param>
 /// <returns>この数式ツリーのノードが返す評価値のデータ型を返却します。
 /// 文法エラーの場合、Noneが返却されます。</returns>
 private static DataType checkNodeDataType(MathTreeNode node, Dictionary <string, DataType> variableDataTypeMap,
                                           Dictionary <string, DataType> functionDataTypeMap)
 {
     if (node.lex is Literal literal)
     {
         return(literal.getDataType(variableDataTypeMap));
     }
     else if (node.lex is UnaryOperator unaryOperator)
     {
         DataType operandDataType = checkNodeDataType(node.right, variableDataTypeMap, functionDataTypeMap);
         return(unaryOperator.getDataType(operandDataType, functionDataTypeMap));
     }
     else if (node.lex is BinaryOperator binaryOperator)
     {
         DataType leftOperandDataType  = checkNodeDataType(node.left, variableDataTypeMap, functionDataTypeMap);
         DataType rightOperandDataType = checkNodeDataType(node.right, variableDataTypeMap, functionDataTypeMap);
         return(binaryOperator.getDataType(leftOperandDataType, rightOperandDataType));
     }
     else
     {
         throw new ApplicationException("リテラル、単項演算子、2項演算子以外の品詞が指定されました。");
     }
 }
Ejemplo n.º 5
0
        /// <summary>
        /// 品詞のリストを解析し、数式ツリーの1ノードを作成する。
        /// </summary>
        /// <param name="lexicalList">品詞のリスト。</param>
        /// <param name="master">数式ツリーのマスター。</param>
        /// <returns>数式ツリーのノード。</returns>
        private static MathTreeNode makeMathTreeNode(List <Lexical> lexicalList, ref MathTree master)
        {
            if (lexicalList.Count == 0)
            {
                throw new ApplicationException("無効な式が指定されました。");
            }
            var node = new MathTreeNode();

            node.master = master;
            if (lexicalList.Count == 1)
            {
                Lexical lex = lexicalList[0];
                if (!(lex is Literal))
                {
                    throw new ArgumentException("最終評価が演算子となる品詞が存在します。");
                }
                node.lex = lex;
                return(node);
            }
            else
            {
                int operatorIndex = leastPrioritizedRightOperatorIndex(lexicalList);
                if (operatorIndex == -1) // 2つ以上項があるのに、演算子が見つからない場合
                {
                    throw new ArgumentException("複数のリテラルからなる式が評価されました。");
                }
                Operator op = (Operator)lexicalList[operatorIndex];
                var      leftLexicalList = new List <Lexical>();
                for (int i = 0; i < operatorIndex; i++)
                {
                    leftLexicalList.Add(lexicalList[i]);
                }
                var rightLexicalList = new List <Lexical>();
                for (int i = operatorIndex + 1; i < lexicalList.Count; i++)
                {
                    rightLexicalList.Add(lexicalList[i]);
                }
                if (op is UnaryOperator)
                {
                    if (leftLexicalList.Count != 0)
                    {
                        throw new ArgumentException("単項演算子の左側にオペランドを持つことはできません。");
                    }
                    else if (rightLexicalList.Count == 0)
                    {
                        throw new ArgumentException("単項演算子の右側にオペランドが存在しません。");
                    }
                    node.lex   = op;
                    node.left  = null;
                    node.right = makeMathTreeNode(rightLexicalList, ref master);
                    return(node);
                }
                else if (op is BinaryOperator)
                {
                    if (leftLexicalList.Count == 0)
                    {
                        throw new ArgumentException("2項演算子の左側にオペランドが存在しません。");
                    }
                    else if (rightLexicalList.Count == 0)
                    {
                        throw new ArgumentException("2項演算子の右側にオペランドが存在しません。");
                    }
                    node.lex   = op;
                    node.left  = makeMathTreeNode(leftLexicalList, ref master);
                    node.right = makeMathTreeNode(rightLexicalList, ref master);
                    return(node);
                }
                else
                {
                    throw new ApplicationException("単項演算子、2項演算子以外の品詞が、演算子として評価されました。");
                }
            }
        }