我应该如何实现命令处理应用程序?


9

我想制作一个简单的概念验证应用程序(REPL),该应用程序需要一个数字,然后处理该数字上的命令。

示例:我从1开始。然后我写“ add 2”,它给我3。然后我写“ multiply 7”,它给我21。然后我想知道它是否是素数,所以我is prime在当前数字上写“ ”( 21),这给了我错误。” is odd将使我成真。等等。

现在,对于具有很少命令的简单应用程序,即使是简单的应用程序switch也可以处理命令。但是,如果我想要扩展性,我将如何实现功能?我是否使用命令模式?我是否为该语言构建简单的解析器/解释器?如果我需要更复杂的命令(例如“ multiply 5 until >200”)怎么办?没有重新编译就可以扩展它(添加新命令)的简单方法是什么?

编辑:为了澄清一些事情,我的最终目标不是制作类似于WolframAlpha的东西,而是制作一个(数字列表)处理器。但是,我想一开始慢慢开始(以单个数字开始)。

我想到的是与使用Haskell处理列表的方式类似的方法,但它是一个非常简单的版本。我想知道像命令模式(或等效命令)之类的内容是否足够,还是我必须制作一个新的迷你语言和一个解析器来实现我的目标?

Edit2:感谢所有答复,所有这些对我都非常有帮助,但是Emmad Kareem对我的帮助最大,所以我选择它作为答案。再次感谢!


2
我不赞成。请说明您的原因,以便下次更好地提出我的问题。
妮妮·迈克尔斯

2
我真的很喜欢这个问题。期待看到人们提出的设计建议。您是否正在专门寻找面向对象的设计(您提到了命令模式,这是一种OO模式)?
Bjarke Freund-Hansen

谢谢:)是的,我更喜欢OOP,但是我不介意是否建议使用其他方法!
妮妮·迈克尔斯

2
似乎是反向波兰符号的实现,这是一个非常酷的编程主题!
Alberto De Caro 2012年

2
你可能会落入犯规条款从什么样的问题,我应该问吗?在FAQ中,即如果您能想象出一本完整的书可以回答您的问题,那么您的要求就太多了
Mark Booth

Answers:


5

听起来像是翻译。看起来您担心的是实现而不是详细的功能(我只是在这里猜测)。如果扩展该项目,则不是一件容易的事。确保您清楚地研究范围,因为这需要工程方法而不是临时开发方法来获得可靠的产品,而不是有时只能工作的具有1000个补丁的产品。

确定语法并准备解析它并执行必要的语法检查。该链接可以帮助您:创建自己的解析器

看看:这个主题涉及到工作的各个方面,也有很好的链接可以为您提供帮助(特别是RMK的回答)。:创建语言解释器。您可能想要看一个外观精美的项目示例,该示例在以下位置有些相似:Ultimate Programmable Scientific Calculator。您可以在此处Command-Line-Implementation-of-C#-Made-for-Teaching中找到命令行C#解释器的源代码和工作程序。使用编译器为您完成复杂的任务,例如解析和变量键入等,可能是摆脱您自己编写所有复杂代码的聪明方法。另外,还有一个Mono选项,它提供了一个charp shell功能,您可能需要看一下:CsharpRepl


谢谢,您的链接真的很有帮助!因此,我想如果我想轻松地进行扩展,那么口译员将是最佳选择。
Nini Michaels 2012年

感谢您的反馈,我想从CodeProject的链接开始可能是个好主意。
NoChance 2012年

2

除非您对自己编写实际的解析器特别感兴趣,否则建议您看一看解析器生成器框架之一。对于C,您可以使用YACCBison,但是如果您愿意,应该有其他语言的替代选择。

这些消除了解析复杂语法的复杂性,使您可以专注于要执行的任务。当然,这对于您在问题中建议的语法可能是矫kill过正,但是由于您提到以后可以选择扩展到更复杂的语法,因此至少值得从这些框架中获得一些启发。


1
大多数解析器生成器的问题在于它们的工件是静态的,并且不容易扩展。我认为OP可以更好地与规则引擎一起使用,其中“规则”(关键字和语法)存储在灵活的数据结构中,并在每次输入后进行评估。
TMN 2012年

2

您所描述的内容非常接近于堆栈语言

例如,在Factor中,您所描述的将像

1
2 +
7 *
even? not

或者,您可以定义自己的单词,然后使用它们,例如

: add ( x y -- sum ) + ;
: multiply ( x y -- product ) * ;
: odd? ( n -- ? ) even? not ;

通过这些定义,上面的示例变为

1
2 add
7 multiply
odd?

通常,堆栈语言很难解析,因为它们使用以空格分隔的单个单词。我建议您看看Factor-可能正是您想要的。定义进行所需处理的单词应该很容易。

编辑:如果您实际上想设计一种类似的语言,我建议您还是使用其中一种。解析堆栈语言是微不足道的-您可以在空白处进行拆分,并且幼稚的处理实现很容易:您只需要注意堆栈上发生的事情即可。


这听起来很容易,也是一个不错的起点。谢谢!
妮妮·迈克尔斯

1

但是,如果我想要扩展性,我将如何实现功能?

你不应该 可扩展性带来了很多复杂性,却很少获得收益。也就是说,您需要提供一个到现有状态的挂钩。一种查看状态,修改状态并提供返回其他结果(打印到屏幕)的机制。您需要一种让核心代码发现模块,加载模块并将命令分发给模块的方法。

我是否使用命令模式?

可以,但是可能不合适。

您不会拿走整个输入并将其发送出去进行处理,而是解析输入,将其分派到正确的处理程序并让其完成工作。该命令在该通信中没有变化;所以没有命令模式。

我是否为该语言构建简单的解析器/解释器?

您将需要一些处理来将输入分解为令牌。对于可扩展的解决方案,您可能不会做更多的事情。对于定义良好的解决方案,拥有完整的分析树将提供更好的性能,错误处理和调试能力。

而是一个(数字列表)处理器

然后,也许您应该研究LIST处理语言。代码和数据的并置应该与您所描述的完全吻合。


感谢您的建议。对于LISP,我很熟悉,甚至更熟悉Haskell,这激发了我这个想法。但是,即使我可能需要重新发明轮子,我也希望通过处理命令和解释它们来使自己不寒而栗。因此,除了实际的“列表处理”之外,它还具有教育目的:)
Nini Michaels

@NiniMichaels当然可以,但是就可扩展性的设计而言,使用lisp的组织/代码/数据链不是一个坏选择。
Telastyn
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.