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 (...).

  1. Is x++ an l-value in C? The context is:

    void f (int x) {
      ...
    }
    
  2. Is arr[x++] an l-value in C? The context is:

    void f (int x) {
      int arr[] = { 5, 6, 7, 8, 9, 10, 11 };
      ...
    }
    
  3. 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 () {
      ...
    } 
    
  4. 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 ();
      ...
    } 
    
  5. Is f ()->x an l-value in C? Recall that this means (*(f())).x, i.e., call f, dereference the pointer, then access the x 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 () {
      ...
    } 
    
  6. 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 };
        ...
      }
    }
    
  7. 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); 
        ...
      }
    }
    
  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)); 
        ...
      }
    }
    

Solution: L-Value or Not?

5. Solutions

5.1. Solution: L-Value or Not?

  1. No, temporary value from ++
  2. Yes, array
  3. No, temporary value from f()
  4. Yes, struct
  5. Yes, pointer is temporary, but field is not
  6. Yes, array
  7. No, temporary Integer
  8. Yes, all object access via pointers/references in Java

Author: James Riely

Created: 2024-04-10 Wed 17:46

Validate