首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >约束定义语言

约束定义语言
EN

Stack Overflow用户
提问于 2018-03-31 17:05:08
回答 1查看 142关注 0票数 1

我需要设计一种语言,它根据下面的定义执行约束。下面的清单是brat的实际注释配置。我的任务是为我们的内部工具设计一种类似的语言。我也计划用python编写解析器。

代码语言:javascript
复制
[entities]
Drug
DrugClass
Procedure
Therapy
AE
SAE
Disease

[relations]
Equiv   Arg1:<ENTITY>, Arg2:<ENTITY>, <REL-TYPE>:symmetric-transitive

BelongsTo   Arg1:Drug         , Arg2:DrugClass
BelongsTo   Arg1:AE           , Arg2:AE
BelongsTo   Arg1:AE           , Arg2:SAE
BelongsTo   Arg1:SAE          , Arg2:SAE
BelongsTo   Arg1:SAE          , Arg2:AE
BelongsTo   Arg1:Disease      , Arg2:Disease
BelongsTo   Arg1:Drug         , Arg2:Therapy
BelongsTo   Arg1:Procedure    , Arg2:Therapy
BelongsTo   Arg1:Surgery      , Arg2:Therapy

<CAUSE>=Drug|DrugClass|Therapy|Procedure
<EV>=AE|SAE

AssociatedWith      Arg1:<CAUSE>    , Arg2:<EV>
NotAssociatedWith   Arg1:<CAUSE>    , Arg2:<EV>

Causes          Arg1:<CAUSE>    , Arg2:<EV>
NotCauses       Arg1:<CAUSE>    , Arg2:<EV>

HasEffect       Arg1:<CAUSE>    , Arg2:Disease
HasNoEffect     Arg1:<CAUSE>    , Arg2:Disease

<OVERLAP>   Arg1:<ANY>, Arg2:<ANY>, <OVL-TYPE>:<ANY>

我的想法是这样的。

代码语言:javascript
复制
[entities]
# subtyping entities which is already present in brat
Entity
  Trigger
    Drug
    DrugClass
    Procedure
    Therapy
  Effect
    AE
    SAE
    Disease

[relations]
# Any subtype of Trigger can be Associated with any subtype of Effect except Disease    
AssociatedWith  Arg1:Trigger    , Arg2:Effect.except(Disease)
NotAssociatedWith   Arg1:Trigger    , Arg2:Effect.except(Disease)

Causes      Arg1:Trigger    , Arg2:Effect.except(Disease)
NotCauses       Arg1:Trigger    , Arg2:Effect.except(Disease)

HasEffect       Arg1:Trigger    , Arg2:Disease
HasNoEffect     Arg1:Trigger    , Arg2:Disease

# Equiv relation can exist between Drug and Drug,
# DrugClass and DrugClass and so on,
# but not between different subtypes Drug and AE
Equiv   Arg1:Entity*          , Arg2: Entity*      

BelongsTo   Arg1:Entity*          , Arg2: Entity*      
BelongsTo   Arg1:Drug         , Arg2:Therapy
BelongsTo   Arg1:Procedure        , Arg2:Therapy
BelongsTo   Arg1:Surgery          , Arg2:Therapy

<OVERLAP>   Arg1:<ANY>, Arg2:<ANY>, <OVL-TYPE>:<ANY>

是否已经有一种语言可以做到这一点。我研究过Prolog,它看起来有点过头了。我想我正在寻找一种可以处理对象分组和粒度寻址的语言,以便可以简洁地指定约束。谢谢

EN

回答 1

Stack Overflow用户

发布于 2018-04-16 04:58:58

更容易思考的是,这些定义在解析后在内存中会是什么样子-然后向后工作。一种简单的解析方法是将每一行都视为一个“方法调用”--例如"BelongsTo Arg1:Drug“可以看作是对ParserContext对象的隐式"this.BelongsTo”方法调用。因此,您基本上是用一个ParserContext类“评估”文件,文件中的每一行都“静默”地调用基类上的方法,慢慢地在内存中构建。当最后一行完成时,内存中的定义也完成了。

在Ruby中,人们不需要在方法和“this”之间加上花边新闻。是隐含的(与大多数其他语言一样)。因此,您认为的DSL/语言只是Ruby中的普通代码。

让我们来看一个简单的Parser类。

代码语言:javascript
复制
class Context
  def new
    # initialize some vars
    this.entities = {}
  end

  def Entity(name, ...args)
    # save to 
    self.entities[name] = ...args
  end

  def BelongsTo(entity, ...args)
    # process belongs to with the entity
  end

  ... every DSL feature is a language method ...
  ... if you want to "zoom-in" or focus on an entity, use blocks

让我们以以下DSL为例。

代码语言:javascript
复制
Entity "Arg1"
BelongsTo "Arg2"

这个简单的阅读器:

代码语言:javascript
复制
ctx = Context.new
ctx.instance_eval File.read "my dsl file"

因此,DSL文件只是通过将"this“设置为context对象来计算的,并且DSL中的每一行都是普通的方法调用。Ruby中的Gemfile,Rails中的Routes文件,许多ORM定义,等等--总是使用这个技巧。看起来DSL只是一段很好的代码。以Ruby - https://github.com/rdsubhas/ruby-blocks/blob/master/Mapping为例,你会发现尽管它看起来像一个领域特定语言,但实际上它只是一段代码,实际上并不需要解析器来解析这些代码。语言本身会对其进行解析。

这不仅仅是针对Ruby的,每种语言都有自己的"eval“技巧。我相信nodejs也可以做到这一点(jasmine/cucumber测试)。

希望这能回答你的问题。总结一下:

  • 查看解析后在内存中的样子
  • 使用语言解析器
  • 向后处理DSL

附注:您展示的DSL看起来足够复杂,业务/产品人员不容易使用它。看起来它是为开发人员或高级用户准备的。所以不要给DSL加上self约束,比如它必须有括号,或者不能有双引号之类的东西。如果这是为高级用户准备的,那么引号或括号的使用将不再重要。选择一个对你来说最不费力的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49586096

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档