Scheme Lexical Analyzer - scheme

Currently working on a lexical analyzer in Scheme. I'm new to scheme but have a general understanding of what to do. I am following a online tutorial, however I keep getting this error because I'm not using UMASS scheme. What can I do to replace this class (Error: record-parse unbound identifier). Below is my code
#lang racket
(define record_parse
(lambda(noun adjective adverb conjunction prep terminator)
((noun) '(dog cat rat house tree))
((adjective) '(furry fast lazy sneaky))
((adverb) '(quickly silently))
((conjunction) '(and or))
((prep) '(with around up))
((terminator) '(!))))
(define noun '(dog cat rat house tree))
(define adjective '(furry fast lazy sneaky))
(define adverb '(quickly silently))
(define conjunction '(and or))
(define prep '(with around up))
(define terminator '(!))
(define class_parse (record-parse 'parse '(full full)))
(define cons_parse (car class_parse))
(define sel_parse (caddr class_parse))
(define tree_parse (car sel_parse))
(define rest_parse (cadr sel_parse))
(define parse_article
(lambda (list_of_tokens)
(cond
((null? list_of_tokens) #f)
((member? (car list_of_tokens) '(a the))
(cons_parse
(car list_of_tokens)
(cdr list_of_tokens)))
(else #f )
)
)
)
(define (member? x list)
(if (null? list) #f
(if (equal? x (car list)) #t
(member? x (cdr list)))))
(define parse_noun
(lambda (list_of_tokens)
(cond
((null? list_of_tokens) #f)
((member? (car list_of_tokens) noun)
(cons_parse
(car list_of_tokens)
(cdr list_of_tokens)))
(else #f )
)
)
)
(define parse_noun_phrase
(lambda (list_of_tokens)
(let ((p_det (parse_article list_of_tokens)))
(if p_det
(let ( (p_n (parse_noun (rest_parse p_det))))
(if p_n
(cons_parse
(list 'noun_phrase
(tree_parse p_det)
(tree_parse p_n))
(rest_parse p_n)
)
#f)
)
#f)
)
))
(define verb '(loves hates eats chases stalks))
(define parse_verb
(lambda (list_of_tokens)
(cond
((null? list_of_tokens) #f)
((member? (car list_of_tokens) verb)
(cons_parse
(car list_of_tokens)
(cdr list_of_tokens)))
(else #f )
)
)
)
(define parse_verb_phrase
(lambda (list_of_tokens)
(let ((p1 (parse_verb list_of_tokens)))
(if p1
(let ((p2 (parse_noun_phrase (rest_parse p1))))
(if p2
(cons_parse
(list 'verb_phrase
(tree_parse p1)
(tree_parse p2))
(rest_parse p2)
)
#f)
)
#f)
)
))
(define parse_sentence
(lambda (list_of_tokens)
(let ((p1 (parse_noun_phrase list_of_tokens)))
(if p1
(let ((p2 (parse_verb_phrase (rest_parse p1))))
(if p2
(cons_parse
(list 'sentence
(tree_parse p1)
(tree_parse p2))
(rest_parse p2)
)
#f)
)
#f)
)
))
;example of parsing a sentence
;(example
; '(parse_sentence '(the dog chases the cat))
; (cons_parse
; '(sentence (noun_phrase the dog)
; (verb_phrase chases
; (noun_phrase the cat)
; (terminator)))
; '()
; )
; )
(begin
(display "Enter a Sentance in (): ")
(let ((input (read)))
(parse_article (parse_sentence input))))
I am getting the error with the (define class_parse (record-parse 'parse '(full full)))

The procedure you defined is called record_parse, but you're trying to invoke it as record-parse. After that typo is fixed, you'll get a different error: record_parse is defined to receive 6 parameters, but you're passing only two: 'parse and '(full full). And the body of record_parse doesn't make sense, it seems that you tried to implement a case expression, but that's not how it's written in Scheme - at all.
That's only for starters, it looks like there are more errors. You should test each procedure individually until you get the hang of the syntax and before writing more complex behavior that involves using all of the procedures.

Related

How might I use letrec in this function so that it does the same job as it does with named let?

I've read here that named let can be rewritten with letrec.
And so I proceeded to rewrite the following function with letrec:
(define (duplicate pos lst)
(let dup ([i 0] [lst lst])
(cond
[(= i pos) (cons (car lst) lst)]
[else (cons (car lst) (dup (+ i 1) (cdr lst)))])))
My attempt at this:
(define (duplicate pos lst)
(letrec ((dup (lambda ([i 0] [lst lst])
(cond
[(= i pos) (cons (car lst) lst)]
[else (cons (car lst) (dup (+ i 1) (cdr lst)))]))))))
Sadly, when I call it with (duplicate 1 (list "apple" "cheese burger!" "banana")) I get from Racket letrec: bad syntax (missing body). How might I rewrite duplicate with letrec?
As you can see in the documentation for letrec, it has these arguments:
(letrec ([id val-expr] ...) body ...+)
So, you have to add at least one body form after definitions.
I also replaced cond with if (you have only two branches of code), (+ ... 1) with add1 and improved indentation:
#lang racket
(define (duplicate pos lst)
(letrec ((dup (lambda ([i 0] [lst lst])
(if (= i pos)
(cons (car lst)
lst)
(cons (car lst)
(dup (add1 i) (cdr lst)))))))
(dup)))
Test:
> (duplicate 1 (list "apple" "cheese burger!" "banana"))
'("apple" "cheese burger!" "cheese burger!" "banana")
The named let is (more or less) a locally defined regular procedure that is called "behind the scenes".
The body of a named let is not the body of the equivalent "unnamed" let, but the body of that procedure;
(let f ([x init])
body)
can be rewritten as
(letrec ([f (lambda ([x init]) body)])
(f))
or, without using default arguments (which some would find clearer),
(letrec ([f (lambda (x) body)])
(f init))

How to create a function that receives a list and creates a new list in Scheme

I'm trying to create a function called evenElememt that takes a list as a parameter and appends all the elements in even positions to a new list and displays the new list.
My attempt:
(define newList '())
(define elementHelper
(lambda lst
((cdr lst)
(cons newList (car lst))
(elementHelper(cdr lst)))
)
)
(define evenElement
(lambda (lst)
(cond
((null? lst) ())
((null? (cdr lst)) ())
(else (elementHelper lst)
(display lst))
)
)
)
Example output: if I enter (evenElement '('a 'b 'c 'f 't 'y)), the output should be (b f y).
This is essentially the same as Can I print alternate elements of a list in Racket?, except that you want to print even positions (1-indexed) instead of odd positions.
(define (even-positions lst)
(cond ((null? lst)
'())
((null? (cdr lst))
'())
(else
(cons (second lst)
(even-positions (cddr lst))))))
(even-positions '(a b c f t y)) returns '(b f y).
Then, this is the function you are looking for:
(define (display-even-positions lst)
(display (even-positions lst)))
You don't need elementHelper. Just make evenElement return the result instead of displaying it.
You also don't need the global variable newList. The function should construct the result as it goes.
(define evenElement
(lambda (lst)
(cond
((null? lst) '())
((null? (cdr lst)) '())
(else (cons (car (cdr lst))
(evenElement (cdr (cdr lst)))))
)
)
)
(display (evenElement '(a b c f t y)))

chicken scheme ; error while using let inside a function

what is wrong with this code ?
(define (make-node key data )
(list key data 'null 'null ) )
(define (right)(2) )
(define (left) (3) )
;;inserts a key to the tree
;; string x string -> list
(define (insert lst key data )
(if (null? lst )
(make-node key data )
(cond ( [(string>? key (car lst)) (list-set lst 2 (insert lst key data)) ]
[(string<? key (car lst)) (list-set lst 3 (insert lst key data)) ]
[(string=? key (car lst)) (list-set lst 1 data ) ]
))))
(define (list-set lst ix data )
(if (eqv? ix 0 ) ( cons data (cdr lst ) ) ( cons (car lst) (list-set ( cdr lst) ( - ix 1 ) data ))))
( define (newdiction) [
let ( ( [ tree '() ]) [ (msg key data )[ cond ( (eqv? msg 'insert ) [ set! tree (insert tree key data ) ] ) ] ] )
] )
the chicken scheme interpreter spits:
CHICKEN
(c) 2008-2014, The Chicken Team
(c) 2000-2007, Felix L. Winkelmann
Version 4.9.0.1 (stability/4.9.0) (rev 8b3189b)
linux-unix-gnu-x86-64 [ 64bit manyargs dload ptables ]
bootstrapped 2014-06-07
; loading dict.scm ...
Error: during expansion of (let ...) - in `let' - symbol expected: (let (((tree (quote ()))) ((msg key data) (cond ((eqv? msg (quote insert)) (set! tree (insert tree key data)))))))
Call history:
<syntax> (define (list-set lst ix data) (if (eqv? ix 0) (cons data (cdr lst)) (cons (car lst) (list-set (cdr lst...
<syntax> (##core#set! list-set (##core#lambda (lst ix data) (if (eqv? ix 0) (cons data (cdr lst)) (cons (car lst...
<syntax> (##core#lambda (lst ix data) (if (eqv? ix 0) (cons data (cdr lst)) (cons (car lst) (list-set (cdr lst...
<syntax> [list-set] (##core#begin (##core#if (eqv? ix 0) (cons data (cdr lst)) (cons (car lst) (list-set (cdr lst) (- ix...
<syntax> [list-set] (##core#if (eqv? ix 0) (cons data (cdr lst)) (cons (car lst) (list-set (cdr lst) (- ix 1) data)))
<syntax> [list-set] (eqv? ix 0)
<syntax> [list-set] (cons data (cdr lst))
<syntax> [list-set] (cdr lst)
<syntax> [list-set] (cons (car lst) (list-set (cdr lst) (- ix 1) data))
<syntax> [list-set] (car lst)
<syntax> [list-set] (list-set (cdr lst) (- ix 1) data)
<syntax> [list-set] (cdr lst)
<syntax> [list-set] (- ix 1)
<syntax> (define (newdiction) (let (((tree (quote ()))) ((msg key data) (cond ((eqv? msg (quote insert)) (set......
<syntax> (##core#set! newdiction (##core#lambda () (let (((tree (quote ()))) ((msg key data) (cond ((eqv? msg...
<syntax> (##core#lambda () (let (((tree (quote ()))) ((msg key data) (cond ((eqv? msg (quote insert)) (set! t...... <--
This code is suffering from too many parentheses. So Scheme is very flexible and thus you can have code like this:
((som-func som-arg) some-other-arg)
What is happening there? Well. Since (some-func som-arg) is not a special form or macro it has to be an expression that leads to a function so it gets evaluated. Since some-func is not a special form or macro it has to be an expression that leads to a function and thus it evalautes it and some-arg and applies it. The result will be the function to call with the evaluation of some-other-arg as the argument.
I see you use [ ... ] as well as ( ... ). Know that the difference between these are just how they look and the interpretation of them is the same. Thus if you change (+ 1 2) to [+ 1 2] you get 3 both times. No difference. You may use them to indicate some sort of grouping in macros like let, but it makes no difference for the implementation.
If you look at your let:
(let ([(tree '())] ...)
body ...)
So the first variable is (tree '()) with no value.. But (tree '()) isn't a symbol but a list.
(let ([tree '()] ...)
body ...)
Here tree is bound to '(). see?
Now looking at you first cond you have one term. Usually cond has more than two or else a simple if would suffice. The predicate in the one term is:
[(string>? key (car lst)) (list-set lst 2 (insert lst key data))]
Now without the extra ( ... ) around the whole thing the whole code above would become a term instead of just playing a predicate.
But hang on.. Why do you have cond and if. A cond is a if-elseif-else. Isn't there a way to make the whole thing one cond? Yes! This is the same with one cond:
(define (insert lst key data)
(cond
[(null? lst) (make-node key data)]
[(string>? key (car lst)) (list-set lst 2 (insert lst key data))]
[(string<? key (car lst)) (list-set lst 3 (insert lst key data))]
[else (list-set lst 1 data)]))
I noticed also that you check if it's less than, greater than and equal to, but no else (alternative) so I assumed if it weren't less or greater than that it must be equal and thus everything goes in the last term since you now have a complete venn diagram.
You're doing (let (((tree '()) ...) but let expects a list of variable/value pairs. So you'd have to remove one set of parentheses: (let ((tree '())) ...)
In Lisp and Scheme, parentheses have a very specific meaning, you can't just add an extra set of parentheses around an expression without changing its meaning, like you can in many languages.

Racket program not working as it should

i made a function which takes a list and two elements of the list. It should return #t if the second argument appears in the list argument before the third argument:
The procedure should also return #f if either of the supposed elements doesn't appear at all.
here is what I got so far:
(define (before-in-list? lst a b )
(cond
((empty? lst ) #f)
((eq? (car lst ) a) ( map b (cdr lst)) #t)
((eq? (car lst ) b) #f)
(else (before-in-list? (cdr lst ) a b ))))
to test it, i used:
(before-in-list? '(back in the ussr) '(in) '(ussr))
(before-in-list? '(back in the ussr) '(the) '(ussr))
the problem is that it gives me f every time.
any tips on how to fix it please?
The way you're using map doesn't make sense. Also, you should use equal? for more general comparisons, and the a and b parameters should not be lists. Try this:
(define (before-in-list? lst a b)
(cond
((empty? lst ) #f)
((equal? (car lst) a)
(if (member b (cdr lst)) #t #f))
((equal? (car lst) b) #f)
(else (before-in-list? (cdr lst ) a b))))
(before-in-list? '(back in the ussr) 'in 'ussr)
=> #t
(before-in-list? '(back in the ussr) 'the 'ussr)
=> #t

Scheme function that returns a function

I need to write a scheme function that returns as a function which then takes another argument, eg a list and in turn return the desired result. In this example (c?r "arg") would return -- (car(cdr -- which then subsequently takes the list argument to return 2
> ((c?r "ar") '(1 2 3 4))
2
> ((c?r "ara") '((1 2) 3 4))
2
The problem I have is how can I return a function that accepts another arg in petite?
Here's how you might write such a function:
(define (c?r cmds)
(lambda (lst)
(let recur ((cmds (string->list cmds)))
(if (null? cmds)
lst
(case (car cmds)
((#\a) (car (recur (cdr cmds))))
((#\d) (cdr (recur (cdr cmds))))
(else (recur (cdr cmds))))))))
Note that I'm using d to signify cdr, not r (which makes no sense, to me). You can also write this more succinctly using string-fold-right (requires SRFI 13):
(define (c?r cmds)
(lambda (lst)
(string-fold-right (lambda (cmd x)
(case cmd
((#\a) (car x))
((#\d) (cdr x))
(else x)))
lst cmds)))
Just wanted to add my playing with this. Uses SRFI-1.
(import (rnrs)
(only (srfi :1) fold)) ;; require fold from SRFI-1
(define (c?r str)
(define ops (reverse (string->list str)))
(lambda (lst)
(fold (lambda (x acc)
((if (eq? x #\a) car cdr) ; choose car or cdr for application
acc))
lst
ops)))
Its very similar to Chris' version (more the previous fold-right) but I do the reverseso i can use fold in the returned procedure. I choose which of car or cdr to call by looking at the character.
EDIT
Here is an alternative version with much more preprocessing. It uses tail-ref and list-tail as shortcuts when there are runs of #\d's.
(define (c?r str)
(let loop ((druns 0) (ops (string->list str)) (funs '()))
(cond ((null? ops)
(let ((funs (reverse
(if (zero? druns)
funs
(cons (lambda (x)
(list-tail x druns))
funs)))))
(lambda (lst)
(fold (lambda (fun lst)
(fun lst))
lst
funs))))
((eq? (car ops) #\d) (loop (+ druns 1) (cdr ops) funs))
((= druns 0) (loop 0 (cdr ops) (cons car funs)))
(else (loop 0 (cdr ops) (cons (lambda (x)
(list-ref x druns))
funs))))))
This can be made even simpler in #!racket. we skip the reverse and just do (apply compose1 funs).
(define (c?r str)
(let loop ((druns 0) (ops (string->list str)) (funs '()))
(cond ((null? ops)
(let ((funs (if (zero? druns)
funs
(cons (lambda (x)
(list-tail x druns))
funs))))
(apply compose1 funs)))
((eq? (car ops) #\d) (loop (+ druns 1) (cdr ops) funs))
((= druns 0) (loop 0 (cdr ops) (cons car funs)))
(else (loop 0 (cdr ops) (cons (lambda (x)
(list-ref x druns))
funs))))))
Assuming a compose procedure:
(define (compose funs . args)
(if (null? funs)
(apply values args)
(compose (cdr funs) (apply (car funs) args))))
(compose (list cdr car) '(1 2 3 4))
=> 2
c?r can be defined in terms of compose like so:
(define (c?r funs)
(lambda (e)
(compose
(map
(lambda (f) (if (char=? f #\a) car cdr))
(reverse (string->list funs)))
e)))
then
((c?r "ar") '(1 2 3 4))
=> 2
((c?r "ara") '((1 2) 3 4))
=> 2

Resources