Worksheet L-Vals
Table of Contents
1. Grammars
1.1. Ambiguity
Write a grammar for if
statements, with an optional else
clause, so that each of the following are accepted:
if x==1 then y="dog" else y="cat" if x==1 then y="dog"
Ensure that your grammar is ambiguous by finding two parse trees for
if x==1 then if z==2 then y="dog" else y="cat"
How can you make a grammar for if
statements that is not ambiguous?
1.2. Precedence and Associativity 1
Write a grammar for the ternary operator that is ambiguous. Give an example with parse trees showing the ambiguity.
Write a grammar that resolves the ambiguity associating to the left (different from C). Show the parse tree for your ambiguous example using this grammar.
Write a grammar that resolves the ambiguity associating to the right (same as C). Show the parse tree for your ambiguous example using this grammar.
What does this exercise tell you about if
statements?
1.3. Precedence and Associativity 2
Write grammars for simple arithmetic with addition and multiplication with the normal precedence/associativity and for different precedence/associativity. Give examples with parse trees showing how the grammars are different.
1.4. Left recursion and right recursion
Left and right recursion are handled differently in parsing lox. Why?
2. Static and Dynamic errors
Lox does not have a static type checker. Write a program that is accepted by lox, but would be rejected if lox had static types like Java.
Java has static types, but also a full dynamic type system. Take the Java
program that you wrote above and convert it to a program that runs in Java.
Hint: Declare all variables at type Object
.
3. Static and Dynamic scope
In static scope, a variable occurrence is always bound to the same declaration/environment.
In dynamic scope, a variable occurrence may be bound to different declarations/environments.
Explore this concept in Javascript with statements by executing the following code in an online REPL or on your machine using your browser or Node.js:
var scope = {}; function f () { with (scope) { console.log (x); }; } // f (); // ReferenceError: x is not defined var x = 1; f (); // 1 scope.x = "dog" f(); // dog
4. L-Value or Not?
Lox only allows assignment to simple names. Other languages use the concept of l-value to distinguish assignable expressions.
In each of the following contexts, determine whether the given expression is
an l-value or not. Your code should replace the ellipsis (...
).
Is
x++
an l-value in C? The context is:void f (int x) { ... }
Is
arr[x++]
an l-value in C? The context is:void f (int x) { int arr[] = { 5, 6, 7, 8, 9, 10, 11 }; ... }
Is
f ().x
an l-value in C? The context is:struct S { int x; int y; }; struct S f () { struct S s; s.x = 5; s.y = 6; return s; // returns a copy of the "struct S", i.e., copies the two int members back } void g () { ... }
Is
t.x
an l-value in C? The context is:struct S { int x; int y; }; struct S f () { struct S s; s.x = 5; s.y = 6; return s; // returns a copy of the "struct S", i.e., copies the two int members back } void g () { struct S t = f (); ... }
Is
f ()->x
an l-value in C? Recall that this means(*(f())).x
, i.e., callf
, dereference the pointer, then access thex
member of the struct. The context is:#include <stdlib.h> struct S { int x; int y; }; struct S *f () { struct S *p = (struct S *) malloc (sizeof (struct S)); p->x = 5; // recall that p->x is just shorthand for (*p).x p->y = 6; return p; // returns a copy of the pointer, i.e., copies just a pointer back } void g () { ... }
Is
arr[x++]
an l-value in Java? The context is:class LValue6 { static void f (int x) { int[] arr = { 5, 6, 7, 8, 9, 10, 11 }; ... } }
Is
list.get (x++)
an l-value in Java? The context is:import java.util.ArrayList; class LValue7 { static void f (int x) { ArrayList<Integer> list = new ArrayList<> (); list.add (5); list.add (6); list.add (7); list.add (8); ... } }
Is
list.get (x++).x
an l-value in Java? The context is:import java.util.ArrayList; class C { int x; int y; C (int x, int y) { this.x = x; this.y = y; } } class LValue8 { static void f (int x) { ArrayList<C> list = new ArrayList<> (); list.add (new C (5, 5)); list.add (new C (6, 6)); list.add (new C (7, 7)); list.add (new C (8, 8)); ... } }
5. Solutions
5.1. Solution: L-Value or Not?
- No, temporary value from
++
- Yes, array
- No, temporary value from
f()
- Yes, struct
- Yes, pointer is temporary, but field is not
- Yes, array
- No, temporary Integer
- Yes, all object access via pointers/references in Java