The next F# assignment is to do the following, all based on the parser.fs inline-calculator program. One disadvantage of the F# way of defining the expr datatype is that it is difficult to add a new expr subtype without editing the existing code. One remaining advantage of the object-oriented approach is that classes and interfaces are more "loosely coupled", which make adding something new easier. So F# addresses some of the deficiencies of dynamic dispatch and oop, but not others. You will have to edit the parser.fs file that I gave you. But you should also ask: is there a language that will give us the best of all worlds? You can base your code on either version of the parser I've posted. The second version allows multi-symbol operators and relies more on .Net. 1. The parser allows for disambiguation of shift-reduce conflicts by operator precedence. However, some shift-reduce conflicts can also arise from the associativity of operators. Addition and multiplication are associative, e.g., (a+b)+c = a+(b+c). But subtraction is not: (2-3)-4 <> 2-(3-4). The way that the parser is currently written, 2-3-4 will be interpreted as equivalent to 2-(3-4), but - is usually assumed to associate to the left. Your task is to add an additional functionality to the parser to allow us to specify the associativity of operators. For example, logical implication (a->b) should associate to the right. Hint: in addition to the precedence table/function. you'll have to construct another one for associativity: you can assume that by default, operators associate to the left, but allow the option of declaring them to associate to the right. 2. Add the following operator to your calculator: "=" for boolean equality. False should be represented by 0 and True by 1. So "3+1=4" should evaluate to 1. However, note that you have to parse this as (3+1)=4 and not 3+(1=4), which evaluates to 3+0=3. 2b. Now add expressions of the form ?a,b,c which represents if (a) b else c. For example, ?(3=2+1),1,0 should evaluate to 1, and ?(0),3,4 should return 4. You will have to change all parts of the program, starting with the expr type, the eval function, and the lexical tokenizer. Change your precedence table as well. 3. Write a compiled version of the calculator by generating AM7B assembly code, which can then be executed by your assembler. You should generate code that would leave the final, computed value on the stack. For example, for "3+4" you can generate the code: push 3 push 4 pop ax pop bx add bx ax push ax This code was generated by performing a post-order traversal on the expr tree: first generate the code to evalute "3", then "4", then "3+4". Each expression should have code that pushes the value on top of the stack. You can also assume that values are always integers. You only need to handle expressions of the form E*E, E+E, E-E, E/E, and -E. You do not need to compile = and if-else, only the basic operators. (the clauses that compiles these expressions can just output nothing). You can just output to Console (stdout): parser.fs > out.7b You can then use your AM7B simulator to run your compiled program. 4 (challenge). Interpret the summation [i:0:10:i*i] (you can change syntax if you want). You must respect the scope of bound variables. This challenge will really give you a feel of how to write an interpreter/compiler because it deals with variables and scope. Some hints may be found on my compiler class homepage: www.cs.hofstra.edu/~cscccl/csc124 There is similar code on this webpage written in Java and uses the visitor pattern. ------