CS655 Assignment 10: Modula-3
You will implement the following interface, which provides
substitution in strings, somewhat as is provided by the Unix comand [[tr(1)]].
TYPE T <: REFANY;
(* Substitution.T represents a mapping from CHAR to CHAR.
It is a checked runtime error to pass a NIL T to
any routine in this interface *)
(* primitive constructors: *)
VAR (*READONLY*) Identity : T;
(* The identity substitution. Clients must not modify this variable. *)
PROCEDURE New(from, to: TEXT) : T;
(* `from' and `to' specify that every character in `from' is mapped
to the corresponding character in `to'. `from' and `to' may use
the ``hyphen abbreviation'' described in the man page for tr(1).
For example "1-5" stands for "12345". ``Backlash escapes'' are
meaningless; a backslash is a backslash. The only way to include
a hyphen in a string is to put it at the beginning or at the end.
It is a checked runtime error to pass two strings that designate
different numbers of characters. For example,
New("1-6", "xyzpdq") is OK
New("abc", "xyzpdq") is a checked runtime error.
It is a checked runtime error for the same character to be
designated twice in `from'.
(* other constructors *)
PROCEDURE Compose(sigma1, sigma2 : T) : T;
(* Compose two substitutions. Must guarantee that
Apply(Compose(sigma1, sigma2), s) = Apply(sigma1, Apply(sigma2, s))
Note that sigma2 is applied first. *)
(* observers *)
PROCEDURE Apply(sigma: T; string : TEXT) : TEXT;
(* apply substitution sigma to the string and return the result *)
PROCEDURE Inplace(sigma: T; VAR chars : ARRAY OF CHAR);
(* apply substitution sigma in place to the chars *)
You will write an implementation called [[Substitution.m3]].
My solution is 84 lines long.
- You'll have to [[IMPORT Text]] to use the procedures in the
- You must reveal a unique concrete representation for
substitutions. There are two reasonable choices. The dense
[[BRANDED REF ARRAY CHAR OF CHAR]].
[[BRANDED REF ARRAY OF RECORD src, dest : CHAR END]].
Choose whichever representation you prefer.
- Don't forget that [[FOR c := 'A' to 'Z' DO ... END]] is legal
Modula-3, and you don't declare [[c]].
- Don't forget you are responsible for all the checked runtime
errors. Some of them will be taken care of automatically by the
implementation. For example, dereferencing a pointer is sufficient
to cause a checked runtime error if it is NIL.
- If you need to create a checked runtime error, you can declare an
exception internal to your module, then raise it. (See Nelson, p
If you do so, you can suppress the resulting warning by using the
[[FATAL]] pragma, e.g., [[<*FATAL FatalError *>]].
- You might find the type [[SET OF CHAR]] useful to help in
checking some of the conditions required in the interface.
- The procedure [[Inplace]] is easy to do character by character.
You could also do [[Apply]] character by character using
[[Text.GetChar]] and the [[TextWr]] interface, or you could try using
[[Inplace]] with [[Text.SetChars]] and [[Text.FromChars]].
- Don't forget to use the module initialization code to intialize [[Identity]].
- To eliminate some warnings, you may find it useful to add
[[<* FATAL Wr.Failure, Thread.Alerted *>]]
to the declarations of some procedure. To make it work, you'll
have to [[IMPORT]] both [[Wr]] and [[Thread]].
- You will probably want to separate the concerns of expanding the
hyphen abbreviation and building a substitution.
You can build a test program using the following main program:
MODULE Tr EXPORTS Main;
IMPORT Fmt, Params, Rd, Substitution, Stdio, Thread, Wr;
VAR sigma : Substitution.T;
buffer : ARRAY [0..512] OF CHAR;
n : CARDINAL;
<* FATAL Rd.Failure, Wr.Failure, Thread.Alerted *>
IF Params.Count # 3 THEN
Wr.PutText(Stdio.stderr, Fmt.F("Usage : %s fromchars tochars\n", Params.Get(0)));
sigma := Substitution.New(Params.Get(1), Params.Get(2));
WHILE NOT Rd.EOF(Stdio.stdin) DO
n := Rd.GetSub(Stdio.stdin, buffer);
Substitution.Inplace(sigma, SUBARRAY(buffer, 0, n));
Wr.PutString(Stdio.stdout, SUBARRAY(buffer, 0, n));
You will also need
the following ``m3makefile''.
To compile your test program, use [[/p/modula-3/bin/m3build]].
(If that doesn't work, try [[/homes/hosking/m3/bin/m3build]].)
You will have to run this on ector, since it is not installed on the
To get [[m3build]] to work, make a directory called [[src]] and put
your [[m3makefile]] and source code in it. Run [[m3build]] from the
You'll find the compiled program in [[SPARC/Tr]].
You can see how it's set up in [[/u/u56/cs565/hw10]].
You can use the identical setup; you'll just edit [[Substitution.m3]].
Your program should compile without warnings.
A good compilation from scratch looks like
: nr@labrador 433 ; m3build
--- building in SPARC ---
m3 -w1 -why -g -o Tr -F/usr/tmp/qkAAAa15701
new source -> compiling ../src/Substitution.i3
new source -> compiling ../src/Substitution.m3
new source -> compiling ../src/Tr.m3
-> linking Tr
For assistance and man pages, check out the Modula-3
Documentation is in the section on ``SRC Modula-3.''
You may have access to a local
The ``alphabetical index to the distributed library sources'' is very
useful; you can click on the name of an interface and see its text and
How to submit your files
For this assignment you should submit the files README and
You should turn in your files from a XINU lab machine,
using the command
turnin -c cs565 -p hw10 < list your files here >
To see the files you have submitted, you may use the command:
turnin -c cs565 -p hw10 -v
Don't be fooled by writing your code on ector! You still have to turn
in from a Xinu machine!