代码之家  ›  专栏  ›  技术社区  ›  TimothyP

我们有一个图形设计师,现在他们想要一个基于文本的设计师。建议?

  •  4
  • TimothyP  · 技术社区  · 17 年前

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

    问题如下:

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

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

    场景类还实现了ICompilable。当编译器()被调用时 在命令上返回一个字节数组,然后可以将其发送到设备 它们的目的是(很抱歉,不能透露太多关于该硬件的信息)

    只是给你一个想法:

    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();
    

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

    最近我们的客户来找我们说:“这位设计师真的很酷, 但我们有一些人更喜欢某种编程语言, 只是一些简单的事情。"

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

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

    我不知道从哪里开始,也不知道我的选择是什么(在不破坏我们现有的情况下)

    我听说有人嵌入Python等语言, 人们编写自己的语言、解析器等。。。

    有什么建议吗?

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

    6 回复  |  直到 17 年前
        1
  •  4
  •   Andrew Bullock    17 年前

    据我所知,你有两个选择

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

    你的选择是,是的,你可以嵌入一种语言,但你真的需要吗?这不是太过分了吗?你怎么能控制它呢?

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

    我在大学用java写了一个非常简单的解释器,并没有你想象的那么难。

        2
  •  2
  •   Charles Merriam    17 年前

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

    例如,这样的语言:

    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 ...
    
        3
  •  2
  •   Bogdan    17 年前

    对于简单的DSL来说,这似乎是一个完美的场景。看见 http://msdn.microsoft.com/en-us/library/bb126235(VS.80).aspx 一些信息。

    您还可以使用lua等脚本语言。网。

        4
  •  1
  •   S.Lott    17 年前

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

    1. 编写一个简单的模块,使Python可以使用C#结构。目标是将允许用户使用的每个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,不需要额外的解析或词法扫描。

        5
  •  1
  •   Chui Tey    17 年前

    要添加到S.Lott的评论中,请按照以下方式操作 eval a Python script from C#

        6
  •  0
  •   Huntrods    17 年前

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

    1. 添加此功能/设施的商业案例是什么?
    2. 谁会为这个功能付费?
    3. 如果你构建了这个功能,谁会“签字”呢?

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

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

    干杯,

    R