CS 224 Project - Part 1

In this project you will create a parser for a small imperative language.  Future parts will involve the complete implementation of an interpreter for this language.

Introduction

The following program is written in the programming language to be parsed and later interpreted.

    func f(x:val y:val)
        return x-x/y*y;
    endfunc

    read k;
    read n;
    m := 1;
    while n-m do
      begin
        if f(m k) then
          skip;
        else
          write m;
        m := m + 1;
      end
The language has just one data type, integer, and variables are not declared. In the while and if statements a positive expression value is interpreted as true while 0 and negative values means false.

The program reads two integers, k and n, and writes all integers between 1 and n that are multiples of k.

The grammar for the language is given by

   program ::= functions statements | statements
   statement ::= variable ':=' expr ';'
           | 'skip' ';'
           | 'begin' statements 'end'
           | 'if' expr 'then' statement 'else' statement
           | 'while' expr 'do' statement
           | 'read' variable ';'
           | 'write' expr ';'
           | 'return' expr ';'
   function ::= 'func' variable '(' {variable ':' ('val' | 'ref')} ')' program 'endfunc'
   statements ::= {statement}
   variable ::= letter {letter}
   functions ::= {function}

Parsing Expressions

The grammar and a parser for an expression, expr, are described in the notes, with the one exception of function calls.  

    expr ::= term expr'
    expr' ::= addOp term expr' | empty
    term ::= factor term'
    term' ::= mulOp factor term' | empty
    factor::= num | var | '(' expr ')' | funCall
    funCall ::= var '(' {expr} ')'
   
addOp ::= '+' | '-'
    mulOp ::= '*' | '/'

The first thing you should do is modify the parser for expressions that you were given to handle function calls.  We need to modify the data type for expressions to handle function calls:

    data Expr = Num Integer | Var String | Add Expr Expr | Sub Expr Expr |
              Mul Expr Expr | Div Expr Expr | Func String [Expr]
              deriving Show

The option Func String [Expr] represents  a function call with the String for the function name and the list of expressions for the actual arguments of the call. 

Now modify the parser for the change in the grammar.

Parsing Statements

Secondly, you need to write a parser for statements given the following data type:

        data Statement =
        Assignment String Expr |
        Skip |
        Begin [Statement] |
        If Expr Statement Statement |
        While Expr Statement |
        Read String |
        Write Expr |
        Return Expr
        deriving Show

Start this by defining a parsing function for each kind of statement.  If the parser has accepted the first reserved word in a statement, you should use require rather than accept to parse other reserved words or symbols in order to get better error messages in case of failure.  An example:

    assignment = word #- accept ":=" # expr #- require ";" >-> buildAss
  buildAss (v, e) = Assignment v e

Use the functions for each kind of statement to define a parsing function for an arbitrary statement.

Parsing Function Definitions

Next you will need to write a parser which will accept a function definition using the data type:

   
data Function = Function String [(String,String)] Program
    deriving Show

This data type has a String for the name of the function and a list for all the formal arguments.  The list contains pairs containing the argument name along with the type "val" or "ref".

Parsing the Program

Finally, write the parser for the entire program using the data type:

   
data Program = Program [Function] [Statement] deriving Show

This data type contains a list of function definitions and the list of statements that make up the program.

Given that the function program parses a program, the following code can be used to test your parsing.  The code reads the program from a file and prints the result of the parse.  You can then create test files in your Eclipse project.

    main1 =
       
do putStr "Filename: "
          
name <- getLine
          
contents <- readFile name
          
putStr (show
(program contents))

Send me your modified zipped project in the dropbox in BlackBoard.