关键词:C# .NET 计算器 词法分析 语法分析 表达式计算 ConExpress Calculator
以上分析部分结束了,这里介绍调用方法以及主程序。
如果把计算器的功能打包成一个dll,那入口只有一个,SyntaxAnalyse类。new一个SyntaxAnalyse类之后,调用其中的Analyse方法,将要计算的运算表达式作为参数传递进去,返回一个顶级TokenRecord对象,再根据返回的TokenRecord对象的值类型取得结果,整个计算过程就结束了,使用起来非常方便。
/// <summary>
/// 表达式分析计算类,功能入口
/// </summary>
/// <remarks>Author:Alex Leo @ ConExpress</remarks>
public class SyntaxAnalyse
{
/// <summary>
/// 构造函数
/// </summary>
/// <remarks>Author:Alex Leo; Date:2007-8-2</remarks>
public SyntaxAnalyse()
{ }
/// <summary>
/// 分析语句并返回记号记录对象
/// </summary>
/// <param name="Code">运算表达式</param>
/// <returns>顶级TokenRecord对象</returns>
public TokenRecord Analyse(string Code)
{
if (Code.Trim().Equals(string.Empty))
{
return new TokenValue(0);
}
List<TokenRecord> ListToken = new List<TokenRecord>();//TokenRecord列表
int intIndex = 0;
TokenFactory.LexicalAnalysis(ListToken, Code, ref intIndex);//词法分析,将代码转换为TokenRecord列表
//语法树分析,将Token列表按优先级转换为树
TokenRecord TokenTop = SyntaxTreeAnalyse.SyntaxTreeGetTopTokenAnalyse(ListToken, 0, ListToken.Count - 1);
TokenTop.Execute();
return TokenTop;
}
}
窗体的调用也很简单,并没有设计漂亮的外观和高级设置等。
在窗体类中建立一个字段SyntaxAnalyse myAnalyse = new SyntaxAnalyse();
在计算按钮中执行计算操作:
private void btnExecute_Click(object sender, EventArgs e)
{
string strInput = this.rtbInput.Text.Trim().Replace("/n", "");//将回车换行删除
if (strInput == "")
{
this.rtbOutput.Text = "输入的表达式不能为空,请重新输入。";
}
else
{
try
{
TokenRecord TokenTop = myAnalyse.Analyse(strInput);//计算表达式
this.rtbOutput.Text = TokenTop.GetValueString();//显示计算结果
this.LoadSyntaxTree(TokenTop);//加载语法树到TreeView控件
}
catch (Exception ex)
{
this.rtbOutput.Text = "发生错误,错误信息为:/n" + ex.Message;//显示错误信息
}
}
}
这里提供了一个TreeView控件来显示程序对表达式的分析情况,在LoadSyntaxTree方法中实现树的加载。在TreeView中节点的显示信息为TokenRecord的类名称+值+值类型,如果需要修改显示信息,只需要对TokenRecord类中的ToString方法进行修改即可。
/// <summary>
/// 加载语法树
/// </summary>
/// <param name="TokenTop">顶级记号对象</param>
/// <remarks>Author:Alex Leo @ ConExpress</remarks>
private void LoadSyntaxTree(TokenRecord TokenTop)
{
this.trvSyntaxTree.BeginUpdate();
this.trvSyntaxTree.Nodes.Clear();
TreeNode nodRoot = new TreeNode(TokenTop.ToString());//新建根节点
nodRoot.Tag = TokenTop;
this.LoadSyntaxTreeSubNode(nodRoot, TokenTop);//递归加载下级节点
this.trvSyntaxTree.Nodes.Add(nodRoot);//添加根节点到TreeView控件
this.trvSyntaxTree.EndUpdate();
}
/// <summary>
/// 加载语法树下级节点
/// </summary>
/// <param name="ParentNode">上级节点</param>
/// <param name="ParentToken">上级记号</param>
/// <remarks>Author:Alex Leo @ ConExpress</remarks>
private void LoadSyntaxTreeSubNode(TreeNode ParentNode, TokenRecord ParentToken)
{
//循环加载下级节点
for (int intIndex = 0; intIndex < ParentToken.ChildList.Count; intIndex++)
{
TokenRecord TokenChild = ParentToken.ChildList[intIndex];
TreeNode nodChild = new TreeNode(TokenChild.ToString());
nodChild.Tag = TokenChild;
ParentNode.Nodes.Add(nodChild);
LoadSyntaxTreeSubNode(nodChild, TokenChild);//递归加载下级节点
}
}
主界面中设置了AcceptButton和CancelButton,AcceptButton为“计算”按钮,CancelButton为“退出”按钮。输入计算表达式之后,按回车即可执行计算,如果需要退出程序,按Esc即可,方便操作。
以下是主界面: