CSE 413 Spring 2011 - A Calculator Language

Introduction

The last two assignments for the quarter involve implementing a simple calculator in Ruby. The calculator allows the user to evaluate formulas involving the usual arithmetic operations, as well as to set and reference variables that can hold the results of these calculations.

Grammar

A calculator program is specified by the following grammar..

program ::= statement | program statement
statement ::= exp | id = exp | unset id | list | quit | exit
exp ::= term  |  exp + term  |   exp - term
term ::= power  |  term * power | term / power
power ::= factor  |  factor ** power
factor ::= id  |  number  |  ( exp ) | sqrt ( exp )

Language Notes

  1. A program consists of one or more statements, each written on a separate input line.
  2. A exp statement causes the given expression to be evaluated and the resulting value printed.
  3. An assignment id = exp is executed by evaluating the expression and binding that value to the given identifier. Any previous value bound to that identifier is replaced. No output is printed.
  4. If an identifier appears in an expression, it evaluates to the value most recently bound to it. If the identifier is not currently bound to a value, an appropriate error message is printed.
  5. The statement unset id deletes the identifier from the list of known (bound) identifiers.
  6. When execution begins, the identifier PI is already defined and is bound to 3.14159... (i.e., Math::PI in Ruby). It may be unset like any other identifier.
  7. The statement list causes all known identifiers to be printed along with the values they are currently bound to. The order in which the identifiers and values are printed is not specified.
  8. The statements quit and exit have the same effect. Both terminate execution of the calculator.
  9. There are two undefined nonterminals in the grammar: id and number.  An identifier, id, must begin with a letter, and consists of one or more letters, digits, and underscores.  Upper- and lower-case letters are distinct, thus aa, AA, Aa, and aA are four different identifiers.  A number is a floating-point number, consisting of one or more digits (0-9) with an optional decimal point and an optional exponent. The syntax of numbers with a decimal point may be restricted to require a digit both before and after the decimal point, as in Ruby, or may be more general, as in many other languages, where digits are not necessarily required on both sides of the decimal point.
  10. The keywords in the grammar (list, unset, quit, and exit) are reserved and may not be used as identifiers. The built-in function name sqrt also is reserved and cannot be used as an identifier.
  11. The arithmetic operations have their usual meaning as defined on floating-point values in Ruby. Note that the grammar implies that all of the binary arithmetic operations are left-associative, except for exponentiation, which is right-associative.
  12. The sqrt function is the usual floating-point square root function.
  13. Statements may contain an arbitrary amount of whitespace (tabs and spaces) between terminal symbols. The end of a line indicates the end of a statement.