Skip to content

Commit

Permalink
Merge branch 'fasit'
Browse files Browse the repository at this point in the history
  • Loading branch information
hamnis committed Sep 2, 2024
2 parents 4b4a143 + e2e24a5 commit bdbed0e
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 85 deletions.
67 changes: 0 additions & 67 deletions foredrag/foredrag2.md

This file was deleted.

177 changes: 159 additions & 18 deletions foredrag/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,19 @@ bruke i dag, så trenger vi å gå litt gjennom basic Scala syntaks.
// en verdi av typen Int
val value: Int = 1
val value = 1
// sløfyer typen, type inference

// metodekall
println("na" * 10 + " Batman")
// val res5: String = nananananananananana Batman

```
<!--
For de observante så kan man se at vi har operator overloading.
Dette er ikke en ikke mye brukt feature av scala, men tok det med her
for å vise at det finnes.
-->


---

Expand All @@ -80,6 +87,7 @@ println("na" * 10 + " Batman")
// Metode definisjon
def sayHello(who: String): Unit = println(s"Hello $who")
def sayHello(who: String) = println(s"Hello $who")
// sløfyer returtypen, type inference

// metode definisjon med generiske typer
def generic[A](input: A): Unit = println(s"called with ${input}")
Expand All @@ -102,34 +110,48 @@ enum EvenOdd {

def even(x: Int) = if isEven(x) then EvenOdd.Even else EvenOdd.Odd

```

---
## Algebraiske datatyper


```scala 3
enum EvenOdd {
case Even(num: Int)
case Odd(num: Int)
}


def even(x: Int): EvenOdd = if isEven(x) then EvenOdd.Even(x) else EvenOdd.Odd(x)


```

---
## case class

```scala 3
case class Dog(name: String)
// Tilsvarer data class i Kotlin - Record types i Java
// men med superkrefter

val dog = Dog("Fido")

println(dog)
//printer ut Dog(Fido)

```


---
## Algebraiske datatyper

## tuple

```scala 3
enum EvenOdd {
case Even(num: Int)
case Odd(num: Int)
}


def even(x: Int): EvenOdd = if isEven(x) then EvenOdd.Even(x) else EvenOdd.Odd(x)
// tilsavarer Pair i kotlin, men kan ha uendelig aritet
val tuple: (String, Int) = ("Don't Panic", 42)

println(tuple)
//printer ut (Don't, Panic, 42)

```

