/** * * @author seagle * @date 2024-7-10 * @Description 表达式计算 */ using MECF.Framework.UI.Core.DxfScript; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; namespace MECF.Framework.UI.Core.DxfScript { public partial class Express { public ExpressNode Root { get; set; } private Dictionary Variables = new Dictionary(); public Express() { Root = null; } private void Trace(string s) { string a = s; } public ExpressNode AddChild(ExpressNode curr, ExpressNode node) { if (curr == null) { if (Root != null ) { throw new Exception("Add tree child error:try to add the fist node,but root is not null"); } else { Root = node; return Root; } } if (curr.FirstChild == null) { //maintain father-child realtionship curr.FirstChild = node; curr.LastChild = node; node.Father = curr; } else { //maintain brothers realtionship curr.LastChild.NextBrother = node; node.PrevBrother = curr.LastChild; //maintain father-child realtionship curr.LastChild = node; node.Father = curr; } return node; } public ExpressNode AddFather(ExpressNode curr, ExpressNode node) { if (curr == null) { throw new Exception("It's invalid to add father to a null node"); } if (curr.Father == null) { if (curr != Root) { throw new Exception("Try to add father and be root,but current node is not root"); } //maintain father-child realtionship curr.Father = node; node.FirstChild = curr; node.LastChild = curr; Root = node; } else { //take over curr's brothers relationship if (curr.PrevBrother != null) { node.PrevBrother = curr.PrevBrother; curr.PrevBrother.NextBrother = node; } curr.PrevBrother = null; if (curr.NextBrother != null) { node.NextBrother = curr.NextBrother; curr.NextBrother.PrevBrother = node; } curr.NextBrother = null; //take over curr's father relationship node.Father = curr.Father; if (node.Father.FirstChild == curr) { node.Father.FirstChild = node; } if (node.Father.LastChild == curr) { node.Father.LastChild = node; } //maintain curr's child realtionship node.FirstChild = curr; node.LastChild = curr; curr.Father = node; } return node; } public void Create(StringReader reader) { CreateMain(reader); ComputeNode(Root, true); } public Variable GetTopVariable() { return Root.Var; } public Variable Compute() { ComputeNode(Root); return Root.Var ; } public void ComputeNode(ExpressNode curr,bool OnlyCheckDataType = false) { if (curr == null) { return ; } if (curr.NodeType == KeywordType.KW_VARIABLE || curr.NodeType == KeywordType.KW_CONST_TRUE || curr.NodeType == KeywordType.KW_CONST_FALSE || curr.NodeType == KeywordType.KW_CONST_INTEGER || curr.NodeType == KeywordType.KW_CONST_DECIMAL || curr.NodeType == KeywordType.KW_CONST_STRING) { //变量或常量 if (curr.Var.IsNone && !OnlyCheckDataType) { throw new Exception("Computing varialbe:" + curr.Var.Name + " is none"); } else { return; } } else if (curr.NodeType == KeywordType.KW_OPERATOR_NEGATIVE) { //单目运算符- if (curr.FirstChild == null) { throw new Exception("Negtive operator error:No data"); } ComputeNode(curr.FirstChild, OnlyCheckDataType); curr.Var.CopyFrom(curr.FirstChild.Var, OnlyCheckDataType); curr.Var.Nigtive(OnlyCheckDataType); return; } else if (curr.NodeType == KeywordType.KW_OPERATOR_NOT) { if (curr.FirstChild == null) { throw new Exception("Not operator error:No data"); } ComputeNode(curr.FirstChild, OnlyCheckDataType); curr.Var.CopyFrom(curr.FirstChild.Var, OnlyCheckDataType); curr.Var.Not(OnlyCheckDataType); return; } else if (curr.NodeType == KeywordType.KW_OPERATOR_BIT_NOT) { throw new Exception("BitNot operator not implemented"); if (curr.FirstChild == null) { throw new Exception("BitNot operator error:No data"); } ComputeNode(curr.FirstChild, OnlyCheckDataType); curr.Var.CopyFrom(curr.FirstChild.Var, OnlyCheckDataType); //curr.Var.BitNot(OnlyCheckDataType); } else if (curr.NodeType == KeywordType.KW_OPERATOR_PLUS) { //双目运算符+(多目) if (curr.FirstChild == null) { throw new Exception("Plus operator error:No data"); } ComputeNode(curr.FirstChild, OnlyCheckDataType); curr.Var.CopyFrom(curr.FirstChild.Var, OnlyCheckDataType); ExpressNode child = curr.FirstChild.NextBrother; if (child == null) { throw new Exception("Plus operator error:No second data"); } while (child != null) { ComputeNode(child, OnlyCheckDataType); curr.Var.Plus(child.Var, OnlyCheckDataType); child = child.NextBrother; } return ; } else if (curr.NodeType == KeywordType.KW_OPERATOR_MINUS) { //双目运算符- if (curr.FirstChild == null) { throw new Exception("Minus operator error:No data"); } ComputeNode(curr.FirstChild, OnlyCheckDataType); curr.Var.CopyFrom(curr.FirstChild.Var, OnlyCheckDataType); ExpressNode child = curr.FirstChild.NextBrother; if (child == null) { throw new Exception("Minus otperator error:No second data"); } ComputeNode(child, OnlyCheckDataType); curr.Var.Minus(child.Var, OnlyCheckDataType); return ; } else if (curr.NodeType == KeywordType.KW_OPERATOR_MULTIPLE) { //双目运算符*(多目) if (curr.FirstChild == null) { throw new Exception("Multiple operator error:No data"); } ComputeNode(curr.FirstChild, OnlyCheckDataType); curr.Var.CopyFrom(curr.FirstChild.Var, OnlyCheckDataType); ExpressNode child = curr.FirstChild.NextBrother; if (child == null) { throw new Exception("Multiple operator error:No second data"); } while (child != null) { ComputeNode(child, OnlyCheckDataType); curr.Var.Multiple(child.Var, OnlyCheckDataType); child = child.NextBrother; } return ; } else if (curr.NodeType == KeywordType.KW_OPERATOR_DEVIDE) { //双目运算符/ if (curr.FirstChild == null) { throw new Exception("Multiple operator error:No data"); } ComputeNode(curr.FirstChild, OnlyCheckDataType); curr.Var.CopyFrom(curr.FirstChild.Var, OnlyCheckDataType); ExpressNode child = curr.FirstChild.NextBrother; if (child == null) { throw new Exception("Devide operator error:No second data"); } ComputeNode(child, OnlyCheckDataType); curr.Var.Devide(child.Var, OnlyCheckDataType); return ; } else if (curr.NodeType == KeywordType.KW_OPERATOR_EQUAL) { //双目运算符== if (curr.FirstChild == null) { throw new Exception("Equal operator error:No data"); } ComputeNode(curr.FirstChild, OnlyCheckDataType); curr.Var.CopyFrom(curr.FirstChild.Var, OnlyCheckDataType); ExpressNode child = curr.FirstChild.NextBrother; if (child == null) { throw new Exception("Equal operator error:No second data"); ; } ComputeNode(child, OnlyCheckDataType); curr.Var.Equal(child.Var, OnlyCheckDataType); return ; } else if (curr.NodeType == KeywordType.KW_OPERATOR_NOT_EQUAL) { //双目运算符!= if (curr.FirstChild == null) { throw new Exception("NotEqual operator error:No data"); } ComputeNode(curr.FirstChild, OnlyCheckDataType); curr.Var.CopyFrom(curr.FirstChild.Var, OnlyCheckDataType); ExpressNode child = curr.FirstChild.NextBrother; if (child == null) { throw new Exception("NotEqual operator error:No second data"); } ComputeNode(child, OnlyCheckDataType); curr.Var.NotEqual(child.Var, OnlyCheckDataType); return ; } else if (curr.NodeType == KeywordType.KW_OPERATOR_GT) { //双目运算符> if (curr.FirstChild == null) { throw new Exception("Gt operator error:No data"); } ComputeNode(curr.FirstChild, OnlyCheckDataType); curr.Var.CopyFrom(curr.FirstChild.Var, OnlyCheckDataType); ExpressNode child = curr.FirstChild.NextBrother; if (child == null) { throw new Exception("Gt operator error:No second data"); } ComputeNode(child, OnlyCheckDataType); curr.Var.Gt(child.Var, OnlyCheckDataType); return ; } else if (curr.NodeType == KeywordType.KW_OPERATOR_GE) { //双目运算符>= if (curr.FirstChild == null) { throw new Exception("Ge operator error:No data"); ; } ComputeNode(curr.FirstChild, OnlyCheckDataType); curr.Var.CopyFrom(curr.FirstChild.Var, OnlyCheckDataType); ExpressNode child = curr.FirstChild.NextBrother; if (child == null) { throw new Exception("Ge operator error:No second data"); } ComputeNode(child, OnlyCheckDataType); curr.Var.Ge(child.Var, OnlyCheckDataType); return ; } else if (curr.NodeType == KeywordType.KW_OPERATOR_LT) { //双目运算符< if (curr.FirstChild == null) { throw new Exception("Lt operator error:No data"); } ComputeNode(curr.FirstChild, OnlyCheckDataType); curr.Var.CopyFrom(curr.FirstChild.Var, OnlyCheckDataType); ExpressNode child = curr.FirstChild.NextBrother; if (child == null) { throw new Exception("Lt operator error:No second data"); } ComputeNode(child, OnlyCheckDataType); curr.Var.Lt(child.Var, OnlyCheckDataType); return ; } else if (curr.NodeType == KeywordType.KW_OPERATOR_LE) { //双目运算符<= if (curr.FirstChild == null) { throw new Exception("Le operator error:No data"); } ComputeNode(curr.FirstChild, OnlyCheckDataType); curr.Var.CopyFrom(curr.FirstChild.Var, OnlyCheckDataType); ExpressNode child = curr.FirstChild.NextBrother; if (child == null) { throw new Exception("Le operator error:No second data"); } ComputeNode(child, OnlyCheckDataType); curr.Var.Le(child.Var, OnlyCheckDataType); return ; } else if (curr.NodeType == KeywordType.KW_OPERATOR_AND) { //双目运算符&& if (curr.FirstChild == null) { throw new Exception("And operator error:No data"); } ComputeNode(curr.FirstChild, OnlyCheckDataType); curr.Var.CopyFrom(curr.FirstChild.Var, OnlyCheckDataType); ExpressNode child = curr.FirstChild.NextBrother; if (child == null) { throw new Exception("And operator error:No second data"); } while (child != null) { ComputeNode(child, OnlyCheckDataType); curr.Var.And(child.Var, OnlyCheckDataType); child = child.NextBrother; } return ; } else if (curr.NodeType == KeywordType.KW_OPERATOR_OR) { //双目运算符|| if (curr.FirstChild == null) { throw new Exception("Or operator error:No data"); } ComputeNode(curr.FirstChild, OnlyCheckDataType); curr.Var.CopyFrom(curr.FirstChild.Var, OnlyCheckDataType); ExpressNode child = curr.FirstChild.NextBrother; if (child == null) { throw new Exception("Or operator error:No second data"); } while (child != null) { ComputeNode(child, OnlyCheckDataType); curr.Var.Or(child.Var, OnlyCheckDataType); child = child.NextBrother; } return ; } else if (curr.NodeType == KeywordType.KW_OPERATOR_BIT_OR) { //双目运算符| throw new Exception("BitOr operator error:Not support"); } else if (curr.NodeType == KeywordType.KW_OPERATOR_BIT_AND) { //双目运算符& throw new Exception("BitAnd operator error:Not support"); } else if (curr.NodeType == KeywordType.KW_OPERATOR_MOVE_LEFT) { //双目运算符<< throw new Exception("Move left operator error:Not support"); } else if (curr.NodeType == KeywordType.KW_OPERATOR_MOVE_RIGHT) { //双目运算符>> throw new Exception("Move right operator error:Not support"); } else if (curr.NodeType == KeywordType.KW_ROUND_LEFT) { //左小括号 if (curr.FirstChild == null) { throw new Exception("Move operator error:No data"); } if (!curr.Closed) { throw new Exception("() not matched"); } ComputeNode(curr.FirstChild, OnlyCheckDataType); curr.Var.CopyFrom(curr.FirstChild.Var, OnlyCheckDataType); return ; } else if (curr.NodeType == KeywordType.KW_FUNCTION) { //函数 if (!curr.Closed) { throw new Exception("() not matched"); } UserFunction function = curr.UserFunc; function(curr, OnlyCheckDataType); return; } else { throw new Exception("Undefined operator:"+ curr.NodeType); } } private void CreateMain(StringReader reader) { ExpressNode curr = Root; KeywordType kw; while ((kw = reader.Next()) != KeywordType.KW_EOF && kw != KeywordType.KW_SEP) { Trace("kw="+kw+","+reader.Data()); if (kw == KeywordType.KW_CONST_INTEGER || kw == KeywordType.KW_CONST_DECIMAL || kw == KeywordType.KW_CONST_TRUE || kw == KeywordType.KW_CONST_FALSE || kw == KeywordType.KW_CONST_STRING) { Variable var; if (kw == KeywordType.KW_CONST_INTEGER) { var = new Variable(null, VariableDataType.DOUBLE); var.DoubleValue=(int.Parse(reader.Data())); } else if (kw == KeywordType.KW_CONST_DECIMAL) { var = new Variable(null, VariableDataType.DOUBLE); var.DoubleValue =(double.Parse(reader.Data())); } else if (kw == KeywordType.KW_CONST_TRUE) { var = new Variable(null, VariableDataType.BOOL); var.BoolValue=true; } else if (kw == KeywordType.KW_CONST_FALSE) { var = new Variable(null, VariableDataType.BOOL); var.BoolValue= false; } else { var = new Variable(null, VariableDataType.STRING); var.StringValue=reader.Data(); } ExpressNode expressNode = new ExpressNode(var, null, KeywordType.KW_VARIABLE); if (curr == null) { curr = AddChild(curr, expressNode); } else { if (curr.NodeType == KeywordType.KW_VARIABLE || curr.Closed) { throw new Exception("Syntax error:Expected operator but const found in line:"+ reader.__line__); } curr = AddChild(curr, expressNode); } } else if (kw == KeywordType.KW_VARIABLE) { string varName = reader.Data(); Variable var = null; if (Variables.ContainsKey(varName)) { var = Variables[varName]; } else { VariableDataType varType = ScriptVariables.GetVariableDataTypeByName(varName); var = new Variable(varName, varType); Variables.Add(varName, var); } ExpressNode expressNode = new ExpressNode(var, null, KeywordType.KW_VARIABLE); if (curr == null) { curr = AddChild(curr, expressNode); } else { if (curr.NodeType == KeywordType.KW_VARIABLE || curr.Closed) { throw new Exception("Syntax error:Expected operator but variable found:"+ reader.__line__); } curr = AddChild(curr, expressNode); } } else if (kw == KeywordType.KW_ROUND_LEFT) { Variable var = new Variable(null, VariableDataType.DOUBLE); ExpressNode expressNode = new ExpressNode(var, null, KeywordType.KW_ROUND_LEFT); if (curr == null) { curr = AddChild(curr, expressNode); } else { if (curr.NodeType == KeywordType.KW_VARIABLE || curr.Closed) { throw new Exception("Syntax error:Expected operator but '(' found:"+ reader.__line__); } curr = AddChild(curr, expressNode); } } else if (kw == KeywordType.KW_FUNCTION) { string funName = reader.Data(); UserFunction function = GetFunAddr(funName); KeywordType kw2 = reader.Next(); if (kw2 != KeywordType.KW_ROUND_LEFT) { throw new Exception("Syntax error:Expected '(' :"+ reader.__line__); } //g_log.info("funName=%s,addr=%d",funName,function); Variable var = new Variable(null, VariableDataType.DOUBLE); ExpressNode expressNode = new ExpressNode(var, function, KeywordType.KW_FUNCTION); if (curr == null) { curr = AddChild(curr, expressNode); } else { if (curr.NodeType == KeywordType.KW_VARIABLE || curr.Closed) { throw new Exception("Syntax error:Expected operator but function found:"+reader.__line__); } curr = AddChild(curr, expressNode); } } else if (kw == KeywordType.KW_ROUND_RIGHT) { while (curr != null) { if ((curr.NodeType == KeywordType.KW_FUNCTION || curr.NodeType == KeywordType.KW_ROUND_LEFT) && !curr.Closed) { break; } curr = curr.Father; } if (curr == null) { reader.rollback(KeywordType.KW_ROUND_RIGHT); return; } curr.Closed = true; } else if (kw == KeywordType.KW_OPERATOR_NEGATIVE || kw == KeywordType.KW_OPERATOR_NOT || kw == KeywordType.KW_OPERATOR_BIT_NOT) { //single data operator Variable var = new Variable(null, VariableDataType.DOUBLE); ExpressNode expressNode = new ExpressNode(var, null, kw); if (curr == null) { curr = AddChild(curr, expressNode); } else { if (curr.NodeType == KeywordType.KW_VARIABLE || curr.Closed) { throw new Exception("Syntax error:Unexpected variable found:"+reader.__line__); } curr = AddChild(curr, expressNode); } } else if (kw == KeywordType.KW_OPERATOR_PLUS || kw == KeywordType.KW_OPERATOR_MINUS || kw == KeywordType.KW_OPERATOR_MULTIPLE || kw == KeywordType.KW_OPERATOR_DEVIDE || kw == KeywordType.KW_OPERATOR_AND || kw == KeywordType.KW_OPERATOR_BIT_AND || kw == KeywordType.KW_OPERATOR_OR || kw == KeywordType.KW_OPERATOR_BIT_OR || kw == KeywordType.KW_OPERATOR_GT || kw == KeywordType.KW_OPERATOR_GE || kw == KeywordType.KW_OPERATOR_LT || kw == KeywordType.KW_OPERATOR_LE || kw == KeywordType.KW_OPERATOR_EQUAL || kw == KeywordType.KW_OPERATOR_NOT_EQUAL || kw == KeywordType.KW_OPERATOR_MOVE_LEFT || kw == KeywordType.KW_OPERATOR_MOVE_RIGHT || kw == KeywordType.KW_OPERATOR_COMMA) { //two data operator Variable var = new Variable(null, VariableDataType.DOUBLE); ExpressNode expressNode = new ExpressNode(var, null, kw); if (curr == null) { throw new Exception("Syntax error:Can not begin with a operator:"+reader.__line__); } int compare = -2; while (curr != null) { compare = -2; if (curr.Father == null) { break; } else if ((compare = curr.Father.ComparePrior(kw)) <= 0) { if (compare < -1) { throw new Exception("Syntax error:Unmatched operator:"+reader.__line__); } break; } curr = curr.Father; } if (curr.Father == null || compare == -1) { curr = AddFather(curr, expressNode); } else { //优先级相等 curr = curr.Father; } } else { reader.rollback(kw); return ; } } //throw new Exception("Syntax error:Found unexpected EOF:"+ reader.__line__); } } }