This is fine, and it’s in fact one reason why I recommend rolling your own combinator, rather than using some of the existing ones. With your own combinator you’re in full control, and you can shape the context to your own particular needs.
My talk is envisioned as a “gentle” introduction, so I oversimplified many things. Don’t treat it as a definitive reference, and feel free to diverge from it wherever it makes sense. For example, as I said in my initial post, parsers such as choice, optional, and many, will lead to uninformative reported errors, so you’ll probably need to invent some alternatives based on a lookahead technique (decide what to do next based on what the next term is).
I just watched the talk and it was great! @sasajuric or anyone, do you know a good library to consume from the input and get the line/column as well?
Or do you just do something like this:
defmodule Buffer do
defstruct text: "", line: 0, column: 0
def new(text) do
new(text, 0, 0)
end
def new(text, line, column) do
%__MODULE__{text: text, line: line, column: column}
end
def take(%__MODULE{text: text, line: line, column: column}) do
case text do
<<?\n, rest::binary>> -> {?\n, new(rest, line + 1, 0)}
<<char::utf8, rest::binary>> -> {char, new(rest, line, column + 1)}
"" -> :EOF
end
end
end