# Built-in Phrases

There is nothing magical about any of these phrases. All of them
are implemented using the same public API available to custom phrases.

All phrases can take the following props:

  - `score: Number` - set to the `score` property of the output `Option`.
  Higher numbers sort higher. Defaults to `1`. 
  - `value: Any` - set to the `result` property of the output `Option`.
  - `qualifiers: Array<Any> | qualifier: Any` - set to the `qualifiers` property of output `Option`.
  - `categories: Array<Any> | category: Any` - set to the `categories` property of output `Option`.
  - `annotations: Array<Any> | annotation: Any` - set to the `annotations` property of output `Option`.
  - `arguments: Array<Any> | argument: Any` - set to the `arguments` property of output `Option`.

## `literal`

Matches or suggests a single literal string.

### Props

- `text: String` - The string to accept as input.
- `strategy: String ('start'|'contain'|'fuzzy')` - the matching strategy
  to use for this element. Note that fuzzy matching should rarely be used
  for literals - if you want to fuzzy match many items, use a [`list`](#list).
- `decorate: Boolean` - if `true`, then suggest `text` even if it does
  not match the input. Useful for displaying implicit information.
- `allowInput: Boolean` - if `true`, then force decoration, and do not
  consume any input even if exists. Only applies with `decorate`.

### Example

```js
const parse = compile(
  <literal text='Lacona' value='http://lacona.io' />
)
parse('Lac')
/* [
  {
    words: [
      {text: 'Lac', input: true},
      {text: 'ona', input: false}
    ],
    score: 1,
    result: 'http://lacona.io'
  }
] */
```

## `choice`

Branches the parsing logic. Consumes no characters.

## Result

`Any` - One of the following items:

- If the child has an `id` prop, the result will be
  an `Object` of the form `{[childId]: childResult}`
- Otherwise, the `result` of the child for this branch

## Score

The score of the child for this branch.

### Props

- children - The `choice` can contain any number of child elements.
  Each child represents a separate branch that the parse can flow through.
- `limit: Integer` - If `limit` children are parsed successfully
  (all the way to the end of the parse chain), then stop attempting to parse
  further children. This is very useful in situations where some children are
  synonymous, and there is no need suggest multiples.

### Example

```js
const parse = compile(
  <choice limit={2}>
    <literal text='Google' value='http://google.com' />
    <literal text='Gmail' value='http://mail.google.com' />
    <literal text='Google Maps' value='http://maps.google.com' />
    <literal text='Google Drive' value='http://drive.google.com' />
  </choice>
)
parse('Goog')
/* [
  {
    words: [
      {text: 'Goo', input: true},
      {text: 'gle', input: false}
    ],
    score: 1,
    result: 'http://google.com'
  },
  {
    words: [
      {text: 'Goo', input: true},
      {text: 'gle Maps', input: false}
    ],
    score: 1,
    result: 'http://maps.google.com'
  }
] */
```

## `sequence`

Parses its children in order, one after the other.

### Optional

Every child of a `sequence` can set a property called `optional`.
If it is `true`, It results in an implicit branch in the parse chain.

If `optional` is set, the child can choose to set the props
`limited` and `preferred`, which effect the output. All of these props are
simply shorthand expressions, which map to `choice`s under the covers.
All 3 props default to `false`. Here is how they are mapped:

##### `optional`

```js
  <sequence>
    <literal text='Google' />
    <literal text=' Maps' optional />
  </sequence>

  // becomes

  <sequence>
    <literal text='Google' />
    <choice>
      <literal text='' />
      <literal text=' Maps' />
    </choice>
  </sequence>
```

##### `optional preferred`

Note the orders of the resulting `choice`'s children.

```js
  <sequence>
    <literal text='Google' />
    <literal text=' Maps' optional preferred />
  </sequence>

  // becomes

  <sequence>
    <literal text='Google' />
    <choice>
      <literal text=' Maps' />
      <literal text='' />
    </choice>
  </sequence>
```

##### `optional limited`

Note the `limit` of the resulting `choice`. This is an easy way to say
"accept this child if it's there, but don't suggest it."

```js
  <sequence>
    <literal text='Google' />
    <literal text=' Maps' optional limited />
  </sequence>

  // becomes

  <sequence>
    <literal text='Google' />
    <choice limit={1}>
      <literal text='' />
      <literal text=' Maps' />
    </choice>
  </sequence>
```


##### `optional preferred limited`

This is an easy way to say "accept this child if it's there,
but don't suggest its absence."

```js
  <sequence>
    <literal text='Google' />
    <literal text=' Maps' optional preferred limited />
  </sequence>

  // becomes

  <sequence>
    <literal text='Google' />
    <choice limit={1}>
      <literal text=' Maps' />
      <literal text='' />
    </choice>
  </sequence>
```

There is another piece of functionality known as the `ellipsis`.
If you sent a `<sequence />`s child to have `ellipsis={true}`, then
it means "it is OK to stop here - make the rest of the sequence optional".
This limits the options displayed to the user and can substantially improve
understanding and performance. These two descriptions are precisely equivalent:

```js
<sequence>
  <literal text='The ' />
  <literal text='Batman' ellipsis />
  <literal text=' and Robin' />
</literal>

//becomes

<sequence>
  <literal text='The ' />
  <literal text='Batman' />
  <sequence optional limited merge>
    <literal text=' and Robin' />
  </sequence>
</literal>
```

### Result

`Any` - One of the following items

- the contents of the `value` prop
- if there is no `value` prop, an `Object` that is composed of
  the results of the children:
    - If the child has an `id` prop, the resulting `Object` will
      have a key `{[childId]: childResult}`
    - If the child has the prop `merge`, the child's result will be
      merged into the resulting `Object` using `_.merge`.

### Score

The score of all parsed children, multiplied together.

### Props

- `unique: Boolean` - If `true`, the sequence will check the `id` prop
  of each child before parsing. If the child's `id` prop is already in the
  `result` object (from an child earlier in the chain), it will be skipped.
  Useful with `optional` children.

### Example

```js
const parse = compile(
  <sequence>
    <literal text='Google' value='google' id='base' />
    <literal text=' Maps' value='maps' id='sub' score={0.5} optional />
    <literal text=' rocks!' />
  </sequence>
)
parse('Goog')
/* [
  {
    words: [
      {text: 'Goo', input: true},
      {text: 'gle', input: false},
      {text: ' rocks!', input: false}
    ],
    score: 1,
    result: {base: 'google'}
  }, {
    words: [
      {text: 'Goo', input: true},
      {text: 'gle', input: false},
      {text: ' Maps', input: false},
      {text: ' rocks!', input: false}
    ],
    score: 0.5,
    result: {base: 'google', sub: 'maps'}
  }
] */
```

## `repeat`

Allows an element to be repeated multiple times, with an optional separator.

### Result

`Array` - An array of the values of each child, in the order they were parsed

### Score

`1`

### Props

- `separator: Element` - A single element, which will be placed
  in sequence between every repetition. Its result is ignored.
- `unique: Boolean` - If `true`, the `repeat` will not allow repetitions
  that have the same `result`. That is to say, the `repeat`'s `result` is
  guaranteed to be `unique`.
- `max: Number` - the maximum number of repetitions to allow. Defaults
  to unlimited.
- `min: Number` - the minimum number of repetitions to allow. Defaults to 1.

### Example

```js
const parse = compile(
  <repeat separator={<literal text=' '/>} max={3}>
    <literal text='wort' value='go' />
  </repeat>
)
parse('wort wort')
/* [
  {
    words: [
      {text: 'wort', input: true},
      {text: ' ', input: true},
      {text: 'wort', input: true}
    ],
    score: 1,
    result: ['go', 'go']
  }, {
    words: [
      {text: 'wort', input: true},
      {text: ' ', input: true},
      {text: 'wort', input: true},
      {text: ' ', input: false},
      {text: 'wort', input: false}
    ],
    score: 1,
    result: ['go', 'go', 'go']
  }
] */
```

## `placeholder`

Parses that have consumed the entire input string will not
continue into this placeholder's `child`. Instead, it will output a word with
`{placeholder: true, label: label}` This improves performance and
usability, as it limits the number of suggestions that are output
for an incomplete input.

### Score

`placeholder`s that suppress input have a very low score, to ensure that
completed suggestions appear before incomplete ones. 

### Props

- `label: Any` - An object describing the placeholder. If the placeholder
  suppresses parsing, it will output this label in its `Word`.
- `suppressEmpty: Boolean` - defaults to `true`. If `true`,
  this `placeholder` will also suppress inputs that are an empty string.
  That is to say, if the preceding elements consume the entire input
  string but have not yet made any suggestions, this placeholder will still
  suppress the input.
- `suppressWhen: (input: String) => Boolean` - When this placeholder is parsed,
  it will call this function. If it returns `true`, this placeholder will suppress
  the input (returning a `placeholder`), even if the input is non-null. This
  is useful to describe incomplete but non-suggestable input.
    - For example, imagine a phrase is designed to accept a 3-digit integer,
      but the user has only entered a single digit. The input is not yet valid,
      and it does not make sense to suggest a completion, but it also needs to
      show the user that they are on their way to a valid input. In this case,
      it makes sense to use something like
      `suppressWhen={(input) => /^\d{1,2}$/.test(input)}`.

## `list`

Logically, a `<list>` can be thought of as a `<choice>` of `<literal>` elements.
However, it has enhancements that allow it to work better for large lists,
especially when limiting and fuzzy matching is used. It also performs better.

In general, everytime you have a `<choice>` containing only `<literal>`
elements, you should use a `<list>` instead.

### Result

`Any` - The `value` of the `item`, or `undefined`

### Props

- `items: Array<{String | Object}>` - An array valid items.
  The parse will branch for each one. If `item` is a `String`, it
  is equivalent to `{text: item}`. Each `item` is an `Object` with
  these properties:
    - `text: String` - The text to parse
    - `value: Any` - The `list`'s result in this parse branch
    - `qualifiers: Array<Any> | qualifier: Any`
    - `arguments: Array<Any> | argument: Any`
    - `annotations: Array<Any> | annotation: Any`
    - `categories: Array<Any> | category: Any`
- `strategy: String ('start'|'contain'|'fuzzy')` - Matching strategy
  to use for these items.
- `limit: Integer` - If `<limit>` `items` are parsed successfully
  (all the way to the end of the parse chain), then stop attempting to
  parse further children. Note that the outputs have a score,
  sorting is applied *before* limiting, so the best matches will not be limited.

### Example

```js
const parse = compile(
  <list limit={2} items={[
    {text: 'Google', value: 'http://google.com'},
    {text: 'Gmail', value: 'http://mail.google.com'},
    {text: 'Google Maps', value: 'http://maps.google.com'},
    {text: 'Google Drive', value: 'http://drive.google.com'}
  ]} />
)
parse('gm')
/* [
  {
    words: [
      {text: 'Gm', input: true},
      {text: 'ail', input: false}
    ],
    score: 1,
    result: 'http://mail.google.com'
  },
  {
    words: [
      {text: 'Goo', input: true},
      {text: 'gle Maps', input: false}
    ],
    score: 1,
    result: 'http://maps.google.com'
  }
] */
```

## `freetext`

Accept arbitrary input. Note that this phrase contains significant
implicit branching, as it will attempt to validate and parse every
substring between `substr(0, 1)` and `substr(0)`. Use the `splitOn` and
`limit` properties to improve performance.

### Result

`String` - the substring that was validated and parsed.

### Score

Higher scores are given to
shorter substrings. Therefore, the highest-scored parse chain will be
the one in which the freetext consumed the fewest characters.

### Props

- `splitOn: String | RegExp` - Argument to `String::split` to determine
  which substrings to attempt parsing.
- `consumeAll: Boolean` - Do not attempt to parse substrings, only parse
  the entire remaining string. Improves performance if the `freetext` is
  the final phrase in a command
- `filter: Function(input: String) => Boolean` - Better-performing
  shorthand for `<filter function={filter}><freetext ...otherProps /></filter>`.
- `limit: Integer` - If `<limit>` substrings are parsed successfully
  (all the way to the end of the parse chain), then stop attempting
  to parse further substrings.
- `greedy: Boolean` - Used alongside limiting. Which order should
  input substrings be attempted in

## `dynamic`

Generate grammars dynamically based upon input.

### Props

- `describe: Function(input:String, option:Option)` - This function is called
  with each input substring. It is also passed the current `option`, which contains
  the current `result`. If it returns an `Element`, that element will be parsed
  with that input in place of this element.
- `splitOn: String | RegExp` - Argument to `String::split` to determine
  which substrings to attempt parsing.
  - `consumeAll: Boolean` - Do not attempt to parse substrings, only parse
  the entire remaining string. Improves performance if the `freetext` is
  the final phrase in a command
- `limit: Integer` - If `<limit>` substrings are parsed successfully
  (all the way to the end of the parse chain), then stop attempting
  to parse further substrings.
- `greedy: Boolean` - Used alongside limiting. Which order should
  input substrings be attempted in

## `filter`

Filter options with an arbitrary function.

### Props

- `inbound: (option: Option) => Boolean` -
  If it returns false, children will not be parsed
- `outbound: (option: Option) => Boolean` -
  Called for each child output option. If it returns true, it will not
  output that option.
- `skipIncomplete: Boolean` - if true, `outbound` will not be called if
  the output option contains a placeholder

### Example

```js
const parse = compile(
  <filter outbound={(option) => _.isString(option.result)}>
    <list items={[
      {text: 'some string', value: 'string'},
      {text: 'some object', value: {key: 'value'}}
    ]} />
  </filter>
)
parse('some ')
/* [{
  words: [
    {text: 'some ', input: true},
    {text: 'string', input: false}
  ],
  score: 1,
  result: 'string'
}] */
```

## `map`

Modify options with an arbitrary function.

### Props

- `inbound: (option: Option) => Option` - Changes an option before parsing
  children
- `outbound: (option: Option) => (Option | Iterable<Option>)` - Changes the
  output options after parsing children. If it returns an Iterable, all
  options will be output
- `limit: Number` - Limits output if `outbound` returns an Iterable
- `skipIncomplete: Boolean` - if true, `outbound` will not be called if
  the output option contains a placeholder

### Example

```js
const parse = compile(
  <map outbound={(option) => _.merge({}, option, {result: 'test'})}>
    <literal text='lacona' value='lacona' />
  </repeat>
)
parse('lac')
/* [{
  words: [
    {text: 'lac', input: true},
    {text: 'ona', input: false}
  ],
  score: 1,
  result: 'test'
}] */
```

## `tap`

Does not effect parsing at all. Calls a function if the parse reaches
it, and continues parsing. Useful for debugging, or interacting with
the outside world based upon parsing.

### Props

- `inbound` - `Function(input: String)` - called everytime this element
  is visited
- `outbound` - `Function(input: String)` - called everytime this element's
  child outputs an option

### Example

```js
const parse = compile(
  <tap outbound={console.log}>
    <literal text='lacona' />
  </repeat>
)
parse('lac')
/* logs: {text: null, words: [...], ...} */
```

## `raw`

The lowest-level phrase, which allows completely arbitrary manipulation
of outputs.
