AbnfParsec (AbnfParsec v1.2.0) View Source

Generates a parser from ABNF definition - text (:abnf) or file path (:abnf_file)

An entry rule can be defined by :parse. If defined, a parse/1 function and a parse!/1 function will be generated with the entry rule.

By default, every chunk defined by a rule is wrapped (in list) and tagged by the rulename. Use the options to :untag, :unwrap or both (:unbox).

Parsed chunks (rules) can be discarded :ignore.

Transformations (:map, :reduce, :replace) can be applied by passing in a :transform map with keys being rulenames and values being 2-tuples of transformation type (:map, :reduce, :replace), and mfa tuple (for :map and reduce) or a literal value (for :replace)

Example usage:

defmodule JsonParser do
  use AbnfParsec,
    abnf_file: "test/fixture/json.abnf",
    parse: :json_text,
    transform: %{
      "string" => {:reduce, {List, :to_string, []}},
      "int" => [{:reduce, {List, :to_string, []}}, {:map, {String, :to_integer, []}}],
      "frac" => {:reduce, {List, :to_string, []}},
      "null" => {:replace, nil},
      "true" => {:replace, true},
      "false" => {:replace, false}
    },
    untag: ["member"],
    unwrap: ["int", "frac"],
    unbox: [
      "JSON-text",
      "null",
      "true",
      "false",
      "digit1-9",
      "decimal-point",
      "escape",
      "unescaped",
      "char"
    ],
    ignore: [
      "name-separator",
      "value-separator",
      "quotation-mark",
      "begin-object",
      "end-object",
      "begin-array",
      "end-array"
    ]
end

json = ~s| {"a": {"b": 1.2, "c": [true]}, "d": null, "e": "e\te"} |

JsonParser.json_text(json)
# or
JsonParser.parse(json)
# => {:ok, ...}
JsonParser.parse!(json)
# =>

[
  object: [
    [
      string: ["a"],
      value: [
        object: [
          [string: ["b"], value: [number: [int: 1, frac: ".2"]]],
          [string: ["c"], value: [array: [value: [true]]]]
        ]
      ]
    ],
    [string: ["d"], value: [nil]],
    [string: ["e"], value: [string: ["e\te"]]]
  ]
]

Link to this section Summary

Functions

All rules by default are wrapped and tagged. See NimbleParsec for more details.

Link to this section Types

Specs

rulename() :: :binary

Specs

rulenames() :: [rulename()]

Specs

transformation() ::
  {:replace | :reduce | :map, mfa :: {module(), atom(), [term()]}}

Specs

transformations() :: %{
  optional(rulename()) => transformation() | [transformation()]
}

Link to this section Functions

Link to this macro

__using__(opts)

View Source (macro)

All rules by default are wrapped and tagged. See NimbleParsec for more details.

Options:

  • :abnf (binary) - ABNF directly in string data

  • :abnf_file (binary) - ABNF file path

  • :debug (boolean) - whether to output generated parser code

  • :skip (rulenames) - rules to be skipped when generating parser code

    • so user can define their own parsec definition
  • :ignore (rulenames) - rules to be discarded after being parsed

  • :untag (rulenames) - rules to be wrapped only after being parsed

  • :unwrap (rulenames) - rules to be tagged only after being parsed

    • needs to be sure that there is only singular parsed entry
  • :unbox (rulenames) - made up term, to both untag and unwrap

  • :transform (transformations) - a map of rulenames to transformations

    • {:map, mfa}
    • {:reduce, mfa}
    • {:replace, val}
    • {:post_traverse, mfa}
    • {:pre_traverse, mfa}
  • :parse (atom) - described in module doc, needs to be an atom that is in normalized form of its original string rulename