您可以解析A
以构造一棵指令树,然后从叶子开始执行它们(因为我假设您想先执行最里面括号的内容)。对于这个解析任务,你可以使用正则表达式,或者任何你想要的。在我的脑海中,我认为您可以首先查找括号和运算符符号来找出树结构,然后用实际的基本指令和运算符的每个连接点填充每个叶子。
存储的数据结构A
可以由Expression
实现接口的对象(调用它们)组成IOperand
;每个都Expression
应该有三个字段:
- 一个字段
Operator
,它是 的一个实例enum Operations {Union, Intersection, SetDiff}
,或者只是一个字符串,这取决于您喜欢哪个。
- 两个字段
Operand1
and Operand2
,可以是“Ah”(定义一组卡片)之类的东西,也可以是另一个Expression
. 因此,它们应该被声明为IOperand
.
你的持有一组卡片的类,比如“Ah”,也应该实现这个IOperand
。接口IOperand
本身实际上不需要做任何事情。
为了将每个给定指令与操作相匹配,您可以使用一个简单的开关,或者使用一个Dictionary
of string
(or enum
) to delegate IOperand SetOp(IOperand, IOperand);
,然后Dictionary
使用(匿名)函数填充您的函数(其中包含 的指令B
)。
在这种Dictionary
情况下,您只需能够做到instructionList[thisExpression.Operation](thisExpression);
(这可能会更优雅地完成以避免引用thisExpression
两次)并且将执行字符串输入的适当 C# 翻译。
概念证明
我已经做了一个基本的实现和一个控制台应用程序来演示这里的用法:https ://bitbucket.org/Superbest/lexer
如果你在整个练习中成功地保持理智(计算机会将你用作代理解析和操作库,祝你好运),那么最后一步应该要求你评估一个等于的表达式C
,然后打印什么你刚回到你身边。(第一次运行时,你可能想遵守程序的指令。我怀疑很容易破坏代码并得到很多异常,如果你想一想你的无效发生了什么,你会很困惑输入。)
如果您按原样运行代码,请尝试以下答案序列(,= Enter):
n, y, 2, n, n, n, y, 2, n, n, y, n, y, 2, n, n, n, n, alpha, beta, gamma
您的输出将是:
gamma
您应该能够简单地更新标记为过时的方法体并拥有一个工作程序。
如果您希望添加更多二进制操作,请参阅Simplification.Simplification()
. 通过查看我已经进行的三个操作,适当的语法将是显而易见的;事实上,该代码仅支持二进制操作。如果您的方法使用字符串,则可以使用该SimplifiedOperand.Symbol
字段。