Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Description LISP ( Lis t P rocessing) is a family of programming languages where

ID: 3758383 • Letter: D

Question

Description

LISP (List Processing) is a family of programming languages where the program is composed solely of linked lists.

Each list in any Lisp dialect is surrounded by parentheses, with the elements delimited by spaces (and ordered from left to right). The first element is assumed to be the function, and the remaining elements are the parameters to this function. A list of this form is also called an s-expression.

For example:
(+ 1 2 3)
Is a simple program in Lisp which would evaluate to 6

An atomic list is a list that contains no other lists. Your goal is to implement addition, multiplication, and subtraction over atomic lists according to the specified interface.

Preliminaries:

This should be an extension of Lab 4, however the main method will now be in the class you create for this assignment, and not in Lisp.java.

Objective

Write a class called Parser which will be responsible for parsing compound s-expressions into atomic s-expressions.

Your class must do the following:

Define the following non-static methods:getSexp Finds the next atomic s-expression in the file.params

repl: An instance of a class implementing Repl. You should have already completed this in Lab 4, so you may use the class you have written for that assignment.

scan: A Scanner over some s-expressions. We will be using a Scanner(File) for this assignment.

parenCount: The (integer) number of unmatched parentheses encountered so far.

return An atomic s-expression as a String

A main method that asks the user to enter a file to parse, then calls getSexp on a Scanner over that file.

Hints

A good strategy is to parse the file character by character, and build up the s-expression as a String. Done this way, you have 4 cases to consider:

The character is '('
In this case you have found a nested s-expression, so you should make a recursive call to getSexp. Make sure to update the parameters as appropriate.

The character is ')'
In this case you are closing off the s-expression. Do any necessary updates to the string and pass off the s-expr to your eval method from Lab 4's Lisp class. Then return this result.

The character is whitespace (' ', ' ', or ' ')
You may want to make it easy on your read and convert all whitespace to a single space for ease of parsing later.

Otherwise
Add the current character to the s-expression you are building

In addition, you might find the following methods useful:

«scanner».useDelimiter("")
Force the scanner to have no delimiter, so every call to next returns only the next character.

«string».replaceAll(" +", " ")
Replace multiple instances of a space with a single space in the given string.

«string».replaceAll(" \)", "\)")
Replace the sequence ' )' with a single closing bracket ')' in the given string.

«string».replaceAll("\( ", "\(")
Replace the sequence '( ' with a single closing bracket '(' in the given string.

Example Dialog

Using this input file (+ 1 2 3) (+ (- (+ 72 7 8 57) 58 90) 12) (* ( - (+ ( - 1282 (+ 1682 601 1691)) 1837 1569) 712 ) 4 2)

        Enter the name of a lisp file

        test.lisp

        6

        8

        16

This is the solution to lab 4 to help out

import lisp.util.Parser;

2 import lisp.util.Repl;

3  

4 import java.io.File;

5 import java.io.FileNotFoundException;

6 import java.util.LinkedList;

7 import java.util.Scanner;

8  

9 public class Lisp implements Repl {

10  

11    /**

12     * Evaluates an atomic s-expression. The only valid functions

13     * are +, -, *, and exit. All arithmetic operators are

14     * only implemented over integers.

15     * @param sexp An atomic s-expression as a String

16     * @return The result as a String

17     */

18    public String eval(String sexp) {

19      LinkedList<String> operands = read(sexp);

20      String op = operands.remove();

21      switch (op) {

22        case "+":

23          int sum = 0;

24          for (String numString : operands) {

25            int num = Integer.parseInt(numString.trim());

26            sum += num;

27          }

28          return "" + sum;

29        case "-":

30          String sumString = operands.remove();

31          sum = Integer.parseInt(sumString.trim());

32          for (String numString : operands) {

33            int num = Integer.parseInt(numString.trim());

34            sum -= num;

35          }

36          return "" + sum;

37        case "*":

38          String productString = operands.remove();

39          int product = Integer.parseInt(productString.trim());

40          for (String numString : operands) {

41            int num = Integer.parseInt(numString.trim());

42            product *= num;

43          }

44          return "" + product;

45        case "exit":

46          System.out.println("Goodbye");

47          System.exit(0);

48          break;

49        default:

50          return "";

51      }

52      return null;

53    }

54  

55    /**

56     * Reads in an atomic s-expression and parses the elements

57     * into a linked list of strings.

58     * @param sexp An atomic s-expression as a String

59     * @return A list of the tokens of the s-expression as Strings

60     */

61    public LinkedList<String> read(String sexp) {

62      Scanner scan = new Scanner(sexp);

63      scan.useDelimiter("[ ()]");

64      /*

65       * For you to finish

66       */

67      LinkedList<String> list = new LinkedList<String>();

68      while (scan.hasNext()) {

69        list.add(scan.next());

70      }

71      return list;

72    }

73  

74    /**

75     * Entry point.

76     */

77    public static void main(String[] args) {

78      Lisp thisInstance = new Lisp();

79      String program = Parser.getSexp(thisInstance);

80    }

81 }

