Skip to content

Commit

Permalink
✨ choice combinato
Browse files Browse the repository at this point in the history
  • Loading branch information
nabeelvalley committed Jul 10, 2024
1 parent 9f9edf6 commit bf4083f
Showing 1 changed file with 34 additions and 4 deletions.
38 changes: 34 additions & 4 deletions src/parsing.gleam
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
import gleam/io
import gleam/list
import gleam/regex
import gleam/result
import gleam/string

pub type ParserError {
InvalidRegex(index: Int, re: String)
EmptySequence(index: Int)
EmptyChoices(index: Int)
ExpectedStr(index: Int, expected: String, found: String)
ExpectedRegex(index: Int, regex: String, found: String)
UnexpectedEndOfFile
}

pub type Parsed {
StartOfFile

// parsers
Str(String)
Regex(String)
Letters(String)
Digits(String)

// combinators
Sequence(List(ParserState))
Choice(ParserState)
}

pub type ParserState {
Expand Down Expand Up @@ -82,10 +89,8 @@ fn sequence_of(parsers: List(Parser)) -> Parser {
case result {
Error(err) -> Error(err)
Ok(ok) -> {
let empty_error = Error(EmptySequence(state.end))

case list.last(ok) {
Error(_) -> empty_error
Error(_) -> Error(EmptySequence(state.end))
Ok(last) ->
Ok(ParserState(last.target, state.end, last.end, Sequence(ok)))
}
Expand All @@ -94,6 +99,30 @@ fn sequence_of(parsers: List(Parser)) -> Parser {
}
}

fn choice_of_rec(
parsers: List(Parser),
state: ParserState,
) -> Result(ParserState, ParserError) {
case parsers {
[] -> Error(EmptyChoices(state.end))
[first, ..rest] -> {
case first(state) {
Error(_) -> choice_of_rec(rest, state)
Ok(ok) -> Ok(ok)
}
}
}
}

fn choice_of(parsers: List(Parser)) -> Parser {
fn(state: ParserState) {
choice_of_rec(parsers, state)
|> result.map(fn(res) {
ParserState(res.target, res.start, res.end, Choice(res))
})
}
}

fn regex(regex: String, t) -> Parser {
fn(state: ParserState) {
case regex.from_string(regex) {
Expand Down Expand Up @@ -139,11 +168,12 @@ fn parse(target) {
str("hello"),
str(" "),
str("world"),
choice_of([str("!"), str("")]),
])
run(parser, target)
}

pub fn main() {
let parsed = parse("message12: hello world")
let parsed = parse("message12: hello world!")
io.debug(parsed)
}

0 comments on commit bf4083f

Please sign in to comment.