Skip to content

Commit

Permalink
Add surrounded parser
Browse files Browse the repository at this point in the history
  • Loading branch information
wlad031 committed Feb 22, 2024
1 parent ee5d975 commit 1ff4a1d
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/main/scala/dev/vgerasimov/slowparse/parser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,22 @@ object Parsers:
def until(parser: P[?], collector: P[?] = anyChar): P[Unit] =
unCapture(rep(!parser ~ collector)(greedy = true))

// TODO: remove, seems completely unneeded
def surrounded[A](
fromParser: P[?],
toParser: P[?],
contentParser: P[A]
): P[A] = fromParser.!! ~ contentParser ~ toParser.!!

def surrounded[A](
surroundingParser: P[?],
contentParser: P[A]
): P[A] = surrounded(surroundingParser, surroundingParser, contentParser)

def surrounded(
surroundingParser: P[?]
): P[String] = surrounded(surroundingParser, (!surroundingParser ~ anyChar.!).*).mkString

/** Parses given character. */
def char(char: Char): P[Unit] = input => {
input.safeHead match
Expand Down Expand Up @@ -351,6 +367,9 @@ object Parsers:

end Parsers

extension (self: P[List[?]])
def mkString: P[String] = self.map(_.mkString)

extension (self: String)
private[slowparse] def safeHead: String = safeSlice(0, 1)
private[slowparse] def safeSlice(from: Int = 0, until: Int = Int.MaxValue): String = self match
Expand Down
20 changes: 20 additions & 0 deletions src/test/scala/dev/vgerasimov/slowparse/ParserTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,26 @@ class ParserTest extends ParserTestSuite:
testSuccess(parser)("\nabc", "")
}

test("*surrounded* should parse everything surrounded by two parsers") {
val parser = surrounded(P("a"), P("b"), d.+.!)
testSuccess(parser)("a123b", "123")
testSuccess(parser)("a12b3b", "12")
testFailure(parser)("a*1*b")
}

test("*surrounded* should parse everything surrounded by one parser") {
val parser = surrounded(P("*"), d.+.!)
testSuccess(parser)("*123*", "123")
testSuccess(parser)("*12*", "12")
testFailure(parser)("*12abc*")
}

test("*surrounded* should parse all characters surrounded by one parser") {
val parser = surrounded(P("```"))
testSuccess(parser)("```\nhello\nworld```", "\nhello\nworld")
testFailure(parser)("``fail``")
}

test("cut fails when needed") {
val andThenParser: P[String] = P(P("val ") ~ alpha.rep(1).! | P("def ") ~ alpha.rep(1).!)
testFailure(andThenParser)("val 1234")
Expand Down

0 comments on commit 1ff4a1d

Please sign in to comment.