---
# System prepended metadata

title: Parsowanie ciąg dalszy
tags: [MP]

---

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