Expand All @@ -138,17 +160,102 @@ def even(x: Int): EvenOdd = if isEven(x) then EvenOdd.Even(x) else EvenOdd.Odd(x
> A parser is a software component that takes input data (typically text) and builds a data structure – often some kind of parse tree, abstract syntax tree or other hierarchical structure, giving a structural representation of the input while checking for correct syntax.
[wikipedia](https://en.wikipedia.org/wiki/Parsing#Parser)

<!--
Hvor mange her har brukt parsere før?
Det finnes mange måter å representere parsere på, i de følgende slidene kommer
vi til å se litt mer på hvordan dette kan representeres i Scala.
Til slutt skal vi vise noen eksempler.
Men først et sidespor med noen flere definisjoner.
-->

---
# Backus–Naur form (BNF)


> In computer science, Backus–Naur form (/ˌbækəs ˈnaʊər/) (BNF or Backus normal form) is a notation used to describe the syntax of programming languages or other formal languages. It was developed by John Backus and Peter Naur. BNF can be described as a metasyntax notation for context-free grammars. [...] BNF can be used to describe document formats, instruction sets, and communication protocols.
[wikipedia](https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form)

<!--
Dette er et språk for å formelt beskrive parsere, De finnes i to vanlige former.
-->

---

# Backus–Naur form (BNF) Variants

> In computer science, extended Backus–Naur form (EBNF) is a family of metasyntax notations, any of which can be used to express a context-free grammar. EBNF is used to make a formal description of a formal language such as a computer programming language.
[wikipedia](https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form)

```
digit excluding zero = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
digit = "0" | digit excluding zero ;
```

<!--
Dette er en vanlig måte å beskriver parsere på, spesielt i programminggspråk.
Det siste oppgavesettet kommer til å bruke dette.
-->


---

# Backus–Naur form (BNF) Variants

> Augmented Backus–Naur form (ABNF) and Routing Backus–Naur form (RBNF) are extensions commonly used to describe Internet Engineering Task Force (IETF) protocols.
[wikipedia](https://en.wikipedia.org/wiki/Augmented_Backus%E2%80%93Naur_form)

```
rule = definition / alternate definition ; comment CR LF
```

<!--
Denne varianten av BNF er den vi skal bruke mest i denne workshoppen.
Oppgavesett 2, pluss i deler av oppgavesett 1.
For de som er kjent med RFCer så er dette brukt i stort sett alle.
--->

---

# ABNF eksempel - JSON Pointer
[RFC6901](https://www.rfc-editor.org/rfc/rfc6901)

Dette her kommer igjen som en oppgave i oppgavesett 2

```
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
```

<!--
Dette er et eksempel på full parser basert på ABNF.
VI har lagt ved en PDF i foredragsfolderen i prosjektet.
Den pdfen forklarer de forskjellige bestandddelene av syntaksen.
Nå når vi har sett litt på hvordan formelt beskrive en parser, la oss se på hvordan
dette kan se ut i Scala.
--->


# Hva er en parser?

```scala 3
def parser[I, O](input: I): ParseResult[I, O] = ???
```

<!--
En parser er kode som transformerer noe input I til
noe av output av `ParseResult[I, O]`.
En parser er kode som transformerer noe input av typen I til
noe av output av typen `ParseResult[I, O]`.
ParseResult vil inneholde posisjonsdata for inputen, og eventuelle feil.
-->
Expand All @@ -163,6 +270,7 @@ def parser[I, O]: I => ParseResult[I, O] = ???

<!--
Litt forenklet kan man se på det som en funksjon fra I til ParseResult[I, O].
Denne er ekvivalent med med definisjonen på forrige slide.
-->

---
Expand All @@ -177,6 +285,9 @@ def parser[O]: String => ParseResult[O] = ???
Enda mer forenklet og det vi kommer til å bruke i resten av presentasjonen og
oppgaveløsningen er at vi tar en input av String og produserer et resultat av
en type O.
Det som er viktig her er at vi kan for enkelhetensskyld på en streng som en collection av karakterer og
det er det vi håndterer.
-->


Expand All @@ -191,7 +302,7 @@ final case class Parser[O](run: String => ParseResult[O])
<!--
Det som vi kan gjøre med nå når vi har etablert hva en parser er, så kan vi pakke den inn i en datatype.
Det finnes flere mulige måter å gjøre det på.
Her har vi pakket inn en funksjon inn i en case klasse, men vi kan også lage et interface eller det som i Scala blir kalt et trait.
Her har vi pakket inn en funksjon inn i en case klasse.
-->

---
Expand All @@ -205,12 +316,11 @@ trait Parser[O] {
```

<!--
Det som vi kan gjøre med nå når vi har etablert hva en parser er, så kan vi pakke den inn i en datatype.
Det finnes flere mulige måter å gjøre det på.
Her har vi pakket inn en funksjon inn i en case klasse, men vi kan også lage et interface eller det som i Scala blir kalt et trait.
Her er den samme definisjonen som på forrige slide, men bruker et trait i stedet.
Med en gang vi har en datatype, så kan vi definere operasjoner på den.
Disse operasjonene blir typisk kalt kombinatorer, derav navnet.
-->


---
# Cats Parse

Expand All @@ -223,11 +333,42 @@ sealed trait Parser[A] extends Parser0[A] {
}
```


`cats-parse` er substring orientert, så vi ser på biter av en streng, og henter ut informasjon fra den.
Dette betyr at vi setter sammen parsere som matcher biter av strenger til vi når EOI (End of Input).


---
## Kombinatorer

```scala 3

def map[B](f: A => B): Parser[B] = ???
def as[B](const: B): Parser[B] = map(_ => const)

// forkast output fra min parser og bruk denne.
def *>[B](p: Parser[B]): Parser[B] = ???

// forkastg output fra denne parseren og bruk min
def <*[B](p: Parser[B]): Parser[A] = ???

// parse også dette, og returner resultatet av min og denne i tuppel.
def ~[B](p: Parser[B]): Parser[(A, B)] = ???

```

<!--
Her har vi definert flere operasjoner som hver av seg produserer en ny parser er kombinert
La oss ta for oss noen av disse:
map er den enkleste her. Den transformerer resultatet av parseren til noe annet.
as er egentlig bare et kall til map der vi ignorerer input til funksjonen.
De tre neste operasjonene er symboltunge, og er de som er brukt i cats-parse som
vi skal bruke i oppgaveløsningen. Ikke få panikk av dette.
Se i ressurser.md filen i foredrag folderen for mer hjelp.
-->

----
# Parser combinators

Expand Down
21 changes: 21 additions & 0 deletions foredrag/setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
theme: gaia
_class: lead
paginate: true
backgroundColor: #fff
backgroundImage: url('https://marp.app/assets/hero-background.svg')
marp: true
---

![bg left:40% 80%](assets/logo.svg)

# **Setup**

En parser som spiser parsere

* `git clone` https://github.com/arktekk/javazone-workshop-parser-combinators
* Installer Intellij IDEA
* Installer Scala plugin
* Bruk Java 21

Åpne prosjektet i IDEA. Kompiler prosjektet. CTRL+F9 eller CMD+F9

0 comments on commit bdbed0e

Please sign in to comment.