Due: Tuesday, May 25 by 11 pm. You should use Gradescope to submit your assignment in two parts, corresponding to the written and programming parts below. Details are given in the "What to hand in" section at the bottom of the assignment.
Added Monday, May 24: we want to allow a bit of extra time for this assignment because of the end of the quarter crunch. So, for this assignment, everyone has two additional free late days, meaning this assignment can be turned in as late as 11 pm, Thursday, May 27, even if you have already used all or most of your late days previously. No further extensions allowed after that deadline and no credit will be awarded for assignments submitted after that time.
|
, *
, +
,
?
, concatenation,
and character classes [...]
.
You may also specify character classes containing
all characters except for specific characters, e.g., [^abc]
.
You can also use abbreviations and be somewhat informal when the meaning is
clear, e.g., allexceptx = a | b | c | ... | w | y | z
.
Note that you cannot use something like "allexceptx" in a solution without first
defining it as a name for a particular regular expression, as in the above example.
You may not use other operations that might be found in some
software packages; in particular, you
cannot use not(
re)
as
a regular expression that matches all other regular expressions except for re.
(a) Write a regular expression that generates C integer constants as described above. (Of course you can break the solution down into a regular expression with several named parts if it makes things easier to write and read.)"An integer constant consisting of a sequence of digits is taken to be octal if it begins with
0
(digit zero), decimal otherwise. Octal constants do not contain the digits8
or9
. A sequence of digits preceded by0x
or0X
(digit zero) is taken to be a hexadecimal integer. The hexadecimal digits includea
orA
throughf
orF
with values 10 through 15."An integer constant may be suffixed with the letter
u
orU
, to specify that it is unsigned. It may also be suffixed by the letterl
orL
to specify that it is long."
This is the first of two programming assignments to build an interpreter for the language given in the Calculator Language description. We will build the interpreter in two parts - a scanner that reads the calculator program from the input stream and breaks the input into tokens, and a parser/evaluator that parses the token stream according to the specifications in the grammar and executes the program. The calculator program should be implemented in Ruby. For the most part it will just be a collection of top-level functions, but you should create classes when these are helpful in organizing the code.
For this assignment you should implement a scanner that provides a
function next_token
. Each time next_token
is
called it should return a new Token
object that describes the
next terminal symbol read from the input. Objects of class Token
should
respond to the following messages:
kind
- return the lexical class of the token as a string.
This should be a distinct string for each lexical class in the program,
possibly just the operator or keyword itself. However, all identifiers should
be treated as instances of a single lexical class and the kind
method
should return the same value for every identifier. Similarly, all numbers
should be treated as a single lexical class. You will also want to have
a lexical class to represent the end of an input line, since end-of-line
is
semantically meaningful - it indicates the end
of a statement.value
- if the token kind
is either an identifier
or number, then this message should return the actual identifier or floating-point
value. Its value is not defined for other lexical classes.to_s
- the standard Ruby "to string" method. This
should produce a descriptive string representation of the token, including
the associated value if the token is an identifier or a number.To test the scanner, you should write a small program that calls next_token
repeatedly
to get the next token from the input and prints the result
(the result of sending to_s
to a Token
object). After reading and
printing a quit
or exit
token, the test program should stop.
Adjacent tokens should be separated by a single space or newline character in the output.
Feel free to take advantage of Ruby's string and regular expression classes
and methods to chop input lines into tokens.
You also might want to use the readline module (require 'readline'
)
to allow convenient input editing while you are typing, but this is not required.
Your scanner and Token
code should be contained in a file scan.rb
and the small program that calls the scanner and prints tokens should be in a file hw7.rb
.
Be sure to include your name and other identifying information as comments
at the beginning of your file. There should also be descriptive comments as needed; in particular,
your Token
class should include documentation of the possible values returned
by the kind
method.
Use Gradescope to submit your solutions to this assignment in two parts.
For the problems in Part I please turn in a pdf file
named hw7.pdf
with your answers. This can be a scanned
handwritten document if that is convenient, as long as it is clear
and legible.
Gradescope's web site has several instructional videos and help pages to outline the process,
and this guide
has specific information about scanning and uploading pdf files containing
assignments.
For Part II, turn in the scan.rb
and hw7.rb
files containing your Ruby code.
Also submit a text file
named hw7.txt
containing some
examples of test input and output that demonstrate that your scanner
works on a variety of test input containing both legal tokens and other
input characters. The hw7.txt
file should be a transcript
of a terminal session showing operation of your scanner and test
program.
On Linux and OS X systems you can create a transcript file using
the command script hw7.txt
to start a new shell and
capture all of the input and output while it is running. Run your ruby
command there, then, when you're done, terminate ruby and type
exit
in the shell window. That will leave you back in the
original window where you ran script
, and there will be a
hw7.txt
file containing your work in the current directory.
Turn in that file.
Historically, Windows has not had a script command.
If no better tool is available, you can create a transcript file as follows.
Run ruby or irb in a command window. When you're done, right-click the window title bar and
pick edit>select all
from the popup menu, then pick edit>copy
.
Open a plain text editor like notepad++
, paste the copied terminal session into
a new window, and save that file as hw7.txt
.
Regardless of how you create the transcript file, you can do some light editing to delete major typos or false starts, but don't worry about minor problems or a few extra characters like backspaces entered to correct typing errors. We're interested in your overall demonstration, not in every small detail (as long as it's clear which things are false starts that should be ignored).