運算式解析中比較重要的是運算式樹狀架構中操作符的插入,需要比較優先順序:
private bool AddOperatorNode(ref Expression.ExpressionNode expTree, Expression.Operator.Operator op) { Expression.ExpressionNode node = new Expression.ExpressionNode() { Token = op }; if (expTree != null && expTree.Token is Expression.Operand.Operand) { node.LeftNode = expTree; expTree = node; } else { if (expTree == null) { expTree = node; } else { if (node.Token <= expTree.Token) { node.LeftNode = expTree; expTree = node; } else { Expression.ExpressionNode parent = null; Expression.ExpressionNode root = expTree; do { // Operand ? if (root.Token is Expression.Operand.Operand) { if (parent != null) { parent.RightNode = node; node.LeftNode = root; break; } else { node.LeftNode = root; root = node; break; } } // Less priority, new node will be add to right child node if (root.Token <= node.Token) { if (root.RightNode == null) { root.RightNode = node; break; } parent = root; root = root.RightNode; } else { // Higher priority if (parent == null) { node.LeftNode = root; expTree = node; } else { parent.RightNode = node; node.LeftNode = root; } break; } } while (true); } } } m_lastExpNode = node; return true; } // func
接著是添加運算元的操作,需要對類型匹配進行驗證:
private bool AddOperandNode(Context ctx, SourceCode src, ref Expression.ExpressionNode expTree, Expression.Operand.Operand op) { Expression.ExpressionNode node = new Expression.ExpressionNode() { Token = op }; if (expTree == null) { expTree = node; m_lastExpNode = node; return true; } // Root should be operator. if (expTree.Token is Expression.Operand.Operand) if (!NotifyError(ctx, src.Location, ParsingErrorType.SyntaxError, "Syntax error.")) return false; Expression.ExpressionNode root = expTree; // Add to end of right side while (root.RightNode != null) root = root.RightNode; // Check type if (root.LeftNode != null) { DataTypeInfo leftDti = root.LeftNode.ResultType(ctx); DataTypeInfo rightDti = op.GetTypeInfo(ctx); if (leftDti != rightDti) { // void type has no meaning if (leftDti.BaseType == PrimitiveDataType.VoidType && !leftDti.IsPointer) if (!NotifyError(ctx, src.Location, ParsingErrorType.TypeError, "Incomplete type void")) return false; if ((leftDti.IsPointer && (!rightDti.IsPointer && rightDti.BaseType == PrimitiveDataType.VoidType || rightDti.BaseType == PrimitiveDataType.FloatType)) || ((!leftDti.IsPointer && leftDti.BaseType == PrimitiveDataType.VoidType || leftDti.BaseType == PrimitiveDataType.FloatType) && rightDti.IsPointer)) { // A warning should be cast. NotifyWarning(ctx, src.Location, rightDti.ToString() + " will be cast to " + leftDti.ToString()); } } } root.RightNode = node; m_lastExpNode = node; return true; }