[SOLVED] Programming Homework #2- BNFs, Parsing, and Higher-Order Functions-Q2

35.00 $

Category:
Click Category Button to View Your Next Assignment | Homework

You will receive the following solution file(s) instantly after successful payment:

zip file icon BNFs-Parsing-and-Higher-Order-Functions-Q2-zko0g1.zip (331.2 KB)
Assignment Instructions Updated Recently? Submit Below and we will provide new Solution!
Submit New Instructions
πŸ”’ Securely Powered by:
Secure Checkout
5/5 - (2 votes)

In this homework (and in all future homeworks) you should be working in the

β€œModule” language, and use the appropriate language using a #lang line. You should also click the β€œShow Details” button in the language selection dialog, and check the β€œSyntactic test suite coverage” option to see parts of your code that are not covered by tests: after you click β€œrun”, parts of the code that were covered will be colored in green, parts that were not covered will be colored in red, and if you have complete coverage, then the colors will stay the same. Note that you can also set the default language that is inserted into new programs to #lang pl, to make things more convenient. There are some variants for the pl language for various purposes β€” in particular, #lang pl untyped will ignore all type declarations, and will essentially run your code in an untyped Racket.

The language for this homework is:

#lang pl 02

As in previous assignment, you need to use the special form for tests: test.

Β 

Reminders (this is more or less the same as the administrative instructions for the previous assignment):

Comments: Submitted code for each question should include at least two lines of comments with your personal description of the solution, the function and its type. In addition, you should comment on the process of solving this question – what were the main difficulties, how you solved them, how much time did you invest in solving it, did you need to consult others. A solution without proper comments may be graded 0. In general, comments should appear above the definition of each procedure (to keep the code readable).

Tests: For each question, you should have enough test cases for complete coverage (DrRacket indicates covered expressions with colors for covered and uncovered source code, unless your code is completely covered). See below on the way to create tests. Note that your tests should not only cover the code, but also all end-cases and possible pitfalls.

Β 

Important: Your tests should cover your whole code; otherwise the server will heavily penalize your submission. You should not have any uncovered expressions after you hit β€œRun” β€” it should stay at the same color, indicating complete coverage. Furthermore, the server will run its own tests over your code, which means that you will not be able to submit code that does not work.

General note: Code quality will be graded. Write clean and tidy code. Consult the Style Guide, and if something is unclear, ask questions on the course forum.

The test form can be used to test that an expression is true, that an expression evaluates to some given value, or that an expressions raises an error with some expected text message. For example, the three kinds of tests are used in this example:

#lang pl

(: smallest : (Listof Number) -> Number)

(define (smallest l)

(match l

[(list)Β Β Β Β Β  (error β€˜smallest β€œgot an empty list”)]

[(list n)Β Β Β  n]

[(cons n ns) (min n (smallest ns))]))

(test (smallest β€˜(5 7 6 4 8 9)) => 4)

(test (zero? (smallest β€˜(0 1 2 3 4))))

(test (smallest β€˜()) =error> β€œgot an empty list”)

In case of an expected error, the string specifies a pattern to match against the error message. (Most text stands for itself, β€œ?” matches a single character and β€œ*” matches any sequence of characters.)

Note that the =error> facility checks only errors that your code throws, not Racket errors. For example, the following test will not succeed:

(test (/ 4 0) =error> β€œdivision by zero”)

The code for all the following questions should appear in a single .rkt file named
<your ID>_2 (e.g., 333333333_2 for a student whose ID number is 333333333).

Β 

1.Β Β  BNF (SE)

  1. In class we have seen the grammar for AE – a simple language for β€œArithmetic Expressions”. Write a BNF for β€œSE”: a similarly simple language of β€œString Expressions”. Valid β€˜programs’ (i.e., words in the SE language) should go along the lines of pl expressions for Strings, with two exceptions: 1. Only digits 0,…,9 are allowed as valid characters within strings; 2. We will have two types of expressions that are not available in the pl language (see below β€˜stringinsert’ and β€˜number->string’ type expressions). The valid operators that can be used in these expressions are string, string-length, and string-append, and also string-insert and number->string. It is also legal to have expressions of the form β€œ<D>”, where <D> stands for a (finite) sequence of digits. Plain values in the language are characters (of digits) and natural numbers, thus the following are also valid expressions: a sequence of digits (such as, 347226) and an expression of the form #\v, where v is a digit.

