Ergo.Terminals (Ergo v1.0.3)
Ergo.Terminals
contains the terminal parsers, which are those parsers not
parameterized with other parsers and therefore work more at the level of text
than structure.
Summary
Functions
The alpha/0
parser accepts a single character in the range a..z or A..Z.
The char/1
parser is a terminal parser that matches a specific character.
The delimited_text/2 parser matches a sequence of text delimited open_char
and
close_char
. Because it is expected that open_char
may appear multiple times
within the sequence it balances the tokens to ensure the right number of closing
tokens is matched.
The digit/0
parser accepts a character in the range of 0..9
The eoi parser is a terminal parser that checks whether the input has been fully consumed. If there is input remaining to be parsed the return context status is set to :error.
The literal/1
parser matches the specified string character by character.
The non_ws/1
parser accepts any character that is not a white space.
The not_char matcher accepts a char or a list of chars and will match any char that is not in the list.
The ws/0
parser accepts a white space character and is equivalent to the \s regular expression.
Functions
The alpha/0
parser accepts a single character in the range a..z or A..Z.
Examples
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = alpha()
iex> assert %Context{status: :ok, input: "ello World", ast: ?H, index: 1, line: 1, col: 2} = Ergo.parse(parser, "Hello World")
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = alpha()
iex> assert %Context{status: :ok, input: "llo World", ast: ?e, index: 1, line: 1, col: 2} = Ergo.parse(parser, "ello World")
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = alpha()
iex> assert %Context{status: {:error, [{:unexpected_char, {1, 1}, "Expected: [|a|..|z|, |A|..|Z|] Actual: | |"}]}, input: " World"} = Ergo.parse(parser, " World")
The any/0
parser matches any character.
Examples
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = any()
iex> assert %Context{status: :ok, ast: ?H} = Ergo.parse(parser, "H")
iex> assert %Context{status: :ok, ast: ?e} = Ergo.parse(parser, "e")
iex> assert %Context{status: :ok, ast: ?!} = Ergo.parse(parser, "!")
iex> assert %Context{status: :ok, ast: ?0} = Ergo.parse(parser, "0")
The char/1
parser is a terminal parser that matches a specific character.
Examples
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = char(?H)
iex> assert %Context{status: :ok, ast: ?H, input: "ello World", index: 1, line: 1, col: 2} = Ergo.parse(parser, "Hello World")
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = char(?h)
iex> assert %Context{status: {:error, [{:unexpected_char, {1, 1}, "Expected: |h| Actual: |H|"}]}, input: "Hello World"} = Ergo.parse(parser, "Hello World")
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = char(?H)
iex> assert %Context{status: {:error, [{:unexpected_eoi, {1, 1}, "Unexpected end of input"}]}} = Ergo.parse(parser, "")
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = char(?A..?Z)
iex> assert %Context{status: :ok, ast: ?H, input: "ello World", index: 1, line: 1, col: 2} = Ergo.parse(parser, "Hello World")
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = char(?a..?z)
iex> assert %Context{status: {:error, [{:unexpected_char, {1, 1}, "Expected: |a|..|z| Actual: |H|"}]},input: "Hello World"} = Ergo.parse(parser, "Hello World")
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = char(?A..?Z)
iex> assert %Context{status: {:error, [{:unexpected_eoi, {1, 1}, "Unexpected end of input"}]}} = Ergo.parse(parser, "")
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = char([?a..?z, ?A..?Z])
iex> assert %Context{status: :ok, ast: ?H, input: "ello World", index: 1, line: 1, col: 2} = Ergo.parse(parser, "Hello World")
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = char([?a..?z, ?A..?Z])
iex> assert %Context{status: {:error, [{:unexpected_char, {1, 1}, "Expected: [|a|..|z|, |A|..|Z|] Actual: |0|"}]}, input: "0000"} = Ergo.parse(parser, "0000")
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = char(-?0)
iex> assert %Context{status: {:error, [{:unexpected_char, {1, 1}, "Should not have matched |0|"}]}, input: "0000"} = Ergo.parse(parser, "0000")
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = char(-?a)
iex> assert %Context{status: :ok, input: "000", ast: ?0, index: 1, col: 2} = Ergo.parse(parser, "0000")
The delimited_text/2 parser matches a sequence of text delimited open_char
and
close_char
. Because it is expected that open_char
may appear multiple times
within the sequence it balances the tokens to ensure the right number of closing
tokens is matched.
Examples
iex> alias Ergo
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = delimited_text(?{, ?})
iex> assert %Context{status: :ok, ast: "{return {foo: \"bar\", bar: {baz: \"quux\"}};}", input: ""} = Ergo.parse(parser, "{return {foo: \"bar\", bar: {baz: \"quux\"}};}")
iex> assert %Context{status: :ok, ast: "{function b(y) {return x + y;}; return b;}", input: "foo"} = Ergo.parse(parser, "{function b(y) {return x + y;}; return b;}foo")
The digit/0
parser accepts a character in the range of 0..9
Examples
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = digit()
iex> assert %Context{status: :ok, ast: ?0, input: "000", index: 1, line: 1, col: 2} = Ergo.parse(parser, "0000")
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> import Ergo.Terminals
iex> parser = digit()
iex> assert %Context{status: {:error, [{:unexpected_char, {1, 1}, "Expected: |0|..|9| Actual: |A|"}]}, input: "AAAA", index: 0, line: 1, col: 1} = Ergo.parse(parser, "AAAA")
iex> alias Ergo.{Context, Parser}
iex> import Ergo.Terminals
iex> ctx = Context.new("")
iex> parser = digit()
iex> assert %Context{status: {:error, [{:unexpected_eoi, {1, 1}, "Unexpected end of input"}]}, input: "", index: 0, line: 1, col: 1} = Parser.invoke(ctx, parser)
The eoi parser is a terminal parser that checks whether the input has been fully consumed. If there is input remaining to be parsed the return context status is set to :error.
Examples
iex> alias Ergo.{Context, Parser}
iex> import Ergo.Terminals
iex> ctx = Context.new("")
iex> assert %Context{status: :ok, ast: nil} = Parser.invoke(ctx, eoi())
iex> alias Ergo.{Context, Parser}
iex> import Ergo.Terminals
iex> ctx = Context.new("Hello World")
iex> assert %Context{status: {:error, [{:not_eoi, {1, 1}, "Input not empty: Hello World"}]}, input: "Hello World"} = Parser.invoke(ctx, eoi())
The literal/1
parser matches the specified string character by character.
Examples
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = literal("Hello")
iex> assert %Context{status: :ok, input: " World", ast: "Hello", index: 5, line: 1, col: 6} = Ergo.parse(parser, "Hello World")
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = literal("Hello")
iex> assert %Context{status: {:error, [{:bad_literal, {1, 5}, "literal<Hello>"}, {:unexpected_char, {1, 5}, "Expected: |o| Actual: |x|"}]}, input: "x World", index: 4, line: 1, col: 5} = Ergo.parse(parser, "Hellx World")
The non_ws/1
parser accepts any character that is not a white space.
The not_char matcher accepts a char or a list of chars and will match any char that is not in the list.
Examples
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = not_char(?0)
iex> assert %Context{status: {:error, [{:unexpected_char, {1, 1}, "Should not have matched |0|"}]}, input: "0000"} = Ergo.parse(parser, "0000")
iex> assert %Context{status: :ok, ast: ?1} = Ergo.parse(parser, "1111")
iex> parser = not_char([?{, ?}])
iex> assert %Context{status: {:error, [{:unexpected_char, {1, 1}, "Should not have matched |{|"}]}, input: "{}"} = Ergo.parse(parser, "{}")
iex> assert %Context{status: {:error, [{:unexpected_char, {1, 1}, "Should not have matched |}|"}]}, input: "}"} = Ergo.parse(parser, "}")
The wc/0
parser parses a word character and is analagous to the \w regular expression.
Examples
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = wc()
iex> assert %Context{status: :ok, ast: ?H, input: "ello World", index: 1, col: 2} = Ergo.parse(parser, "Hello World")
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = wc()
iex> assert %Context{status: :ok, ast: ?0, input: " World", index: 1, col: 2} = Ergo.parse(parser, "0 World")
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = wc()
iex> assert %Context{status: :ok, ast: ?_, input: "Hello", index: 1, col: 2} = Ergo.parse(parser, "_Hello")
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = wc()
iex> assert %Context{status: {:error, [{:unexpected_char, {1, 1}, "Expected: [|0|..|9|, |a|..|z|, |A|..|Z|, |_|] Actual: | |"}]}, input: " Hello"} = Ergo.parse(parser, " Hello")
The ws/0
parser accepts a white space character and is equivalent to the \s regular expression.
Examples
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = ws()
iex> assert %Context{status: :ok, ast: ?\s, input: "World", index: 1, line: 1, col: 2}= Ergo.parse(parser, " World")
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = ws()
iex> assert %Context{status: :ok, ast: ?\t, input: "World", index: 1, line: 1, col: 2} = Ergo.parse(parser, "\tWorld")
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = ws()
iex> assert %Context{status: :ok, ast: ?\n, input: "World", index: 1, line: 2, col: 1} = Ergo.parse(parser, "\nWorld")
iex> alias Ergo.Context
iex> import Ergo.Terminals
iex> parser = ws()
iex> assert %Context{status: {:error, [{:unexpected_char, {1, 1}, "Expected: [| |, |\t|, |\r|, |\n|, |\v|] Actual: |H|"}]}, input: "Hello World"} = Ergo.parse(parser, "Hello World")