pj1/text-challenges

44 lines
1.7 KiB
Plaintext
Raw Normal View History

Chapter 5, challenge 1:
Earlier, I said that the | , * , and + forms we added to our grammar metasyntax
were just syntactic sugar. Take this grammar:
expr → expr ( "(" ( expr ( "," expr )* )? ")" | "." IDENTIFIER )+
| IDENTIFIER
| NUMBER
Produce a grammar that matches the same language but does not use any of the notational sugar.
solution:
expr -> IDENTIFIER
expr -> NUMBER
expr -> expr callOrIndex
callOrIndex -> "." IDENTIFIER
callOrIndex -> "(" call ")"
call ->
call -> expr
call -> expr callListEnd
callListEnd ->
callListEnd -> "," expr precedingCommaCall
The grammar here clearly describes a number, or an identifier to a number, or a
function call, or a structure access
Chapter 5, challenge 2:
The Visitor pattern lets you emulate the functional style in an object-oriented
language. Devise a complementary pattern for a functional language. It should let
you bundle all of the operations on one type together and let you define new types
easily.
(SML or Haskell would be ideal for this exercise, but Scheme or another Lisp works
as well.)
solution:
Here, we're supposed to be able to define a new type that "inherits" an
existing one and bundle all the function implementations on that type together.
We could simply write the functions by specific type in one place, since Haskell is just that flexible, but that doesn't guarrantee we wrote the needed functions.
Another thing we could do is to put all necessary functions in a single structure, and define a type for this structure, for example if our supertype is Expr, with functions like "printInStr", "execute" and "optimize", our function bundle would look like:
data ExprFuncs a = ExprFuncs (a -> str) (a -> IO ()) (a -> Expr)