Ergo.Terminals (Ergo v0.4.4)
Ergo.Terminals contains the terminal parsers.
A terminal parser is a parser that is not parameterised with another parser and works directly with the input.
Parsers
- eoi
- char
- digit
- alpha
- ws
- wc
- literal
Link to this section Summary
Functions
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 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 not_char matcher accepts a char or a list of chars and will match any char that is not in the list.
Link to this section Functions
alpha()
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}, message: "Expected: [a..z, A..Z] Actual: ", input: " World"} = Ergo.parse(parser, " World")
char(c, opts \\ [])
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}, message: "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}, message: "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}, message: "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}, message: "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}, message: "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}, message: "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")
delimited_text(open_char, close_char)
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")
digit()
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}, message: "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> context = Context.new(&Ergo.Parser.call/2, "")
iex> parser = digit()
iex> assert %Context{status: {:error, :unexpected_eoi}, message: "Unexpected end of input", input: "", index: 0, line: 1, col: 1} = Parser.invoke(parser, context)
eoi()
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> context = Context.new(&Ergo.Parser.call/2, "")
iex> assert %Context{status: :ok, ast: nil} = Parser.invoke(eoi(), context)
iex> alias Ergo.{Context, Parser}
iex> import Ergo.Terminals
iex> context = Context.new(&Ergo.Parser.call/2, "Hello World")
iex> assert %Context{status: {:error, :not_eoi}, message: "Input not empty: Hello World…", input: "Hello World"} = Parser.invoke(eoi(), context)
literal(s, opts \\ [])
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("Hellx")
iex> assert %Context{status: {:error, :unexpected_char}, message: "Expected: x Actual: o [in literal(Hellx)]", input: "o World", ast: [?l, ?l, ?e, ?H], index: 4, line: 1, col: 5} = Ergo.parse(parser, "Hello World")
not_char(char)
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}, message: "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}, message: "Should not have matched {", input: "{}"} = Ergo.parse(parser, "{}")
iex> assert %Context{status: {:error, :unexpected_char}, message: "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}, message: "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}, message: "Expected: [\s, \t, \r, \n, \v] Actual: H", input: "Hello World"} = Ergo.parse(parser, "Hello World")