Current section
Files
Jump to
Current section
Files
lib/minipeg/parsers/parse_functions.ex
defmodule Minipeg.Parsers.ParseFunctions do
@moduledoc false
use Minipeg.Types
alias Minipeg.{Cache, Failure, Input, Parser, Success}
alias Minipeg.Parsers.Helpers
import Failure, only: [fail: 4]
import Success, only: [succeed: 5]
@spec any_char_parser(Input.t(), Cache.t(), binary()) :: result_t()
def any_char_parser(input, cache, name) do
case input.input do
"" ->
fail("encountered end of input", input, cache, name)
_ ->
{char, input1} = Input.take(input, 1)
succeed(char, input1, cache, Input.position(input), name)
end
end
@spec compile_token(token1_spec_t()) :: token1_comp_t()
def compile_token(token_spec)
def compile_token({token, rgx_string}) when is_binary(rgx_string) do
{rgx, _} = Helpers.mk_rgx(rgx_string)
{token, rgx}
end
def compile_token({token, %Parser{} = parser}) do
{token, parser}
end
def compile_token({token, rgx_string, postprocessor}) when is_binary(rgx_string) do
{rgx, _} = Helpers.mk_rgx(rgx_string)
{token, rgx, postprocessor}
end
def compile_token({token, %Parser{} = parser, postprocessor}) do
{token, parser, postprocessor}
end
@spec int_map_fun(ast_t()) :: ast_t()
def int_map_fun(ast)
def int_map_fun([nil | rest]), do: int_map_fun(rest)
def int_map_fun(ast) do
ast
|> IO.chardata_to_string()
|> String.to_integer()
end
@spec token_parser(token_comp_t(), Input.t(), Cache.t(), binary(), maybe(Regex.t()), boolean()) :: result_t()
def token_parser(tokens, input, cache, name, skip_rgx, flatten_ast)
def token_parser(tokens, input, cache, name, nil, flatten_ast) do
token_parser_after_skip(tokens, input, cache, name, flatten_ast)
end
def token_parser(tokens, input, cache, name, skip_rgx, flatten_ast) do
case Regex.run(skip_rgx, input.input) do
nil -> token_parser_after_skip(tokens, input, cache, name, flatten_ast)
[match] -> case token_parser_after_skip(tokens, Input.drop(input, match), cache, name, flatten_ast) do
%Success{} = s -> s
_ -> fail("No token matches in #{name} at #{Input.report_position(input, name)}", input, cache, name)
end
end
end
@spec token_parser_after_skip(token_comp_t(), Input.t(), Cache.t(), binary(), boolean()) :: result_t()
def token_parser_after_skip(tokens, input, cache, name, flatten_ast)
def token_parser_after_skip([], input, cache, name, _flatten_ast) do
fail("No token matches in #{name} at #{Input.report_position(input, name)}", input, cache, name)
end
def token_parser_after_skip([{token, parser_or_rgx}|rest], input, cache, name, flatten_ast) do
case Helpers.parse_or_match(parser_or_rgx, input, cache) do
%Failure{} -> token_parser_after_skip(rest, input, cache, name, flatten_ast)
%Success{ast: ast, rest: input1} ->
ast1 = Helpers.mk_ast(token, ast, flatten_ast)
succeed(ast1, input1, cache, Input.position(input), name)
end
end
def token_parser_after_skip([{_token, parser_or_rgx, postprocessor}|rest], input, cache, name, flatten_ast) do
case Helpers.parse_or_match(parser_or_rgx, input, cache) do
%Failure{} -> token_parser_after_skip(rest, input, cache, name, flatten_ast)
%Success{ast: ast, rest: input1} ->
succeed(postprocessor.(ast), input1, cache, Input.position(input), name)
end
end
end
# SPDX-License-Identifier: Apache-2.0