Scheme Lexical Parser - functional-programming

New to scheme and currently working on a lexical analyzer. Below is my code and I am getting the error
map: contract violation
expected: list?
given: #
argument position: 2nd
other arguments...:
#
#lang racket
(define tokens '((dog noun)
(cat noun)
(chases verb)
(the article)))
(define (getToken word)
(cadr (assq word tokens)))
(define ttw (lambda (l)
(map getToken l)))
(define (parse-sentence list)
(article list))
(define (article list)
(if (eq? (car list) 'article)
(begin
(display "Article: ")
(display (car list))
(noun (cdr list))
)
(begin
(display "Not an Article!!!")
(display (car list)))
))
(define (noun list)
(if (eq? (car list) 'noun)
(begin
(display "Noun:")
(display (car list))
(noun (cdr list))
)
"Not a noun!!!")
)
(begin
(display "Enter a Sentance in (): ")
(let ((input (read)))
(ttw (parse-sentence input))))
My input is (the dog chases the cat)

Running the program, I see that DrRacket colors this expression red:
(map getToken l)
which is part of the function
(define ttw (lambda (l)
(map getToken l)))
and since the error is
map: contract violation
expected: list?
given: #<void>
argument position: 2nd
other arguments...:
we now know that ttw is called with void as input and not a list as expected.
Where is ttw called? Clicking the "Check Syntax" icon (the check mark with the magnifying glass) and then hovering the mouse over ttw shows all uses.
The only use is in:
(ttw (parse-sentence input))
This means that parse-sentence returned void. Let's see the definition of parse-sentence:
(define (parse-sentence list)
(article list))
Okay, so the error must be in article:
(define (article list)
(if (eq? (car list) 'article)
(begin
(display "Article: ")
(display (car list))
(noun (cdr list))
)
(begin
(display "Not an Article!!!")
(display (car list)))
))
And here we see this:
(if ...
...
(begin
(display "Not an Article!!!")
(display (car list))))
The construct begin returns the value of the last expression. Here (display ...) returns void.
Checking the output, we see right before the error message:
Not an Article!!!the
So the problem is that article returns something other than a list.
However since you have found an error, I suggest you look into the function error. Something like: (error 'article (~a "Not an article, got: " (car list)). If you use error DrRacket will directly show you that an error has been found in article.

Related

Replaces occurrences in a list - Racket

I am writing a function called ptyper that takes a nested list, nl. This function replaces all occurrences of a number with n and all occurrences of a symbol with s. This is what I have now:
(define (ptyper nl) (cond
((null? nl) '())
((list? nl)
(let ((ls (car nl)))
(list (ptyper ls))))
((number? (car nl))
(cons "n" (cdr nl)))
((symbol? (car nl))
(cons "s" (cdr nl)))
(else
(cons (car nl) (cdr nl)))))
I ran this test (ptyper '(2 (abc () "abc"))) but received an error that their was a contract violation. I'm not exactly sure what I'm doing wrong so if could use some help. Thanks!
Here is a possible solution with one function:
(define (ptyper nl)
(cond
((null? nl) '()) ; if the argument is an empty list, return the empty list
((list? nl) ; if the argument is a list, then
(let* ((c (car nl)) ; get its first element
(nc (cond ((number? c) "n") ; transform it for numbers
((symbol? c) "s") ; and symbols
((list? c) (ptyper c)) ; if a list recur over it
(else c)))) ; otherwise (e.g. a string) return as it is
(cons nc (ptyper (cdr nl))))) ; recursive call on the rest of the list
(else nl))) ; this should never happen for the specification,
; return the parameter or cause an error
Note that the error in your case is caused by the recursive call. When the function is called on an atom, for instance 2, first it checks for null and list?, and those checks returns false. Then it checks for (number (car nl)), but nl is equal to 2 and so car fails.
Here is a data definition for an S-expression, this models your data.
; An S-expr is one of:
; – Atom
; – SL
; An SL is one of:
; – '()
; – (cons S-expr SL)
; An Atom is one of:
; – Number
; – String
; – Symbol
We have predicates for every kind of data except Atom, so we make atom?:
;; Any -> Boolean
;; is the x an atom?
(define (atom? x)
(not (list? x)))
We follow the structure of the data to build "templates" for our functions:
(define (func sexp)
(cond
[(atom? sexp) (func-atom sexp)]
[else (func-sl sexp)]))
(define (func-sl sl)
(cond
[(empty? sl) ...]
[else (... (func (first sl)) ... (func-sl (rest sl)) ...)]))
(define (func-atom at)
(cond
[(number? at) ...]
[(string? at) ...]
[(symbol? at) ...]))
We fill in the gaps:
; Atom -> String
(define (subs-atom at)
(cond
[(number? at) "n"]
[(string? at) at]
[(symbol? at) "s"]))
; SL -> SL
(define (subs-sl sl)
(cond
[(empty? sl) sl]
[else (cons (subs-sexp (first sl))
(subs-sexp (rest sl)))]))
; S-exp -> S-exp
(define (subs-sexp sexp)
(cond
[(atom? sexp) (subs-atom sexp)]
[else (subs-sl sexp)]))
Using the interface for ptyper:
(define (ptyper nl)
(subs-sexp nl))
(ptyper '(2 (abc () "abc")))
; => '("n" ("s" () "abc"))

Illegal argument in functor position - possible bracket issue

I am new to LISP and am trying to develop a few applications. Here I am trying to count the number of occurrences of every element in a list passed to this function. But unfortunately I am getting a " Illegal argument in functor position" error. Can somebody help me solve this and get this program working? Any help would be appreciated
(defun length1 (lst)
(let ((list1 (remove-duplicates lst)))
(cond ((null list1) 0)
(let ((number (count (car list1) lst))))
(print "Word was: ")
(print '(car list1))
(print "Number of Occurances: ")
(print number)
(length (rest lst)))))
In Common Lisp syntax (which appears to be the one used, not Scheme's) this is how it would look:
(defun length1 (lst)
(let ((list1 (remove-duplicates lst)))
(cond ((null list1) 0)
(t (let ((number (count (car list1) lst)))
(print "Word was: ")
(print (car list1))
(print "Number of Occurrences: ")
(print number)
(length (rest lst)))))))

Scheme syntax error when recursing

I'm writing a recursive function that will convert an expression from prefix to infix. However, I need to add in a check to make sure part of the input is not already in infix.
For example, I may get input like (+ (1 + 2) 3).
I want to change this to ((1 + 2) + 3)
Here is what I have so far:
(define (finalizePrefixToInfix lst)
;Convert a given s-expression to infix notation
(define operand (car lst))
(define operator1 (cadr lst))
(define operator2 (caddr lst))
(display lst)
(cond
((and (list? lst) (symbol? operand));Is the s-expression a list?
;It was a list. Recusively call the operands of the list and return in infix format
(display "recursing")
(list (finalizePrefixToInfix operator1) operand (finalizePrefixToInfix operator2))
)
(else (display "not recursing") lst);It was not a list. We can not reformat, so return.
)
)
However, this is giving me syntax errors but I cant figure out why. Any help?
You have to check to see if the lst parameter is a list at the very beginning (base case), otherwise car and friends will fail when applied to an atom. Try this:
(define (finalizePrefixToInfix lst)
(cond ((not (pair? lst)) lst)
(else
(define operand (car lst))
(define operator1 (cadr lst))
(define operator2 (caddr lst))
(cond
((symbol? operand)
(list (finalizePrefixToInfix operator1)
operand
(finalizePrefixToInfix operator2)))
(else lst)))))

How to remove a given symbol from a list?

I am trying to remove a given symbol from a list.
Here is the code i wrote:
(define member?
(lambda (in-sym in-seq)
(if (and (symbol? in-sym) (sequence? in-seq))
(if (null? in-seq)
'()
(append
(if (equal? in-sym (car in-seq)) '() (list (car in-seq)))
(member? in-sym (cdr in-seq)))))))
It turns out that i remove all occurences of the given symbol although i want to remove only the first occurence. Can somebody help me with this?
You can use a built-in procedure for this, check if your interpreter provides remove:
(remove 'b '(a b b c b))
=> '(a b c b)
Now, if you intend to implement the functionality yourself, I advice you to split the problem in two parts: one procedure that checks if the procedure can be executed (if inSymbol is a symbol and inSeq is a sequence), and the other, remove-member that performs the actual removal of data:
(define member?
(lambda (inSym inSeq)
(if (and (symbol? inSym) (sequence? inSeq)) ; can remove?
(remove-member inSym inSeq) ; then remove!
'can-not-remove))) ; otherwise, present an error message
(define remove-member
(lambda (inSym inSeq)
(cond ((null? inSeq)
'())
((equal? (car inSeq) inSym)
(cdr inSeq))
(else
(cons (car inSeq)
(remove-member inSym (cdr inSeq)))))))
Your problem is that you append to ( member? inSym ( cdr inSeq)) whether you found the symbol or not. What you want to do is this:
(define member?
(lambda (inSym inSeq)
(if (and (symbol? inSym) (sequence? inSeq))
(if (null? inSeq) '()
(if (equal? inSym (car inSeq)) (cdr inSeq)
(append (list (car inSec)) (member? inSym (cdr inSeq)))
)
)
)
)
)
I.e. if you found the symbol, just return (cdr inSeq) instead because you are done.

Return value in Lisp

So i started learning Lisp yesterday and started doing some problems.
Something I'm having a hard time doing is inserting/deleting atoms in a list while keeping the list the same ex: (delete 'b '(g a (b) l)) will give me (g a () l).
Also something I'm having trouble with is this problem.
I'm suppose to check if anywhere in the list the atom exist.
I traced through it and it says it returns T at one point, but then gets overriden by a nil.
Can you guys help :)?
I'm using (appear-anywhere 'a '((b c) g ((a))))
at the 4th function call it returns T but then becomes nil.
(defun appear-anywhere (a l)
(cond
((null l) nil)
((atom (car l))
(cond
((equal (car l) a) T)
(T (appear-anywhere a (cdr l)))))
(T (appear-anywhere a (car l))(appear-anywhere a (cdr l)))))
Let's look at one obvious problem:
(defun appear-anywhere (a l)
(cond
((null l) nil)
((atom (car l))
(cond
((equal (car l) a) T)
(T (appear-anywhere a (cdr l)))))
(T (appear-anywhere a (car l))(appear-anywhere a (cdr l)))))
Think about the last line of above.
Let's format it slightly differently.
(defun appear-anywhere (a l)
(cond
((null l) nil)
((atom (car l))
(cond
((equal (car l) a) T)
(T (appear-anywhere a (cdr l)))))
(T
(appear-anywhere a (car l))
(appear-anywhere a (cdr l)))))
The last three lines: So as a default (that's why the T is there) the last two forms will be computed. First the first one and then the second one. The value of the first form is never used or returned.
That's probably not what you want.
Currently your code just returns something when the value of a appears anywhere in the rest of the list. The first form is never really used.
Hint: What is the right logical connector?

Resources