CSE 413 19wi - Calculator Language

Introduction

The last two assignments for the quarter involve implementing a simple calculator in Ruby. This document specifies the input language for the calculator. The calculator allows the user to evaluate formulas involving floating-point values and 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 | clear 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 and the value of the expression is not defined.
  5. The statement clear 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 cleared 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 identifier, value pairs 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 decimal floating-point number, consisting of one or more digits (0-9) with an optional decimal point and an optional exponent. The implementation may restrict the syntax of numbers with a decimal point 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, clear, 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 and is defined only on non-negative numbers. The value of an expression that attempts to evaluate the square root of a negative number is not defined.
  13. Statements may contain an arbitrary amount of whitespace (tabs and spaces) before, after, and in between terminal symbols. The end of a line indicates the end of a statement.