static void BuildTree(Function f, Node Parent) { LexerState state; //今の部分木のRootになる要素を見つける。何が見つかったかはstateに格納されている。 var Key = SearchRoot(f, out state); if (Key == null) { throw new Exception("式の解析を中断します。"); } switch (state) //stateに対応するNodeを生成し、parentと関連付ける。 { case LexerState.Constant: ConstantNode constantNode = new ConstantNode(double.Parse(Key[0]), Parent); if (Parent != null) { Parent.Children.Add(constantNode); } // Console.WriteLine("CONSTATNT:" + Key[0]); break; case LexerState.Number: NumberNode numberNode = new NumberNode(double.Parse(Key[0]), Parent); if (Parent != null) { Parent.Children.Add(numberNode); } // Console.WriteLine("NUMBER:" + Key[0]); break; case LexerState.Parameter: ParameterNode parameterNode = new ParameterNode(Key[0], Parent); if (Parent != null) { Parent.Children.Add(parameterNode); } // Console.WriteLine("PARAMTER:" + Key[0]); break; case LexerState.Counter: CounterNode CounterNode = new CounterNode(Key[0], Parent); if (Parent != null) { Parent.Children.Add(CounterNode); } // Console.WriteLine("COUNTER:" + Key[0]); break; case LexerState.BinaryExpression: //左辺 演算子 右辺の順で格納されているはず。 BinaryNode binaryNode = new BinaryNode(Key[1], Parent); if (Parent != null) { Parent.Children.Add(binaryNode); } //Key[i]をBodyとするFunctionオブジェクトを生成(コピーコンストラクタ) BuildTree(new Function(f, Key[0]), binaryNode); BuildTree(new Function(f, Key[2]), binaryNode); // Console.WriteLine("BINARY:" + Key[0] + " " + Key[1] + " " + Key[2]); break; case LexerState.Expression: ExpressionNode expressionNode = new ExpressionNode(Parent); if (Parent != null) { Parent.Children.Add(expressionNode); } BuildTree(new Function(f, Key[0]), expressionNode); // Console.WriteLine("Expression:" + Key[0]); break; case LexerState.Function: FunctionNode functionNode = new FunctionNode(Key[0], Parent); if (Parent != null) { Parent.Children.Add(functionNode); } foreach (var item in Key.Skip(1)) { //子ノードになる引数についてParseを進める。(Key[0]は関数名なのでSkip) //Key[i]をBodyとするFunctionオブジェクトを生成(コピーコンストラクタ) BuildTree(new Function(f, item), functionNode); } #region for DEBUG /* * string message = "FUNCTION:"; * foreach (var item in Key) { * message += item; * if (item != Key.Last()) message += ","; * } * Console.WriteLine(message); */ #endregion break; case LexerState.SigmaExpression: FunctionNode SumfunctionNode = new FunctionNode(Key[0], Parent); if (Parent != null) { Parent.Children.Add(SumfunctionNode); } foreach (var item in Key.Skip(1)) { //子ノードになる引数についてParseを進める。(Key[0]は関数名なのでSkip) //Key[i]をBodyとするFunctionオブジェクトを生成(コピーコンストラクタ) BuildTree(new Function(f, item), SumfunctionNode); } break; case LexerState.PiExpression: FunctionNode PifunctionNode = new FunctionNode(Key[0], Parent); if (Parent != null) { Parent.Children.Add(PifunctionNode); } foreach (var item in Key.Skip(1)) { //子ノードになる引数についてParseを進める。(Key[0]は関数名なのでSkip) //Key[i]をBodyとするFunctionオブジェクトを生成(コピーコンストラクタ) BuildTree(new Function(f, item), PifunctionNode); } break; case LexerState.Undefined: throw new Exception("解釈できない要素が見つかりました。"); case LexerState.Root: break; } }
/// <summary> /// 式を要素に分割する。 /// 例:左辺、演算子、右辺 /// 例;関数名前、引数、引数、引数・・・・ /// 再帰的に潜っていく。 /// どんな式を発見したのかをLexerStateで知らせる。 /// /// </summary> /// <example> (10*5+x)+(45/5) => <10*5+x> <+> <45/5> </example> /// <param name="input"></param> /// <returns></returns> static string[] SearchRoot(Function function, out LexerState state) { string input = function.Body; string[] Elements; try { //括弧の外に入っている+と-を探す。 Elements = SearchPlusMinus(input); if (Elements != null) { state = LexerState.BinaryExpression; return(Elements); } //全部が掛け算割り算でできている。 Elements = SearchMulDiv(input); if (Elements != null) { state = LexerState.BinaryExpression; return(Elements); } //全部が冪算だけである。 Elements = SearchPow(input); if (Elements != null) { state = LexerState.BinaryExpression; return(Elements); } //ノードが1つだけあるような状態。 //考えられる状態としては、「実数が1つ」「定数が1つ」「変数が1つ」「関数呼び出しが1つ」「括弧式が1つ」 Elements = SearchNumber(input); if (Elements != null) { state = LexerState.Number; return(Elements); } Elements = SearchConstant(input, function.Constants); if (Elements != null) { state = LexerState.Constant; return(Elements); } Elements = SearchParameter(input, function.Parameters.ToArray()); if (Elements != null) { state = LexerState.Parameter; return(Elements); } Elements = SearchCounter(input, function.Counters.ToArray()); if (Elements != null) { state = LexerState.Counter; return(Elements); } Elements = SearchFunctionCall(input, function.Constants, function.Parameters.ToArray(), function.Counters.ToArray()); if (Elements != null) { switch (Elements[0]) //特別な処理を要する関数があるので。 { case "Sum": state = LexerState.SigmaExpression; return(Elements); case "Pi": state = LexerState.PiExpression; return(Elements); default: state = LexerState.Function; return(Elements); } } Elements = SearchParenthesis(input); if (Elements != null) { state = LexerState.Expression; return(Elements); } state = LexerState.Undefined; throw new ExpressionLexerException("解釈不能な式です。" + input); } catch (Exception e) { state = LexerState.Undefined; Console.WriteLine(e.Message); return(null); } }