UNPKG

elliptical

Version:

Interactive natural-language interfaces

125 lines (93 loc) 3.33 kB
# Phrases In elliptical, natural language is modeled using `Phrases`. This allows you to model language in an extensible, composable, dynamic way. At its most basic level, a `Component` is just an object that has a single function called `describe`. ```jsx const Exclamation = { describe() { return <literal text='elliptical rocks!' /> } } ``` `describe` returns an `element`. ## Parsing Components Once we have a `Component`, we can use it in `element`s of our own. ```jsx const parse = compile(<Exclamation />) parse('') // => 'elliptical rocks!' ``` ## Props We can also set `props` on our elements. The element itself is exposed as the first argument to `describe`. Here we access `props` using ES2015 argument destructuring. ```jsx const Exclamation = { describe({props}) { return <literal text={`${props.app} rocks!`} /> } } const parse = compile(<Exclamation app='Lacona' />) parse('') // => 'Lacona rocks!' ``` ## Children `describe` is also passed its `children` as an Array. We can use this to build "Higher-order Phrases" - that is, `Component`s that take `elements` and augment them. ```jsx const Exclamation = { describe({children}) { return ( <sequence> {children[0]} <literal text=' rocks!' /> </sequence> ) } } const grammar = <Exclamation><literal text='Batman' /></Exclamation> const parse = compile(grammar) parse('') // => 'Batman rocks!' ``` ## defaultProps We don't want consumers of our Phrase to need to specify every `prop` every time, so we can use the `defaultProps` helper. It is an object that is always merged onto the provided `props` using [`_.defaults`](https://lodash.com/docs#defaults). ```jsx const Exclamation = { defaultProps: {app: 'Google Chrome'}, describe({props}) { return <literal text={`${props.app} rocks!`} /> } } const parse = compile(<Exclamation />) parse('') // => 'Google Chrome rocks!' ``` ## Result Helpers Every Phrase can have two functions, `mapResult` and `filterResult`, which can be used to modify phrase behavior based upon their `result` in a simple, imperative way. These these methods are only called if the phrase is *complete* - that is, if any `Word`s with `placeholder: true` are in the `words`. Therefore, they do not need to worry about errors because of partial results. If both are declared, `mapResult` runs *before* `filterResult`. These functions do not allow for any functionality that `<map>` and `<filter>` do not already provide, but they are a simpler, more declarative approach. Additionally, elliptical addons can make use of them easily. ### `mapResult` ```js mapResult: (result: Any, element: Element) => Any ``` The return value of this call will set as the `result` from this phrase. This should be used sparingly, only when the element structure returns data in the wrong format. If you need to do validation on *incomplete* outputs, use `<map>`. Unlike `<map>`, `mapResult` cannot return an iterable and cannot be limited. ### `filterResult` ```js filterResult: (result: Any, element: Element) => Boolean ``` If this function returns `false`, this branch will not continue parsing. This should be used agressively to ensure that invalid outputs never make it past the phrase. If you need to do validation on *incomplete* outputs, use `<filter>`.