• MDSF:LOP使用MPS来做个计算器的示例


      在上一篇面向语言编程LOP(Language Oriented Programming)方法介绍中介绍了LOP以及一种LOP的实现方法MPS,本篇主要讲解一下使用MPS1.5的一个示例,以便大家能更好的理解是如何使用MPS实现LOP项目的。

    需求

    计算一个Java/PHP开发人员的收入,输入在Java和PHP项目投入的时间,计算器自动计算收入值,界面表示如下:

    目标

    通过写以下4行代码来生成这个计算器(10和5是常量)

      calculator MySalary
      input PHP Hours
      input Java Hours
      output Java Hours*10 + PHP Hours*5

    主要步骤

    • 生成前面目标中提到的语法的一种语言来实现计算器。语言定义基本的逻辑概念、组成规范、关系以及各自的行为
    • 生成一个生成器,定义构建swing应用程序的规则
    • 使用我们创建的语言来实现一个计算器
      看起来完成这个示例使用现有语言会更快些,但是这里我们的意图是想展示是当你如何使用MPS来建立一种特定功能的语言。

    下面主要讲解一下语言定义部分,代码生成器部分请参考MPS1.5的示例

    生成项目

    生成一个新的项目,项目名为:calculator

    按Next后,生成一种新的语言,设定语言命名空间为: jetbrains.mps.tutorial.calculator命名空间一般为companyName.meaningful.name)

    再按Next,生成一种新的方案(方案是一套特定语言的模型):

    理想情况下,语言和使用语言的方案是分离的两个项目,但是建议在生成语言时把这个项目放在一起,便于测试新的语言。

    按Finish后进入项目视图,默认展开语言项目jetbrains.mps.tutorial.calculator()节点:

    语言项目下有多个节点,这些节点前面都带有M图标,分别代表模型的不同方面:

    • structure:描述语言语法
    • editor:描述编写语言时的编辑器
    • constraints:描述一些约束
    • type system:描述如何计算节点类型

    jetbrains.mps.tutorial.calculator.sandbox)表示我们的测试方案节点,Modules Pool() 包含一系列可以参考使用的语言和方案,后面会再介绍这些内容。

     

    下面我们开始来建立Calculator语言

    Calculator概念(concept)

      就像类定义它的实例字段、方法和其他成员的结构一样,概念定义它的实例属性、引用和子概念定义的结构。概念是可以继承的,缺省每一个概念都从BaseConcept继承下来,它将会继承父概念的所有属性、子概念和引用等结构。

      首先我们需要生成一个新的概念:Calculator。设置instance can be roottrue,实现INamedConcepts接口以便具有Name属性,

     

    提示:Tab/Shift+Tab可以导航编辑焦点<> ;按Ctrl+Space可以打开自动完成提示列表

    生成一个编辑器

      MPS编辑器看上去是文本编辑器,但是它是一个直接使用语法树的一个结构化编辑器。编辑器使用单元格(cells)来表示概念节点,这里有以下几种节点类型:

    • 属性单元格: 编辑节点属性
    • 常量单元格:显示常量值
    • 集合单元格:在内部嵌套其他单元格

    前面定义了概念calculator,它的编辑器应该为:calculator name

    选择Calculator概念的【Editor】页签,新增一个概念编辑器,

    1. 添加一个缩进集合类型编辑器:[-
    2. 输入常量:calculator
    3. 建立一个属性单元格编辑器
      在‘calculator’常量单元格编辑器后按Enter键,通过‘{’选择属性name:{name}

    测试一下概念编辑器

      在语言项目中,点击右键选择 Generate Language 来生成语言。生成之后,我们在方案项目新建一个模型:

    Model name中输入类型 jetbrains.mps.tutorial.calculator.sandbox

    jetbrains.mps.tutorial.calculator语言加入到Model Properties对话框的Used Languages中,这样才能使用这个语言来编写应用:

    在测试模型sandbox中新建一个Calculator概念测试应用,显示如下:

    到现在我们已经简单建立了第一条语言,下面建立输入字段概念

    给Calculator加上子概念InputField

    新建一个InputField概念,设置instance can be rootfalse,实现INamedConcepts接口以便具有Name属性,然后再生成编辑器:[- input { name } -]

    为了使得计算器包含输入字段,需要把InputField类型作为Calculator概念子对象:

    选择在Calculator编辑器中的属性name,按Alt+Enter弹出意图列表,选择Add New Line

    为了每个输入字段显示一行,我们可以对子对象InputField选择Add newline for children意图:

    Ctrl+F9重新生成语言后,再次进入应用界面:

    输出概念:OutputField

    生成一个默认的输出概念:OutputField,编辑器如下:

    把OutputField添加到calculator概念子对象中:

    Calculator编辑器更改如下:

    现在我们能够在outfield中输入任何表达式:

    添加表达式支持

    MPS中有基础语言,新的语言使用它们需要让自己的语言扩展基础语言。现在我们需要使用表达式功能,打开语言属性对话框:

    Dependencies 页签中的Extended Languages 列表选择jetbrains.mps.baseLanguage:

    BaseLanguage包含一个Expression概念,它表示一个表达式,格式如"2", "2+3", "abc+abc"等。这个就是我们这里示例中output需要的。

    现在给OutputField添加expression子类型:

    更改编辑器:

    现在可以输入表达式,但是还不能通过input计算,应用界面如下:

    扩展表达式概念

    为了支持通过input来计算,我们需要生成自己的表达式类型。建立概念InputFieldReference,从Expression继承下来,添加InputField为引用概念field

    生成InputFieldReference编辑器:%field%-> {name}表示引用概念属性

    应用界面如下:MPS的智能引用会在当前上下文决定哪些引用可以使用,这里自动完成列表会列出width

    定义生成器

      MPS生成器语言使用两种参数引用:property macros (marked with $) andnode macros ($$)。

      我更关注的是前面语言定义部分,这部分还没有具体看,刚兴趣的可以参考MPS1.5的示例

    MPS网站

     Download MPS

     A Language Workbench in Action - MPS

     

    欢迎转载,转载请注明:转载自周金根 [ http://zhoujg.cnblogs.com/ ]

  • 相关阅读:
    Canny边缘检测高低阈值问题
    EffectiveC++ Item25测试
    下载videolectures.net里的视频的方法
    01章 象数易理篇之一
    论文格式问题
    反序列化笔记
    什么是动爻
    EffectiveC++ Item25说的东东
    优化功能
    论文修改意见
  • 原文地址:https://www.cnblogs.com/zhoujg/p/1839523.html
Copyright © 2020-2023  润新知