Converting BNF grammar to s-expression - racket

I defined a grammar called msl
#lang plai-typed
(define-type msl
[msl-num (n : number)]
[msl-add (l : msl) (r : msl)]
[msl-mul (l : msl) (r : msl)]
[msl-sub (l : msl) (r : msl)]
[msl-pow (l : msl) (r : msl)]
[msl-error (s : string)]
)
(define(** u t)
(cond
((= u 1) t)
(else
(* t(**(sub1 u) t)))))
I have a parser function which converts s-expression to msl
(define (parse [s : s-expression]) : msl
(cond
[(s-exp-number? s) (msl-num (s-exp->number s))]
[(s-exp-list? s)
(let ([sl (s-exp->list s)])
(case (s-exp->symbol (first sl))
[(+) (msl-add (parse (second sl)) (parse (third sl)))]
[(*) (msl-mul (parse (second sl)) (parse (third sl)))]
[ (-) (msl-sub (parse (second sl)) (parse (third sl)))]
[ (**) (msl-pow (parse (second sl)) (parse (third sl))) ]
[else (error 'parse "invalid list input")]))]
[else (error 'parse "invalid input")]))
My question is: How can I convert msl expression to s-expression like this? I'm beginner on this subject

You can definitely do this.
Before I answer the question, though... why do you want to do this? It's not generally necessary in order to implement an evaluator.
With that said: it's fairly straightforward. I would begin by writing some test cases:
(test (unparse (msl-add (msl-num 3) (msl-num 4))) '(+ 3 4))
... and the the code itself
;; convert an msl to an s-expression:
(define (unparse parsed)
(type-case msl parsed
[msl-num (n) ...]
...))
... and so forth. Let me know if this doesn't make sense.

Related

Scheme racket question about finding vowels in str

I tried to write a code about get-vowels and its running 100% but I'm trying to show these 4 output,
I just want to show these 4 output as well and I couldn't find a solution.
> (define vowels (string->list "aeiouyæøå"))
> (define (vowel? c)
(member c vowels))
> (define (filter p xs)
(define (more) (filter p (cdr xs)))
(cond
((null? xs) '())
((p (car xs)) (cons (car xs) (more)))
(else (more))))
> (define (count-vowels s)
(length (filter vowel? (string->list s))))
> (display (count-vowels "foobarbaz"))
4
example:
output:
4
"ooaa"
You shouldn't name a procedure filter, it clashes with a built-in procedure that does exactly the thing that you intend. In fact, you just need to delete your filter implementation and it'll work :)
(define vowels (string->list "aeiouyæøå"))
(define (vowel? c)
(member c vowels))
(define (count-vowels s)
(length (filter vowel? (string->list s))))
; there's a bit of code duplication here, you could
; refactor it if you want, to avoid repeating yourself
(define (extract-vowels s)
(list->string (filter vowel? (string->list s))))
(count-vowels "foobarbaz")
=> 4
(extract-vowels "foobarbaz")
=> "ooaa"

Going over a list of strings to find the string with the needed prefix

I need to define the function plPrefixContained – that consumes 5 strings and
returns the first one that contains the string "pl" as a prefix – if one such
exists, and returns #f otherwise.
What I'm trying to do is to use the prefixes function to go over all the strings in the list and check their prefixes, put them in a new list and to output the first string as the result.
(I will handle the #f case later) my code is down below but it keeps giving me the error-
first: contract violation
expected: (and/c list? (not/c empty?))
given: '()
any help would be appreciated
(: plPrefixContained : String String String String String -> String)
(define (plPrefixContained x y z w v)
(list-ref (prefixes (list x y z w v) '()) 0))
(: prefixes : (Listof String) (Listof String) -> (Listof String))
(define (prefixes lis em)
(cond
[(and (eq? (string-ref (first lis) 0) "p") (eq? (string-ref (first lis) 1) "l"))
(cons (first lis) em)]
[else
(prefixes (rest lis) em)]))
this is how I want my output to be like-for example
(test (plPrefixContained "yypl" "opl" "lpTT" "plpl" "lol")
=>
"plpl")
There are two problems:
intensional equality eq?, instead of extensional equality such as equal? or string=?
comparing string / char, instead of comparing char / char or string / string
You are using eq?, which always makes me suspicious. eq? uses "intensional" equality, which is basically pointer equality, meaning that a string which is allocated somewhere in memory won't necessarily be eq? even if it has the same characters. You can see this with (eq? "abc123" (string-append "abc" "123")).
If you're dealing with strings, lists, or any other data which "contains" things, you should avoid eq?. Instead you should use an "extensional" equality predicate such as equal?, or even better, a predicate specific to the types of values you expect, such as string=?. Here's how they behave better than eq?:
> (eq? "abc123" (string-append "abc" "123"))
#f
> (equal? "abc123" (string-append "abc" "123"))
#t
> (string=? "abc123" (string-append "abc" "123"))
#t
Since you're comparing using the strings "p" and "l", I should be able to substitute eq? with string=? in your code:
(: prefixes : (Listof String) (Listof String) -> (Listof String))
(define (prefixes lis em)
(cond
[(and (string=? (string-ref (first lis) 0) "p") (string=? (string-ref (first lis) 1) "l"))
(cons (first lis) em)]
[else
(prefixes (rest lis) em)]))
However, this reveals the second problem, which I only spotted after seeing the error message:
string=?: contract violation
expected: string?
given: #\y
argument position: 1st
other arguments...:
"p"
The string=? isn't working because its first argument, the result of string-ref, is a character (like #\y), not a string. To fix this, use char=? instead of string=?, and compare with the characters #\p and #\l instead of the strings "p" and "l".
(: prefixes : (Listof String) (Listof String) -> (Listof String))
(define (prefixes lis em)
(cond
[(and (char=? (string-ref (first lis) 0) #\p) (char=? (string-ref (first lis) 1) #\l))
(cons (first lis) em)]
[else
(prefixes (rest lis) em)]))

Defining a function that accepts a List of Lists in racket

My assignment is to count how many lists I have with length 3 in my list (List of List).
I thought I built everything correctly, but when I want to send the first list to my recursive function it fails because my list has the type Any, and I can't find a way to make it a list of lists.
#lang pl
(: count-3lists : (Listof Any) -> Number)
(define (count-3lists l)
(cond
[(null? l) 0]
[else (+ (count-3lists-helper (first l)) (count-3lists (rest l)))]))
(: count-3lists-helper : (Listof Any) -> Number)
(define (count-3lists-helper l)
(cond [(= (length l) 3) 1]
[else 0]))
(: length : (Listof Any) -> Number)
(define (length l)
(cond
[(null? l) 0]
[else (add1 (length (rest l)))]))
The error I get is:
. Type Checker: Polymorphic function `first' could not be applied to
arguments:
Types: (Pairof a (Listof b)) -> (a : ((! False # (car) (0 0)) | (False # (car) (0 0))) : (car (0 0)))
(Listof a) -> a
Arguments: (Pairof Any (Listof Any))
Expected result: (Listof Any)
in: (first l)
It seems like you want your count-3lists function to take a list of lists as its input. Right now you have (Listof Any).
What you want is express something like (Listof List), but the inner list has to be a list of something, so you can write that as (Listof (Listof Any)).
Then the first part of your code becomes this:
(: count-3lists : (Listof (Listof Any)) -> Number)
(define (count-3lists l)
(cond
[(null? l) 0]
[else (+ (count-3lists-helper (first l)) (count-3lists (rest l)))]))
After that, the rest of your code works. It turns out that your length function was fine. (So you should probably rename your question.)

showing a distinct list of specific atoms in a list in lisp

I am modeling boolean expressions as lisp lists like this : '(NOT (AND 0 (OR B C)))
I need to write a function that displays the variables in the expression
the variabels are everything except for digits , AND , OR.
any body can help me ?
example : the output of the previous expression is : (B C)
Here's my attempt:
(defun print-vars (L1)
"Append L1 by L2."
(if (= 0 (list-length (L1)))
nil
(if (= 1 (list-length (L1)))
L1
(cons (print-vars (remove-duplicates (first (L1))))
(print-vars (remove-duplicates (rest (L1))))))))
You could do something like this:
(defun vars (exp &optional (res nil))
(if exp
(if (consp exp)
(vars (cdr exp) (vars (car exp) res))
(if (or (numberp exp) (member exp '(and or not)))
res
(adjoin exp res)))
res))
then
? (vars '(NOT (AND 0 (OR B C))))
(C B)
? (vars '(NOT (AND C (OR B C))))
(B C)

Evaluation of {with {x 3} {+ x x}} from page 76 in PLAI

I am studying PLAI's Chapter8 "Implementing Laziness", and finished the following CFAE/L:
(define-type CFAE/L
[num (n number?)]
[add (lhs CFAE/L?)(rhs CFAE/L?)]
[id (name symbol?)]
[fun (param symbol?)(body CFAE/L?)]
[app (fun-expr CFAE/L?)(arg-expr CFAE/L?)])
(define-type CFAE/L-Value
[numV (n number?)]
[closureV (param symbol?)
(body CFAE/L?)
(env Env?)]
[exprV (expr CFAE/L?)
(env Env?)])
(define-type Env
[mtSub]
[aSub (name symbol?)(value CFAE/L-Value?)(env Env?)])
(define (num+ x y) ;; need this because we can't just use Scheme + to add FAE-values
(numV (+ (numV-n x) (numV-n y))))
(define (parse sexp)
(cond [(number? sexp) (num sexp)]
[(symbol? sexp) (id sexp)]
[(list? sexp)
(case (first sexp)
((+)
(add (parse (second sexp))
(parse (third sexp))))
((with)
(app (fun (first (second sexp))
(parse (third sexp)))
(parse (second (second sexp)))))
((fun)
(fun (first (second sexp))
(parse (third sexp))))
(else
(app (parse (first sexp))
(parse (second sexp)))))]))
(define (lookup name env)
(type-case Env env
[mtSub() (error 'lookup "no binding for identifier")]
[aSub (bound-name bound-value rest-ds)
(if (symbol=? bound-name name)
bound-value
(lookup name rest-ds))]))
(define (interp expr env)
(type-case CFAE/L expr
[num (n) (numV n)]
[add (l r)(num+ (interp l env)(interp r env))]
[id (v) (lookup v env)]
[fun (bound-id bound-body)
(closureV bound-id bound-body env)]
[app (fun-expr arg-expr)
(local ([define fun-val (interp fun-expr env)]
[define arg-val (exprV arg-expr env)])
(interp (closureV-body fun-val)
(aSub (closureV-param fun-val)
arg-val
(closureV-env fun-val))))]))
According to this interpreter, I want to evaluate the page76's
{with {x 3} {+ x x}}
(1) when typing:
(interp (parse '{with {x 3} {+ x x}}) {mtSub})
I got errors as below:
numV-n: contract violation, expected: numV?, given: (exprV (num 3) (mtSub))
contract from: numV-n, blaming: use
contract: (-> numV? number?)
at: /study/lisp/plai/chapter8.scm:10.9
(2) I wanted to write down the steps by hand for understanding page76's description as below:
"The interpreter evaluates each x in the body to an expression closure (because that’s what is bound to x in the environment), but the addition procedure cannot handle these: it (and similarly any other arithmetic primitive) needs to know exactly which number the expression closure corresponds to.", but I am still not clear about this description after finishing the steps. there are my steps : (interp (parse '(with (x 3) (+ x x))) (mtSub))
step1: (parse '(with (x 3) (+ x x))) => (app (fun 'x (add (id 'x) (id 'x))) (num 3))
NOTE: fun-exp is (fun 'x (add (id 'x), arg-expr is (num 3)
step2: (cloSureV 'x (add (id 'x) (id 'x)) (mtSub)) (as fun-val)
and (experV (num 3) (mtSub)) (as arg-val)
step3: (interp (add (id 'x) (id 'x)) (aSub 'x (num 3) (mtSub)))
Thanks in advance!
Ad 1)
This is the expected behaviour. The error message you got was:
numV-n: contract violation,
expected: numV?,
given: (exprV (num 3) (mtSub))
...
This numV-n was the one in num+. This es explained in the last
paragraph of page 75. The primitives such as num+ expected non-closure
values, but the value (exprV (num 3) (mtSub)) is the number 3 closed
over the empty environment.
Therefore the primitives such as num+ must force the arguments.
From page 76:
(define (num+ n1 n2)
(numV (+ (numV-n (strict n1) ) (numV-n (strict n2) ))))
Ad 2)
Do the explanation of 1) help with 2) ?
ADDED
Why not let the interpreter write out the steps for you?
The quick fix:
(define (interp expr env)
(displayln (list 'expr expr 'env env))
(type-case CFAE/L expr
To get more readable output, first write unparse that converts
a CFAE/L to a (readable) string.