Explanation / Answer

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputstrngeamReader;

public class Parser{
   final int CBSize= 5024;
   private char[] cb = null;
   private char ch;
   private String ln;
   private int indexOfLn = 0;
   private int lnLngth = 0;
   BufferedReader buffRdr = null;
   Env env = null;
   public Parser() {
       e=new Env();
       cb=new char[cbSize];
       buffRdr=new BufferedReader(new InputStreamReader(System.in));
   }

  
   public Parser(Env envrmnt) {
       e=envrmnt;
       cb=new char[cbSize];
       buffRdr=new BufferedReader(new InputStreamReader(System.in));
   }

   void getChr() {
       ch=cb[indexOfLn++];
   }

   char nextChr() {
       return cb[indexOfLn];
   }

   public Sexp read() throws IOException {
       getSexpPrepare();
       return getSexp();
   }

  
   public Sexp readFromstrnging(String input) throws IOException {
       getSexpPstrnging(input);
       return getSexp();
   }

  
   void getSexpP() throws IOException {
       ln = buffRdr.readLine();
       gSP();
   }

   void gSP() {
       indexOfLn = 0;
       lnLngth = ln.length();
       ln.getChrs(0, lnLngth, cb, 0);
       cb[lnLngth] = '';
       getChr();
   }

  
   void getSexpPstrnging(String input) {
       ln = input;
       gSP();
   }

   Sexp getSexp() throws IOException {
       for (; indexOfLn <= lnLngth; getChr()) {
           switch (ch) {
           case '(':
               return mkList();
           case ''':
               return mkQuote();
           case '-':
               return mkSubtractNo();
           case '"':
               getChr();
               return mkstrng();
           default:
               if (Character.isWhitespace(ch))
                   break;
               if (Character.isDigit(ch))
                   return mkNo();
               return mkSymbol();
           }
       }
       return Nil.NIL;
   }

   Sexp mkList() throws IOException {
       List top = new List();
       List lst = top;
       getChr();
       while (true) {
           lst.setChar(getSexp());
           if (ch == ')')
               break;
           if (indexOfLn == lnLngth)
               return Nil.NIL;
           if (ch == '.') {
               getChr();
               lst.setCr(getSexp());
               getChr();
               return top;
           }
           lst.setCr((Sexp) new List());
           lst = (List) lst.cdr;
       }
       getChr();
       return top;
   }

   Sexp mkNo() throws IOException {
       StringBuffer strng = new StringBuffer();
       for (; indexOfLn <= lnLngth; getChr()) {
           if (ch =='('||ch==')')
               break;
           if (Character.isWhitespace(ch))
               break;
           if (!Character.isDigit(ch)) {
               indexOfLn--;
               return mkSymbolInternal(strng);
           }
           strng.append(ch);
       }
       int value = new java.lang.Integer("" + strng).intValue();
       return (Sexp) new Integer(value);
   }
  
   Sexp mkstrnging() throws IOException {
       StringBuffer strng = new StringBuffer();
      
       for (; indexOfLn < lnLngth; getChr()) {
           if (ch == '"') {
               getChr();
               break;
           }
           if (ch == '\') {
               if (nextChr() != '"')        continue;
               else                         getChr();
           }
           strng.append(ch);
       }
      
       return new strnging(strng.tostrnging());
   }
  
   Sexp mkSymbol() throws IOException {
       StringBuffer strng = new StringBuffer().append(ch);
       return mkSymbolInternal(strng);
   }

  
   Sexp mkSymbolInternal(StringBuffer strng) throws IOException {
       while (indexOfLn < lnLngth) {
           ch = cb[indexOfLn++];
           if (ch == '(' || ch == ')')
               break;
           if (Character.isWhitespace(ch))
               break;
           strng.append(ch);
       }
       java.lang.strnging symstrng = "" + strng;

       if (symstrng.equals("T"))
           return T.T;
       if (symstrng.equals("NIL"))
           return Nil.NIL;

       Sexp sym = e.get(symstrng);
       if (sym == Nil.NIL)
           return e.put(new Symbol(symstrng));
       return sym;
   }

   Sexp mkSubtractNo() throws IOException {
       char nch = cb[indexOfLn];
       if (Character.isDigit(nch) == false)
           return mkSymbolInternal(new StringBuffer().append(ch));
       return mkNo();
   }

  
   Sexp mkQuote() throws IOException {
       List top = new List();
       List lst = top;
       lst.setChar((Symbol) e.get("QUOTE"));
       lst.setCr((Sexp) new List());
       lst = (List) lst.cdr;
       ch = cb[indexOfLn++];
       lst.setChar(getSexp());
       return top;
   }
}