Skip to content

Commit

Permalink
tatt bort løsning
Browse files Browse the repository at this point in the history
  • Loading branch information
eirikm committed Aug 16, 2024
1 parent cb4613a commit 8004c7b
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 432 deletions.
3 changes: 3 additions & 0 deletions oppgaver/src/test/scala/arktekk/ParserSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import org.scalatest.funsuite.AnyFunSuite

trait ParserSuite extends AnyFunSuite {

inline def implement_me: Parser[Unit] = ???
inline def implement_me[A]: Parser[A] = ???

inline def assertParses[A](parser: Parser[A], inputs: (String, A)*) = {
inputs.foreach { (input, expectedResult) =>
val result = parser.parseAll(input)
Expand Down
116 changes: 1 addition & 115 deletions oppgaver/src/test/scala/arktekk/json/JsonParser.scala
Original file line number Diff line number Diff line change
@@ -1,119 +1,5 @@
package arktekk.json

import cats.data.NonEmptyList
import cats.parse.{Parser, Rfc5234}
import arktekk.ParserSuite

import scala.util.Try

class JsonParser extends ParserSuite {

enum JsonValue {
case JsonNull
case JsonBoolean(value: Boolean)
case JsonNumber(value: BigDecimal)
case JsonString(value: String)
case JsonArray(values: List[JsonValue])
case JsonObject(pairs: List[(String, JsonValue)])
}
import JsonValue.*

val ows = (Rfc5234.wsp | Rfc5234.crlf).rep0.void
val comma = Parser.char(',').surroundedBy(ows).withContext("comma")
val colon = Parser.char(':').surroundedBy(ows)
val openBracket = Parser.char('[').surroundedBy(ows)
val closeBracket = Parser.char(']').surroundedBy(ows).withContext("closeBracket")
val openBrace = Parser.char('{').surroundedBy(ows)
val closeBrace = Parser.char('}').surroundedBy(ows).withContext("closeBrace")

val jsonNull: Parser[JsonValue] = Parser.string("null").as(JsonNull).withContext("null")
val jsonBoolean: Parser[JsonValue] =
(Parser
.string("false")
.as(JsonBoolean(false)) | Parser.string("true").as(JsonBoolean(true))).withContext("boolean")
val jsonNumber: Parser[JsonValue] =
cats.parse.Numbers.jsonNumber.mapFilter(s => Try(JsonNumber(BigDecimal(s))).toOption)

val jsonStringParser: Parser[String] = cats.parse.strings.Json.delimited.parser

val jsonString: Parser[JsonValue] = jsonStringParser.map(JsonString.apply)

val jsonScalar: Parser[JsonValue] = jsonNull | jsonBoolean | jsonNumber | jsonString

val jsonRecur: Parser[JsonValue] = Parser.defer {
val jsonValue = (jsonRecur | jsonScalar).surroundedBy(ows)
val jsonArray: Parser[JsonValue] = {
(openBracket ~ closeBracket).as(JsonArray(List.empty)).backtrack |
jsonValue
.repSep(comma)
.between(openBracket, closeBracket)
.map(nel => JsonArray(nel.toList))
}

val jsonObject: Parser[JsonValue] = {
(openBrace ~ closeBrace).as(JsonObject(List.empty)).backtrack |
((jsonStringParser <* colon) ~ jsonValue)
.repSep(comma)
.between(openBrace, closeBrace)
.map((pairs: NonEmptyList[(String, JsonValue)]) => JsonObject(pairs.toList))
}

jsonArray | jsonObject
}

val jsonValue: Parser[JsonValue] = jsonScalar | jsonRecur

test("null") {
assertParses(jsonValue, "null" -> JsonNull)
}

test("true/false") {
val validInputs = List(
"false" -> JsonBoolean(false),
"true" -> JsonBoolean(true)
)

assertParses(jsonValue, validInputs*)
}

test("jsonNumber") {
val validInputs = List(
"123" -> JsonNumber(BigDecimal("123")),
"123.123" -> JsonNumber(123.123)
)

assertParses(jsonValue, validInputs*)
}

test("jsonString") {
val validInputs = List(
"\"foo\"" -> JsonString("foo"),
"\"æøå\"" -> JsonString("æøå")
)
assertParses(jsonValue, validInputs*)
}

test("jsonArray") {
val validInputs = List(
" [ ] " -> JsonArray(List.empty),
"[ 1, 20 ]" -> JsonArray(List(JsonNumber(1), JsonNumber(20)))
)

assertParses(jsonValue, validInputs*)
}

test("jsonObject") {
val validInputs = List(
"{ }" -> JsonObject(List.empty),
"""{"test": 1}""" -> JsonObject(List("test" -> JsonNumber(BigDecimal(1)))),
"""{"foo": "bar","fizz":[1,2,3,"fizz"]}""" -> JsonObject(
List(
("foo", JsonString("bar")),
("fizz", JsonArray(List(JsonNumber(1), JsonNumber(2), JsonNumber(3), JsonString("fizz"))))
)
)
)

assertParses(jsonValue, validInputs*)
}
}
class JsonParser extends ParserSuite {}
19 changes: 3 additions & 16 deletions oppgaver/src/test/scala/arktekk/oppgave1/Backtracking.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package arktekk.oppgave1

import arktekk.ParserSuite
import cats.parse.{Parser, Rfc5234}
import cats.parse.Parser

class Backtracking extends ParserSuite {

Expand All @@ -17,12 +17,7 @@ class Backtracking extends ParserSuite {
".55" -> Tall.Flyttall(0.55)
)

val heltall = Rfc5234.digit.rep.string.map(s => Tall.Heltall(s.toInt)).withContext("heltall")
val flyttall = (Rfc5234.digit.rep0.with1 ~ Parser.char('.') ~ Rfc5234.digit.rep).string
.map(s => Tall.Flyttall(s.toDouble))
.withContext("flyttall")

val p = flyttall.backtrack | heltall
val p: Parser[Tall] = implement_me

assertParses(p, validInputs*)
}
Expand All @@ -42,15 +37,7 @@ class Backtracking extends ParserSuite {
"19m" -> Lengde.Meter(19)
)

val heltall: Parser[Int] = Rfc5234.digit.rep.string.mapFilter(_.toIntOption)

val millimeter: Parser[Lengde] =
(heltall <* Parser.string("mm")).map(Lengde.Millimeter.apply).withContext("millimeter")
val centimeter: Parser[Lengde] =
(heltall <* Parser.string("cm")).map(Lengde.Centimeter.apply).withContext("centimeter")
val meter: Parser[Lengde] = (heltall <* Parser.string("m")).map(Lengde.Meter.apply).withContext("meter")

val p = millimeter.backtrack | centimeter.backtrack | meter
val p: Parser[Lengde] = implement_me

assertParses(p, validInputs*)
}
Expand Down
17 changes: 14 additions & 3 deletions oppgaver/src/test/scala/arktekk/oppgave1/ParsersWithCapture.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package arktekk.oppgave1

import cats.parse.{Parser, Rfc5234}
import arktekk.ParserSuite
import cats.parse.Parser

class ParsersWithCapture extends ParserSuite {

Expand All @@ -13,7 +13,7 @@ class ParsersWithCapture extends ParserSuite {
" a " -> "a"
)

val p: Parser[String] = Parser.char('a').string.surroundedBy(Rfc5234.wsp.rep0)
val p: Parser[String] = implement_me

assertParses(p, validInputs*)
}
Expand All @@ -25,7 +25,18 @@ class ParsersWithCapture extends ParserSuite {
"æøåÆØÅ" -> "æøåÆØÅ"
)

val p = Parser.charIn(0x00.toChar to 0x10ffff.toChar).rep.string
val p: Parser[String] = implement_me

assertParses(p, validInputs*)
}

test("boolean") {
val validInputs = List(
"true" -> true,
"false" -> false
)

val p: Parser[Boolean] = implement_me

assertParses(p, validInputs*)
}
Expand Down
37 changes: 12 additions & 25 deletions oppgaver/src/test/scala/arktekk/oppgave1/SimpleParsers.scala
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
package arktekk.oppgave1

import cats.parse.{Parser, Rfc5234}
import arktekk.ParserSuite
import cats.parse.Parser

class SimpleParsers extends ParserSuite {

test("parse \"a\"") {
val input = "a"
val p = Parser.char('a')
val p = implement_me

assertParsesValid(p, input)
}

test("parse \"ab\"") {
val input = "ab"
val p = Parser.char('a') ~ Parser.char('b')
val p = implement_me

assertParsesValid(p, input)
}

test("parse \"aba\"") {
val input = "aba"
val p = Parser.char('a') ~ Parser.char('b') ~ Parser.char('a')
val p = implement_me

assertParsesValid(p, input)
}
Expand All @@ -30,7 +30,7 @@ class SimpleParsers extends ParserSuite {
val validInputs = List("aaba", "aba", "aaaabaaa")
val invalidInputs = List("baaa", "aabbaa")

val p = Parser.char('a').rep ~ Parser.char('b') ~ Parser.char('a').rep
val p = implement_me

assertParsesValid(p, validInputs*)
assertParsesInvalid(p, invalidInputs*)
Expand All @@ -39,7 +39,8 @@ class SimpleParsers extends ParserSuite {
test("parse \"aa\" og \"aaa\", men ikke \"a\" eller \"aaaa\"") {
val validInputs = List("aa", "aaa")
val invalidInputs = List("a", "aaaa")
val p = Parser.char('a').rep(2, 3)

val p = implement_me

assertParsesValid(p, validInputs*)
assertParsesInvalid(p, invalidInputs*)
Expand All @@ -49,10 +50,7 @@ class SimpleParsers extends ParserSuite {
val validInputs = List("(a, a, a)", "(a, a)", "(a, a)")
val invalidInputs = List("()", "(a)", "(a, aa)", "(a,a)")

val p =
Parser.char('(') ~
Parser.char('a').repSep(2, Parser.string(", ")) ~
Parser.char(')')
val p = implement_me

assertParsesValid(p, validInputs*)
assertParsesInvalid(p, invalidInputs*)
Expand All @@ -61,7 +59,7 @@ class SimpleParsers extends ParserSuite {
test("parse \"a\" med vilkårlig mange spaces før og/eller etter") {
val validInputs = List("a", " a", " a", " a ")

val p = Parser.char('a').surroundedBy(Rfc5234.wsp.rep0)
val p = implement_me

assertParsesValid(p, validInputs*)
}
Expand All @@ -70,7 +68,7 @@ class SimpleParsers extends ParserSuite {
val validInput = "nananananananananana Batman"
val invalidInputs = List("nanana Batman", "nananananananananananananananananananana Batman")

val p = Parser.string("na").rep(10, 10) ~ Rfc5234.wsp ~ Parser.string("Batman")
val p = implement_me

assertParsesValid(p, validInput)
assertParsesInvalid(p, invalidInputs*)
Expand All @@ -80,7 +78,7 @@ class SimpleParsers extends ParserSuite {
val validInputs = List("123", "234", "1", "0")
val invalidInputs = List("-1", "0xff", "a", "12c")

val p = Parser.charsWhile(_.isDigit)
val p = implement_me

assertParsesValid(p, validInputs*)
assertParsesInvalid(p, invalidInputs*)
Expand All @@ -89,19 +87,8 @@ class SimpleParsers extends ParserSuite {
test("DNA") {
val validInputs = List("ACGT", "AAA", "TT", "ATGG", "CCAATG")

val p = Parser.charIn("ACGT").rep
val p = implement_me

assertParsesValid(p, validInputs*)
}

test("boolean") {
val validInputs = List(
"true" -> true,
"false" -> false
)

val p: Parser[Boolean] = Parser.string("true").as(true) | Parser.string("false").as(false)

assertParses(p, validInputs*)
}
}
34 changes: 6 additions & 28 deletions oppgaver/src/test/scala/arktekk/oppgave2/PointerParser.scala
Original file line number Diff line number Diff line change
@@ -1,37 +1,15 @@
package arktekk.oppgave2

import cats.data.NonEmptyList
import cats.parse.*

object PointerParser {
val unescaped = Parser.charIn(0x00.toChar to 0x2e.toChar) | Parser.charIn(0x30.toChar to 0x7d.toChar) | Parser.charIn(
0x7f.toChar to 0x10ffff.toChar
)
val escaped = Parser.string("~0") | Parser.string("~1")
val zero = Parser.char('0').as(Ref.Index(0))
// json-pointer = *( "/" reference-token )
// reference-token = *( unescaped / escaped )
// unescaped = %x00-2E / %x30-7D / %x7F-10FFFF ; %x2F ('/') and %x7E ('~') are excluded from 'unescaped'
// escaped = "~" ( "0" / "1" ) ; representing '~' and '/', respectively

val endOfList = Parser.char('-').as(Ref.EndOfList)

val digitWithOutZero = Parser.charIn('1' to '9')
val digit = Parser.charIn('0' to '9')
val numericIndex = (digitWithOutZero ~ digit.rep0).string.map(x => Ref.Index(x.toInt))

val sep = Parser.char('/')
val emptyProp = sep.as(Ref.Property(""))

val index: Parser[Ref & ArrayRef] = zero | endOfList | numericIndex
val property: Parser[Ref] =
(unescaped | escaped).rep.string.map(Ref.Property(_)) | emptyProp

val root = Parser.end.as(Path.Root)

val refs = (emptyProp ~ (index | property).repSep0(sep.?) ~ emptyProp.?).map { case ((empty, list), maybeEnd) =>
if list.isEmpty then Path.Refs(NonEmptyList.of(empty))
else Path.Refs(NonEmptyList.fromListUnsafe(list ++ maybeEnd.toList))
}

val parser: Parser0[Path] =
root | refs
// skal være val
def parser: Parser0[Path] = ???

def parse(input: String): Either[Parser.Error, Path] = parser.parseAll(input)

Expand Down
Loading

0 comments on commit 8004c7b

Please sign in to comment.