Are fluent interfaces described by contextual or regular grammars?
I'm playing around with fluid interfaces in the style of Martin Fowlers' text, and I'm wondering if the grammar they describe is contextual or normal? I'm talking about interfaces like:
var car = new Car();
car.Configure().MakeCar.With.Wheels(4).And.Engine.Using.Petrol;
What I am trying to do is write a program that can generate them. Currently it requires entry into a context free grammar, but it seems to me that there is some difficulty converting this into a source code application. I suspect the answer is that I can only use regular grammars, since the state of the "stack" cannot be known, since the result of each "terminal" method must be known in advance.
Now I have works, but this is on some grammars.
Edit: I went with regular grammars, the code is open source and now works in case anyone wants to play around with it. https://github.com/Dervall/Snout
source to share
the set of options at any point is determined by the methods available in the class at that point. the class returned by this method defines the following set of methods.
so the grammar rules that generate the chaining are the correct regular grammar , where start characters are classes, characters are methods, and non-terminal are classes returned by methods:
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
ignoring the args (int) method:
Car -> "configure" Configurator
Configurator -> "with" Configurator
Configurator -> "and" Configurator
Configurator -> "wheels" Configurator
Configurator -> "windows" WindowDetails
WindowDetails -> "transparent" Configurator
WindowDetails -> "tinted" Configurator
but what this fails to capture is the argument to wheels (number of wheels). and a regular grammar can't handle it because different integer arguments can result in different classes (for example after "(2)" do you have a configurator or WindowDetails?):
Configurator -> "wheels" Integer
Configurator -> "windows" Integer
Integer -> ?
so it depends what you want. the method chain can be described by a regular grammar. but a regular grammar cannot describe the arguments passed to methods either. AFAICT.
you can handle the arguments by adding the complexity of context free grammars, because then you can do something like:
Configurator -> "wheels" Integer Configurator
Configurator -> "windows" Integer WindowDetails
which has the extra information needed to proceed correctly after an integer argument.
NOTE : the above assumes that method names are unique across all classes. if you have two different classes with the same method name then you are in trouble, obviously (I hope) (and it may not be that uncommon if you use things like "with" and "and" ... .)
source to share