【问题标题】:Are fluent interfaces described by context free or regular grammars?流畅的接口是由上下文无关的还是规则的语法描述的?
【发布时间】:2012-03-25 18:49:51
【问题描述】:

我在玩 Martin Fowlers 文本风格的流畅界面,我想知道他们描述的语法是上下文无关的还是常规的?我说的是这样的接口:

var car = new Car();
car.Configure().MakeCar.With.Wheels(4).And.Engine.Using.Petrol;

我想做的是编写一个可以生成它们的程序。目前它需要输入上下文无关语法,但我似乎很难将其转换为源代码应用程序。我怀疑答案是我只能使用常规语法,因为无法知道“堆栈”的状态,因为必须事先知道每个“终端”方法的结果。

我现在得到的东西有效,但它在某些语法上出错了。

编辑:我使用常规语法,代码是开源的,如果有人热衷于玩弄它,现在可以使用它。 https://github.com/Dervall/Snout

【问题讨论】:

  • 它应该是 C# 中的属性,作为示例语言。
  • 确实是我的错。由于 Fowler 的提及,我错过了 var 并假设是 Java。顺便说一句,从 CFG 生成它的好主意!
  • 至少是这样的想法,但我认为我们必须满足于常规语法,否则我正在编写错误代码。 :)

标签: fluent-interface context-free-grammar regular-language


【解决方案1】:

任何时候的选项集都由该类上可用的方法决定。该方法返回的类确定下一组方法。

所以生成链的语法规则是right regular grammar,其中开始符号是类,符号是方法,非终结符是方法返回的类:

class Car:
    configure: Configurator

class Configurator:
    with: Configurator // noise method
    and: Configurator // noise method
    wheels: int -> Configurator
    windows: int -> WindowDetails

class WindowDetails:
    transparent -> Configurator
    tinted -> Configurator

忽略方法 args (int):

Car -> "configure" Configurator
Configurator -> "with" Configurator
Configurator -> "and" Configurator
Configurator -> "wheels" Configurator
Configurator -> "windows" WindowDetails
WindowDetails -> "transparent" Configurator
WindowDetails -> "tinted" Configurator

但是这没有捕捉到wheels的参数(轮子的数量)。并且常规语法无法处理该问题,因为不同的整数参数可能会导致不同的类(例如,在“(2)”之后,您是否有配置器或WindowDetails?):

Configurator -> "wheels" Integer
Configurator -> "windows" Integer
Integer -> ?

所以这取决于你想要什么。方法链可以用正则文法来描述。但是常规语法也不能描述传递给方法的参数。有事。

可以通过添加上下文无关语法的复杂性来处理参数,因为这样您就可以执行以下操作:

Configurator -> "wheels" Integer Configurator
Configurator -> "windows" Integer WindowDetails

在整数参数之后具有正确继续所需的额外信息。

注意:以上假设方法名称在所有类中都是唯一的。如果您有两个具有相同方法名称的不同类,那么您显然会遇到问题(我希望)(如果您使用诸如“with”和“and”之类的东西,这可能并不罕见......)

【讨论】:

  • 我对未处理的参数很好,但它们不能,因为我们需要知道编译时返回的类以呈现下一组选项。但是你的意思是语法类是regular语法而不是context free对吧?
  • 以上使用的是常规语法。我认为在简单的方法链中不需要上下文无关语法。他们将需要处理参数(过度简化,但任何带括号的东西都倾向于暗示上下文无关,因为一旦括号关闭,您需要“弹回”到您之前所做的事情)。所以“是的”。查看更新。
  • 我明白了,我试图做的是使用普通的 LR 解析表来生成“状态”类,但问题是你不能给一个单一的状态来判断哪个状态将是减持的目标。我当然可以生成ExpandoObjects 并跟踪堆栈,但是我不会有语法高亮,这是重点。似乎常规语法是要走的路
  • 我不懂 LR 解析,所以我不能帮你详细说明。但由于常规语法是上下文无关语法的一个子集,我会认为你可以让它工作。 en.wikipedia.org/wiki/Chomsky_hierarchy - 常规语法真的很愚蠢。它所能做的就是方法链。 cfg 可以做更多事情(包括方法链)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-12
  • 2012-03-27
  • 1970-01-01
  • 2019-04-12
  • 2010-11-23
  • 2014-02-08
  • 2014-02-27
相关资源
最近更新 更多