pete-murphy/elm-nlds/1.0.1

NOTE: the latest version is 3.0.1

elm-nlds

Build Status

Natural language parser for loosely ordered token sequences.

Parse user input where tokens can appear in any order, with synonyms, and get results ranked by how well they match. Perfect for command palettes, search boxes, and natural language interfaces.

import Nld exposing (Nld, word, words, tuple2, runTake)

-- Parse "delete file" even if user types "file delete"
deleteCommand : Nld ( String, String )
deleteCommand =
    tuple2
        (words [ "delete", "remove", "rm" ])  -- synonyms
        (word "file")

runTake 1 deleteCommand [ "file", "delete" ]
    |> List.map Tuple.second
--> [ ( "delete", "file" ) ]

runTake 1 deleteCommand [ "please", "remove", "the", "file" ]
    |> List.map Tuple.second
--> [ ( "delete", "file" ) ]  -- ignores irrelevant tokens, canonicalizes synonyms

Design Goals

  1. Order-independent parsing - Tokens can appear in any order. The parser prefers the specified order but handles reordering gracefully.

  2. Noise-tolerant - Irrelevant tokens are ignored. Users can type "please delete the file" and it still works.

  3. Synonym support - Define synonyms that canonicalize to a single value. "delete", "remove", and "rm" all become "delete".

  4. Ranked results - Results are produced in priority order. Better matches (correct order, fewer gaps) come first.

  5. Autocomplete-ready - Get suggestions for what tokens would complete a partial parse.

When to use elm-nlds

  • Command palettes with flexible input
  • Search interfaces that tolerate word reordering
  • Natural language command parsing
  • Fuzzy matching where order doesn't matter

When NOT to use elm-nlds

  • Strict grammar parsing (use elm/parser)
  • Performance-critical parsing of large inputs
  • Parsing structured data formats (JSON, etc.)

Installation

elm install pete-murphy/elm-nlds

Usage

Basic Token Matching

import Nld exposing (word, words, token, nat, runList)

-- Match a specific word
runList (word "hello") [ "hello", "world" ]
    |> List.map Tuple.second
--> [ "hello" ]

-- Match any of several synonyms (canonicalizes to first)
runList (words [ "yes", "yeah", "yep" ]) [ "yeah" ]
    |> List.map Tuple.second
--> [ "yes" ]

-- Match any token
runList token [ "anything" ]
    |> List.map Tuple.second
--> [ "anything" ]

-- Match a natural number
runList nat [ "42" ]
    |> List.map Tuple.second
--> [ 42 ]

Combining Parsers

import Nld exposing (tuple2, tuple3, map, map2, choice, repeat)

-- Combine two parsers into a tuple
tuple2 (word "buy") nat
-- Parses: "buy 3" or "3 buy"

-- Transform results
map String.toUpper (word "hello")

-- Try multiple alternatives
choice [ word "yes", word "no" ]

-- Match zero or more
tuple2 (word "add") (repeat nat)
-- Parses: "add 1 2 3"

Autocomplete

import Nld exposing (topK, word)
import Set

-- Get completion suggestions for what could come next
topK 5 (word "buy") []
-- Returns: [ Set containing "buy" ]

Modules

  • Nld - The main parser type and combinators
  • Peach - Priority search data structure (used internally, but exposed for advanced use)

Attribution

This is an Elm port of Paul Chiusano's Unison libraries:

License

MIT