void CombineTerms(char[] operators) { foreach (EquationElement element in Stack) { if (element is Term) { ((Term)element).CombineTerms(operators); } } if (NeedSubTerms(operators) == false) { return; } int startIndex = 0; int startpoint = 0; while (startIndex < Stack.Count) { startIndex = FindOperator(startIndex, operators); if (startIndex < 0) { return; } Term newterm = new Term(); newterm.Parent = this; startIndex--; startpoint = startIndex; while (startIndex < Stack.Count) { EquationElement item = Stack[startIndex]; if (item is EquationValue) { newterm.Add(item); startIndex++; } if (item is Operator) { Operator op = item as Operator; if (op == null || operators.Contains(op.Value) == false) { Stack.RemoveRange(startpoint, newterm.Stack.Count); Stack.Insert(startpoint, newterm); break; } newterm.Add(item); startIndex++; } if (startIndex >= Stack.Count) { Stack.RemoveRange(startpoint, newterm.Stack.Count); Stack.Insert(startpoint, newterm); return; } } } }
static string GetVarName(string equation, int index, EquationElement root) { string varname = Term.ExtractName(equation, index).ToLower(); if (root != null && root.VarExist(varname)) { return(varname); } char ch = equation[index]; if (ch >= 'a' && ch <= 'z') { //return new string(new char[] { ch }); return(varname); } if (ch >= 'A' && ch <= 'Z') { // return new string(new char[] { ch }); return(varname); } if (ch == '_') { // return new string(new char[] { ch }); return(varname); } return(string.Empty); }
/// <summary> /// 최상위에서부터 차근차근 풀어감 /// 연산전 제곱과 나눔 곱셈을 구분해서 연산 순위를 정참. /// </summary> /// <param name="equation"></param> /// <param name="root"></param> public void Parse(string equation, EquationElement root) { Stack.Clear(); Parse(equation, 0, root); CombineTerms(new char[] { '^' }); CombineTopDown(); CombineTerms(new char[] { '*', '/' }); }
public void ClearVars() // 내부의 변수를 모두 초기화 { EquationElement root = Root; if (root.m_variables != null) { root.m_variables.Clear(); } }
public Variable(string src, int start, EquationElement root) { string varname = GetVarName(src, start, root); if (varname.Length > 0) { m_sb.Append(varname); } }
/// <summary> /// 변수를 설정함 /// </summary> /// <param name="varname"></param> /// <param name="value"></param> public void SetVar(string varname, double value) { EquationElement root = Root; if (root.m_variables == null) { root.m_variables = new Dictionary <string, double>(); } root.m_variables[varname.ToLower()] = value; }
/// <summary> /// 모든 변수를 얻어옴 /// </summary> /// <returns></returns> public string[] GetVars() { EquationElement root = Root; if (m_variables == null) { return(new string[0]); } List <string> I = new List <string>(m_variables.Keys); I.Sort(); return(I.ToArray()); }
EquationElement Add(EquationElement item) { item.Parent = this; if (item is EquationValue) { // 변수와 변수 사이에 *를 삽입 if (LastElement is EquationValue) { Stack.Add(new Operator('*')); } if (PopSignOperator() != null) { ((EquationValue)item).Signed = true; } Stack.Add(item); return(item); } if (item is Operator) { // 괄호앞에 - 이외엔 쓸수 없음. if (((Operator)item).CanStartTerm == false && Stack.Count == 0) { throw new ParseException(string.Empty, 0, "- 기호 이외엔 괄호앞에 사용 할 수 없습니다."); } // -(-) 일 경우도 생각 Operator op = LastElement as Operator; if (op != null && ((Operator)item).IsSign == false) { throw new ParseException(Root.ToString(), 0, "연속된 연산자는 유효하지 않습니다."); } if (OperatorCount >= 2) { throw new ParseException(Root.ToString(), 0, "연속된 연산자는 유효하지 않습니다."); } Stack.Add(item); return(item); } if (item is CompareOperator) { Stack.Add(item); return(item); } return(null); }
void CombineTopDown() { // ^연산자의 경우 가장 먼저 처리. // 2^3^4 일 경우엔 2^(3^4) right -> left(top->down) 형태로 처리 char operatorCh = '^'; foreach (EquationElement element in Stack) { if (element is Term) { ((Term)element).CombineTopDown(); } } int index = Stack.Count - 1; while (index > 0) { Operator op = Stack[index] as Operator; index--; if (op == null || op.Value != operatorCh) { continue; } EquationElement left = Stack[index]; EquationElement right = Stack[index + 2]; Term newterm = new Term(); newterm.Parent = this; newterm.Add(left); newterm.Add(op); newterm.Add(right); // move signed to outer term if (((EquationValue)left).Signed) { ((EquationValue)left).Signed = false; newterm.Signed = true; } Stack.RemoveRange(index, newterm.Stack.Count); Stack.Insert(index, newterm); } }
/// <summary> /// 변수를 얻어옴 /// </summary> /// <param name="varname"></param> /// <returns></returns> public double GetVar(string varname) { EquationElement root = Root; double result = 0; if (root.m_variables == null || root.m_variables.TryGetValue(varname.ToLower(), out result) == false) { throw new ParseException(this.ToString(), 0, string.Format("변수 {0}가 정의되지 않았습니다.", varname)); } if (m_usedVars == null) { m_usedVars = new Dictionary <string, bool>(); } if (m_usedVars.ContainsKey(varname) == false) { m_usedVars[varname] = true; } return(result); }
/// <summary> /// 해당 변수명을 찾아서 지움 /// </summary> /// <param name="varname">변수명</param> /// <returns>변수지우는데 성공을 하면 True 실패시 false</returns> public bool removeVar(string varname) // { EquationElement root = Root; if (root != null) { if (root.m_variables == null) { root.m_variables = new Dictionary <string, double>(); return(false); } if (root.m_variables.ContainsKey(varname)) { root.m_variables.Remove(varname); return(true); } } return(false); }
public Function(string src, int start, EquationElement root) { m_startIndex = start; m_func = Term.ExtractName(src, start).ToLower(); start += m_func.Length; // space는 무시, 다음문자는 무조건 괄호가 와야함. while (src[start] == ' ') { start++; } if (src[start] != '(') { throw new ParseException(src, m_startIndex, "함수는 무조건 () 로 실행해야 합니다.'"); } int termstart = start; int end = Term.FindMatchingEnd('(', src, termstart); if (end < termstart) { throw new ParseException(src, m_startIndex, "함수 매칭 실패"); } m_endindex = end; string allterms = src.Substring(termstart + 1, end - termstart - 1); //string[] terms = allterms.Split(','); string[] terms = GetTerms(allterms); m_terms = new List <Term>(); foreach (string term in terms) { Term newterm = new Term(); newterm.Parse(term, root); newterm.Parent = this; m_terms.Add(newterm); } }
/// <summary> /// 파싱함수 /// </summary> /// <param name="equation"></param> /// <param name="index"></param> /// <param name="root"></param> /// <returns></returns> int Parse(string equation, int index, EquationElement root) { while (index < equation.Length) { char ch = equation[index]; if (char.IsWhiteSpace(ch)) // 공백무시 { index++; continue; } if (Operator.IsValidOperator(ch)) // 각 클래스에 정의된 Valid옵션을 토대로 Parse { EquationElement n = Add(new Operator(equation, index)); // Add에서 해당 Element의 길이를 구해서 스택에 저장. index += n.Length; //인덱스를 n의 길이만큼 늘려서 계속 검색 continue; } if (Number.IsValidDigit(equation, index)) { EquationElement n = Add(new Number(equation, index)); index += n.Length; continue; } if (Constant.IsValidDigit(equation, index)) { EquationElement n = Add(new Constant(equation, index)); index += n.Length; continue; } if (Function.IsValidDigit(equation, index)) { EquationElement n = Add(new Function(equation, index, root)); index += n.Length; continue; } if (CompareOperator.IsValidOperator(equation)) { EquationElement n = Add(new CompareOperator(equation)); index += n.Length; continue; } if (Variable.IsValidDigit(equation, index, root)) { EquationElement n = Add(new Variable(equation, index, root)); index += n.Length; continue; } index++; if (Term.IsValidDigit(ch)) // 괄호가 또나오면 그 괄호를 풀어야됨. { int endindex = FindMatchingEnd(ch, equation, index - 1); if (endindex > index) { int len = endindex - index; string s = equation.Substring(index, len); Term g = Add(new Term(s, 0)) as Term; len = g.Parse(s, 0, root) + 1; index += len; continue; } throw new ParseException(equation, index - 1, "매칭되는 괄호를 찾을 수 없습니다."); } else { if (ch == ']' || ch == ')') { throw new ParseException(equation, index - 1, " 매칭되는 괄호를 찾을 수 없습니다"); } } } return(index); }
/// <summary> /// 해당 변수가 존재하는가 /// </summary> /// <param name="varname"></param> /// <returns></returns> public bool VarExist(string varname) { EquationElement root = Root; return(root.m_variables != null && root.m_variables.ContainsKey(varname.ToLower())); }
public bool IsValid(string equation, int index, EquationElement root) { return(GetVarName(equation, index, root).Length > 0); }