1.properties
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;// 将 ComVisible 设置为 false 使得此程序集中的类型对 COM 组件不可见。
// 如果需要从 COM 访问此程序集中的类型,请将 ComVisible 属性设置为 true,使得该类型在 COM 中可见。
[assembly: ComVisible(false)]// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("74dcb954-ca11-4e84-bb02-1ccad61cee48")]
这段代码是程序集级别的属性设置,用于控制程序集的 COM 可见性。ComVisible(false)
意味着该程序集中的类型不对 COM 组件可见。Guid
用于唯一标识该程序集,如果此程序集需要向 COM 公开,则 COM 组件可以使用此 GUID 来引用该程序集。
2.evaluator
using System.Collections.Generic;namespace Macad.Common.Evaluator
{// 定义了一个用于表达式求值的上下文类public class Context{// 静态字段,用于存储默认的上下文实例private static Context defaultContext;// 获取默认的上下文实例属性public static Context Default{get{// 如果默认的上下文实例为空,则创建一个新的实例并返回if (defaultContext == null)defaultContext = new Context();return defaultContext;}}// 存储当前作用域中的变量列表// 注意,这通常是非线程安全的。private List<Variables> inScope;// 存储函数集合public Functions Functions { get; private set; }// 存储全局变量集合public Variables Globals { get; private set; }// 存储当前堆栈大小,用于调试目的和错误处理以防止堆栈溢出public int CurrentStackSize{get{return inScope.Count;}}// 获取当前作用域public Variables CurrentScope{get {// 如果当前作用域为空,则返回 nullif (inScope.Count <= 0)return null;// 否则返回最后一个作用域return inScope[inScope.Count-1];}}// 将一个变量集合推入作用域堆栈public void PushScope(Variables vars){inScope.Add(vars);}// 从作用域堆栈中弹出一个变量集合public Variables PopScope(){if (inScope.Count <= 0)return null;Variables vars = inScope[inScope.Count-1];inScope.RemoveAt(inScope.Count - 1);return vars;}// 构造函数,初始化上下文public Context(){Reset();}// 重置上下文到默认值public void Reset(){// 初始化作用域列表、函数集合和全局变量集合inScope = new List<Variables>();Functions = new Functions();Globals = new Variables();// 初始化默认的数学常数,如 Pi 和 EGlobals["Pi"] = 3.1415926535897932384626433832795; // Math.Pi is not very preciseGlobals["E"] = 2.7182818284590452353602874713527; // Math.E is not very precise either}}
}
这段代码定义了一个用于表达式求值的上下文类 Context
,它包含了当前作用域中的变量、函数集合以及全局变量集合,并提供了一些操作方法来管理作用域。
3.
using System;namespace Macad.Common.Evaluator
{// 定义了一个静态类 Evaluator,用于评估表达式public static class Evaluator{// 评估表达式并返回结果,同时返回错误描述public static double? EvaluateExpression(string expression, out string errorDescription){try{// 创建一个 Expression 实例来解析和计算表达式var evalExp = new Expression(expression);// 如果解析过程中存在错误,则返回相应的错误描述if (evalExp.Errors.Count > 0){errorDescription = "The expression cannot be parsed:\n" + evalExp.Errors[0].Message;return null;}// 计算表达式的值var value = evalExp.Eval();// 如果计算过程中存在错误,则返回相应的错误描述if(evalExp.Errors.Count > 0){errorDescription = "The expression cannot be interpreted:\n" + evalExp.Errors[0].Message;return null;}// 如果表达式的结果不是 double 类型,则返回相应的错误描述if (!(value is double)){errorDescription = "The expression does not evaluate to a valid value.";return null;}// 返回表达式的结果,并将错误描述设置为 "Finished."errorDescription = "Finished.";return (double) value;}// 捕获异常,返回相应的错误描述catch (Exception e){errorDescription = "The expression cannot be evaluated:\n" + e.Message;return null;}}}
}
这段代码定义了一个静态类 Evaluator
,其中包含了一个静态方法 EvaluateExpression
,用于评估表达式并返回结果。在评估过程中,会捕获异常并返回相应的错误描述。
4.
using System;namespace Macad.Common.Evaluator
{// 表达式类,用于解析和评估表达式public class Expression{private string expression; // 表达式字符串private ParseTreeEvaluator tree; // 解析树// 获取解析过程中的错误public ParseErrors Errors{get{if (tree != null)return tree.Errors;else return null;}}// 构造函数,根据给定的表达式创建 Expression 实例public Expression(string exp){expression = exp; // 存储表达式字符串Scanner scanner = new Scanner(); // 创建扫描器Parser parser = new Parser(scanner); // 创建解析器tree = new ParseTreeEvaluator(Context.Default); // 使用默认上下文创建解析树tree = parser.Parse(expression, tree) as ParseTreeEvaluator; // 解析表达式并构建解析树}// 对表达式进行求值public object Eval(){object result = tree.Eval(null); // 调用解析树的求值方法if (tree.Context.CurrentStackSize > 0) // 检查求值过程中是否有未清空的堆栈Errors.Add(new ParseError("Stacksize is not empty", 0, null)); // 将错误信息添加到错误列表中return result; // 返回求值结果}// 静态方法,直接对给定的表达式进行求值,并返回结果public static object Eval(string expression){return Expression.Eval<object>(expression); // 调用下面重载的 Eval 方法}// 静态方法,对给定的表达式进行求值,并返回指定类型的结果public static T Eval<T>(string expression) {object result = null; // 初始化结果变量try{Expression exp = new Expression(expression); // 创建 Expression 实例if (exp.tree.Errors.Count > 0) // 检查解析过程中是否存在错误result = exp.tree.Errors[0].Message; // 如果存在错误,将错误信息作为结果elseresult = exp.Eval(); // 否则,对表达式进行求值}catch (Exception ex) // 捕获异常{result = ex.Message; // 将异常信息作为结果}return result != null ? ((T)(result)) : default(T); // 返回结果}}
}
这段代码定义了一个 Expression 类,用于解析和评估表达式。它包含了构造函数和多个 Eval 方法,用于执行表达式的求值操作。同时提供了获取解析过程中的错误信息的功能。
5.
using System.Linq;namespace Macad.Common.Evaluator
{// 定义委托类型 FunctionDelegate,用于表示动态函数的委托public delegate object FunctionDelegate(object[] parameters);// 抽象类 Function,表示函数的基类public abstract class Function{// 定义函数的参数列表public Variables Arguments { get; protected set; } // 函数名称public string Name { get; protected set; }// 最大允许参数数量,默认为 0 表示不限制public int MaxParameters { get; protected set; }// 最小允许参数数量,默认为 0 表示不限制public int MinParameters { get; protected set; }// 抽象方法,用于对函数进行求值public abstract object Eval(object[] parameters, ParseTreeEvaluator tree);}// 动态函数类,继承自 Function,用于表示动态函数public class DynamicFunction : Function{// 函数对应的语法树节点private ParseNode Node;// 构造函数,初始化动态函数的相关属性public DynamicFunction(string name, ParseNode node, Variables args, int minParameters = 0, int maxParameters = 0){Node = node;Arguments = args;MinParameters = minParameters;MaxParameters = maxParameters;}// 对函数进行求值的方法public override object Eval(object[] parameters, ParseTreeEvaluator tree){// 创建参数的作用域Variables pars = Arguments.Clone();// 将函数参数推入作用域栈中tree.Context.PushScope(pars);// 将参数赋值给当前函数作用域的变量int i = 0;string[] keys = pars.Keys.ToArray();foreach (string key in keys)pars[key] = parameters[i++];// 执行函数object result = Node.Eval(tree, null);// 清理作用域栈tree.Context.PopScope();return result;}}// 静态函数类,继承自 Function,用于表示静态函数public class StaticFunction : Function{// 函数的实际委托实现public FunctionDelegate FunctionDelegate { get; private set; }// 构造函数,初始化静态函数的相关属性public StaticFunction(string name, FunctionDelegate function, int minParameters = 0, int maxParameters = 0){Name = name;FunctionDelegate = function;MinParameters = minParameters;MaxParameters = maxParameters;Arguments = new Variables(); }// 对函数进行求值的方法public override object Eval(object[] parameters, ParseTreeEvaluator tree){// 推入空作用域栈tree.Context.PushScope(null);// 调用函数委托进行求值object result = FunctionDelegate(parameters);// 清理作用域栈tree.Context.PopScope();return result;}}
}
这段代码定义了函数相关的类,包括抽象类 Function
以及其派生类 DynamicFunction
和 StaticFunction
。其中:
Function
类是所有函数的基类,定义了函数的基本属性和抽象方法。DynamicFunction
类表示动态函数,它根据表达式的语法树节点进行求值。StaticFunction
类表示静态函数,它通过委托来实现函数的具体功能
6.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace Macad.Common.Evaluator
{// Functions 类继承自 Dictionary<string, Function>,用于管理函数列表public class Functions : Dictionary<string, Function>{// 默认函数集合,使用静态属性 Defaults 获取private static Functions defaultFunctions;// 获取默认函数集合public static Functions Defaults {get {// 如果默认函数集合为 null,则创建新的默认函数集合并初始化if (defaultFunctions == null){defaultFunctions = new Functions();defaultFunctions.InitDefaults();}return defaultFunctions;}}// 初始化默认函数集合public void InitDefaults(){// 添加内置函数// 添加静态函数 "help",用于获取函数帮助信息this.Add("help", new StaticFunction("Help", Help, 0, 0));// 高精度数学函数// 例如:绝对值、反余弦、反正弦等// 每个函数有不同数量的参数限制// 添加了一些数学常量和字符串处理函数// 添加了一些统计函数,如平均值、中位数、方差等}// Help 函数,用于生成函数帮助信息private static object Help(object[] ps){StringBuilder help = new StringBuilder();help.AppendLine("Tiny Expression Evalutator can evaluate expression containing the following functions:");string[] keys = Functions.Defaults.Keys.OrderBy(s => s).ToArray();foreach (string key in keys){Function func = Functions.Defaults[key];help.Append(func.Name + " ");}return help.ToString();}// 计算一组数的平均值private static object Avg(object[] ps) { /* 实现略 */ }// 计算一组数的中位数private static object Median(object[] ps) { /* 实现略 */ }// 计算一组数的方差private static object Var(object[] ps) { /* 实现略 */ }// 计算一组数的标准差private static object StDev(object[] ps) { /* 实现略 */ }// 计算对数private static object Log(object[] ps) { /* 实现略 */ }// 计算阶乘private static object Fact(object[] ps) { /* 实现略 */ }// 查找一组数中的最大值private static object Max(object[] ps) { /* 实现略 */ }// 查找一组数中的最小值private static object Min(object[] ps) { /* 实现略 */ }}
}
这段代码定义了一个 Functions
类,继承自 Dictionary<string, Function>
,用于管理各种函数。在 InitDefaults
方法中初始化了一系列内置函数,例如数学函数、字符串函数和统计函数等。其中,Help
方法用于生成函数帮助信息,而其他方法实现了不同的数学和统计功能。
7.
// Generated by TinyPG v1.3 available at www.codeproject.comnamespace Macad.Common.Evaluator
{#region Parserpublic partial class Parser {private Scanner scanner; // 用于词法分析的扫描器对象private ParseTree tree; // 解析树对象public Parser(Scanner scanner){this.scanner = scanner;}public ParseTree Parse(string input){tree = new ParseTree(); // 创建新的解析树对象return Parse(input, tree); // 调用重载的 Parse 方法进行解析}public ParseTree Parse(string input, ParseTree tree){scanner.Init(input); // 初始化扫描器this.tree = tree; // 设置解析树对象ParseStart(tree); // 解析输入字符串的起始部分tree.Skipped = scanner.Skipped; // 设置解析树的 Skipped 属性为扫描器的 Skipped 属性return tree; // 返回解析树}private void ParseStart(ParseNode parent) // 解析起始部分的方法{Token tok; // 令牌对象ParseNode n; // 解析节点对象ParseNode node = parent.CreateNode(scanner.GetToken(TokenType.Start), "Start"); // 创建解析节点parent.Nodes.Add(node); // 将节点添加到父节点中// 拼接规则tok = scanner.LookAhead(TokenType.FUNCTION, TokenType.VARIABLE, TokenType.BOOLEANLITERAL, TokenType.DECIMALINTEGERLITERAL, TokenType.HEXINTEGERLITERAL, TokenType.REALLITERAL, TokenType.STRINGLITERAL, TokenType.BRACKETOPEN, TokenType.PLUS, TokenType.MINUS, TokenType.NOT, TokenType.ASSIGN); // 选项规则if (tok.Type == TokenType.FUNCTION|| tok.Type == TokenType.VARIABLE|| tok.Type == TokenType.BOOLEANLITERAL|| tok.Type == TokenType.DECIMALINTEGERLITERAL|| tok.Type == TokenType.HEXINTEGERLITERAL|| tok.Type == TokenType.REALLITERAL|| tok.Type == TokenType.STRINGLITERAL|| tok.Type == TokenType.BRACKETOPEN|| tok.Type == TokenType.PLUS|| tok.Type == TokenType.MINUS|| tok.Type == TokenType.NOT|| tok.Type == TokenType.ASSIGN){ParseExpression(node); // 解析表达式}// 拼接规则tok = scanner.Scan(TokenType.EOF); // 终端规则: 文件结束符n = node.CreateNode(tok, tok.ToString() ); // 创建解析节点node.Token.UpdateRange(tok); // 更新节点的令牌范围node.Nodes.Add(n); // 将节点添加到父节点中if (tok.Type != TokenType.EOF) {tree.Errors.Add(new ParseError("Unexpected token '" + tok.Text.Replace("\n", "") + "' found. Expected " + TokenType.EOF.ToString(), 0x1001, 0, tok.StartPos, tok.StartPos, tok.Length)); // 如果不是预期的终端符,则生成错误信息return;}parent.Token.UpdateRange(node.Token); // 更新父节点的令牌范围} // 非终端符号: Startprivate void ParseFunction(ParseNode parent) // 解析函数的方法{Token tok; // 令牌对象ParseNode n; // 解析节点对象ParseNode node = parent.CreateNode(scanner.GetToken(TokenType.Function), "Function"); // 创建解析节点parent.Nodes.Add(node); // 将节点添加到父节点中// 拼接规则tok = scanner.Scan(TokenType.FUNCTION); // 终端规则: 函数关键字n = node.CreateNode(tok, tok.ToString() ); // 创建解析节点node.Token.UpdateRange(tok); // 更新节点的令牌范围node.Nodes.Add(n); // 将节点添加到父节点中if (tok.Type != TokenType.FUNCTION) {tree.Errors.Add(new ParseError("Unexpected token '" + tok.Text.Replace("\n", "") + "' found. Expected " + TokenType.FUNCTION.ToString(), 0x1001, 0, tok.StartPos, tok.StartPos, tok.Length)); // 如果不是预期的函数关键字,则生成错误信息return;}// 拼接规则tok = scanner.Scan(TokenType.BRACKETOPEN); // 终端规则: 左括号n = node.CreateNode(tok, tok.ToString() ); // 创建解析节点node.Token.UpdateRange(tok); // 更新节点的令牌范围node.Nodes.Add(n); // 将节点添加到父节点中if (tok.Type != TokenType.BRACKETOPEN) {tree.Errors.Add(new ParseError("Unexpected token '" + tok.Text.Replace("\n", "") + "' found. Expected " + TokenType.BRACKETOPEN.ToString(), 0x1001, 0, tok.StartPos, tok.StartPos, tok.Length)); // 如果不是预期的左括号,则生成错误信息return;}// 拼接规则tok = scanner.LookAhead(TokenType.FUNCTION, TokenType.VARIABLE, TokenType.BOOLEANLITERAL, TokenType.DECIMALINTEGERLITERAL, TokenType.HEXINTEGERLITERAL, TokenType.REALLITERAL, TokenType.STRINGLITERAL, TokenType.BRACKETOPEN, TokenType.PLUS, TokenType.MINUS, TokenType.NOT, TokenType.ASSIGN, TokenType.SEMICOLON); // 选项规则if (tok.Type == TokenType.FUNCTION|| tok.Type == TokenType.VARIABLE|| tok.Type == TokenType.BOOLEANLITERAL|| tok.Type == TokenType.DECIMALINTEGERLITERAL|| tok.Type == TokenType.HEXINTEGERLITERAL|| tok.Type == TokenType.REALLITERAL|| tok.Type == TokenType.STRINGLITERAL|| tok.Type == TokenType.BRACKETOPEN|| tok.Type == TokenType.PLUS|| tok.Type == TokenType.MINUS|| tok.Type == TokenType.NOT|| tok.Type == TokenType.ASSIGN|| tok.Type == TokenType.SEMICOLON){ParseParams(node); // 解析参数列表}// 拼接规则tok = scanner.Scan(TokenType.BRACKETCLOSE); // 终端规则: 右括号n = node.CreateNode(tok, tok.ToString() ); // 创建解析节点node.Token.UpdateRange(tok); // 更新节点的令牌范围node.Nodes.Add(n); // 将节点添加到父节点中if (tok.Type != TokenType.BRACKETCLOSE) {tree.Errors.Add(new ParseError("Unexpected token '" + tok.Text.Replace("\n", "") + "' found. Expected " + TokenType.BRACKETCLOSE.ToString(), 0x1001, 0, tok.StartPos, tok.StartPos, tok.Length)); // 如果不是预期的右括号,则生成错误信息return;}parent.Token.UpdateRange(node.Token); // 更新父节点的令牌范围} // 非终端符号: Functionprivate void ParsePrimaryExpression(ParseNode parent) // 解析主表达式的方法{Token tok; // 令牌对象//ParseNode n;ParseNode node = parent.CreateNode(scanner.GetToken(TokenType.PrimaryExpression), "PrimaryExpression"); // 创建解析节点parent.Nodes.Add(node); // 将节点添加到父节点中tok = scanner.LookAhead(TokenType.FUNCTION, TokenType.VARIABLE, TokenType.BOOLEANLITERAL, TokenType.DECIMALINTEGERLITERAL, TokenType.HEXINTEGERLITERAL, TokenType.REALLITERAL, TokenType.STRINGLITERAL, TokenType.BRACKETOPEN); // 选择规则switch (tok.Type){ // 选择规则case TokenType.FUNCTION:ParseFunction(node); // 解析函数break;case TokenType.VARIABLE:ParseVariable(node); // 解析变量break;case TokenType.BOOLEANLITERAL:case TokenType.DECIMALINTEGERLITERAL:case TokenType.HEXINTEGERLITERAL:case TokenType.REALLITERAL:case TokenType.STRINGLITERAL:ParseLiteral(node); // 解析字面量break;case TokenType.BRACKETOPEN:ParseParenthesizedExpression(node); // 解析括号表达式break;default:tree.Errors.Add(new ParseError("Unexpected token '" + tok.Text.Replace("\n", "") + "' found.", 0x0002, 0, tok.StartPos, tok.StartPos, tok.Length)); // 如果是意外的令牌类型,则生成错误信息break;} // 选择规则parent.Token.UpdateRange(node.Token); // 更新父节点的令牌范围} // 非终端符号: PrimaryExpressionprivate void ParseParenthesizedExpression(ParseNode parent) // 解析带括号表达式的方法{Token tok; // 令牌对象ParseNode n; // 解析节点对象ParseNode node = parent.CreateNode(scanner.GetToken(TokenType.ParenthesizedExpression), "ParenthesizedExpression"); // 创建解析节点parent.Nodes.Add(node); // 将节点添加到父节点中// 拼接规则tok = scanner.Scan(TokenType.BRACKETOPEN); // 终端规则: 左括号n = node.CreateNode(tok, tok.ToString() ); // 创建解析节点node.Token.UpdateRange(tok); // 更新节点的令牌范围node.Nodes.Add(n); // 将节点添加到父节点中if (tok.Type != TokenType.BRACKETOPEN) {tree.Errors.Add(new ParseError("Unexpected token '" + tok.Text.Replace("\n", "") + "' found. Expected " + TokenType.BRACKETOPEN.ToString(), 0x1001, 0, tok.StartPos, tok.StartPos, tok.Length)); // 如果不是预期的左括号,则生成错误信息return;}// 拼接规则ParseExpression(node); // 解析表达式// 拼接规则tok = scanner.Scan(TokenType.BRACKETCLOSE); // 终端规则: 右括号n = node.CreateNode(tok, tok.ToString() ); // 创建解析节点node.Token.UpdateRange(tok); // 更新节点的令牌范围node.Nodes.Add(n); // 将节点添加到父节点中if (tok.Type != TokenType.BRACKETCLOSE) {tree.Errors.Add(new ParseError("Unexpected token '" + tok.Text.Replace("\n", "") + "' found. Expected " + TokenType.BRACKETCLOSE.ToString(), 0x1001, 0, tok.StartPos, tok.StartPos, tok.Length)); // 如果不是预期的右括号,则生成错误信息return;}parent.Token.UpdateRange(node.Token); // 更新父节点的令牌范围} // 非终端符号: ParenthesizedExpressionprivate void ParseUnaryExpression(ParseNode parent) // 解析一元表达式的方法{Token tok; // 令牌对象ParseNode n; // 解析节点对象ParseNode node = parent.CreateNode(scanner.GetToken(TokenType.UnaryExpression), "UnaryExpression"); // 创建解析节点parent.Nodes.Add(node); // 将节点添加到父节点中tok = scanner.LookAhead(TokenType.FUNCTION, TokenType.VARIABLE, TokenType.BOOLEANLITERAL, TokenType.DECIMALINTEGERLITERAL, TokenType.HEXINTEGERLITERAL, TokenType.REALLITERAL, TokenType.STRINGLITERAL, TokenType.BRACKETOPEN, TokenType.PLUS, TokenType.MINUS, TokenType.NOT); // 选择规则switch (tok.Type){ // 选择规则case TokenType.FUNCTION:case TokenType.VARIABLE:case TokenType.BOOLEANLITERAL:case TokenType.DECIMALINTEGERLITERAL:case TokenType.HEXINTEGERLITERAL:case TokenType.REALLITERAL:case TokenType.STRINGLITERAL:case TokenType.BRACKETOPEN:ParsePrimaryExpression(node); // 解析主表达式break;case TokenType.PLUS:// 拼接规则tok = scanner.Scan(TokenType.PLUS); // 终端规则: 加号n = node.CreateNode(tok, tok.ToString() ); // 创建解析节点node.Token.UpdateRange(tok); // 更新节点的令牌范围node.Nodes.Add(n); // 将节点添加到父节点中if (tok.Type != TokenType.PLUS) {tree.Errors.Add(new ParseError("Unexpected token '" + tok.Text.Replace("\n", "") + "' found. Expected " + TokenType.PLUS.ToString(), 0x1001, 0, tok.StartPos, tok.StartPos, tok.Length)); // 如果不是预期的加号,则生成错误信息return;}// 拼接规则ParseUnaryExpression(node); // 解析一元表达式break;case TokenType.MINUS:// 拼接规则tok = scanner.Scan(TokenType.MINUS); // 终端规则: 减号n = node.CreateNode(tok, tok.ToString() ); // 创建解析节点node.Token.UpdateRange(tok); // 更新节点的令牌范围node.Nodes.Add(n); // 将节点添加到父节点中if (tok.Type != TokenType.MINUS) {tree.Errors.Add(new ParseError("Unexpected token '" + tok.Text.Replace("\n", "") + "' found. Expected " + TokenType.MINUS.ToString(), 0x1001, 0, tok.StartPos, tok.StartPos, tok.Length)); // 如果不是预期的减号,则生成错误信息return;}// 拼接规则ParseUnaryExpression(node); // 解析一元表达式break;case TokenType.NOT:// 拼接规则tok = scanner.Scan(TokenType.NOT); // 终端规则: 逻辑非n = node.CreateNode(tok, tok.ToString() ); // 创建解析节点node.Token.UpdateRange(tok); // 更新节点的令牌范围node.Nodes.Add(n); // 将节点添加到父节点中if (tok.Type != TokenType.NOT) {tree.Errors.Add(new ParseError("Unexpected token '" + tok.Text.Replace("\n", "") + "' found. Expected " + TokenType.NOT.ToString(), 0x1001, 0, tok.StartPos, tok.StartPos, tok.Length)); // 如果不是预期的逻辑非,则生成错误信息return;}// 拼接规则ParseUnaryExpression(node); // 解析一元表达式break;default:tree.Errors.Add(new ParseError("Unexpected token '" + tok.Text.Replace("\n", "") + "' found.", 0x0002, 0, tok.StartPos, tok.StartPos, tok.Length)); // 如果是意外的令牌类型,则生成错误信息break;} // 选择规则parent.Token.UpdateRange(node.Token); // 更新父节点的令牌范围} // 非终端符号: UnaryExpressionprivate void ParseMultiplicativeExpression(ParseNode parent) // 解析乘法表达式的方法{Token tok; // 令牌对象ParseNode n; // 解析节点对象ParseNode node = parent.CreateNode(scanner.GetToken(TokenType.MultiplicativeExpression), "MultiplicativeExpression"); // 创建解析节点parent.Nodes.Add(node); // 将节点添加到父节点中// 拼接规则ParseUnaryExpression(node); // 解析一元表达式// 拼接规则tok = scanner.LookAhead(TokenType.MULTIPLY, TokenType.DIVIDE); // 选择规则switch (tok.Type){ // 选择规则case TokenType.MULTIPLY:// 拼接规则tok = scanner.Scan(TokenType.MULTIPLY); // 终端规则: 乘号n = node.CreateNode(tok, tok.ToString() ); // 创建解析节点node.Token.UpdateRange(tok); // 更新节点的令牌范围node.Nodes.Add(n); // 将节点添加到父节点中if (tok.Type != TokenType.MULTIPLY) {tree.Errors.Add(new ParseError("Unexpected token '" + tok.Text.Replace("\n", "") + "' found. Expected " + TokenType.MULTIPLY.ToString(), 0x1001, 0, tok.StartPos, tok.StartPos, tok.Length)); // 如果不是预期的乘号,则生成错误信息return;}// 拼接规则ParseUnaryExpression(node); // 解析一元表达式break;case TokenType.DIVIDE:// 拼接规则tok = scanner.Scan(TokenType.DIVIDE); // 终端规则: 除号n = node.CreateNode(tok, tok.ToString() ); // 创建解析节点node.Token.UpdateRange(tok); // 更新节点的令牌范围node.Nodes.Add(n); // 将节点添加到父节点中if (tok.Type != TokenType.DIVIDE) {tree.Errors.Add(new ParseError("Unexpected token '" + tok.Text.Replace("\n", "") + "' found. Expected " + TokenType.DIVIDE.ToString(), 0x1001, 0, tok.StartPos, tok.StartPos, tok.Length)); // 如果不是预期的除号,则生成错误信息return;}// 拼接规则ParseUnaryExpression(node); // 解析一元表达式break;default:break;} // 选择规则parent.Token.UpdateRange(node.Token); // 更新父节点的令牌范围} // 非终端符号: MultiplicativeExpressionprivate void ParseAdditiveExpression(ParseNode parent) // 解析加法表达式的方法{Token tok; // 令牌对象ParseNode n; // 解析节点对象ParseNode node = parent.CreateNode(scanner.GetToken(TokenType.AdditiveExpression), "AdditiveExpression"); // 创建解析节点parent.Nodes.Add(node); // 将节点添加到父节点中// 拼接规则ParseMultiplicativeExpression(node); // 解析乘法表达式// 拼接规则tok = scanner.LookAhead(TokenType.PLUS, TokenType.MINUS); // 选择规则switch (tok.Type){ // 选择规则case TokenType.PLUS:// 拼接规则tok = scanner.Scan(TokenType.PLUS); // 终端规则: 加号n = node.CreateNode(tok, tok.ToString() ); // 创建解析节点node.Token.UpdateRange(tok); // 更新节点的令牌范围node.Nodes.Add(n); // 将节点添加到父节点中if (tok.Type != TokenType.PLUS) {tree.Errors.Add(new ParseError("Unexpected token '" + tok.Text.Replace("\n", "") + "' found. Expected " + TokenType.PLUS.ToString(), 0x1001, 0, tok.StartPos, tok.StartPos, tok.Length)); // 如果不是预期的加号,则生成错误信息return;}// 拼接规则ParseMultiplicativeExpression(node); // 解析乘法表达式break;case TokenType.MINUS:// 拼接规则tok = scanner.Scan(TokenType.MINUS); // 终端规则: 减号n = node.CreateNode(tok, tok.ToString() ); // 创建解析节点node.Token.UpdateRange(tok); // 更新节点的令牌范围node.Nodes.Add(n); // 将节点添加到父节点中if (tok.Type != TokenType.MINUS) {tree.Errors.Add(new ParseError("Unexpected token '" + tok.Text.Replace("\n", "") + "' found. Expected " + TokenType.MINUS.ToString(), 0x1001, 0, tok.StartPos, tok.StartPos, tok.Length)); // 如果不是预期的减号,则生成错误信息return;}// 拼接规则ParseMultiplicativeExpression(node); // 解析乘法表达式break;default:break;} // 选择规则parent.Token.UpdateRange(node.Token); // 更新父节点的令牌范围} // 非终端符号: AdditiveExpressionprivate void ParseAssignmentExpression(ParseNode parent) // 解析赋值表达式的方法{Token tok; // 令牌对象ParseNode n; // 解析节点对象ParseNode node = parent.CreateNode(scanner.GetToken(TokenType.AssignmentExpression), "AssignmentExpression"); // 创建解析节点parent.Nodes.Add(node); // 将节点添加到父节点中// 拼接规则ParseAdditiveExpression(node); // 解析加法表达式// 拼接规则tok = scanner.LookAhead(TokenType.ASSIGN); // 选择规则switch (tok.Type){ // 选择规则case TokenType.ASSIGN:// 拼接规则tok = scanner.Scan(TokenType.ASSIGN); // 终端规则: 赋值操作符n = node.CreateNode(tok, tok.ToString() ); // 创建解析节点node.Token.UpdateRange(tok); // 更新节点的令牌范围node.Nodes.Add(n); // 将节点添加到父节点中if (tok.Type != TokenType.ASSIGN) {tree.Errors.Add(new ParseError("Unexpected token '" + tok.Text.Replace("\n", "") + "' found. Expected " + TokenType.ASSIGN.ToString(), 0x1001, 0, tok.StartPos, tok.StartPos, tok.Length)); // 如果不是预期的赋值操作符,则生成错误信息return;}// 拼接规则ParseAssignmentExpression(node); // 解析赋值表达式break;default:break;} // 选择规则parent.Token.UpdateRange(node.Token); // 更新父节点的令牌范围} // 非终端符号: AssignmentExpressionprivate void ParseExpression(ParseNode parent) // 解析表达式的方法{Token tok; // 令牌对象ParseNode n; // 解析节点对象ParseNode node = parent.CreateNode(scanner.GetToken(TokenType.Expression), "Expression"); // 创建解析节点parent.Nodes.Add(node); // 将节点添加到父节点中// 拼接规则ParseAssignmentExpression(node); // 解析赋值表达式// 拼接规则tok = scanner.Scan(TokenType.SEMICOLON); // 终端规则: 分号n = node.CreateNode(tok, tok.ToString() ); // 创建解析节点node.Token.UpdateRange(tok); // 更新节点的令牌范围node.Nodes.Add(n); // 将节点添加到父节点中if (tok.Type != TokenType.SEMICOLON) {tree.Errors.Add(new ParseError("Unexpected token '" + tok.Text.Replace("\n", "") + "' found. Expected " + TokenType.SEMICOLON.ToString(), 0x1001, 0, tok.StartPos, tok.StartPos, tok.Length)); // 如果不是预期的分号,则生成错误信息return;}parent.Token.UpdateRange(node.Token); // 更新父节点的令牌范围} // 非终端符号: Expression}#endregion
}
这是一个使用TinyPG生成的解析器。解析器类 Parser
包含了一系列用于解析输入的方法,这些方法根据输入的语法规则递归地构建解析树。注释提供了对每个方法和规则的解释,包括它们如何根据不同的令牌类型进行选择和拼接。
8.
// Generated by TinyPG v1.3 available at www.codeproject.com
// 由 TinyPG v1.3 生成,可在 www.codeproject.com 上找到using System;
using System.Collections.Generic;
using System.Text;namespace Macad.Common.Evaluator
{#region ParseTree// 定义解析错误集合类public class ParseErrors : List<ParseError>{}// 定义解析错误类public class ParseError{private string message;private int code;private int line;private int col;private int pos;private int length;// 错误代码、行号、列号、位置、长度、消息的属性public int Code { get { return code; } }public int Line { get { return line; } }public int Column { get { return col; } }public int Position { get { return pos; } }public int Length { get { return length; } }public string Message { get { return message; } }// 用于序列化的构造函数public ParseError(){}// 带有消息、代码和节点的构造函数public ParseError(string message, int code, ParseNode node) : this(message, code, 0, node.Token.StartPos, node.Token.StartPos, node.Token.Length){}// 带有消息、代码、行号、列号、位置和长度的构造函数public ParseError(string message, int code, int line, int col, int pos, int length){this.message = message;this.code = code;this.line = line;this.col = col;this.pos = pos;this.length = length;}}// 解析树的根节点public partial class ParseTree : ParseNode{public ParseErrors Errors; // 解析过程中的错误集合public List<Token> Skipped; // 被跳过的令牌集合// 解析树的构造函数public ParseTree() : base(new Token(), "ParseTree"){Token.Type = TokenType.Start;Token.Text = "Root";Errors = new ParseErrors();}// 打印解析树的方法public string PrintTree(){StringBuilder sb = new StringBuilder();int indent = 0;PrintNode(sb, this, indent);return sb.ToString();}// 打印解析节点的方法private void PrintNode(StringBuilder sb, ParseNode node, int indent){string space = "".PadLeft(indent, ' ');sb.Append(space);sb.AppendLine(node.Text);foreach (ParseNode n in node.Nodes)PrintNode(sb, n, indent + 2);}/// <summary>/// this is the entry point for executing and evaluating the parse tree./// </summary>/// <param name="paramlist">additional optional input parameters</param>/// <returns>the output of the evaluation function</returns>// 解析树的执行和评估入口点方法public object Eval(params object[] paramlist){return Nodes[0].Eval(this, paramlist);}}// 解析节点类public partial class ParseNode{protected string text; // 节点文本protected List<ParseNode> nodes; // 子节点列表// 子节点列表的属性public List<ParseNode> Nodes { get {return nodes;} }public ParseNode Parent; // 父节点public Token Token; // 令牌/规则// 节点文本的属性public string Text {get { return text;} set { text = value; }} // 创建节点的虚拟方法public virtual ParseNode CreateNode(Token token, string text){ParseNode node = new ParseNode(token, text);node.Parent = this;return node;}// 节点的构造函数protected ParseNode(Token token, string text){this.Token = token;this.text = text;this.nodes = new List<ParseNode>();}// 获取值的方法protected object GetValue(ParseTree tree, TokenType type, int index){return GetValue(tree, type, ref index);}protected object GetValue(ParseTree tree, TokenType type, ref int index){object o = null;if (index < 0) return o;// 从左到右遍历子节点foreach (ParseNode node in nodes){if (node.Token.Type == type){index--;if (index < 0){o = node.Eval(tree);break;}}}return o;}/// <summary>/// this implements the evaluation functionality, cannot be used directly/// </summary>/// <param name="tree">the parsetree itself</param>/// <param name="paramlist">optional input parameters</param>/// <returns>a partial result of the evaluation</returns>// 评估功能的实现,不能直接使用internal object Eval(ParseTree tree, params object[] paramlist){object Value = null;switch (Token.Type){// 根据令牌类型选择对应的评估方法case TokenType.Start:Value = EvalStart(tree, paramlist);break;case TokenType.Function:Value = EvalFunction(tree, paramlist);break;case TokenType.PrimaryExpression:Value = EvalPrimaryExpression(tree, paramlist);break;case TokenType.ParenthesizedExpression:Value = EvalParenthesizedExpression(tree, paramlist);break;case TokenType.UnaryExpression:Value = EvalUnaryExpression(tree, paramlist);break;case TokenType.PowerExpression:Value = EvalPowerExpression(tree, paramlist);break;case TokenType.MultiplicativeExpression:Value = EvalMultiplicativeExpression(tree, paramlist);break;case TokenType.AdditiveExpression:Value = EvalAdditiveExpression(tree, paramlist);break;case TokenType.ConcatEpression:Value = EvalConcatEpression(tree, paramlist);break;case TokenType.RelationalExpression:Value = EvalRelationalExpression(tree, paramlist);break;case TokenType.EqualityExpression:Value = EvalEqualityExpression(tree, paramlist);break;case TokenType.ConditionalAndExpression:Value = EvalConditionalAndExpression(tree, paramlist);break;case TokenType.ConditionalOrExpression:Value = EvalConditionalOrExpression(tree, paramlist);break;case TokenType.AssignmentExpression:Value = EvalAssignmentExpression(tree, paramlist);break;case TokenType.Expression:Value = EvalExpression(tree, paramlist);break;case TokenType.Params:Value = EvalParams(tree, paramlist);break;case TokenType.Literal:Value = EvalLiteral(tree, paramlist);break;case TokenType.IntegerLiteral:Value = EvalIntegerLiteral(tree, paramlist);break;case TokenType.RealLiteral:Value = EvalRealLiteral(tree, paramlist);break;case TokenType.StringLiteral:Value = EvalStringLiteral(tree, paramlist);break;case TokenType.Variable:Value = EvalVariable(tree, paramlist);break;default:Value = Token.Text;break;}return Value;}// 各种评估方法,需要在具体的子类中实现protected virtual object EvalStart(ParseTree tree, params object[] paramlist){return "Could not interpret input; no semantics implemented.";}protected virtual object EvalFunction(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}protected virtual object EvalPrimaryExpression(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}protected virtual object EvalParenthesizedExpression(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}protected virtual object EvalUnaryExpression(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}protected virtual object EvalPowerExpression(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}protected virtual object EvalMultiplicativeExpression(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}protected virtual object EvalAdditiveExpression(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}protected virtual object EvalConcatEpression(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}protected virtual object EvalRelationalExpression(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}protected virtual object EvalEqualityExpression(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}protected virtual object EvalConditionalAndExpression(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}protected virtual object EvalConditionalOrExpression(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}protected virtual object EvalAssignmentExpression(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}protected virtual object EvalExpression(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}protected virtual object EvalParams(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}protected virtual object EvalLiteral(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}protected virtual object EvalIntegerLiteral(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}protected virtual object EvalRealLiteral(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}protected virtual object EvalStringLiteral(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}protected virtual object EvalVariable(ParseTree tree, params object[] paramlist){throw new NotImplementedException();}}#endregion ParseTree
}
这段代码是一个用于语法解析的框架,包括了解析器类 ParseTree
和解析节点类 ParseNode
。其中 ParseTree
表示整个解析树,而 ParseNode
则表示解析树中的节点。解析器类提供了构造解析树、打印解析树、执行解析树的功能,而解析节点类则提供了节点的创建和评估功能。
9.
// 引入必要的命名空间
using System;
using System.Collections.Generic;
using System.Globalization;namespace Macad.Common.Evaluator
{// 定义解析树评估器类,继承自解析树类public partial class ParseTreeEvaluator : ParseTree{// 上下文对象属性,用于存储环境上下文信息public Context Context { get; private set; }// 默认构造函数public ParseTreeEvaluator() : base(){}// 带上下文对象参数的构造函数public ParseTreeEvaluator(Context context) : base(){Context = context;}// 重写创建节点方法,确保创建的节点类型正确public override ParseNode CreateNode(Token token, string text){ParseTreeEvaluator node = new ParseTreeEvaluator();node.Token = token;node.text = text;node.Parent = this;return node;}// 解析树起始节点的评估方法protected override object EvalStart(ParseTree tree, params object[] paramlist){return this.GetValue(tree, TokenType.Expression, 0);}// 解析一元表达式的评估方法protected override object EvalUnaryExpression(ParseTree tree, params object[] paramlist){// 获取一元表达式节点的类型TokenType type = this.nodes[0].Token.Type;// 如果是主要表达式类型,则直接返回主要表达式的值if (type == TokenType.PrimaryExpression)return this.GetValue(tree, TokenType.PrimaryExpression, 0);// 如果是负号,则取其后的表达式的相反数if (type == TokenType.MINUS){object val = this.GetValue(tree, TokenType.UnaryExpression, 0);if (val is double)return -((double)val);// 错误处理tree.Errors.Add(new ParseError("Illegal UnaryExpression format, cannot interpret minus " + val.ToString(), 1095, this));return null;}// 如果是正号,则返回其后的表达式的值else if (type == TokenType.PLUS){object val = this.GetValue(tree, TokenType.UnaryExpression, 0);return val;}// 如果是逻辑非,则取其后表达式的逻辑非值else if (type == TokenType.NOT){object val = this.GetValue(tree, TokenType.UnaryExpression, 0);if (val is bool)return !((bool)val);// 错误处理tree.Errors.Add(new ParseError("Illegal UnaryExpression format, cannot interpret negate " + val.ToString(), 1098, this));return null;}// 错误处理Errors.Add(new ParseError("Illegal UnaryExpression format", 1099, this));return null;}// 解析参数表达式的评估方法protected override object EvalParams(ParseTree tree, params object[] paramlist){// 解析参数表达式,将参数值存储在列表中返回List<object> parameters = new List<object>();for (int i = 0; i < nodes.Count; i += 2){if (nodes[i].Token.Type == TokenType.Expression){object val = nodes[i].Eval(tree, paramlist);parameters.Add(val);}}return parameters;}// 解析函数表达式的评估方法protected override object EvalFunction(ParseTree tree, params object[] paramlist){// 获取函数名节点和参数节点ParseNode funcNode = this.nodes[0];ParseNode paramNode = this.nodes[2];// 获取解析树评估器的根节点ParseTreeEvaluator root = tree as ParseTreeEvaluator;if (root == null){// 错误处理tree.Errors.Add(new ParseError("Invalid parser used", 1040, this));return null;}// 检查上下文是否存在if (root.Context == null){// 错误处理tree.Errors.Add(new ParseError("No context defined", 1041, this));return null;}// 检查堆栈溢出if (root.Context.CurrentStackSize > 50){// 错误处理tree.Errors.Add(new ParseError("Stack overflow: " + funcNode.Token.Text + "()", 1046, this));return null;}// 将函数名转换为小写,进行查找string key = funcNode.Token.Text.ToLowerInvariant();if (!root.Context.Functions.ContainsKey(key)){// 错误处理tree.Errors.Add(new ParseError("Fuction not defined: " + funcNode.Token.Text + "()", 1042, this));return null;}// 获取函数对象Function func = root.Context.Functions[key];// 解析函数参数object[] parameters = new object[0];if (paramNode.Token.Type == TokenType.Params)parameters = (paramNode.Eval(tree, paramlist) as List<object>).ToArray();// 检查参数数量是否合法if (parameters.Length < func.MinParameters) {// 错误处理tree.Errors.Add(new ParseError("At least " + func.MinParameters.ToString() + " parameter(s) expected", 1043, this));return null; // 参数数量不合法}else if (parameters.Length > func.MaxParameters){// 错误处理tree.Errors.Add(new ParseError("No more than " + func.MaxParameters.ToString() + " parameter(s) expected", 1044, this));return null; // 参数数量不合法}// 调用函数的评估方法并返回结果return func.Eval(parameters, root);}// 解析变量表达式的评估方法protected override object EvalVariable(ParseTree tree, params object[] paramlist){// 获取解析树评估器的根节点ParseTreeEvaluator root = tree as ParseTreeEvaluator;if (root == null){// 错误处理tree.Errors.Add(new ParseError("Invalid parser used", 1040, this));return null;}// 检查上下文是否存在if (root.Context == null){// 错误处理tree.Errors.Add(new ParseError("No context defined", 1041, this));return null;}// 获取变量名string key = this.nodes[0].Token.Text;// 先在函数作用域中查找变量if (root.Context.CurrentScope != null && root.Context.CurrentScope.ContainsKey(key))return root.Context.CurrentScope[key];// 如果不在函数作用域中,则在全局变量中查找if (root.Context.Globals != null && root.Context.Globals.ContainsKey(key))return root.Context.Globals[key];// 变量未找到,错误处理tree.Errors.Add(new ParseError("Variable not defined: " + key, 1039, this));return null;}// 解析主要表达式的评估方法protected override object EvalPrimaryExpression(ParseTree tree, params object[] paramlist){// 获取主要表达式节点的类型TokenType type = this.nodes[0].Token.Type;// 根据类型返回相应的值if (type == TokenType.Function)return this.GetValue(tree, TokenType.Function, 0);else if (type == TokenType.Literal)return this.GetValue(tree, TokenType.Literal, 0);else if (type == TokenType.ParenthesizedExpression)return this.GetValue(tree, TokenType.ParenthesizedExpression, 0);else if (type == TokenType.Variable)return this.GetValue(tree, TokenType.Variable, 0);// 错误处理tree.Errors.Add(new ParseError("Illegal EvalPrimaryExpression format", 1097, this));return null;}// 解析括号表达式的评估方法protected override object EvalParenthesizedExpression(ParseTree tree, params object[] paramlist){// 返回括号内表达式的值return this.GetValue(tree, TokenType.Expression, 0);}// 解析幂运算表达式的评估方法protected override object EvalPowerExpression(ParseTree tree, params object[] paramlist){// 获取幂运算左边表达式的值object result = this.GetValue(tree, TokenType.UnaryExpression, 0);// 从左到右计算幂运算的值for (int i = 1; i < nodes.Count; i += 2){Token token = nodes[i].Token;object val = nodes[i + 1].Eval(tree, paramlist);if (token.Type == TokenType.POWER)result = Math.Pow(Convert.ToDouble(result), Convert.ToDouble(val));}return result;}// 解析乘法运算表达式的评估方法protected override object EvalMultiplicativeExpression(ParseTree tree, params object[] paramlist){// 获取乘法运算左边表达式的值object result = this.GetValue(tree, TokenType.PowerExpression, 0);// 计算乘法运算的值for (int i = 1; i < nodes.Count; i+=2 ){Token token = nodes[i].Token;object val = nodes[i+1].Eval(tree, paramlist);if (token.Type == TokenType.ASTERIKS)result = Convert.ToDouble(result) * Convert.ToDouble(val);else if (token.Type == TokenType.SLASH)result = Convert.ToDouble(result) / Convert.ToDouble(val);else if (token.Type == TokenType.PERCENT)result = Convert.ToDouble(result) % Convert.ToDouble(val);}return result;}// 解析加法运算表达式的评估方法protected override object EvalAdditiveExpression(ParseTree tree, params object[] paramlist){// 获取加法运算左边表达式的值object result = this.GetValue(tree, TokenType.MultiplicativeExpression, 0);// 计算加法运算的值for (int i = 1; i < nodes.Count; i += 2){Token token = nodes[i].Token;object val = nodes[i + 1].Eval(tree, paramlist);if (token.Type == TokenType.PLUS)result = Convert.ToDouble(result) + Convert.ToDouble(val);else if (token.Type == TokenType.MINUS)result = Convert.ToDouble(result) - Convert.ToDouble(val);}return result;}// 解析连接表达式的评估方法protected override object EvalConcatEpression(ParseTree tree, params object[] paramlist){// 获取连接运算左边表达式的值object result = this.GetValue(tree, TokenType.AdditiveExpression, 0);// 连接字符串for (int i = 1; i < nodes.Count; i += 2){Token token = nodes[i].Token;object val = nodes[i + 1].Eval(tree, paramlist);if (token.Type == TokenType.AMP)result = Convert.ToString(result) + Convert.ToString(val);}return result;}// 解析关系表达式的评估方法protected override object EvalRelationalExpression(ParseTree tree, params object[] paramlist){// 获取关系运算左边表达式的值object result = this.GetValue(tree, TokenType.ConcatEpression, 0);// 比较大小或字符串for (int i = 1; i < nodes.Count; i += 2){Token token = nodes[i].Token;object val = nodes[i + 1].Eval(tree, paramlist);// 比较数值if (result is double && val is double){if (token.Type == TokenType.LESSTHAN)result = Convert.ToDouble(result) < Convert.ToDouble(val);else if (token.Type == TokenType.LESSEQUAL)result = Convert.ToDouble(result) <= Convert.ToDouble(val);else if (token.Type == TokenType.GREATERTHAN)result = Convert.ToDouble(result) > Convert.ToDouble(val);else if (token.Type == TokenType.GREATEREQUAL)result = Convert.ToDouble(result) >= Convert.ToDouble(val);}else // 比较字符串{int comp = string.Compare(Convert.ToString(result), Convert.ToString(val));if (token.Type == TokenType.LESSTHAN)result = comp < 0;else if (token.Type == TokenType.LESSEQUAL)result = comp <= 0;else if (token.Type == TokenType.GREATERTHAN)result = comp > 0;else if (token.Type == TokenType.GREATEREQUAL)result = comp >= 0;}}return result;}// 解析等式表达式的评估方法protected override object EvalEqualityExpression(ParseTree tree, params object[] paramlist){// 获取等式运算左边表达式的值object result = this.GetValue(tree, TokenType.RelationalExpression, 0);// 比较是否相等for (int i = 1; i < nodes.Count; i += 2){Token token = nodes[i].Token;object val = nodes[i + 1].Eval(tree, paramlist);if (token.Type == TokenType.EQUAL)result = object.Equals(result, val);else if (token.Type == TokenType.NOTEQUAL)result = !object.Equals(result, val);}return result;}// 解析逻辑与表达式的评估方法protected override object EvalConditionalAndExpression(ParseTree tree, params object[] paramlist){// 获取逻辑与运算左边表达式的值object result = this.GetValue(tree, TokenType.EqualityExpression, 0);// 逻辑与运算for (int i = 1; i < nodes.Count; i += 2){Token token = nodes[i].Token;object val = nodes[i + 1].Eval(tree, paramlist);if (token.Type == TokenType.AMPAMP)result = Convert.ToBoolean(result) && Convert.ToBoolean(val);}return result;}// 解析逻辑或表达式的评估方法protected override object EvalConditionalOrExpression(ParseTree tree, params object[] paramlist){// 获取逻辑或运算左边表达式的值object result = this.GetValue(tree, TokenType.ConditionalAndExpression, 0);// 逻辑或运算for (int i = 1; i < nodes.Count; i += 2){Token token = nodes[i].Token;object val = nodes[i + 1].Eval(tree, paramlist);if (token.Type == TokenType.PIPEPIPE)result = Convert.ToBoolean(result) || Convert.ToBoolean(val);}return result;}// 解析赋值表达式的评估方法protected override object EvalAssignmentExpression(ParseTree tree, params object[] paramlist){// 获取赋值运算左边表达式的值object result = this.GetValue(tree, TokenType.ConditionalOrExpression, 0);// 处理条件表达式的情况if (nodes.Count >= 5 && result is bool && nodes[1].Token.Type == TokenType.QUESTIONMARK&& nodes[3].Token.Type == TokenType.COLON){if (Convert.ToBoolean(result))result = nodes[2].Eval(tree, paramlist); // 返回第一个参数elseresult = nodes[4].Eval(tree, paramlist); // 返回第二个参数}return result;}// 解析表达式的评估方法protected override object EvalExpression(ParseTree tree, params object[] paramlist){// 如果只有左边的表达式,不是赋值,直接计算表达式的值if (nodes.Count == 1) return this.GetValue(tree, TokenType.AssignmentExpression, 0); // 返回结果// 如果节点数不等于3,报错if (nodes.Count != 3){tree.Errors.Add(new ParseError("Illegal EvalExpression format", 1092, this));return null;}// 进行赋值操作// 赋值只允许给函数或变量ParseNode v = GetFunctionOrVariable(nodes[0]);if (v == null){tree.Errors.Add(new ParseError("Can only assign to function or variable", 1020, this));return null;}ParseTreeEvaluator root = tree as ParseTreeEvaluator;if (root == null){tree.Errors.Add(new ParseError("Invalid parser used", 1040, this));return null;}// 检查上下文是否存在if (root.Context == null){// 错误处理tree.Errors.Add(new ParseError("No context defined", 1041, this));return null;}// 变量赋值if (v.Token.Type == TokenType.VARIABLE){// 简单的覆盖之前的定义string key = v.Token.Text;root.Context.Globals[key] = this.GetValue(tree, TokenType.AssignmentExpression, 1);return null;}// 函数赋值else if (v.Token.Type == TokenType.Function){string key = v.Nodes[0].Token.Text;// 函数查找是不区分大小写的if (root.Context.Functions.ContainsKey(key.ToLower()))if (!(root.Context.Functions[key.ToLower()] is DynamicFunction)){tree.Errors.Add(new ParseError("Built in functions cannot be overwritten", 1050, this));return null;}// 确定输入变量Variables vars = new Variables();ParseNode paramsNode = v.Nodes[2];if (paramsNode.Token.Type == TokenType.Params){ // 函数有参数,检查是否都是变量声明for (int i = 0; i < paramsNode.Nodes.Count; i += 2){ParseNode varNode = GetFunctionOrVariable(paramsNode.Nodes[i]);if (varNode == null || varNode.Token.Type != TokenType.VARIABLE){tree.Errors.Add(new ParseError("Function declaration may only contain variables", 1051, this));return null;}// 只是声明变量,此时不需要计算值vars.Add(varNode.Token.Text, null);}}// 声明动态定义的函数DynamicFunction dynf = new DynamicFunction(key, nodes[2], vars, vars.Count, vars.Count);root.Context.Functions[key.ToLower()] = dynf;return null;}// 返回结果为空return null;}// 获取函数或变量的方法private ParseNode GetFunctionOrVariable(ParseNode n){// 找到正确的节点,返回if (n.Token.Type == TokenType.Function || n.Token.Type == TokenType.VARIABLE)return n;if (n.Nodes.Count == 1) // 只查找左边的节点,不包含其他节点分支return GetFunctionOrVariable(n.Nodes[0]);// 函数或变量未在分支中找到return null;}// 解析字面量的评估方法protected override object EvalLiteral(ParseTree tree, params object[] paramlist){// 返回字面量的值return this.Token.Value;}// 根据类型和索引获取节点值的方法private object GetValue(ParseTree tree, TokenType type, int index){// 获取节点ParseNode node = this.GetNode(type, index);if (node == null) return null;// 获取节点的值return node.Eval(tree, null);}// 获取节点的方法private ParseNode GetNode(TokenType type, int index){// 遍历节点,找到指定类型的节点foreach (ParseNode node in this.nodes){if (node.Token.Type == type && index-- == 0)return node;}// 没有找到对应类型的节点return null;}}
}
这是一个包含解析树评估器的C#代码。解析树评估器是一个用于解析和评估表达式的类。它通过递归地遍历解析树的节点来执行表达式的计算。
10.
// 导入所需的命名空间
using System.Collections.Generic;
using System.Text.RegularExpressions;// 定义命名空间和类
namespace Macad.Common.Evaluator
{#region Scanner// 定义词法分析器类public partial class Scanner{// 声明类的成员变量和数据结构// Input:输入字符串// StartPos, EndPos:当前标记的起始和结束位置// CurrentLine, CurrentColumn, CurrentPosition:当前行、列和位置信息// Skipped:被跳过的标记列表// Patterns:存储不同标记类型的正则表达式// LookAheadToken:向前查看的标记// Tokens:存储所有标记类型的列表// SkipList:需要跳过的标记类型列表public string Input;public int StartPos = 0;public int EndPos = 0;public int CurrentLine;public int CurrentColumn;public int CurrentPosition;public List<Token> Skipped; // tokens that were skippedpublic Dictionary<TokenType, Regex> Patterns;private Token LookAheadToken;private List<TokenType> Tokens;private List<TokenType> SkipList; // tokens to be skipped// 构造函数,用于初始化词法分析器public Scanner(){// 初始化 Patterns 字典、Tokens 列表、LookAheadToken 和 Skipped 列表// 初始化 SkipList 列表并添加需要跳过的标记类型// 使用正则表达式初始化 Patterns 字典,添加各种标记类型及其对应的正则表达式// 将标记类型添加到 Tokens 列表中}// 初始化词法分析器的输入public void Init(string input){// 初始化输入字符串和其他位置、行列信息}// 根据标记类型创建标记对象public Token GetToken(TokenType type){// 根据指定的类型和位置信息创建一个标记对象并返回}// 执行向前查看并推进扫描位置到下一个标记public Token Scan(params TokenType[] expectedtokens){// 执行向前查看,获取下一个标记,并将扫描位置推进到下一个标记的位置}// 向前查看下一个标记public Token LookAhead(params TokenType[] expectedtokens){// 执行向前查看,获取下一个标记但不改变扫描位置}}#endregion#region Token// 定义标记类型的枚举public enum TokenType{// 定义各种标记类型}// 定义标记类,表示词法分析器生成的一个标记public class Token{// 标记的起始位置、结束位置、文本内容等属性// 包含了被跳过的标记列表}#endregion
}
这段代码实现了一个词法分析器(Scanner),用于将输入的字符串分解成一系列标记(tokens)。其中,Scanner 类负责扫描输入字符串并生成标记,而 TokenType 枚举定义了不同类型的标记。Token 类表示一个标记,包含了标记的各种属性信息。
11.
// 导入所需的命名空间
using System.Collections.Generic;// 定义命名空间和类
namespace Macad.Common.Evaluator
{// 定义 Variables 类,继承自 Dictionary<string, object>// Variables 类用于存储变量名和对应的值public class Variables : Dictionary<string, object>{// 定义 Clone 方法,用于复制当前变量集合// 此方法在支持局部作用域和递归时是必需的// 在函数中,变量集合(参数)的副本将被推送到作用域栈上public Variables Clone(){// 创建一个新的 Variables 对象来存储副本Variables vars = new Variables();// 遍历当前变量集合,将每个键值对复制到新的 Variables 对象中foreach (string key in Keys)vars.Add(key, this[key]);// 返回新的 Variables 对象副本return vars;}}
}
这段代码定义了一个名为 Variables 的类,该类继承自 Dictionary<string, object>,用于存储变量名和对应的值。其中包含了一个 Clone 方法,用于复制当前的变量集合,以便支持局部作用域和递归。Clone 方法会创建一个新的 Variables 对象,并将当前变量集合中的每个键值对复制到新对象中,最后返回该新对象的副本。