CMSC 430, Spring 2012

Introduction to Compilers

Home Schedule Piazza Grades Submit Syllabus Resources

Project 1

Due Fri, Feb 17, 2012

Updates

Introduction

In this project, you will develop a unit calculator that implements functionality similar to the unit conversions available in Google's calculator. For example, if your calculator is asked to compute 1 pound in grams it should return 453.59237 grams. As another example, if your calculator you is asked to compute 60 miles hour^-1 in m s^-1, it should return 26.8224 m s^{-1}.

To get you started, we've provided a code skeleton for your unit calculator. After unpacking this directory, make should build an executable calc intended to be used as follows:

Input language

The input to your calculator will be a list of expressions es given by the following grammar:
es::=εEmpty list
|e ;; esList of expressions
e::=fpDimensionless quantity
|fp uDimensional quantity
|e + eAddition
|e - eSubtraction
|e * eMultiplication
|e / eDivision
|e in uUnit conversion
|( e )Grouping
u::=ft | lbs | m | s | ...Base units
|u ^ nUnit Exponentiation
|u uUnit multiplication
|( u )Grouping

Here fp is a floating point number (whose syntax follows the OCaml convention, except the decimal point should not be required) and n is an integer (which may be negative, and may contain leading zeroes). The expression language is straightforward: the base quantities that can be calculated with may either be dimensionless or have dimensions. Standard arithmetic operations are permitted, along with a special form e in u, which converts the expression e from its current units into the units specified by u. Note that this conversion must be sensible; for example, 3 miles in lbs is an error.

Units u can either be base units such as ft, lbs, etc, or can be hybrid units composed from base units, e.g., s, m^2 s^-1, ft lbs, etc. Base units are sequences of upper or lower-case letters. Notice that multiplication of units is indicated by juxtaposition, and division by negative exponentiation; this avoids some annoying parsing conflicts.

Note that the input file is a list of expressions, each of which must be terminated by ;;.

Part 1: Parsing

The first step in building your calculator is to develop a parser for the input language. Your parser will accept strings produced from e in the grammar above, and from them should produce an abstract syntax tree (AST) in the form of an instance of the expr type, defined as:

type unit_t = (string * int) list

type value = float * unit_t

type expr =
  | Val of value
  | Plus of expr * expr
  | Minus of expr * expr
  | Mult of expr * expr
  | Div of expr * expr
  | In of expr * unit_t

Here units are represented by unit_t, which is a (possibly empty) list of dimensions and their exponents (either positive or negative). For example, s is represented by ["s",1], m^2 s^-1 is represented by ["m",2; "s",-1], and ft lbs is represented by ["ft",1; "lbs",1]. Quantities are paired with a unit. For example, 42 is represented as Val (42, []), and 3 ft s^-2 is represented as Val (3, ["ft", 1; "s", -2]).

Your parser should obey the following conventions:

You must implement your parser using ocamllex and ocamlyacc. Below, we've provided you with skeleton code to add your parser to; you should modify the files lexer.mll and parser.mly for this part of the project.

Part 2: Unit configuration files

In order to perform unit conversions, your calculator will need to know some basic ratios among units. Rather than hard-code this into your calculator, we'll use a configuration file instead. For example, the following configuration file gives conversions for feet, pounts, and kilgrams in terms of meters, grams, and kilgrams, respectively:

{
 "ft": [0.3048, "m"],
 "lb": [453.59237, "g"],
 "kg": [1000, "g"],
 "acres": [4046.85642, "m^2"],
 "newton": [1000, "m g s^-2"]
}
The first line says that 1 ft is equal to 0.3048 m, the second and third lines give conversions for pounds and kilgrams, the fourth line gives a conversion for acres in terms of square meters, and the last line converts newtons (force) in terms of base units. We will refer to units defined in this way as derived units.

Configuration files are in JSON format; you can use Yojson to parse these files. The Makefile supplied with the project includes a commented-out line to load the Yojson package; you can uncomment that when you're ready to start on this part of the project. A valid configuration file consists of a single object representing a mapping from unit abbreviations to an array of [ratio, target-unit], where target-unit is produced by u from the grammar from part 1.

To keep things a bit simpler, target units for this project will always be the SI units for meters, grams, or seconds.

For this part of the project, you should write a function parse_config : string -> config -> unit where config is defined as

type config = (string, float * unit_t) Hashtbl.t
This function takes the name of a configuration file, a configuration hash table, and parses the file, adding the configuration definitions to the hash table. You may assume the hash table is empty when your parsing function is called. Your configuration file parser should raise an exception (any exception) if any of the following hold:

Part 3: Semantics

Finally, write a function eval : config -> expr -> value that calculates the value of an expession under the given configuration. Your evaluation function should work as follows:

What to turn in

Put all your code in the code skeleton we have supplied, and upload your solution to the submit server. Here are some public tests for you to try out. Note that almost all testing will be with secret tests.

Important note: You should implement your project in ocaml-3.12.1. To access this version of ocaml on the linuxlab, you need to add /usr/local/ocaml-3.12.1/bin to the front of your path. To check that you have the right version, just run ocaml from the command line and it will print the version number.

Academic Integrity

The Campus Senate has adopted a policy asking students to include the following statement on each assignment in every course: "I pledge on my honor that I have not given or received any unauthorized assistance on this assignment." Consequently your program is requested to contain this pledge in a comment near the top.

Please carefully read the academic honesty section of the course syllabus. Any evidence of impermissible cooperation on projects, use of disallowed materials or resources, or unauthorized use of computer accounts, will be submitted to the Student Honor Council, which could result in an XF for the course, or suspension or expulsion from the University. Be sure you understand what you are and what you are not permitted to do in regards to academic integrity when it comes to project assignments. These policies apply to all students, and the Student Honor Council does not consider lack of knowledge of the policies to be a defense for violating them. Full information is found in the course syllabus---please review it at this time.

Web Accessibility