Computer Science 3 - 2007 - Test on Prac 24

You may use your notes, or refer to material on the website if you like. Keep your solutions as simple as possible! Answer on the question sheet (4 sides)

Many people did this really well; but those wh dod not really crashed badly. please study these solutions carefully.

1. Some people never remember, no matter how often you remind them - What is your name (surname)? [1]

Pat (Terry) 63T0844

2. The grammar below attempts to describe your present hard-working lifestyle.

    COMPILER Prac $CN
    /* Describe progress of a compiler practical */

    CHARACTERS
      letter  = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
    TOKENS
      name = letter { letter } .
    IGNORE CHR(0) .. CHR(31)

    PRODUCTIONS
      Prac         = Handouts { Task } "Submit" .
      Handouts     = "PracSheet" { "HintSheet" } .
      Task         = "Attempt" { ConsultTutor  "Attempt" }  .
      ConsultTutor = name .
    END Prac.

As you know, we sometimes have trouble finding tutors. As you may not know, we are going to have problem paying them, because they have recently told me that they want to be paid a fee for each occasion they are consulted. So what I need now is a list of tutors with a count of such occasions for each one. What must I add to the grammar to produce me such a list?

A typical list might be as follows (it does not have to be in alphabetic order):

       Tham       12
       Nyasha      5
       John        8
       Pat        45

Here is a solution using an ArrayList that contains objects of a simple Tutor class. The list is declared static for simplicity:

    import java.util.*;
    import Library.*;

    COMPILER Prac $CN
    /* Determine how often each tutor has been consulted during a practical
       P.D. Terry, Rhodes University, 2004 */

    static class Tutor {
      public String name;
      public int count;

      public Tutor(String name, int count) {
        this.name = name; this.count = count;
      }

      public void writeLine() {
        IO.write(this.name, -14);
        IO.writeLine(this.count);
      }

    } // Tutor

    static ArrayList<Tutor> list = new ArrayList<Tutor>();  // global for simplicity here!

    static int position(String name) {
    // Finds position of entry with search key name in list, or -1 if not found
      int i = list.size() - 1;                              // index of last entry
      while (i >= 0 && !name.equals(list.get(i).name))      // short-circuit protection
        i--;                                                // will reach -1 if no match
      return i;
    }


    CHARACTERS
      letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
    TOKENS
      name   = letter { letter } .
    IGNORE CHR(0) .. CHR(31)

    PRODUCTIONS
      Prac
      = Handouts { Task }
        "Submit"           (. for (int i = 0; i < list.size(); i++)
                                list.get(i).writeLine(); .) .

      Handouts
      = "PracSheet" { "HintSheet" } .

      Task
      = "Attempt" { ConsultTutor "Attempt" } .

      ConsultTutor
      = name               (. int pos = position(token.val);
                              if (pos >= 0) list.get(pos).count++;
                              else list.add(new Tutor(token.val, 1)); .) .

    END Prac.

3. The following Cocol description is of a set of letters in envelopes ready to take to the post office.

    COMPILER Mail $CN
    /* Describe simple set of mailing envelopes */

    CHARACTERS
      control   = CHR(0) .. CHR(31) .
      digit     = "0123456789" .
      inaddress = ANY - control - '$:' .
      sp        = CHR(32) .
    TOKENS
      number    = "postcode:" sp digit { digit } .
      info      = inaddress { inaddress } .
    IGNORE control

    PRODUCTIONS
      Mail      = { Envelope } EOF .
      Envelope  = Stamp { Stamp } Person Address .
      Stamp     = "$1" | "$2" | "$3" /* values of stamps implied */ .
      Address   = Street Town [ PostCode ] .
      Person    = info .
      Street    = info .
      Town      = info .
      PostCode  = number .
    END Mail.

How would you add to this grammar so that the parser system could tell you (a) the total value of the stamps on all the envelopes (b) the names of all people whose addresses did not contain postcodes?

Here is a solution that uses parameters on the parsing methods:

    import Library.*;

    COMPILER Mail1 $CN
    /* Describe simple set of mailing envelopes */

    CHARACTERS
      control   = CHR(0) .. CHR(31) .
      digit     = "0123456789" .
      inaddress = ANY - control - '$:' .
      sp        = CHR(32) .
    TOKENS
      number    = "postcode:" sp digit { digit } .
      info      = inaddress { inaddress } .
    IGNORE control

    PRODUCTIONS
      Mail1                   (. int cost, total = 0; .)
      = { Envelope<out cost>  (. total += cost; .)
        } EOF                 (. IO.writeLine("Total cost " + total); .) .


      Envelope<out int cost>  (. String name;
                                 int value;
                                 boolean hasCode;
                                 cost = 0; .)
      = Stamp<out value>      (. cost += value; .)
        { Stamp<out value>    (. cost += value; .)
        } Person<out name>
        Address<out hasCode>  (. if (!hasCode) IO.writeLine(name + " has no postcode"); .) .

      Stamp<out int cost>     (. cost = 0; .)
      =   "$1"                (. cost = 1; .)
        | "$2"                (. cost = 2; .)
        | "$3"                (. cost = 3; .) .

      Address<out boolean hasCode>
      = Street Town           (. hasCode = false; .)
        [ PostCode            (. hasCode = true; .)
        ] .

      Person<out String name>
      = info                  (. name = token.val; .) .

      Street   = info .
      Town     = info .
      PostCode = number .
    END Mail1.

Using parameters is really more complicated than a simple problem like this deserves! Here is a simple solution using static variables in the Parser class. Note the way in which the production for Address has been subtly modified, and an "action" attached to an "empty" alternative. This technique is amazingly useful at times.

    import Library.*;

    COMPILER Mail2 $CN
    /* Describe simple set of mailing envelopes */
    /* This does it all with "global" variables for simplicity */

    static int cost = 0;
    static String name;

    CHARACTERS
      control   = CHR(0) .. CHR(31) .
      digit     = "0123456789" .
      inaddress = ANY - control - '$:' .
      sp        = CHR(32) .
    TOKENS
      number    = "postcode:" sp digit { digit } .
      info      = inaddress { inaddress } .
    IGNORE control

    PRODUCTIONS
      Mail2
      = { Envelope } EOF       (. IO.writeLine("Total cost " + cost); .) .

      Envelope = Stamp { Stamp } Person Address .

      Stamp
      =   "$1"                 (. cost += 1; .)
        | "$2"                 (. cost += 2; .)
        | "$3"                 (. cost += 3; .) .

      Address
      = Street Town
        (   PostCode
          |                    (. IO.writeLine(name + " has no postcode"); .)
        ) .

      Person   = info          (. name = token.val; .) .
      Street   = info .
      Town     = info .
      PostCode = number .
    END Mail2.


Home  © P.D. Terry