Here, we do not care about implementing anything – neither the parser nor the evaluator. Thus, your code should be commented out. Still, it may be helpful to consider some future semantics that will help you understand the requirements. The operations ” β€œ, string, string-append,

string-insert, and number->string are considered expressions

that represent a string (they would return a string). The operation string-length, and digit sequences are considered expressions that represent a natural number (they would return a natural number).

Expression of the form #\v represent a character.

Note the following requirements for the grammar:

stringΒ  is allowed with a sequence of any number of characters. string-append is allowed with a sequence of any number of expressions that represent strings. string-insert is allowed with an expression that represents a string, a character, and a natural number.Β  Β 

number->string is allowed with a natural number.

For example, some valid expressions in this language are:

β€œ12344”

12

( string #\1 #\2 #\4 )

( string-append ( string #\1 #\2 #\4 ) β€œ12” )

( string-insert β€œ1357” #\4 66 )

( number->string 156879 )

( number->string ( string-length β€œ0033344” ) )

( string-append β€œ45” ( number->string ( string-length

β€œ0033344” ) ))

( string-append )

( string-append β€œβ€ ( string-insert β€œ1357” #\4 66 ) β€œβ€ )

#\3

but the following are invalid expressions:

β€œa2b”

12 13 4 67

( string 124 )

( string-append ( string-length β€œ44” ) β€œ12” )

( string-insert β€œ1357” 4 66 )

( number->string β€œ156879” ) ( string-append 33 44 66)

#\3 #\4

#\32

#\q

Β 

NOTE: The use of ellipsis (β€˜β€¦β€™) or β€˜*’ is not allowed here (find ways within the BNF framework to specify zero-or-more occurrences of a previous piece of syntax). Use πœ† to specify the empty string. Β 

Important remark: Β Your solution should only be a BNF and not a code in Racket (or in any other language). You cannot test your code!!! Indeed, your answer should appear inside a comment block (write the grammar in a #|β€”|# comment). Β 

  1. Add to your BNF a derivation process for 3 different SE expressions, such that every operator (e.g., string-append, string-length, and

number->string) appears in at least one of these expressions. You may either provide a derivation tree or a series of replacements starting with <SE> and

(𝑖)

ending with your string. Mark each derivation rule by an index (use β€œΒ Β Β Β Β Β  ” to state

=> that in a certain step, you have used rule number 𝑖 of your BNF).

Β 

2.Β Β  Higher Order Functions

As you already know, lists are a fundamental part of Racket. They are often used as a generic container for compound data of any kind. It is therefore not surprising that Racket comes with plenty of useful functions that operate on lists. One of the most useful list functions is foldl: it consumes a combiner function, an initial value, and an input list. It returns a value that is created in the following way:

  • For the empty list, the initial value is returned,
  • For a list with one item, it uses the combiner function with this item and the initial value,
  • For two items, it uses the combiner function with the first and the result of folding the rest (a one-item list),

In the general case, the value of foldl is:

(foldl f init (list x1 x2 x3 … xn))

= (f xn (… (f x3 (f x2 (f x1 init)))))

Note that foldl is a higher-order function, like map. Its type is:

(: foldl : (All (A B) (A B -> B) B (Listof A) -> B))

Use foldl together with (or without) map to define a sum-of-squares function which takes a list of numbers as input, and produces a number which is the sum of the squares of all of the numbers in the list. A correct solution should be a oneliner. Remember to write a proper description and contract line, and to provide sufficient tests (using the test form). You will need to do this for a definition of square too, which you would need to write for your implementation of sum-ofsquares.

A more detailed explanation on both functions can be found at the bottom of the assignment or here.

Β 

Here is an example of a test that you might want to perform:

Β 

Β 

(test (sum-of-squares β€˜(1 2 3)) => 14)

Β 

Β 

Β 

3.Β Β  PAE (and more H.O. functions)

  1. In this question, you are asked to write a function createPolynomial that takes as arguments a list of π‘˜ numbers π‘Ž0, … , π‘Žπ‘˜βˆ’1 and returns as output a function. The returned function takes a number π‘₯0 and return the value of the polynomial π‘Ž0 β‹… π‘₯0 + β‹― + π‘Žπ‘˜βˆ’1 β‹… π‘₯π‘›βˆ’1 at π‘₯0. To this end, you can use the built-in pl expt function taking two numbers π‘Ž and 𝑏, and returning π‘Žπ‘.

The following should help you understand the task at hand:

> (createPolynomial β€˜(1 2 4 2))

– : (Number -> Number)

#<procedure:polyX>

Β 

(define p2345 (createPolynomial β€˜(2 3 4 5)))

(test (p2345 0) =>

(+ (* 2 (expt 0 0)) (* 3 (expt 0 1)) (* 4 (expt 0 2)) (* 5

(expt 0 3))))

(test (p2345 4) =>

(+ (* 2 (expt 4 0)) (* 3 (expt 4 1)) (* 4 (expt 4 2)) (* 5 (expt 4 3))))

(test (p2345 11) => (+ (* 2 (expt 11 0)) (* 3 (expt 11 1)) (* 4 (expt 11 2)) (* 5 (expt 11 3))))

Β 

Β 

(define p536 (createPolynomial β€˜(5 3 6)))

(test (p536 11) => (+ (* 5 (expt 11 0)) (* 3 (expt 11 1)) (* 6

(expt 11 2))))

Β 

(define p_0 (createPolynomial β€˜()))

(test (p_0 4) => 0)

Remark: all recursive calls should be in tail recursion.

You are given the following partial code. Use it as a basis for your full code. Don’t forget to add comments and tests.

(: createPolynomial : (Listof Number) -> <-fill in->)

(define (createPolynomial coeffs)

Β  (: poly : (Listof Number) Number Integer Number ->

Number)

Β  (define (poly argsL x power accum)

Β Β Β Β  (if <-fill in->

Β Β Β Β Β Β Β  <-fill in->

Β Β Β Β Β Β Β  <-fill in-> )Β 

Β  (: polyX : Number -> Number)

Β  (define (polyX x)

Β Β Β Β  ßfill inβ†’)Β Β  ßfill inβ†’)

Β 

Β 

Β 

  1. We now move on to define a language PLANG that supports evaluating a polynomial on a sequence of points (numbers). You should base your solution on the interpreter we have written for the AE language. Specifically, your code should keep most of the definitions therein. The changes you do need to make are described next.

Β 

  1. Write the BNF for the new language to allow for expressions of the

form {{ π’‘π’π’π’š π‘ͺ𝟏 π‘ͺ𝟐 … π‘ͺπ’Œ} {π‘·πŸ π‘·πŸ … 𝑷𝓡}} where all 𝐢𝑖 and all 𝑃𝑗 are valid AE expressions (and both π‘˜ β‰₯ 1 and β„“ β‰₯ 1).

See examples for valid expressions:

Β 

β€œ{{poly 1 2 3} {1 2 3}}”

β€œ{{poly 4/5 } {1/2 2/3 3}}”

β€œ{{poly 2 3} {4}}”

β€œ{{poly 1 1 0} {-1 3 3}}”

Β Β Β Β  β€œ{{poly {/ 4 2}Β  {- 4 1}} {{- 8 4}}}”

Β Β Β Β  β€œ{{poly {+ 0 1} 1 {* 0 9}} {{- 4 5} 3 {/ 27 9}}}”

Β 

Also see examples for invalid expressions:

Β 

β€œ{{poly } {1 2 3} }”

β€œ{{poly 4/5 } {1/2 2/3 3} {poly 1 2 4} {1 2}}”

β€œ{{poly 2 3} {}}”

β€œ{{poly 1 1 3} }”

Β 

Β 

Β 

Β 

You may use the following skeleton for your BNF:

#|

Β  The grammar:

Β Β Β  <PLANG> ::=Β 

Β Β Β  <AEs>Β Β  ::=Β 

Β Β Β  <AE>Β Β Β  ::=Β 

Β  |#

Β 

  1. Write the parser for the new language. Use the following partial code as well the test examples provided below.

Β 

(define-type PLANG

Β Β Β  [Poly (Listof AE) <-fill in->])

Β 

Β  (define-type AE

Β Β Β  [NumΒ  Number]

Β Β Β  [AddΒ  AE AE]

Β Β Β  [SubΒ  AE AE]

Β Β Β  [MulΒ  AE AE]

Β Β Β  [DivΒ  AE AE])

Β 

Β  (: parse-sexpr : Sexpr -> AE)

Β  ;; to convert s-expressions into AEs

Β  (define (parse-sexpr sexpr)

Β Β Β  (match sexpr

Β Β Β Β Β  [(number: n)Β Β Β  (Num n)]

Β Β Β Β Β  [(list β€˜+ lhs rhs) (Add (parse-sexpr lhs)Β 

Β Β  Β Β Β Β  Β Β Β Β Β  Β Β Β Β Β  Β Β Β Β Β  Β Β Β (parse-sexpr rhs))]

Β Β Β Β Β  [(list β€˜- lhs rhs) (Sub (parse-sexpr lhs)Β Β Β Β  Β Β  Β Β Β Β  Β Β Β Β  Β  Β Β Β (parse-sexpr rhs))]

Β Β Β Β Β  [(list β€˜* lhs rhs) (Mul (parse-sexpr lhs)Β 

Β Β  Β Β Β Β  Β Β Β Β Β  Β Β Β Β Β  Β Β Β Β Β  Β Β Β (parse-sexpr rhs))]

Β Β Β Β Β  [(list β€˜/ lhs rhs) (Div (parse-sexpr lhs)Β 

Β Β  Β Β Β Β  Β Β Β Β Β  Β Β Β Β Β  Β Β Β Β Β  Β Β Β (parse-sexpr rhs))]

Β [else (error β€˜parse-sexpr β€œbad syntax in ~s”            sexpr)]))

Β Β 

Β  (: parse : String -> PLANG)

Β  ;; parses a string containing a PLANG expressionΒ Β Β Β Β Β Β Β  to a PLANG ASTΒ Β  (define (parse str)

Β Β Β  (let ([code (string->sexpr str)])

Β Β Β Β Β  <-fill in->))

Β 

(test (parse β€œ{{poly 1 2 3} {1 2 3}}”)Β 

Β Β Β Β  => (Poly (list (Num 1) (Num 2) (Num 3))Β 

Β Β Β Β Β Β Β Β Β Β Β Β Β  (list (Num 1) (Num 2) (Num 3))))

(test (parse β€œ{{poly } {1 2} }”)Β 

Β Β Β Β  =error> β€œparse: at least one coefficient isΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β  required in ((poly) (1 2))”)

(test (parse β€œ{{poly 1 2} {} }”)Β Β Β Β Β Β  =error> β€œparse: at least one point isΒ 

Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β  required in ((poly 1 2) ())”)

Β 

Β 

iii. Β Β Β Β  Write the evaluation process. In order to leave the AE eval unchanged (for the sake of keeping your work as simple as possible), we wrap it with an eval-poly function (which will be the core of the evaluator). We start with presenting the formal specification of the semantics:

Β 

eval-poly({{ π’‘π’π’π’š π‘ͺ𝟏 π‘ͺ𝟐 … π‘ͺπ’Œ} {π‘·πŸ π‘·πŸ … 𝑷𝓡}}) =

β€²(𝑝(π‘’π‘£π‘Žπ‘™(𝑃1), … , π‘’π‘£π‘Žπ‘™(𝑃ℓ))) where 𝑝 is the polynomial defined by coefficients

(π‘’π‘£π‘Žπ‘™(𝐢1), … , π‘’π‘£π‘Žπ‘™(πΆπ‘˜). That is, the expressions π‘ͺ𝟏 π‘ͺ𝟐 … π‘ͺπ’ŒΒ Β  are evaluated to coefficients and theΒ  expressions π‘·πŸ π‘·πŸ … π‘·π’Œ are evaluated to numbers on which we evaluate the polynomial.

Here are some possible tests:

Β 

(test (run β€œ{{poly 1 2 3} {1 2 3}}”)Β 

=> β€˜(6 17 34))

(test (run β€œ{{poly 4 2 7} {1 4 9}}”)Β  => β€˜(13 124 589))

(test (run β€œ{{poly 1 2 3} {1 2 3}}”)Β Β  => β€˜(6 17 34))

(test (run β€œ{{poly 4/5 } {1/2 2/3 3}}”)Β 

=> β€˜(4/5 4/5 4/5))

(test (run β€œ{{poly 2 3} {4}}”)Β  => β€˜(14))

(test (run β€œ{{poly 1 1 0} {-1 3 3}}”)Β  => β€˜(0 4 4)))Β 

(test (run β€œ{{poly {/ 4 2} {- 4 1}} {{- 8 4}}}”)

=> β€˜(14))

(test (run β€œ{{poly {+ 0 1} 1 {* 0 9}} {{- 4 5} 3

{/ 27 9}}}”)

=> β€˜(0 4 4))

Β 

Use the following partial code as a basis for your code.

;; evaluates AE expressions to numbers

Β  (define (eval expr)

Β Β Β  (cases expr

Β Β Β Β Β  [(Num n)Β  n]

Β Β Β Β Β  [(Add l r) (+ (eval l) (eval r))]

Β Β Β Β Β  [(Sub l r) (- (eval l) (eval r))]

Β Β Β Β Β  [(Mul l r) (* (eval l) (eval r))]

Β Β Β Β Β  [(Div l r) (/ (eval l) (eval r))]))Β 

Β  (: eval-poly : PLANG ->Β Β  <-fill in-> )

Β  (define (eval-poly p-expr)

Β Β Β  <-fill in-> )

Β 

Β  (: run : String -> (Listof Number))

Β  ;; evaluate a FLANG program contained in a string

Β  (define (run str)

Β Β Β  (eval-poly (parse str)))

Β 

HINT: You may want to use the procedure map (twice).Β  See more about map below.

Β 

On the procedures map and fold-l

Χ”Χ€Χ•Χ Χ§Χ¦Χ™Χ” map:

קלט: Χ€Χ¨Χ•Χ¦Χ“Χ•Χ¨Χ” proc Χ•Χ¨Χ©Χ™ΧžΧ” lst ׀לט: Χ¨Χ©Χ™ΧžΧ” Χ©ΧžΧ›Χ™ΧœΧ” אוΧͺΧ• מב׀ר איברים Χ›ΧžΧ• Χ‘- lst – Χ©Χ Χ•Χ¦Χ¨Χ” ג”י Χ”Χ€Χ’ΧœΧͺ Χ”Χ€Χ¨Χ•Χ¦Χ“Χ•Χ¨Χ” proc גל Χ›Χœ אחד ΧžΧΧ™Χ‘Χ¨Χ™ Χ”Χ¨Χ©Χ™ΧžΧ” lst. )Χ”Χ”Χ‘Χ‘Χ¨ הבא הוא Χ›ΧœΧœΧ™ Χ™Χ•ΧͺΧ¨ – Χ›Χ™ ΧœΧžΧ’Χ©Χ” Χ”Χ€Χ•Χ Χ§Χ¦Χ™Χ” map Χ™Χ›Χ•ΧœΧ”

לט׀ל Χ‘ΧžΧ‘Χ€Χ¨ Χ¨Χ©Χ™ΧžΧ•Χͺ – ΧœΧ¦Χ•Χ¨Χš Χ”Χ©ΧΧœΧ” Χ”Χ ΧͺΧ•Χ Χ” לא ΧͺΧ–Χ“Χ§Χ§Χ• ΧœΧ©Χ™ΧžΧ•Χ© Χ›Χ–Χ”( Β map proc lst …+) β†’ list?) proc : procedure?Β  Β lst : list?

Applies proc to the elements of the lsts from the first elements to the last. The proc argument must accept the same number of arguments as the number of supplied lsts, and all lsts must have the same number of elements. The result is a list containing each result of proc in order. Β :Χ“Χ•Χ’ΧžΧΧ•Χͺ > (map add1 (list 1 2 3 4))

β€˜(2 3 4 5)

> (map (lambda (x) (list x))

β€˜(sym1 sym2 33)) β€˜((sym1) (sym2) (33))Β  :foldl Χ”Χ€Χ•Χ Χ§Χ¦Χ™Χ”

קלט: Χ€Χ¨Χ•Χ¦Χ“Χ•Χ¨Χ” proc, גרך Χ”ΧͺΧ—ΧœΧͺΧ™ init Χ•Χ¨Χ©Χ™ΧžΧ” lst ׀לט: גרך Χ‘Χ•Χ€Χ™ )ΧžΧΧ•ΧͺΧ• Χ˜Χ™Χ€Χ•Χ‘ Χ©ΧžΧ—Χ–Χ™Χ¨Χ” Χ”Χ€Χ¨Χ•Χ¦Χ“Χ•Χ¨Χ” proc( Χ©Χ Χ•Χ¦Χ¨ ג”י Χ”Χ€Χ’ΧœΧͺ Χ”Χ€Χ¨Χ•Χ¦Χ“Χ•Χ¨Χ” proc גל Χ›Χœ אחד ΧžΧΧ™Χ‘Χ¨Χ™ Χ”Χ¨Χ©Χ™ΧžΧ” lst ΧͺΧ•Χš Χ©Χ™ΧžΧ•Χ© Χ‘ΧžΧ©ΧͺΧ Χ” Χ©Χ©Χ•ΧžΧ¨ אΧͺ Χ”Χ’Χ¨Χš Χ©Χ—Χ•Χ©Χ‘ Χ’Χ“ Χ›Χ” – משΧͺΧ Χ” Χ–Χ” ΧžΧ§Χ‘Χœ Χ›Χ’Χ¨Χš Χ”ΧͺΧ—ΧœΧͺΧ™ אΧͺ Χ”Χ’Χ¨Χš של init. )Χ”Χ”Χ‘Χ‘Χ¨ הבא הוא Χ›ΧœΧœΧ™ Χ™Χ•ΧͺΧ¨ – Χ›Χ™ ΧœΧžΧ’Χ©Χ” Χ”Χ€Χ•Χ Χ§Χ¦Χ™Χ” foldl Χ™Χ›Χ•ΧœΧ” לט׀ל Χ‘ΧžΧ‘Χ€Χ¨ Χ¨Χ©Χ™ΧžΧ•Χͺ – ΧœΧ¦Χ•Χ¨Χš Χ”Χ©ΧΧœΧ” Χ”Χ ΧͺΧ•Χ Χ” לא ΧͺΧ–Χ“Χ§Χ§Χ• ΧœΧ©Χ™ΧžΧ•Χ© Χ›Χ–Χ”(

Β 

(foldl

proc init lst …+) β†’ any/c Β Β proc : procedure?

init : any/c Β Β lst : list?

Like map, foldl applies a procedure to the elements of one or more lists. Whereas map combines the return values into a list, foldl combines the return values in an arbitrary way that is determined by proc. Β :Χ“Χ•Χ’ΧžΧΧ•Χͺ > (foldl + 0 β€˜(1 2 3 4))

10

> (foldl cons β€˜() β€˜(1 2 3 4))

β€˜(4 3 2 1)

Β 

Β 

Β 

Β 

Β 

Β 

  • BNFs-Parsing-and-Higher-Order-Functions-Q2-zko0g1.zip