###### tags: `MP`
# Parsowanie ciąg dalszy
Na ćwiczenia parser był zrobiony brzydko lub tak,że trudno było go powiększać. Były też jakieś błędy w stylu, że nie sprawdzaliśmy, czy liczba argumentów była dobra, po prostu braliśmy pierwsze 2 i ignorowaliśmy resztę.
## Jak to zrobić trochę prościej / ładniej?
`s-exp-match?` bierze dwa s-wyrażenia i sprawdza czy pasują.
```plait
(s-exp-match? `(ANY ANY ANY) `(1 2 3)) ;#t
(s-exp-match? `(ANY NUMBER ANY) `(1 2 3)) ;#t
(s-exp-match? `(lambda ANY ANY) `(1 2 3)) ;#f
```
Teraz sprawdzanie, czy wyrażenie jest dobrego kształtu jest znacznie prostsze:
```plait
(define (parse-Exp s)
(cond
[(s-exp-match? 'NUMBER s) (exp-number (s-exp->number s))]
[(s-exp-match? '(SYMBOL ANY ANY) s)
(let ([xs (s-exp->list s)])
(exp-op (parse-op (first xs))
(parse-Exp (second xs))
(parse-Exp (third xs))))]))
```
### Napiszmy w rackecie własny match
```racket
;sytnax.rkt
(define (match-sexp pat s)
(match pat
[`ANY #t]
[`SYMBOL (symbol? s)]
[`NUMBER (number? s)]
[`() (null? s)]
[(cons p1 p2) (and (pair? s)
(match-sexp p1 (car s))
(match-sexp p2 (cdr s)))]))
(require (only-in plait s-exp-content))
(provide (my-match-sexp?))
(define (my-match-sexp? pat s) ;pat jest plaitowym wyrazeniem
(match-sexp (s-exp-content pat) (s-exp-content s)))
```
### Jak tego użyć w plaicie?
```plait
(require "syntax.rkt")
(require (typed-in "parser.rkt"
(my-match-sexp? : (S-Exp S-Exp -> Boolean)))) ;potrzebujemy cos, co otypuje (nie sprawdza tego ale to nie problem)
(define (parse-Exp s)
(cond
[(my-match-sexp? 'NUMBER s) (exp-number (s-exp->number s))]
[(my-match-sexp? '(SYMBOL ANY ANY) s)
(let ([xs (s-exp->list s)])
(exp-op (parse-op (first xs))
(parse-Exp (second xs))
(parse-Exp (third xs))))]))
```
Najważniejsze - jak mamy dużo powtarzającego się kodu to można wyrzucić to do osobnego języka i napisać interpreter.
**Coś było dalej ale nie słuchałam**
## Piszemy jakieś nowe rzeczy
```racket
(define (my-match-sexp? pat s)
(match-sexp pat s))
```
```racket
(define (parse-Op )
cond []
[]
[]
[]
[])
```
Na ten moment każdy parser jest wielkim `cond`-em i wszystko w środku się powtarza, można to uprościć:
```racket
(define op-parser
`((+ ,opp-add)
(- ,opp-sub)
(* ,opp-mul)
(/ ,opp-div)))
(define exp-parser
`((NUMBER ,exp-number)
(SYMBOL ANY ANY ,(lambda (op e1 e2) (exp-op (parse-Op op)
(parse-Exp e1)
(parse-Exp e2))))))
(define run-parser)
```