4

很抱歉我想不出更好的标题。

问题如下:

对于我们的客户,我们创建了(作为更大应用程序的一部分)一个图形设计器,他们可以使用它来构建“场景”。

这些场景由“复合”组成,而“复合”又由“命令”组成。这些命令对象都派生自 CommandBase 并实现了一个名为 ICompilable 的接口。

场景类还实现了 ICompilable。当在命令上调用 Compile() 时,会返回一个字节数组,然后可以将其发送到它们所针对的设备(无法透露有关该硬件的太多信息,抱歉)

只是给你一个想法:

var scenario = new Scenario();

scenario.Add(new DelayCommand(1));
scenario.Add(new CountWithValueCommand(1,ActionEnum.Add,1));
scenario.Add(new DirectPowerCommand(23,false,150));
scenario.Add(new WaitCommand(3));
scenario.Add(new DirectPowerCommand(23,false,150));
scenario.Add(new SkipIfCommand(1,OperatorEnum.SmallerThan,10));
scenario.Add(new JumpCommand(2));

byte[] compiledData = scenario.Compile();

图形设计师从用户那里抽象出所有这些,并允许他(或她)简单地将复合材料拖放到设计师表面上。(组合可以对命令进行分组,因此我们可以为返回任务提供构建块)

最近我们的客户来找我们说,“设计师真的很酷,但我们有些人更愿意拥有某种编程语言,只是一些简单的东西。”

(当然对他们来说很简单)

我非常想为他们提供一种简单的语言,它可以调用各种命令,还可以用更好的结构替换 SkipIfCommand 等...

我不知道从哪里开始或我的选择是什么(不破坏我们所拥有的)

我听说有人嵌入诸如 Python 之类的语言,有人编写自己的语言和解析器,等等……

有什么建议么?

PS:用户只使用复合,从不使用命令。组合是在运行时动态加载的(连同它们的图形设计器),并且可以由第三方在单独的程序集中提供。

4

6 回答 6

4

据我所知,我理解你有两种选择

您可以使用 XML 样式的“标记”让他们定义实体及其分组,但这可能不是最好的。

你的选择是肯定的,你可以嵌入一种语言,但你真的需要吗,那不是矫枉过正,你怎么能控制它?

如果您只需要非常简单的语法,那么也许可以编写自己的语言。实际上,创建一个简单的解释器并不难,只要你有一种严格、明确的语言。看看你使用的任何编译器的一些例子,c#?

我在 uni 用 java 写了一个非常简单的interperter,它没有你想象的那么难。

于 2008-11-04T21:47:19.053 回答
2

对于简单的 DSL,这看起来是一个完美的场景。有关一些信息,请参阅http://msdn.microsoft.com/en-us/library/bb126235(VS.80).aspx

您还可以使用脚本语言,例如 lua.Net。

于 2008-11-04T22:08:12.163 回答
2

如果您真的只想要一种简单的语言,那么您需要一个“递归下降解析器”。

例如,这样的语言:

SCENARIO MyScenario
DELAY 1
COUNT 1 ADD 1
DIRECT_POWER 23, False, 150
WAIT 3
...
END_SCENARIO

你可能有这样的语法:

scenario :: 'SCENARIO' label newline _cmds END_SCENARIO
cmds::  _delay or _count or _direct_power or...
delay:: 'DELAY' number

这给出了如下代码:

def scenario():
    match_word('SCENARIO')
    scenario_name = match_label()
    emit('var scenario = new Scenario();')
    cmds()
    match_word('END_SCENARIO')
    emit('byte[] ' + scenario_name + ' = scenario.Compile();')

def delay():
    match_word('DELAY')
    length = match_number()
    emit('scenario.Add(new DelayCommand('+ length +'))')

def cmds():
    word = peek_next_word()
    if word == 'DELAY':
       delay()
    elif ...
于 2008-11-04T22:11:58.990 回答
1

这是一个用于构建 DSL 的 Pythonic 解决方案,您可以使用它来编译和创建字节码数组。

  1. 编写一个简单的模块,使您的 C# 结构可用于 Python。目标是将允许用户使用的每个 C# 类(Composites 或 Commands 或其他)定义为 Python 类。

    通常,这涉及实现一组最小的方法,其中包含从 C# 类型到本机 Python 类型的不同转换,反之亦然。

  2. 编写一些不错的演示,展示如何使用这些 Python 类定义来创建它们的脚本。你应该能够在 Python 中创建这样的东西。

    import * from someInterfaceModule
    scenario= Scenario(
        Delay(1),
        Repeat( Range(10),
            DirectPower( 23, False, 150),
            Wait(3),
            DirectPower( 23, False, 150)
        )
    )
    scenario.compile()
    

这些是定义相对简单的类。这里的每个类都可以相当容易地实现为直接调用基本 C# 模块的 Python 模块。

语法是纯 Python,不需要额外的解析或词法扫描。

于 2008-11-04T22:31:45.050 回答
1

要添加到 S.Lott 的评论中,以下是您如何从 C# 评估 Python 脚本

于 2008-11-04T22:36:41.420 回答
0

虽然创建这种迷你语言并将其全部编码可能会很有趣,但您需要提出的真正问题是:

  1. 添加此功能/设施的商业案例是什么?
  2. 谁来为这个功能买单?
  3. 如果您构建此功能,谁将“签署”此功能?

当现实可能表明对此类请求的真正答案是“不”时,“非常整洁”的功能有一种构建方式。

在继续之前,看看您是否有愿意赞助的利益相关者。然后在提交项目之前与最终用户核实,看看他们真正想要什么。

干杯,

-R

于 2008-11-04T23:57:34.313 回答