THESIS
IMPLEMENTATION OF A COMPILER FOR THE
FUNCTIONAL PROGRAMMING LANGUAGE PHI -
(D
by
Eugene J. Cole
and
Joseph E. Connell II
June 1987
Th esis Advisor:
Daniel Davis
233190
UNCLASSIFIED
security ClaSS. fiCaTiQn Of Tm.S paGE
'a
RESTRICTIVE
'b
MARKINGS
Unclassified
SfCuR'TY classification authority
2a
2b
6a
6b OFF.CE
and
Stare
8a
8c
ADDRESS (Cry
''
".
and
7a
Code 52
939^3-5000
State
(O'fy,
and
ZIP Code)
Monterey, California
8b OFFICE SYMBOL
(it apphcabie)
Sfare
SYMBOL
applicable)
ZIP Cod*)
Monterey, California
(if
6<
ZIP Cod*)
93943-5000
'0
PROGRAM
PROJECT
TAS<
WORK
ELEMENT NO
NO
NO
ACCESSION NO
jNI
PERSONA L AuThOR(S)
!ole,
jj
-yP OF p.fpOR''
'ME COVERED
TQ
FROM
"(aster's Thesis
6
DATE OF REPORT
19 87
(Year
Month Day)
15
PAG
Dl-NT
1""
June
Supplementary no t at:qn
COSAT. CODES
group
E
14
3b
Su9-GR0UP
it
SUBJECT
ERMS \Contmue on
revert*
if
of a prototy pe comrii er
design is hi ghly modu larthe understa nding of both
compiler imp lements
>a
(408
83
APR
other
edt.om
are.
obsolete
646-309
22c
OFFICE
Code
SyMBO:
5
2~v
WL
ur
Approved
is
unlimited.
PHI
by
Eugene
J.
Cole
and
Joseph E. Connell II
Captain, United States Marine Corps
B. S., University of Missouri
Rolla, 1974
MASTER OF SCIENCE
IN
COMPUTER SCIENCE
from the
ABSTRACT
This thesis describes the design and implement of a prototype compiler for the
functional
is
think this should facilitate the understanding of both concept and implementation.
The
front-end of the compiler implements machine independent lexical and syntactic analyzers;
employed.
are
machine
is
a prototype,
it
to a full
are present
implementation.
is
all
of the qualities
mature enough
to
allow
1$
TABLE OF CONTENTS
I.
II.
INTRODUCTION
A.
BACKGROUND GENERAL
B.
BACKGROUND THESIS
C.
IV.
V.
2.
Functional
Languages
10
D.
ASSUMPTIONS
11
E.
CONSTRAINTS
12
B.
THE SCANNER
SYNTACTIC ANALYSIS THE PARSER
C.
ERROR HANDLING
A.
III.
LEXICAL ANALYSIS
13
13
18
23
25
A.
OVERVIEW
25
B.
RUN-TIME ORGANIZATION
25
C.
31
D.
OPTIMIZATION
40
42
A.
RESULTS
42
B.
CONCLUSIONS
43
FURTHER RESEARCH
LIST
OF REFERENCES
44
46
(concrete syntax
of*
10/16/86
03/03/87
47
50
APPENDIX E
APPENDIX F
APPENDIX G
APPENDIX H
APPENDLX
APPENDIX J
APPENDIX K
APPENDIX L
APPENDIX
53
(right recursive
HEADER FILES
ROCK COMPILER MAIN MODULE
ROCK COMPILER SCANNER
ROCK COMPILER PARSER
ROCK COMPILER ERROR HANDLER
ROCK COMPILER SEMANTIC CHECKER
ROCK COMPILER CODE GENERATION MODULE
ROCK COMPILER USER INTERFACE
ROCK COMPILER RUNTIME UTILITIES
54
grammar)
ROCK COMPILER
57
67
71
76
106
112
1
37
142
145
157
USER'S MANUAL
68
174
I.
A.
BACKGROUND
In
its
INTRODUCTION
GENERAL
at the
One of
known
the courses
as applicative,
programming. Both the theory and the practice of functional programming are covered,
concentrating more on the practice than the theory. In order to fully appreciate the nuances
of functional programming
it
would be desirable
when programming
ference in methodologies
programming
Of
in traditional
a first
hand look
in functional
with a functional
fundamental
at the
languages as opposed
its
many
this
requirement. Although
of functional programming.
It is
Modem LISP
LISP
is
to
is
UNIX
considered
it
into
dialects
do not support
all
to teach techniques
aspects of functional
make
it
a pedagogical nightmare to
UNIX
on the
programming.
dif-
imperative languages.
the
In an 11
week
LISP would
significantly detract
programming.
PHI
MacLennan
little
difficulty in learning
The syntax of
have
now
J.
how
to write legitimate
PHI
Instruction can
statements.
programming.
B.
BACKGROUND
Creation of
THESIS
PHI solved
the
problem of finding
PHI language. So
to
remedy
the
environment
it is
exists
PHI
first
in a
PHI programming
compiler.
By choosing
thesis attempts
this
implementation
address the problems associated with utilizing conventional methods for implementing a
system would change, the authors wanted a well documented and understood
methodology.
The
2:p.
478]. Therefore,
it
was imperative
much
to
choose a methodology
Following conventional methodologies, the authors separated the PHI compiler design
into a front-end 3
shown
in
Figure
and a back-end4
The
1.1.
PHI compiler
is
(syntactic analyzer) is essentially responsible for analysis of the external file containing the
source program.
generation to produce code suitable for execution on the target machine. [Ref. 3:pp. 5-6]
The authors
felt that a
of the system, simplify division of labor, and increase ease of development and
maintenance.
It
PHI
interpreter.
C abstract
user data
svntax tree
parsed
parse f tree
text file
prog
input) data
2.1
1.1
scanner- tokens
ascn
prog
parser-
'lexical
syntactic
v
analyzer
3.0
attrib'd
semantic
analyzer tree
code
generator
asm t
PC
file
analyzer
tokens
output
data
tokens \
results
tables
Figure
C.
BACKGROUND
FUNCTIONAL PROGRAMMING
Functional programming
applicative
functional
is
programming goes
programming
1.1
traces
methodology
further back,
its
it is
roots to John
in favor
Backus
[Ref. 4:p.
404, Ref.
is
is
5:p.
65].
In
ACM
his acceptance
He went on
styles.
to
methodology
is
propose a new
combining forms
known today
as functional
programming.
1.
Backus
conventional languages
is
613-619]
problem with
The assignment
statement plays a central role in conventional languages and breaks programming into two
worlds. Backus calls the right-hand side of assignment statements, expressions, the
is
the
first
programs
First,
they permit
imitate the machine's storage cells; assignment statements allow, even encourage, state
and aliasing
indirect, permits
to arise.
It
reason about the correctness of these programs, so proving simple programs correct
to be
is
virtually impossible.
is
an
Additionally,
critical.
of code produce dramatically different results depending on which statement inside the for
loop
is
executed
for
{
(i
first.
= 0;
!= some_value; ++i)
for
if(
2 == 0)
= 0;
i != some_value; ++i)
DoSomething(i);
if( i
2 == 0);
continue;
DoSomething(i);
}
(i
continue;
}
These problems
interact so that
old ones.
6:pp.
[Re'f.
613
it
becomes extremely
1-2
difficult to create
one-word
result.
programmers
to
what Backus
2.
is this
programming languages.
[Ref. 6:pp.
is
that
to think in a
word-at-a-time
out of
1-20]
new programs
Neumann
it
bottleneck" of conventional
613-619]
Functional Languages
Backus proposes
the
as the solution to
these problems.
statement from their syntax so that their basic building block becomes the function.
becomes possible
to
is
set
It is
able to build
new
It
thus
functions together.
etc.
the
program
is
to
practical to prove
It is
problems
the
programmer
to
now
maintain
It
now becomes
625].
effects
is
order.
The
values of expressions are no longer dependent on the order in which they are evaluated.
35].
10
functional
parallel
to
the
key
to
programming
the massively
computers entering service nowadays. All of the above benefits have applicability
ongoing research
in the
The authors
following thought
SDI program.
programming can
assignment statements
best be
are to functional
summarized by
programming what
the
GOTO
D.
ASSUMPTIONS
An IBM 5
target
its
machine for
this
felt that
intended use were better suited for the PC/personal work station environment as
opposed
to a
future compiler
improvements
will not
need
to take into
the system.
known
PC environment
PC
PHI
have to be concerned
environment eliminates
account the effects the PHI environment will have on another user of
The implementor
is
able to
work with
quantity.
The assumed
target
machine configuration
is
640K
bytes of
should
MS-DOS 6
IBM
MS-DOS
is
drive,
at the
is
These machines
is
Each machine
RAM, one
lab.
in the
11
when executing
E.
the
It is
PHI compiler.
CONSTRAINTS
As
is
most implementation
major
effort be directed
particular
component of
was probably
theses, time
towards a
full
e.g.
the biggest
should the
major
effort
be directed towards a
full
implementation of the compiler while concentrating on a subset of the PHI language? The
benefit could be gained by implementing a complete compiler.
authors
Having
and interfacing a
about them in a
Since PHI
full
text.
As
an experimental language
is
much
it
is still
Trying to modify and update the compiler design with each version proved to be an
impossibility.
stood on
07
description of the
grammar
January 1987.
This subset
is
need
to
as
latest
Appendixes.
12
it
to
in the
will
version of the
n.
PHI compiler
into
1.1.
The authors
to
is
between the
lexical
Two
possible
The
first
incorporates the scanner into the parser, and tokens are produced by the scanner only upon
method
is to
some data
Thus,
this
system acts
like a pipeline.
An
alternate
allow the scanner to tokenize the entire source program, store the tokens in
structure,
and pass
[Ref. 3:p.
10]
For the prototype implementation of a PHI compiler, the authors based the design on
the first interaction.
enhancements.
this
Any
is
is
who work on
the
PHI
programming environment.
A.
LEXICAL ANALYSIS
The PHI compiler reads
lexical analysis.
program
is
The
THE SCANNER
a source file of
ASCII
text
which
is to
in the
13
accomplished
is
155].
This
may
be found
identifiers,
in the
header
the
complete
Appendix
program
is that
comments and
Once tokenization
file
is
One means
available
is to
In this
method
This simplifies the design of the parser because provisions do not have to be
7].
made
of the PHI
E.
syntactic analyzer needs to take into account only one type of data unit
3:p.
listing
terminal
is to
142].
ways of describing
method "generative
An
tokens.
rules are
it
easier to visualize this as a recognitive vice generative problem. For this reason the various
An example
shown
Figure
in
2.
The
interested reader
is
directed to
that utilizing
The
ideal
identified.
one
FSAs
picture
to
was worth
hundred
Due
debugging
of code.
14
to
lines
[Ref.
model tokens.
Once
FSAs
is
it
would be
digit
digit
digit
integer
f
\_J
\z^/
Figure
ASCII character
2. 1
This resulted in
PHI overloads
((
compound token
it
if
it
is
">"
is
is
SUB_, and
SUB_
NEG_.
or
lets the
parser
make
it.
Some examples
^or example, +
and
for
its
= and <>
it
in the scanner!
true meaning,e.g.
for *.
15
If the
(--).
"-", the
type, e.g.
them
types.
is
or characters, to
next character
^ ))
the designer of
set,
digit
68 do [Ref.
originally
It
certainly
keywords from
to distinguish
PHI has
debugging of programs.
PHI's
91].
3:p.
ALGOL
may
makes
made
life
life
comment with
a special character.
only did
the
would ignore
Comments
The authors
programmer comments.
for
all
following
Ada 11
and
are in
ALGOL 60
programmer by simplifying
as
based on
identifiers
comment
terminator
is
are
now implemented
the
Not
also completely
it
removed
the
A name
table
was
names of
makes analyzing an
all identifiers
when
instance of each
first
words, regardless of
how many
11
PHI
The
A complete
symbol
10
and constants.
listing
name
rimes and in
table.
of PHI keywords
name
Joint
is
now
how many
may be found
16
in the
name
table.
Programming
to the parser
header
file for
would
the scanner in
is
tree.
In other
used,
indicate a
Appendix E.
know
name, X.
identifier
implemented a keyword
shown
For
lookup, which
worst 0(log
is at
efficient
way of
only comparisons.
this
most
n), is
Knuth
first
be compared
table.
The authors
must
name
[Ref. 10:pp.
406-4101 has
is
table.
In an attempt to
a hash table.
McKeeman
summing
[Ref. ll:pp.
with
its
The
possibility of collisions
However, since
this
is
name of the
it
last
make
name
size.
name
list
of names.
same
In PHI's
can contain
type.
So each
is
conceptually easy to
visualize/work with, and also solves the problem of possibly overflowing the hash table.
12:pp.
as
both the
and
implemented
left.
method
far
memory
to
It
outweighed the
83-93]
17
[Ref.
B.
SYNTACTIC ANALYSIS
The purpose of
THE PARSER
determine
the parser
is
twofold:
is
syntactically correct; 2) to
fitting
it
1) to
if
impose a hierarchical
which
[Ref. 8:pp. 7-8, Ref. 9:p. 7], Traditionally, these tasks are
bottom-up methodology
[Ref. 8:p.
41].
is
structure
Top-down
symbols
the
at the leaves.
The parse
nonterminals.
at the
bottom
from
On
to the top
tree is constructed
bottom-up methodologies
The parse
start
it
its
from
the top to
from
and
the terminal
tree is constructed
from
authors can attest to the fact that the concept of top-down parsing
parsing PHI,
downward
When
tree are
strings of terminals
It is
is
to
is
8:p.
its
"due to the
41]
The
is
So, partially
implement
each nonterminal of the grammar [Ref. 3:pp. 219-220]. This technique gets
18
in
its
distinctive
To
state
it
more
recursively
itself,
if
on
150]
[Ref.9:p.
itself
nonterminal
'B'
Regardless of
and
how one
with recursion.
'B'
'A'.
What made
this
mechanism
not have to explicitly maintain a stack of symbols for each function call; instead, the
information was implicit in the stack of activation records resulting from each function
Top-down
means of implementing
a syntactic analyzer.
grammar
[Ref. 3:p.
'A'
211].
with
it is
for
essential that
'A'
appearing as the
would cause
as
PHI
the
is
19
in
any
element on the
this type
never leave
In order to
PHI grammar
exist
would be possible
an example of
this
The PHI
of
string.
employ top-down
to be right-recursive 12
12 The right
recursive syntax of
first
it
recursion be
must not
all left
However,
call.
Appendix
From
view the
ideal
the correct
production rule to be applied in every step of the parsing process. Constructing the parse
tree
there are
two
in a
methods
nondeterminism
[Ref. 9:pp.
When
is
in the
grammar
recursive-descent techniques, the parser picks an arbitrary production and continues with
the parse [Ref. 9:p.
151].
parse
If the
new production
an error
if
is
successful
is
is later
is
it
assumed
is
This
productions to chose from. The second method requires a modification to the grammar
which
grammar
among nonterminals
part, the
design of PHI
is
[Ref. 9:p.
is
151].
conducive
this
is
problem
at
When
13
had
to be used.
is
tn the other.
hand.
parsed.
PHI
or that backtracking
single
one case a two token look-ahead was employed and backtracking was used
This
].
is
degree of nondeterminism arose in the parser design. The authors attempted to solve
left
the token
The
first
'['
is
found, a flag
look-ahead token
is
the production 13
is set
utilized
to indicate that
when
ARGBINDING =
parsing the
found
in the
an
QUALEXP OP
ARGBINDING
is
being
Appendices
may
for example,
FACTOR*TERM.
MULOP,
*, to
TERM, which
parse as
FACTOR,
After succeeding on
see
if
in turn
as
QUALEXP was
called
in the
QUALEXP production
the
ARGBINDING production
is
TERM
employed
is
should be
sentential
and
TERM
is
allowed
to
is
DENOTATION when
first
the
was
']'
If
make
is
this
found
l->
ACTUAL: ACTUAL =
COMPOUND = ( ELEMENTS
identifiers
may
),
excluding
apply
it
proceed to completion.
If
terminated, e.g., term does not recursively call itself again, and
parentheses,
This
initiated.
production. In order to
or
ARGBINDING.
COMPOUND
FACTOR
parse as either
a look-ahead
may
it
finds "|->".
FORMALS
this choice.
production.
The root
to the
14
A purist would say
employ a recursive-descent
was parsing
made and
the parser
If "|->" is later
The normal
costs
As described below,
FORMALS
it
compound
parser.
21
means
that the
in fact
produced by FORMALS. After ascertaining FORMALS, the parser now continues the parse
using the
DENOTATION
production.
WHERE AUXDEFS
an identifier)
may
be used prior to
its
works
its
way
to the
definition.
However,
writer.
this
is
parsed
and
first
is
analogous to that of mutual recursion in Pascal, without the benefit of the forward
declaration [Ref. 4:p. 213].
was designed
essentially a post-order
walk of the
management
However,
routines.
tree.
QUALEXP =
would be too
Management of the
inefficient.
unwieldy
to
work
with.
table
this
now
status of the
in tree form.
This
itself.
The parser
is
able to analyze the source program by walking the tree and decorating the
is
insignificant
The
is
tree in
memory does
trivial
because
it
tree.
more
the benefits.
DENOTATION became
require
benefits.
COMPOUND
and
22
.
.
modicum of
authors to perform a
PHI
becomes
maximum
One
possibility
would be
interpreter.
relatively
tree.
It
enhancements
to use this
in this
front-end to
manner
simplifies
functional understanding of the front-end and should lead to increased ease of maintenance
and
portability.
executed
it
on a
To demonstrate
C run-time
header
new
to
target machine.
ERROR HANDLING
C.
b.
c.
2.
Compiler crashes
Compiler loops indefinitely
Compiler continues, producing incorrect object program
Compiler reports
first
error
and then
halts
Acceptable responses
1
Possible responses
a.
b.
2.
Compiler reports error and recovers, continuing to find later errors if they exist
Compiler reports the error and repairs it, continuing the translation and producing a
valid object program
In the prototype
recovery.
PHI compiler,
The primary
11]
Unacceptable responses
1
II.
[Ref. 3:p.
is to
the translation of
maximum number
is
life
of the
[Ref.
shortening the edit, compile, debug cycle inherent to writing computer programs.
decided that lexical analysis and syntactic analysis were the most likely source of errors.
23
Common examples
when
the
the
programmer
program
One
is
arise
185]
3:p.
These errors
is
bogus errors or executing an erroneous program. To insure erroneous programs are not
executed, the authors inhibited object
file
production
if
authors do not believe the compiler should allow code generation to continue, or even
begin,
if
the source
program has
and
attempted to minimize
this is
errors.
overwhelmed with
Also, for
codes.
found
To
it
The authors
insure the
programmer convenience,
programming
actual error
errors.
better.
10
PHI compiler,
PHI language.
24
It is
error
assumed
messages have
their
PHI
III.
A.
OVERVIEW
The back-end of
in
This output
file,
ASCII
is
B.
in
to output
make
characters.
is
These
an object
file.
RUN-TIME ORGANIZATION
Since
PHI
is
is set
up
to
it
lends itself to a
accomplish two
tasks:
1) to
hold pointers to the current operands, and 2) to hold activation records for functions
currentiy in use. Both of these tasks are described below.
There
is
limitation is
and the
64 kilobytes
imposed because
maximum
variables,
offset is
limit
the
memory
64K.
3.1).
is
The
is
competed
stack
placed
for
This
this
space
at the top
running.
This space
is
is
is
memory
is
25
from each
2) there is
1) all
data types
no fragmentation of
memory because
all
two topmost
The
pointers.
new operands.
If the
is
If the
next operation
is
a binary operation, a
placed on the stack, and the operation takes place using the
result
is
next operation
static.
is
memory
is altered
as the
program
directs.
Address
64Kb
-4-
^^>
Stack
TOS
Values
(Variables and
Constants)
Kb
Figure 3.1
Organization
Memory
If the
f(x)"),
an activation record
is
is
function result
is
function's value
calculated.
is to
at the
26
is
first
(e.g.,
"2 *
Static
Link
Static Nesting
Level
Figure 3.2
Activation Record
The
activation record itself, Figure 3.2, contains three parts: the static link, the static
The
stored.
static link is
is
The
i.e.
is
to
base of the storage space for a scope's values are used to access variables and
memory where
is
following the
is
static
By
activation record of the scope of the target value can be accessed. Then, the address of the
variable
is
calculated by adding
to the
low address of
However,
this is a
An
alternate
between or within
it
is
the variables.
straightforward.
and pointers to
Whenever
its
side effects,
a function
is
called,
its
routine.
Using
this
is
is
27
to
If the
function
is
recursive, the assembly language subroutine simply calls itself until the base of
recursion
is
reached or
until stack
overflow
its
is
that the
data definition ("answer") has no arguments and simply calls the factorial function. The
factorial function,
is
is
When
it
fac (n
1) is
1), is
evaluated, a pointer to
its
is
evaluated.
Address
64000
64000
^
?
J
Base of
Value Space
Answer
Activation Record
(no actuals)
61998
1
Fac
1
(5)
^Activation Record
Ptr to Actual
Ptr to 5
63997
2
Fac (4)
3
Activation Record
Ptr to Actual
:
Ptr to 4
63992
Fac
J,
J
Kb
answer where answer
fac(n)
==
if
==
where
fac(5)
then
(3)
Activation Record
else n * fac(n-l)
endif
Figure 3.3
Factorial
As an example of
PHI program fragment
the
is
used
(n)
==
if
n =
28
then
calls
else
(n
1) *
n endif.
is
Figure 3.4
is
the
which returns
the
Assembly Language
Address/Machine Code
0150 jmpalOOOO
0103E94A00
alOOOl:
mov cx,0
0106 B90000
0109 E80000
call
Lformal
mov
010C B80000
010FE80000
0112E80000
0115E80000
0118 3D0100
E
E
E
0126
01 IB 7509
011DB80100
E
0120 E80000
0123 E92600
ax,0
call iputvalue
calliequ
call igetvalue
cmp ax,l
jne al0003
mov ax,l
call iputvalue
mov
0126 B90000
0129 E80000
call
Lformal
mov
012CB90000
012F E80000
call
mov
0132B80100
0135E80OOO
0138E80OOO
013BE80OOO
013E51
013F57
0140BB0100
cx,0
Lformal
ax,l
E
E
E
call iputvalue
0143 E80000
0146 E8BDFF
0149 E80000
call
call imult
014C E80000
call
call isub
ppop
push ex
push di
call
mov
i
bx,
mov
0106 callalOOOl
al0002:
del_scope
014FC3
ret
alOOOO:
Figure 3.4
The
factorial.
If the
label
"alOOOl"
When
it is
subroutine
label a 10003.
memory,
is
at
address 0103
is
is
1) is
is
reached, a
jump
is
stack.
made
to
pu^ on the stack, and the values are prepared for calling
29
(lines
0126
to 0143).
The
is
put
at the
is
down
is
made
to label a 10002.
PHI
compiler.
jump around
inline
code
in spite
jump and
in
Figure 3.4
is
is that
there
is
an unconditional
However,
it.
jumps
is
Another solution
trivial.
considered was to generate code for functions and the "main" program separately, then
combine
the
the output
for
reasons put forth in the section that describes the semantic analyzer.
is
word oriented
bit capability.
boolean representation
is
somewhat wasteful
in
terms of
memory
space,
planned to represent
linked
lists.
real
it
or 0. While
allows for a
and comparisons.
Neither of these types have been fully implemented; however, there are
30
There
is
currently no
dynamic allocation of
BP and SP registers
are used to
When
auxiliaries as needed.
allocated and,
when
AX
variable space
a function
is
is
Some
registers.
mark
manage
program
stack,
is
is
Any
run time
error such as overflow or division by zero errors will result in an appropriate error
to the user (see
will terminate
C.
Appendix
and control
name of
the node.
is
and
CODE GENERATION
SEMANTIC CHECKING
The PHI compiler
message
in
semcheck
function,
These procedures,
which
in turn, call
In
tree.
calls various
semcheck
perform semantic
most cases,
tree
nodes
repeated until the leaves of the tree are reached. The function semcheck
its
subtree.
With
do one of
from
the
semcheck
is set
to a buffer in
is
generated.
memory.
If
As noted above,
an error condition
is
this is
declared,
until
the tree is completely traversed or ten errors are accumulated; then, the semantic checking
31
process terminates.
at error
recovery; top-down checking simply continues normally from where the error was
detected.
solve.
some problems
if
there
is
that pure
top-down checking
will not
as explained
below.
The scoping
checker.
the
One
number of
item
is
the
rules of
solution
its
is
PHI provided
a multiplicity of stacks.
The
depends upon
However, because of
the semantics of
this
convention.
There are four stacks used by the semantic checker: the type- stack, the variable-stack,
the definition-stack,
lists.
and the and-stack. All but the type-stack are implemented as linked
slight increase in
array of
300
memory and
static
will be accessed
and
trivial
and
sequence, and because they can be more easily accessed from an array than from a linked
list,
and
2) a
list
3) the
type-stack
of
an array.
32
if
the
# of Bytes
Type Name
Link
to
Next Type
Figure 3.5
Type-Stack Entry
3.5, is
meant
to
name of
the type
bytes needed in
memory
and user defined types are added as they are encountered. The begin-end
to
initialization,
it
contains the
construct of the language (not implemented yet) allows declared types to be visible over a
specified range.
the stack
It is
planned to implement
upon encountering
the begin
this construct
by
Variable Type
Node
Formal Flag
Pointer
Figure 3.6
Variable-Stack Entry
The
all
whether or not
it is
a formal.
Whenever a
variable
scope
is
it
is
name
and a flag
33
to designate
is
it,
stack.
is
not
when
For example,
Definition
Formals
Type
Pointer
Link
to
Next Entry
Figure 3.7
Definitions Stack Entry
The
node
This
in this
way.
However,
SR
this
$Z
and a pointer
in the
->
to a linked list
be null
same way
if
which contains
the declaration
is
its
a data
the definitions-stack
fact,
designed
would contain
that contains C,
Integer).
all
variables considerably, and the overhead needed to implement these two as separate stacks
is
The need
is
PHI such
a
way
as the
that the
subtree of the
WHERE
construct.
However, the
AND
all
AND
This
is
it
is
statement can define variables used by the other subtree. So, a program
is
AND
34
is
it
can detect
such a vehicle.
that the
k^^
Where
==
c(l)
Auxand
*Datauxdef
Funauxdef
c(n)
^-t\^
d
c (1)
where c
(n) == =
n * d
andd = =
Figure 3.8
Tree With Forward Variables
When
indicate that
and-stack.
AUXAND
"Notfound"
Note
that
is later
is
AND
semcheck
AUXAND
removed from
AUXAND
set,
function
a pointer to
(DATAUXDEF
in the variable-stack.
the and-stack.
is set to
all
If a
set.
is
AUXANDS
marked when
is
is
auxand node
35
is
when both
found, d
is
the left
is
when
defined and
the
AUXAND
(UNDEFINED VARIABLE)
this condition
at the
the variable
not found
the
is
entry of the
would be
when
node), and
match
the top
is set to
traversed.
when
the
AUXAND
no problem because
the
'
names
are generated
in the
begins with the letter "a", followed by 6 digits. Examples can be seen in Figure 3.4.
Funauxdef
Funid
uf^
Formal
Comma
/
y
f (x,y)
==
x * y
Figure 3. 9
Tree for Function
Function definitions presented a problem that was solved with a deviation from pure
a function definition
(FUNAUXDEF
in
Figure 3.9)
is
encountered by semantic checker, the following procedure would be followed (see Figure
entry):
funid node:
(ERROR)
first
formal of
first
<>
Nil do
36
'
'
'
list
==
nil)
(FORMALS MISMATCH)
return
else
put "f
'
end
in the
variable-stack
(Type of
return
= INTEGER)
else
end.
fnnaiixrief node:
left
type
right type
if (left
type
<>
call a
right type)
left
endif
end.
When
a function
is
Figure 3.11):
actualist
Input
is
Output
Check
if
is
error condition
set error
list
elist (elistptr)
found,
if
not found
ifand_flag
TRUE
else
set error
end.
elist
Input
if
is
pointer->rptr
<>
list
node
nil
elist (pointer->rptr)
37
else
Integer
$Z
\ Formal
/Types
$z
Figure 3.10
Definitions-Table Entry For Function f
Type conversions
does not yet support
found
in the
are
implemented
this feature.
module semO)
will
in the
check
to see if a
(half number-convert,
This
converse
module)
is
not acceptable.
is
numconvert (found
in the
will convert either the left tree type or the right tree type of a node. This
is
semO
useful
integer-to-real and
done, since both of these types are represented in exactly the same way.
On
the other
hand, an attempt to return an integer value for a function which has a declared type of
natural will result in an error.
38
Actualist
Actualist
Elementlist
Comma
f (1,2)
Figure 3.11
Tree for Function Call
Variables of simple type
(i.e,
may
be made.
If a variable is
is
AND
it
it
definition,
it
will
As noted
in the section
is
semantic checker
and an entry
is
If a variable is
If the
it.
the
used before
LETDEF
it is
defined by a data
construct.
to
generating
all
functions and data definitions to one buffer and the "main" program which calls these
functions to another buffer. However, this
would be an
39
inefficient use of
memory
space,
since one buffer might run out of space while the other
a proliferation of
eliminate
D.
jump
but one
all
call,
is
is
as noted above.
OPTIMIZATION
There
is
attempt will be
made
PHI
in the
included.
The
folding
first suitable
type of optimization
to
function.
implement
It
constant folding.
is to
which
is
numconvert
this optimization.
would be straightforward
if
This
is
structure in
and
call this
right children
numconvert,
in
call.
However, since
would have
do not
to be inserted in idiv
call
and rdiv
also.
is
jump
jump
definitions
is n,
> 0,
there will be n
one
if
the
unnecessary
jump
first
The
because "jmp"
can be eliminated.
40
all
is
first
other unconditional
jumps and
their labels
The
last
type of optimization
will be a "call
is
"call
is
unnecessary,
and can be eliminated. The 8086 assembly code equivalent of "push" followed by "pop"
should not occur in the present design.
It is
inside a
jump when
that
code contains no
not necessary to implement this type of optimization with the current design,
since unconditional
jumps
it
if
might be
worthwhile to keep track of which functions are called and eliminate code for those which
are not.
message
to the
programmer concerning
41
this
IV.
A.
RESULTS
The implementation described
in
this
this
implementation
full
implementation.
enough
to allow
a prototype,
is
However,
it
the necessary
all
This implementation
is
mature
to a full implementation.
is
lexical
and syntactic
07
include in the front-end and back-end, the authors were originally guided by the traditional
back-end [Ref.
8:p.
in the front-end
in
it
with code
8086 code
generator.
is
fully
may
the basic
congruent to that of the semantic analyzer, with the exception that the real
42
B.
CONCLUSIONS
It is
functional
It is
implement a compiler
for the
PHI compiler
required in the
The
overall design
is
front-end.
It
thesis to drive a
this
flexibility in
to the
PHI programming
PHI
interpreter.
make
Being able
the implementation of a
PHI
in this
and use
it
Modularizing the design also increases portability of the compiler to other machines. To
demonstrate portability, the authors recompiled the front-end and executed
Removing
C run-time
header
from
new
target
it
to the source
on a
program, just
machine.
methodology
is
is
The authors
PHI
compiler.
is
dynamic
43
68000
PHI and
believe
FURTHER RESEARCH
V.
Further research
may
be broken
projects.
down
into
further broken
two major
down
short
into
areas:
two main
adding
On
the other
all
All of these
unimplemented.
Compound
all
checker will not recognize complex types and no code will be generated. The Real type
recognized by the semantic checker, which can discern
natural type should be accomplished; however,
in the
no code
if
is
is
run-time structures. Note also that operators which operate solely on complex types
and reals
One
FILEs
is
In addition,
argument
code generator.
Short-range improvements to the PHI environment
implementation
is
is
just
enough
to
know
that the
mode.
is
system
would be
good
is
running!
mode of PHI,
starting point
44
full
analogous to instrumentation on a
interpreter
may come
as
opposed
in [Ref. l:pp
1-17].
Also, an
environment for PHI. As noted above, the front end of the prototype compiler
adapted for
this
One
to
final short-range
64K
may wish
to write
improvement which
of run-time memory.
When
become
the
viable.
is
be
PHI and
an interpreter in LISP.
is
It
would be worthwhile
may
based, gobbles up
to take
advantage
memory
with abandon.
will
in use
would need
this direction
PHI programming,
a debugger
substantial improvement.
The most
would be a necessary
45
programmer.
LIST OF
1.
REFERENCES
IEEE
2.
3.
Tremblay,
4.
5.
Bellot, P.,
Computer Science,
1985.
6.
Backus, J., "Can Programming Be Liberated from the von Neumann Style? A
Functional Style and its Algebra of Programs," Communications of the ACM, vol.
21, No. 8, August 1978.
7.
8.
Aho, A. V., Sethi, R., Ullman, J. D., Compilers Principles, Techniques, and Tools,
Addison-Wesley Publishing Company, 1986.
9.
Press, 1979.
E., Sorting and Searching, The Art of Programming, Vol.
Addison-Wesley Publishing Company, 1973.
10.
Knuth, D.
11.
12.
S.,
3,
46
APPENDIX A
THE FUNCTIONAL LANGUAGE PHI
(CONCRETE SYNTAX OF O 10/16/86
Grammatical Notation:
mean
Similarly, '[Ci
...
Cn
mean
and
]'
at
most one of
Cn
C n The
.
,/-.*.
notation 'C
means zero or more Cs; 'C + means one or more Cs; 'CD ...' means a list of one or more
Cs separated by Ds. Terminal symbols are quoted when they could be confused with
'
metasymbols.
Grammar:
BLOCKBODY
QUALEXP
LET DEFS
BLOCKBODY
FORMALS = QUALEXP
TYPEEXP
TYPE ID [FORMALS] = TYPEEXP
[ID]
ID
DEF
QUALEXP
EXPRESSION
AUXDEFS
AUXDEF AND...
AUXDEF
[ID]
FORMALS
FORMALS
ID
EXPRESSION
1
FORMALS,
...
V] CONJUNCTION
EXPRESSION
[EXPRESSION
CONJUNCTION
[CONJUNCTION A] NEGATION
47
RELATION
NEGATION
RELATION
RELATOR
[=l*l>l<l<l>lele]
SIMPLEXP
[SIMPLEXEP ADDOP]
ADDOP
TERM
MULOP
FACTOR
II
TERM
A
:
primary
APPLICATION
PRIMARY
APPUCATION
PRIMARY
nT TT mn
APPUCATION
,
[APPUCATION] ACTUAL
ID
DENOTATION
CONDITIONAL
COMPOUND
ACTUAL
ARGBINDING
BLOCK
^ FILE
'
CHAR +
'CHAR
DENOTATION
DIGIT+
'
[.
DIGIT +
FORMALS
ARM
'
|->
ACTUAL
[ELSE EXPRESSION] ENDIF
CONDITIONAL
IF
ARM
COMPOUND
'{'ELEMENTS
ELEMENTS
<
ELEMENTS
[QUALEXP,
ARGBINDING
'['<
OP
BLOCK
...
ELEMENTS)
f(
{
ELSIF
]
'}'
>
\
J
...]
OP
OP QUALEXP
QUALEXP OP
RELATOR
>
']'
ADDOP
48
MULOP
DEFS
DEF AND
TYPEEXP
TYPEDOM
TYPEDOM
TYPETERM + TYPEDOM
TYPETERM
TYPEFAC X TYPETERM
...
->
TYPEPRIMARY
TYPEPRIMARY
ID << TYPEEXP,
TYPEFAC
ID
(TYPEEXP
SESSION
COMMAND
is
>>
considered a
DEF
QUALEXP
1
J
TYPE
BLOCKBODY;
COMMAND+
>
)
RIZIN
PRIMTYPE
TYPEPRIMARY
PRIMTYPE
TYPEEXP
'
49
it is
considered a
APPENDIX B
THE FUNCTIONAL LANGUAGE PHI
(CONCRETE SYNTAX OF O 03/03/87
Grammatical Notation:
Ci
mean
Cn
Cn
Ci
Similarly, '[Cl
...
C n and
]'
LC n
i,...,
C n The
.
i/-.*!
'
notation 'C
means zero or more Cs; 'C + means one or more Cs; 'CD
means a list of one or more
Cs separated by Ds. Terminal symbols are quoted when they could be confused with
.'
'
metasymbols.
Grammar:
BLOCKBODY
QUALEXP
LET DEFS
QUALEXP
[REC]
...
EXPRESSION
I QUALEXP
WHERE AUXDEFS
AUXDEFS
AUXDEF AND...
AUXDEF
[ID]
FORMALS
TYPEEXP (BE
TYPE ID [FORMALS]
[ID,
DEF
BLOCKBODY
FORMALS
EXPRESSION
(ID
I
FOR MALS,
...
V] CONJUNCTION
EXPRESSION
[EXPRESSION
CONJUNCTION
[CONJUNCTION A] NEGATION
50
IS
}]
[ID]
TYPEEXP
FORMALS
QUALEXP
""
RELATION
NEGATION
RELATION
RELATOR
(=|*l>l<l<l>
SIMPLEXP
[SIMPLEXEP ADDOP]
ADDOP
TERM
MULOP
(X
FACTOR
[:] PRIMARY
PRIMARY
J
I
T)
X}
APPLICATION
PRIMARY
APPUCATION
APPLICATION
TERM
[APPUCATION] ACTUAL
TYPEEXP,
DENOTATION
CONDITIONAL
ID [
...
COMPOUND
ACTUAL
ARGBINDING
BLOCK
{
FILE
'CHAR
DIGIT+
DENOTATION
STREAM
CHAR +
}'
'
[.
DIGIT+
NIL
^FORMALS
ARM ELSIF
ACTUAL
|->
CONDITIONAL
IF
ARM
...
ELEMENTS
(ELEMENTS
']'
'['
COMPOUND
'{'ELEMENTS
<
ELEMENTS
ELEMENTS
[EXPRESSION,
ARGBINDING
'['
'}'
>
...]
rop
<
I
OP
OP ACTUAL
ACTUAL OP
RELATOR
>
']'
ADDOP
51
MULOP
SUB
BLOCK
DEFS
DEF AND
TYPEEXP
TYPEDOM
TYPEDOM
TYPETERM + TYPEDOM
TYPETERM
TYPEFAC X TYPETERM
...
-> TYPEEXP
I TYPEPRIMARY
f
TYPEPRIMARY
<
I
PRIMTYPE
COMMAND
"
TYPEEXP,
PRIMTYPE
ID
ACTUAL
...
R
is
considered a
LET DEF
QUALEXP
>
TYPE
BLOCKBODY;
COMMAND+
(TYPEEXP)
TYPEPRIMARY*
TYPEFAC
'
52
it is
considered a
APPENDIX C
ASCII REPRESENTATION OF
Reference
ASCII
==
<
LESS
<
<=
>
>=
<>
IN
NOTIN
-s-
->
A
|->
Ai
A!i
T*
T@
R
Z
$R
$N
$B
$1
$Z
53
-O
APPENDIX D
THE FUNCTIONAL LANGUAGE
RIGHT-RECURSIVE GRAMMAR
(
Note:
(...)
(-)
means one
more occurrences
or
BLOCK
::=
BLOCKBODY
::=
DEFS
::=
DEF
::= (ID)
ID
FORMALS a QUALEXP
TYPEEXP
TYPE
ID
(FORMALS) a TYPEEXP
1
QUALEXP
::=
AUXDEFS
::=
AUXDEF
::= (ID)
FORMALS
::=
FORMALS a EXPRESSION
FORMALS (NORMALS)*
ID
EXPRESSION
::=
CONJUNCTION
CONJUNCTION
::=
NEGATION(
NEGATION
::= (-)
RELATION
::=
CONJUNCTION)
NEGATION)
RELATION
54
RELATOR
;;=
=
*
LESS
GREATER
<
>
e
SIMPLEXP
::=
TERM(ADE
ADDOP
::=
TERM
:=
MULOP
+ PRIMARY
FACTOR
PRIMARY
PRIMARY
-
PRIMARY
APPLICATION
(ACTUAL)
APPLICATION
ACTUAL
(!
APPLICATION)
ID
DENOTATION
CONDITIONAL
COMPOUND
ARGBINDING
BLOCK
FILE '(CHAR)
DENOTATION
:=
'(CHAR)
(DiGrr) +
(DiGrr) +
'
:=
Note
Note
CHAR
can = ASCII 32
...
ASCII 126
CHAR
can = ASCII 32
...
ASCII 126
FORMALS
ID
(DIGIT) +
|-
ACTUAL
ALF (ALFNUM)*
Note
ALF can =
ALFNUM
ARM
...
a...z,
a...z,
A...Z
A...Z, 0...9, _
CONDITIONAL
IF
ARM
(ELSIF
can =
55
COMPOUND
::=
(ELEMENTS)
(ELEMENTS)
)
1
}
1
ELEMENTS
::=
QUALEXP(,QUALEXP)*
ARGBINDING
::=
[
[
[
op
OP QUALEXP
QUALEXP OP
]
]
OP
RELATOR
ADDOP
MULOP
t
TYPEEXP
::=
TYPEDOM
TYPEDOM
::=
TYPETERM
(+
TYPETERM
::=
TYPEFAC
TYPEFAC
::=
TYPEPRIMARY
TYPEPRIMARY
ID
TYPEPRIMARY
::=
TYPEDOM)*
TYPETERM)*
TYPEFAC)*
TYPEEXP
(,TYPEEXP)*
(TYPEEXP)
ID
PRIMTYPE
PRIMTYPE
::=K
7L
N
IB
TYPE
::=
(COMMAND)"*"
COMMAND
::=
(DEF
QUALEXP)
56
APPENDIX E
FILES
/A****************************************************************
*
THIS FILE CONTAINS HEADER FILES REQUIRED BY THE ROCK COMPILER
***********************************************************************/
*
/***********************************************************************
*
PUBLIC DOMAIN SOFTWARE
scanner definitions
Name
scanner h
File
* Authors
Ma j E.J. COLE / Capt J.E. CONNELL
* Started
10/10/86
* Archived
12/11/86
* Modified
01/10/87 - Update keywords
JC
*********** ************* ************************************************
* This file contains def initions used by the scanner, parser,
*
and
*
* error rec overy routine s
*********** ************* r****************** *****************************
* Modified
01/10/87 Corrections to comply with latest definitions *
*
*
of the 1 anguage and update keywords. JC
*********** ************************************************************ /
*
*
#ifndef
EOF
define EOF_
define FALSE
-2
tdefine TRUE
1
#define BYTENUM
2
define MAX_KEYWORDS 17
define NAMESIZE
18
define MAXLINE
80
107
define TABLESIZE
/*
0-17
'
/*
/* General Token
Types */
Listing of symbols can be found at end of list
define EOLN_
define LEQ_
define NEQ_
3
4
define GEQ_
define
define
define
define
define
define
define
define
EQ_
ADD_
SUB_
MULT_
IDIV_
RDIV
SEMI_
SUBSCRIPT
10
11
12
13
14
15
16
57
*/
'
*/
*/
*/
'/
define COMMA_
17
define LTPAREN_
define RTPAREN_
EQUIV_
ORLOG_
ANDLOG_
NEGLOG_
COLON_
CAT_
LTBRAKET_
RTBRAKET_
LTSQUIG_
RTSQUIG_
EMPT_LIT_
RTARROW_
LINERTARROW_
LITERAL_
IDENTIFIER_
CONSTANT_
REAL_
INTEGER_
NATURAL_
BOOLEAN_
TRIVIAL_
CHAR_
STRING_
STAR_
POS_
NEG_
KW_
#define
#define
#define
#define
define
define
define
#define
#define
#define
define
define
define
define
define
define
define
define
define
define
define
define
define
define
define
define
define
error,
/* eof,
,,
(,
18
),
==,
19
20
21
22
23
24
25
26
2 7
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/* KEYWORD
4 6
\//
A,
~,
:,
A
,
[,
],
{,
<,
\,
>=,
",
>,
=,
->,
+,
define
define
define
define
define
define
define
define
define
define
define
define
define
define
define
define
define
define
AND_
BEGIN_
ELSE_
ELSIF_
END_
ENDIF_
FILE_
GREATER
IF_
IN
LESS_
LET_
NOTIN_
READ_
THEN_
TYPE_
WHERE_
WRITE
Keywords */
1
2
3
4
6
7
10
11
12
13
14
15
16
17
58
-,
*,
%,
literal,
string, @,
l->,
/,
#define
struct
CALLOC(y,x)
NStruct
((x*)
calloc
(y,
sizeof
(x)
/*
/*
char
struct NStruct
name[NAMESIZE]
*link;
};
NameRec;
typedef struct NStruct
char
*cailoc();
extern
char
*inaloc(| ;
extern
#endif
59
*/
*/
'**********************************************************************
PUBLIC DOMAIN SOFTWARE
parser definitions
Name
parser .h
File
Maj E.J. COLE / Capt J.E. CONNELL
Authors
Started
10/20/86
Archived
12/11/86
01/12/87 - update NodeStruct definition JC
Modified
A******************************************************
*
* This file contains definitions used by the parser
a********************************************************************
* Modified
01/10/87 - update NodeStruct to hold the type of the *
*
*
node
a*********************************************************************/
:
#ifndef
LETDEF
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
LETDEF
DEFAND
KINDEF
FUN ID
FUNDEF
DATADEF
TDEFID
TDEFFUN
DATAAUXDEF
FUNAUXDEF
AUXAND
ACTUALLIST
SEQUENCE
FORMAL
ELLIST
EMPTYCOMPOUND
EMPTYSEQUENCE
ARGBINDOP
ARGLEADOP
ARGTRAILOP
TYPEPLUS
TYPETIMES
TYPEEXPLIST
#def ine
#def ine
#def ine
#def ine
LEFT
RIGHT
ERROR_
BUFSIZE
typedef
int NodeType;
#define
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
88
89
90
91
92
93
94
95
1
2
-1
512
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
struct NodeStruct
name;
NodeType
long
index;
type;
int
*/
operator node in tree
*/
int defined as the operator
pointer to constant literal, id */
*/
the type of the node
*/
line no in source text where
*/
token can be found
*/
Label used by functions to
*/
refer to code
*/
Addr of the var or function
value in the run time's virtual*/
*/
/* memory
int
In;
char
label
long
addr;
[8];
60
struct
struct
;;
)
NodeStruct
NodeStruct
/* left ptr
/* right ptr
*lptr;
*rptr;
};
typedef
NodeRec
char
*CreateNode
*NodeName
(
num_errors;
argbind;
extern int
extern int
extern
extern
extern
extern
*nodal;
char *calloc()
char *malloc()
ErrorHandler
WriteErrors ()
NodeRec *CreateNode
char
*NodeName();
MakeNewRoot
IsFormalO;
IBall ()
EatEm
long ByPass();
(
#include <scanner.h>
include <errors.h>
#endif
61
*/
*/
*/
*/
'
'
**********************************************************************
PUBLIC DOMAIN SOFTWARE
error file definitions
Name
erors h
File
* Authors
COLE / Capt J.E.
J.E
Maj
E
Mai E.J.
* Started
01/20/87
* Archived
04/07/87
* Modified
***********************************************************************
*
* This file contains definitions used by the error recovery routines.
***********************************************************************
*
* Modified
********************************************************************** /
*
*
ifndef
MAXERRORS
#define MAXERRORS
10
#def ine
#def ine
#def ine
#def ine
#def ine
ERRO
ERR1
ERR2
ERR3
ERR4
ERR5
ERR6
ERR7
ERR8
define
ERR9
#def ine
#def ine
#def ine
define
'
'
2
3
4
5
6
7
'
25
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
#def ine
ERR_a
10
#define
ERR_b
11
12
define
define
define
define
ERR_c
ERR_d
ERR_e
ERR_f
ERR_g
ERR_h
ERR_i
define
define
ERR_j
ERR_k
19
20
define
ERR_1
21
define
ERR_m
22
define
define
define
ERR_n
ERR_o
ERR_p
23
24
#def ine
define
#def ine
13
14
15
16
17
18
define
ERR q
26
define
ERR
27
/*
r
/*
/*
62
*/
*/
*/
definition
invalid QualExp
invalid TypeExp
bad or missing formals
missing or misplaced
missing ID after 'TYPE'
bad definition after AND
missing or bad AuxDef after
WHERE
missing or misplaced
error in processing
successive Actuals
missing literal after keyword
FILE"
missing or invalid exp after
keyword ==>
IF statement w/o ENDIF
error in formals preceding ->
missing or invalid QualExp
following comma op
error in ArgBinding - check
QualExp or
off in OZONE-unimplemented
feature
*/
*/
'
*/
*V
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
#def ine
31
/*
/*
/*
/*
32
/*
32,
/*
ERR_ s
ERR_ _t
ERR_ u
ERR V
ERR_ w
ERR_ X
ERR_ y
28
ERR
35
29
30
/*
/*
34
/* NOTE:
through
*/
define
#def ine
#def ine
define
define
define
define
define
define
define
define
ERR_ aa
ERR_ hb
ERR_ cc
ERR_ _dd
ERR_ ee
ERR_ "ff
ERR_ .99
ERR_ _hh
ERR_ ii
ERR_ _jj
ERR_ _kk
ERR_ ]ll
ERR_ mm
~-
/*
/*
35
35
35
/*
/*
35
35
/*
/*
/*
/*
/*
/*
/*
/*
35
35
35
35
35
35
35
35
/*
endif
63
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
/************* *********************************************************
*
PUBLIC DOMAIN SOFTWARE
*
*
*
Semantic Definitions Header File
Name
*
Semcheck.h
File
* Authors
*
Maj E.J. COLE / Capt J.E. CONNELL
* Started
01/01/87
*
* Archived
04/10/87
*
* Modified
"FILENAME" eliminated EC
04/13/87
************** *********************************************************
* This file co ntains the header file and definitions for the semantic *
*
* checker and code generator of the PHI compiler
************** *********************************************************
* Modified
*
04/13/87
"FILENAME" eliminated; output path now
*
depends on user's input EC
**********************************************************************
*
<scanner.h>
<parser.h>
<errors.h>
<stdio.h>
NOTFOUND
UNTYPED
BOOLEAN 1
BOL_BYTES 2
REAL 2
REAL_BYTES 4
INTEGER 3
INT_BYTES 2
NATURAL 4
NAT BYTES 2
define ERROR
define MAXADDR 64000
/* Max
/* Max
of types in one scope
/* Max size of code buffer
/* Starting address for varspace
/* Pointer to the last initial
define
CNTRL_Z
2 6
define
ENDSTRING
define NUM_BASE 4 8
define STACKSIZE 10000
define SIZEBUFFER 30000
/*
/*
/*
/*
/*
/*
define
define
define
define
typetable entry
Control Z ascii
String terminator
Lowest ascii number
Increase in stack size
Size of output buffer
/* Flag to indicate
/* error follows
ifndef NULL
define NULL
endif
64
*/
ADD 1
SUB 2
DIVIDE
MULT 4
*/
semantic
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
Type Definitions
*
*
/* Arithmetic operations
/* Generic flag type
/* Types found in language
PHITYPE;
*/
*/
*/
/*
*/
*/
/*
Typetable entries
*/
/* Formal stack
/* formname, formtype
/* Link for list
type;
struct formnode "link;
fnode;
int name,
*/
*/
*/
/it********************** Vartable
typedef struct varnode
Definitions **********************/
/*
/*
/*
/*
/*
/*
/*
int type,
form,
def;
nodal nptr;
fnode *fptr;
*/
*/
*/
*/
*/
*/
*/
/it*********************** Deftable
typedef struct defnode
int type;
nodal nptr;
fnode *fptr;
struct defnode *link;
*defptr;
Definitions **********************/
/* varname, vartype
/* ptr to defining node
/* ptr to formals
/* Link
for list
*/
*/
*/
*/
*/
name
*/
/* Ptr to buffer where
/* name is called
int buffptr;
/* Link
};
65
*/
*/
/A*****************************************************************
*
PUBLIC DOMAIN SOFTWARE
*
User Header
Name
*
user.h
File
* Authors
*
Maj E.J. COLE / Capt J.E. CONNELL
*
* Started
04/01/87
*
* Archived
04/10/87
* Modified
***********************************************************************
*
* This file is the header file for the user interface module
*
*
(user.c)
a**********************************************************************
*
* Modified
A********************************************************************/
:
#define NOTFOUND
#define BSIZE 1000
#aefine BLOCKSIZE 50
tdefine BACKSPACE
#define EOLN 13
#define ESCAPE 27
#define
#define
#define
#define
#define
fdefine
tdefine
/* ASCII Equivilents
*/
/* Messages to observer
GETPROGRAM "Program to Compile -> "
HEADER1 "ROCK COMPILER"
HEADER2 "Press Escape Key to Exit Compiler"
FILE1_ERR0R "File not Found"
FILE2_ERR0R "Press ESCAPE to exit, any other key to continue"
WAIT "Compiling: Please Wait"
PAUSE "PRESS ANY KEY TO CONTINUE"
/* Textfile of errors
66
*/
*/
*/
*/
/*
/*
file name
*/
*/
APPENDIX F
ROCK COMPILER
MAIN MODULE
**********************************************************************
* PUBLIC DOMAIN SOFTWARE
/
R Initial
Semcheck
Main
Algorithm
This contains the main procedure for the phi compiler, in addition to the initialization procedure & the main semantic checking
procedure.
The main module inits the program, sets up the screen
by calling "user ()", & decides whether an error routine needs
It also closes out the input file.
to be called.
The "semcheck procedure is designed to be called by any function
with a ptr to a parse tree node as an argument.
It will then
determine which sub-module is necessary to check the node.
"R_Initial" presently has the function of initializing the type
table.
*
*
*
*
*
*
*
*
***********************************************************************
* Modified
*
04/13/87 Output files written to vdisk, "d:"
EC
a************************************************************/
:
#inciude <semcheck.h>
extern void c_startup
c_ending
user
user_err
p_close
set_page
mov_cursor
(
unsigned _stack =
STACKSIZE;
67
; ;
/*
strcpy
types
strcpy
types
strcpy
types
strcpy
types
strcpy
types
*/
[];
/* Set
up type table
*/
(ptr->name)
(ADD_)
(SUB_)
(MULT_)
(RDIV_)
(IDIV_)
(COLON_)
(CAT_)
(),
type
arithop (ptr)
break;
case (POS_)
case (NEG_)
type = tprimary (ptr)
break;
case (ORLOG_)
type = tor (ptr);
break;
type = tand (ptr)
case (ANDLOG_)
break;
case (NEGLOG_)
type = tnegation (ptr)
break;
case (KINDEF)
tkindef (ptr)
break;
case (RTARROW_)
type = trtarrow (ptr);
break;
case (LETDEF)
tletdef (ptr)
break;
case (KW_ + WHER_)
type = twhere (ptr)
break;
case (AUXAND)
tauxand (ptr)
break;
case (DATAAUXDEF)
tdatauxdef (ptr)
break;
case (FUNAUXDEF)
type = tfunauxdef (ptr)
break;
type = tfunid (ptr);
case (FUNID)
break;
type = tactuals (ptr)
case (ACTUALLIST)
break;
case (COMMA
:
68
tactuals
();
into cases
*/
; ; ;
; ;
telist (ptr);
(ELLIST)
break;
type = ttypetimes (ptr);
case (TYPETIMES)
break;
case (EQ_)
case (LEQ_)
case (NEQ_)
case (GEQJ
case (KW_ + GREATER_)
case (KW_ + LESS_)
IN_)
case (KW_
type = tcomp (ptr)
case (KW_ + NOTIN_)
break;
type = tif (ptr)
case (KW_ + IF_)
break;
type = telse (ptr)
case (KW_ + ELSE_)
break;
type = tthen (ptr);
case (KW_ + THEN_)
break;
type = telseif (ptr)
case (KW_ + ELSIF_)
break;
type = tid (ptr);
case (IDENTIFIER_)
break;
type = tconstant (ptr)
case (CONSTANT_)
break;
case (REAL_)
type = REAL;
break
type == INTEGER;
case (INTEGER_)
break;
case (BOOLEAN_)
type
break;
case (NATURAL_)
type = NATURAL;
break;
case
default
/* Unimplemented feature
/* so sandbag programmer
found,
*/
*/
break;
}
return
(type)
c_startup
r initial
user
if
();
/*
/* User
parser
(root
/*
()
display
if
err_f ound)
ending
(
interface
set_page (2
cursoff
semcheck (root);
/*
/*
/*
/*
/*
/*
69
*/
*/
*/
*/
forkl
forkl
;; ;
;;
*/
*/
*/
*/
if
(err_found
set_page
curson
user_err
(
0)
root
p_close
/*
();
70
*/
*/
*/
APPENDIX G
ROCK COMPILER
SCANNER
/***********************************************************************
*
PUBLIC DOMAIN SOFTWARE
*
* Name
Scanner
*
* File
Scan2
* Authors
J.E.
CONNELL
*
COLE
Capt
Maj E.J.
/
* Started
10/10/86
*
* Archived
12/11/86
* Modified
04/23/87 tokens no longer output to intermediate file. *
************************************************************************
*
* This file contains the execution modules for the scanner:
*
IsKeyWordO
GetTokenO,
*
GetToken is called from FillBufferO and returns an
*
integer code to uniquely identify the token.
*
*
IsKeyWordO checks each identifier to insure it's not
*
*
a PHI Keyword.
************************************************************************
* Modified
01/10/87 Corrections to comply with latest definitions *
x
*
of the language. JC
*
*
01/10/87 GetTokenO returns CONSTANT_ vice REAL_ or
*
*
INTEGER_. JC
*
*
01/21/87 Error Recovery added and files combined. JC
*
*
03/10/87 Corrections to partially comply with latest
*
*
definitions of the language. JC
*
04/23/87 tokens no longer output to intermediate file *
*
*
GetToken called directly by the Parser now.
a*****************************************************/
Algorithm
include
include
include
include
<scanner.h>
<stdio.h>
<errors.h>
<ctype.h>
extern
FILE *infile,
*errorfile;
/*
working files
*/
/**********************************************************************/
int
GetToken (token)
char *token;
/* Calls
*
*
*
fgetc (inf ile) for the next char from the input file & builds
*
the token a char at a time.
Returns an internal integer value
*/
representing the type of token found
/*
line num =
1;
71
lookahead is
/* is current
line
*/
flag, line_num
of user prog */
; ;
;;
; ; ;; ; ;
; ;; ;
;
;
'
/* ch holds last
/* input prog
int
k;
i,
extern ErrorHandler
character from
while (TRUE)
{
/*
= 1;
/* will
if
(!
lookahead)
while
{
isspace
if (ch ==
{
+-
(ch)
/*
'\n'
+ line_num;
return (EOLN_)
/* end if
'
\n
if
(ch == EOF
switch
case
case
case
case
case
case
case
case
case
case
case
case
case
case
case
case
case
return (EOF
);
(ch)
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
return
(ADD_)
(MULT_
(IDIV_)
(SEMI_)
(SUBSCRIPT^)
(COMMA_)
(LTPAREN_)
(RTPAREN_)
(NEGLOG_)
(COLON_)
(CAT_)
(STAR_)
(LTBRAKET_);
(RTBRAKET_)
(LTSQUIG_)
(RTSQUIGJ
== '>')
(ch = fgetc (inf ile)
return (RTARROW_)
else if (ch == '-'
while((ch = fgetc (inf ile)
if
/*
process comment
!=
'\n'
&S
ch
!=
EOF)
/* do nothing
if (ch ==
'\n')
++line_num;
return (EOLN_)
else return (EOF_)
else
lookahead = TRUE;
return (SUB_)
case <
if((ch = fgetc(infile)
return (LEQ_)
else if(ch == >)
return (NEQ_)
else lookahead = TRUE;
'
'
== '=')
72
*/
*/
*/
*/
; ;; ;
;; ;
;
)
; ;
return (ST_SEQUENCE_)
case
'
>
'
(ch = fgetc(infile)
return (GEQ_)
else lookahead = TRUE;
i'f
case '='
if((ch = fgetc (inf ile)
return (EQUIV_)
else lookahead = TRUE;
return (EQ
)
'
==
==
W)
.)
case /
if((ch = fgetc (inf ile)
return (ANDLOG_)
else lookahead = TRUE;
return (RDIV
'
case \ \
== '/')
if((ch = fgetc (inf ile)
return (ORLOG_)
else
lookahead = TRUE;
ErrorHandler (line_num, ERR2,NULL)
return (ORLOG
/*
case
== '-')
if((ch = fgetc (inf ile)
== >')
if((ch = fgetc (infile)
return (LINERTARROW_)
lookahead = TRUE;
ErrorHandler line_num, ERRO, ch)
return (LINERTARROW );
/* ch is either
or '-'
/* figured that's what he
'
'
'
'
case
'
'
'
wanted
*/
*/
$
'
'
'n')
return (NATURAL_)
else if
(ch == 'Z'
(ch == 'z'
II
return (INTEGER_)
else if
(ch == 'B') II (ch == b")
return (BOOLEAN_)
else if (ch == 1
return (TRIVIALJ
else lookahead = TRUE;
ErrorHandler (line_num, ERR3, NULL
return (INTEGERJ
(
'
'
if
{
isalpha
(ch)
do
/* end do
/* end the string
ch
73
*/
-/
if
it's a
-/
*/
);
)
;
;
)
;; ; ;
>=
k = IsKeyWordftoken +1))
return (KW_ + k)
if((
0)
*/
*/
*/
return (IDENTIFIER_)
I
if
{
(isdigit (ch)
if (ch == '0'
while (ch=fgetc(inf ile)
{
==
'0')
/* do nothing,
if
isdigit (ch)
token[i++] =
zeros
eat
'
'
/* end if
leading
/* end
if
{
(ch ==
token [i++]
'
while is
digit
'
= ch;
isdigit (ch)
token[i] = '\0';
Error Handler (line_num, ERR 4,
token+1)
token [i + 1] = token [i];
token [i] = 0;
return (CONSTANT_)
else
do
token [i++] = ch;
ch = fgetc inf ile)
while (isdigit (ch)
(
/* end do
/* end if ch ==
/* end the string
'
'\0';
token [i
lookahead = TRUE;
return (CONSTANT^)
/* end if isdigit
/* process LITERALS
if
(
(ch ==
token
while
{
'V
'
= ch;
(ch= fgetc (inf ile) !=EOF) SS
(ch!='\n') && (i< MAXLINE)
token [i++] = ch;
if (ch == '\")
[
i++
if
{
(ch =
!=
>\")
lookahead = TRUE;
token [i] = '\0';
(strlen (token) >
return (LITERAL_)
return (EMPT LIT
if
3)
/* end if !=
/* end while
/* end the string
'
token[i]='\0';
ErrorHandler line_num, ERR 5, token+1)
return (LITERAL_)
(
/" Default
continue;
74
he wanted
*/
/a***********************
Scanner Utilities
it*********************/
int
IsKeyWord(token)
char *token;
*
*
*/
int
i;
register int
lo
=0,
hi
mid;
/* list of PHI keywords
/* alphabetical order!!
char
KEEP in */
*/
*keywords[] =
[MAXLINE] ; static
char
"AND", "BEGIN", "ELSE" "ELSIF" "END" "ENDIF", "FILE", "GREATER", "IF",
"IN", "LESS", "LET", "NOTIN", "READ", "THEN", "TYPE", "WHERE", "WRITE"
,
strcpy
for
(i
s,
token)
0;
if('a'
hi =
whiledo
{
/*
'z'l
*/
<= hi)
)) <0)
hi =
mid;
else if(i>0)
lo = ++mid;
else
return(mid);
/* found a keyword
/* end while
/* didn't find a keyword
/* end IsKeyWord
return(-i);
}
75
*/
*/
*/
*/
APPENDIX H
ROCK COMPILER
PARSER
/***********************************************************************
PUBLIC DOMAIN SOFTWARE
* Name
parser pt I
* File
parserl
* Authors
Maj E.J. COLE / Capt J.E. CONNELL
* Started
10/20/86
* Archived
12/11/86
* Modified
04/23/87 No longer set up to work, with file of tokens. *
************ ************************************************************
*
* This file contains the following modules for the PHI parser:
*
BlockBo dyC
AuxExp
)
LetDefs
AuxDef s
()
(
Defs ()
AuxAnd
DefAndO
Formals
QualExp ()
Expression
Algorithm
'
************************************************************************
Modified
^include <stdio.h>
#include <parser.h>
/*
int
rtbrket = FALSE,
int
line no
argbind
/* PHI
= FALSE;
/*
/*
/*
/*
/*
1;
76
*/
*/
*/
global var, current line no
*/
of program
tokenbuff holds tokens provided*/
- ptr is a ptr to*/
by GetToken
*/
next token in tokenbuffer -
; ;
because buffer
*/
*/
long
tokenbuff [BUFSIZE+1]
FILE
*poutfile,
*ptr
&
tokenbuff BUFSIZE
(
/*
*errorfile;
working files
*/
/********************************************************************/
nodal
Parser ()
{
"root = NULL;
void p_close(), mov_cursor
NodeRec
extern
num_errors
/*
/* init number
= 0;
if
!ByPass (EOF_)
/* rewrite
jof errors
*/
*/
*/
BlockBody (Sroot
*/
*/
*/
*/
/*
mov_cursor (20, 0) ;
print f "WARNING ...additional text found
at completion of your program (
#ifdef
if
DEBUG
/* write parser's output
*/
*/
/* to data file
/* case it's needed for debugging */
/* need that carrage return
*/
!= NULL)
(root
PostOrder root
fprintf (poutfile, "\n")
f close (pout file)
#endif
(
fclose(infile)
p_close
(num_errors
return (NULL)
else
return (root)
if
>
0)
/*
end main
*/
/A*******************************************************************/
void
PostOrder root)
NodeRec
*root;
(
/*
/*
Does a post order walk of the tree with (root) as its head.
Just prints out the node name to the screen now
77
*/
*/
static
if
ir.t
;)
Oj
(root
!= NULL)
PostOrder (root->lptr) ;
PostOrder (root ->rptr)
switch (root->name)
case IDENTIFIER
case CONSTANT_
case LITERAL_
fprintf (pout file, "%d ",root ->name)
fprintf (poutfiie, "%ld
", root->index)
break;
default
fprintf (poutfiie, "%d
",root ->name)
:
LITERAL
/* end switch
if
++i
7)==0))
/A***********************************************************/
BlockBody (root)
NodeRec
**root;
<BLOCKBODY>
<QUALEXP>
*/
*/
<LETDEFS>
flag;
iff ((flag = LetDefs (root)
return (TRUE)
== TRUE))
/* looking for LETDEFS; BL0CK30DY
/* look for plain ol' QUALIX?
*/
*/
return flag)
(
/A*************************************************************/
mt
/* root is a ptr to tree/subtree
/* currently working with
LetDefs (root)
NodeRec
**root;
<LETDEFS>
/*
let <DEFS>
<BLOCKBODY>
tifdef DEBUG
printf(" ietdefs entered\n");
#endif
scanf("%*c"
/*
/*
/*
/*
/*
report it
(long)SEMI_)
if (!ByPass (SEMI_)
&
try to continue
(long) SEMI_)
ByPass (SEMI_)
== TRUE)
if (BlockBody (& (*root) ->rptr)
return (TRUE)
ErrorHandler (line no, ERR a, NULL);
(
78
/* found everything
/* report it, no fix
*/
*/
return (ERROR
; ;
, ;;
/*
#ifdef DEBUG
printf!" letdefs exited\n")
#endif
/
*/
*/
scanf("%*c")
/* default - no LET at
/* end LetDefs
return (FALSE)
beginning
/A*********************************************************************/
int
Def s (root)
NodeRec
'root;
/* <DEFS>
/*
/*
*/
*/
NodeRec
long
"temp;
flag;
id ptr;
extern
long *ptr;
int
if (ByPass (EQUIV_)
TRUE)
!=
/*
/*
/*
/*
/
/*
looking for ID ==
found '==' It's a DATADEr
attach temp ptr to root
now need QualExp
note, try & fix
else
if (ByPass (COLON_)
*root = CreateNode (KINDEF)
(root) ->lptr = temp;
if (TypeExp(& (*root) ->rptr)
!=
TRUE)
else
f
/*
/*
/*
!=TRUE)
/* note
(long)EQUIV_)
if
ByPass (EQUIV_)
else if
!=TRUE)
79
*/
*/
))
;;
)
;
;; ; ;
, ;
fix
&
goto CHECK;
/*
'== or
*/
/******
*/
*/
!= FALSE))
else if (((flag = Formals root
if (flag==ERROR_)
ErrorHandler line_no, ERR_e,
(long) EQUIV_)
if (ByPass(EQUIV_)
MakeNewRoot root DATADEF, LEFT)
if (QualExp(S (*root) ->rptr) !=TRUE)
(
/*
****** */
found something
/* note,
try
fix
/* looking for ==
/* found ==, so fix tree
/* need QualExp on rt
/* note, try S fix
}else
/*****
nothing so far
/*
/*
if (ByPass (EQUIV_)
*/
*/
*****/
*/
*/
==
/* not
yet
/* note it, try to
'
'
fix
(long)
EQUIVJ
if
(TypeExptS
(*root) ->rptr)
!=
TRUE)
*/
/*
*/
*/
>
else
ErrorHandler (line_no, ERR_g,
(long)KW_+AND_)
goto CHECK;
fix
return flag)
(
80
for
*/
*/
*/
)
;
/*
CHECK:
/* check
*/
*/
return (TRUE)
}
notea,
*/
*/
*/
/*******************************************************************/
void
DefAnd(root)
NodeRec
/*
/*
/*
**root;
:= and <DEFS>
<DEFAND>
Where " and <DEFS> " need not be present.
This function assumes root is not NULL upon entry
:
Note:
*/
*/
*/
*/
*/
if (ByPass (KW_
{
AND_)
/*
*/
!= TRUE)
*/
-/
*/
/a**********************************************************/
int
/* root is a ptr to tree/subtree
/* currently working with
QualExp root
NodeRec
**root;
(
/*
/*
*/
*/
*/
*/
flag;
int
#ifdef DEBUG
print f(" qualexp entered\n")
#endif
scanf "%*c")
(
== ERROR_)
EatEm(KW_+END_)
if (ByPass (KW_+ WHERE_)
MakeNewRoot (root, (KW_+WHERE_)
AuxExp(& (*root) ->lptr)
(
RIGHT)
#ifdef DEBUG
printfC qualexp exited
scanf ("%*c")
fendif
%d\n",
f lag)
*/
/*
*/
/*
*/
*/
*/
*/
*/
*/
return flag)
(
/* end
/************************************************************/
int
AuxExp(root)
NodeRec
/*
"root;
81
*/
*/
*/
; ;
, ;
);
);
'
flag;
int
if
AuxExp
(S
WHERE_)
(*root) ->lptr)
RIGHT)
return flag)
(
*/
*/
/*
/*
*/
*/
/* default - return
/* first AuxDefs
/* end AuxExp
*/
*/
result of
*/
*/
*/
/*****************************************************************/
int
AuxDefs root
NodeRec
/*
/*
'root
/*
/*
*/
*/
*/
*/
NodeRec
int
long
*temp;
flag;
ptr;
holding */
temp = CreateNode(IDENTIFIER_)
temp ->index = ptr;
/*
if (ByPass (EQUIV_)
/*
looking for ID ==
"root = CreateNode(DATAAUXDEF)
(root) ->lptr = temp;
if (Expression (& (*root) ->rptr)
Error Handler (line_no, ERR_c,
(long) KW_+WHERE_)
)
TRUE)
*/
/* not
else
'root = CreateNode(FUNAUXDEF)
(root) ->lptr = CreateNode (FUNID)
(root) ->lptr->lptr = temp;
if (Formals (& (*root) ->lptr->rptr)
!= TRUE)
/* note,
try to fix
ByPass (EQUIV_)
ErrorHandler (line_no, ERR_f
(long)KW_+WHERE_)
else
if (Expression (S
*root ->rptr)
(
!= TRUE)
/ end else
not
'
==
goto CHECK;
82
*/
*/
*/
*/
*/
ID FORMALS */
if
*/
******
;)
; ;;
; ;
***********
!= FALSE))
if(((flag =' Formals (root)
if (flag==ERROR_)
ErrorHandler (line_no, ERR_e,
(long)EQUIVJ
if (3yPass(EQUIV_)
MakeNewRoot (root DATAAUXDEF, LEFT)
if (Expression (& ('root) ->rptr)
)
found something
/* note,
fix
looking for ==
found ==, so fix tree
/* need Exp on rt
/*
/*
try
!= TRUE)
goto CHECK;
for
return flag)
(
/* default
CHECK:
AuxAnd (root)
/* any errors have been noted,
/* so press on
/* end AuxDefs
return (TRUE)
*/
*/
*/
a*******************************************************************/
void
AuxAnd (root!
NodeRec
root;
/*
/*
/*
{
if (ByPass (KW_+AND_)
if
(AuxDefs
/*
(&
/* note it,
try
&
fix
(long)KW_+WHERE_)
/* end ByPass AND
/*
end AuxAnd
/a*********************************************************************/
int
/* root is a ptr to tree/subtree
/* currently working with
Formals (root)
NodeRec
**root;
<FORMALS>
/*
= <ID>
'
<FORMALS>
NodeRec
*temp,
long
ptr;
if
{
((ptr
*rcot
=
=
(*root)
*workingroot
ByPass (IDENTIFIER^)
CreateNode( IDENTIFIER^
->index = ptr;
/*
return (TRUE)
83
);
; ;
; ;
/* end if ByPass
if (ByPass (LTPARENJ
{
workingroot
/*
recursive search
if (ByPass
')'
*/
fix
*/
'('
*/
*/
*/
*/
for
/*
/*
/*
/*
found ',
attach it to rt side */
*/
recursive search
*/
need FORMALS following ','
*/
note it, try & fix
/*
(RTPARENJ
&
FORMALS
/*
',
*/
'
'
/* end
'('
/* use
/* have
checking for
/*
(*root);
/*
*/
ID
looking for
')
'
already found
</
*/
/*
*/
FORMALS
/* compact the tree - only one ID */
(
'
if(*root == workingroot)
"root = (*root) ->lptr;
free (workingroot
'
/* end of compaction
/* end of compaction
*/
*/
return (TRUE)
/* end if RTPAREN
/* missing ')' after
'('
return (FALSE)
}
*/
*/
*/
/
*/
/a********************************************************************/
int
Expression (root)
NodeRec
**root;
\/
*/
*/
<EXPRESSION>)
flag;
int
== TRUE))
if (((flag = Con junction (root)
if (ByPass (ORLOG_)
MakeNewRoot (root, ORLOG_, LEFT)
if (Expression (& (*root) ->rptr) !=TRUE)
ErrorHandler (line_no, ERR8,
)
(long)ORLOGJ
/*
return (ERROR_)
}
return flag)
(
/* end Expression!)
/A*******************************************************************/
84
*
.
/A*******************************************************************
PUBLIC DOMAIN SOFTWARE
* Name
parser pt 2
* File
parser2
* Authors
Maj E.J. COLE / Capt J.E. CONNELL
* Started
10/20/86
* Archived
12/11/86
* Modified
JC
01/27/87 - Error Recovery added.
************************************************************************
*
* This file contains the following modules for the PHI parser:
*
Relation ()
Relator ()
Negation ()
Con junction ()
*
MullOPO
Term()
AddOpO
SimplExpO
*
Application
Primary ()
Actual ()
Factor ()
.
Algorithm
************************************************************************
*
* Modified
12/26/86 Flattened tree output changed to abstract
*
*
syntax tree form. JC
*
*
comply
Corrections
to
with
latest
definitions
01/10/87
:
of the language. JC
*
01/27/87 Error Recovery added and files combined. JC
a*************************************************************/
include <stdio.h>
include <parser.h>
extern int
line_no;
extern int
rtbrket;
*/
*/
*/
*/
/A**************************************************************/
int
Conjunction (root)
NodeRec
**root;
<CONJUNCTION>
/*
<NEGATION>
/\
<CONJUNCTION>)
int
flag;
if ((flag = Negation (root)
if (ByPass (ANDLOGJ
{
== TRUE)
/*
!=
TRUE)
return (ERROR
*/
/* Just
(long)
note it,
no fix
/* end recursive
search
*/
*/
*/
*/
ANDLOGJ ;/*
>
return flag)
(
/*
/a*********************************************************************/
int
Negation (root)
NodeRec
"root;
/*
/*
85
*/
*/
;) ;
<NEGATION>
I-
if (ByPass
(NEGLOGJ
<RELATION>
/* look for /* found a /* ~ w/o Relation. Just
/* note it, no fix
TRUE)
*/
*/
note it
*/
*/
else
return (TRUE)
/* end if NEGLOG
/* just check for
/*
*/
single relation */
end NEGATION
*/
********************************************************************** /
int
/* root is a ptr to tree/subtree
/* currently working with
Relation root
NodeRec
**root;
(
<RELATION> ::=
<SIMPLEXP>
<RELATORXSIMPLEXP>)
Where <RELATOR><SIMPLEXP> need not be present
/*
/*
*/
*/
*/
*/
int
flag,
/* type is
type;
if ((flag = SimplExp(root)
== TRUE)
/*
/*
/*
/*
/*
/*
*/
*/
*/
/
*/
*/
'
'
'
'
*/
*/
*/
*/
*/
/*
/*
!= TRUE)
(long) type)
return (ERROR_)
}
return flag)
(
/*
end RELATION
*/
1**********************************************************************1
int
Relator
()
>=
<=
=
<>
<
>
in
notin
<RELATOR> ::=
returns the Relator value vice TRUE if found
I
Note:
flag;
if (flag=ByPass (EQ_)
else
if (flag=ByPass
else
if (flag=ByPass
else
if (flag=ByPass
else
if (flag=ByPass
else
if
f lag=ByPass
else
if (flag=ByPass
else
if (flag=ByPass
(
/* do nothing
(NEQ_)
(LEQ_)
(GEQ_)
(KW_+IN_)
(KW_+NOTIN_)
(KW_+LESS_)
(KW_+GREATER_)
)
86
*/
*/
;;
))
/* return result
/* end Relator
return flag)
(
of search
*/
*/
/a*********************************************************************/
int
/* root is a ptr to tree/subtree
/* currently working with
SimplExp(root)
**root;
NodeRec
<TERM>
<SIMPLEXP>
<ADDOPXSIMPLEXP>)
*/
*/
flag,
int
/* type is
type;
(flag=Term(root) == TRUE)
if(argbind && IBall (RTBRAKET_,
return (flag)
if
*/
looking for a Term
Need to look ahead for
due */
to possibility of having been
called from ArgBindO and
/*ArgBind looking for <QualExp>
/* <0p> ']' following <0p>
/* recursively check for more
/* SIMPLEXP's
/* found AddOp, so fix root for
/* return
/* AddOp w/o SimpExp. Note it
/* note it, no fix
2)
else if (type=AddOp()
*/
/*
/*
/*
/*
(long) type)
return (ERROR_)
}
return flag)
(
/* end
SimplExp
/A****************************************************************/
int
AddOp
:=
"
<ADDOP>
+
Returns the AddOp value vice TRUE if found
/*
/*
*/
*/
flag;
int
if
else
else
else
lag=ByPass (ADD_)
if (flag=ByPass (SUB_)
if (flag=ByPass (COLONJ
if (flag=ByPass (CAT_)
/* do nothing
return flag)
/a**************************************************
int
MulOp
()
:=
*
<MULOP>
%
(idiv)
/
Returns the MulOp value vice TRUE if found
/*
/*
flag;
int
if
else
else
if
if
/* do nothing
(flag=ByPass (RDIV_)
(flag=ByPass (IDIV
)
87
*/
*/
;;
;;
; ;)
'
/* return result of
/* end Relator
return flag)
(
search
/
/
/it*********************************************************************/
int
Term (root)
NodeRec
**root;
<FACTOR>
<TERM>
I-
int
flag,
<MULOPXTERM>
/* type
type;
*/
*/
is
*/
*/
TRUE)
'
rtn */
!= TRUE)
(*root) ->rptr)
ErrorHandler (line_no, ERR8,
(long) type)
return (ERROR_)
)
*/
*/
*/
*/
return flag)
(
/*
end Term
*/
/a***************************************************************/
int
Factor (root)
NodeRec
**root;
<FACTOR>
*/
*/
-]<PRIMARY>
[+|
/* check for
'
or
/*
(status)
if (Primary
(S
found
'
+'
or
'
else
return (TRUE)
else
return (Primary (root)
/* default, check
/* end FACTOR
for Primnary
/*****************************************************************/
int
/* root is a ptr to tree/subtree
/* currently working with
Primary root)
NodeRec
**root;
(
/*
<PRIMARY>
<APPLICATION> (!<PRIMARY>)
88
*/
*/
flag;
int
Application (root
if (flag =
/*
/*
/*
/*
/*
*/
'
'
'
'
*/
/* <QualExp><0p>
following
/* recursively look for next
/* Application
/* found one so fix tree
/*
w/o following Primary.
/* note it, no fix
*/
'
/*
return flag)
(
/* end Primary
()
a*********************************************************************
int
/* root is a ptr to tree/subtree
/* currently working with
Application (root
**root;
NodeRec
<APPLICATION>
/*
*/
*/
(<ACTUAL>)
flag;
*tnode;
int
NodeRec
/* temp pointer to
== TRUE)
if ((flag = Actual (root)
== TRUE)
if ((flag = Application (Stnode)
/* look
/* look
node
for an actual
for an actual list
/*
-/
*/
/*
/* end
*/
*/
*/
*/
*/
*/
A****************************************************************/
int
Actual root)
NodeRec
**root;
<ACTUAL>
/*
/*
int
if
*/
*/
long
NodeRec
*/
*/
ptr;
'temp;
flag;
/*
89
checking for ID
; ;
; ;
)
; ;
; ;
/
/*
/
/
/
/
<DENOTATION>
found one so fix tree
look for trail ACTUAL
note it,
no fix
/
/
/*
end if ID
/*
()
return (TRUE)
if
root
else
ErrorHandler line_no, ERR_1, NULL)
return (ERROR_)
{
end if LITERAL_
note it, no fix
end if FILE
/
/
/
/
/
/
/
/
/
/
/
!= FALSE)
((flag = Conditional (root)
return flag)
if ((flag = Block (root)) != FALSE)
return flag)
if
if
if
ByPass (LINERTARROWJ
temp
return (TRUE)
root;
IsFormal (temp)
ErrorHandler (line_no, ERR_o, NULL)
root) ->name = FORMAL;
MakeNewRoot (root, LINERTARROW_, LEFT)
== TRUE)
if (Actual (&( (root) ->rptr)
return (TRUE)
else
ErrorHandler (line_no, ERR8,
long) LINERTARROWJ
return (ERROR
if
changed
/
/
== TRUE)
else
{
/
/
/
/
/
/
/
else if (flag == ERROR
return (ERROR
)
90
/
/
/
/
/
if
!=
FALSE)
!=
FALSE)
if
return (FALSE)
}
/a**************************************************************/
91
;)
*
PUBLIC DOMAIN SOFTWARE
*
parser pt 3
Name
*
* File
parser3 .c
*
* Authors
Maj E.J. COLE / Capt J.E. CONNELL
* Started
10/20/86
*
* Archived
12/11/86
*
* Modified
01/27/87 - Error Recovery added.
JC
************************************************************************
*
* This file contains the following modules for the PHI parser:
*
*
Conditional
Arm()
Compound
BlockO
*
*
Elements ()
Denotation
ArgBindO
opo
*
*
TypeFac ()
TypeExpO
TypeDomO
TypeTermO
*
*
TypePrimary
PrimType
*
*
Algorithm
************************************************************************
*
* Modified
12/26/86 Flattened tree output changed to abstract
*
*
syntax tree form. JC
*
01/10/87 Corrections to comply with latest definitions *
:
*
JC
*
01/27/87 Error Recovery added and files combined. JC
***********************************************************************/
of the language.
*
*
include <stdio.h>
include <parser.h>
extern int
rtbrket;
extern int
line_no;
*/
*/
*/
*/
/**********************************************************************/
int
Conditional root
NodeRec
**root;
(
/*
/*
/*
(else<EXPRESSION)
/* ptrs to
NodeRec
*temp
NULL,
*subroot,
*/
*/
endif */
*/
'workingptr;
/*
/*
/*
/*
*/
*/
*/
*/
*/
*/
&
fix
ELSIFJ
92
*/
*/
*/
if (Expression (Stemp)
!=
; ;
TRUE)
/* note it,
try
&
*/
fix
(long) ELSE_)
if (ByPass(KW_
*/
*/
*/
*/
ENDIFJ
}else
{
return (TRUE)
)
return (FALSE)
*/
*/
*/
/* end if IF
/* didn't see an IF
/* end Conditional
*/
*/
*/
*/
*/
*/
/**************************************************************/
int
Arm(root)
NodeRec
**root;
<EXPRESSION>then<EXPRESSION>
<ARM> ::=
/*
*/
*/
*/
int
flag;
!= TRUE)
EatEm(KW_+THEN_)
if
{
*/
/*
*/
else
ErrorHandler (line_no, ERR_f
(long)KW_+THEN_)
return (flag)
*/
on
/* end Arm()
*/
*/
/a********************************************************************/
int
Block (root)
NodeRec
"root;
<BLOCK>
/*
::=
*/
*/
*/
if
{
(BlockBody
(S
BEGIN_)
(*root) ->lptr)
!=
TRUE)
93
*/
*/
for BLOCKBODY
*/
/* look
;;
;; ;
)
)
,
,
>
/* note it,
(long) BEGIN_)
if (ByPass (KW_ + END_)
(*root) ->rptr = CreateNode (KW_
return (TRUE)
&
fix
END_
try
/* end ByPass
BEGIN
return (FALSE)
;e
/* end BLOCK
/it*********************************************************************/
int
Compound (root
NodeRec
**root;
/*
/*
<COMPOUND>
/*
'< <ELEMENTS>
<ELEMENTS>
<ELEMENTS> }
where <ELEMENTS> may be empty */
)
(
'
'
'
'
'
(LTPARENJ
Elements (root
*/
*/
'
'
'
'
'
if (ByPass
{
'
(! ByPass (RTPAREN_)
ErrorHandler (line_no, ERR_f
if
*/
*/
*/
(long)RTPAREN_)
root == NULL)
root = CreateNode (EMPTYCOMPOUND)
else if (*root) ->name == COMMA_)
(root) ->name = ELLIST;
return (TRUE)
if
(*
/* end if
(LTSQUIGJ
Elements (root
!ByPass (RTSQUIGJ
if
ErrorHandler (line_no, ERR_f
(long)RTSQUIG
/*
/*
if (ByPass
(
LTPAREN)
if
/* note it,
(Toot == NULL)
root
no fix
CreateNode (EMPTYCOMPOUND)
else if ("root) ->name == COMMA_)
(root) ->name = ELLIST;
return (TRUE)
=
/* end if LTSQUIG)
(ST_SEQUENCE_)
Elements (root
if
ByPass (END_SEQUENCE_)
ErrorHandler (line_no, ERR_f
(long) END SEQUENCE
if (3yPass
i
(Toot
*/
/* note it
*7
*/
&
no fix
NULL)
*root = CreateNode (EMPTYSEQUENCE)
else
MakeNewRoot (root SEQUENCE, RIGHT)
return (TRUE)
if
/*
return (FALSE)
/************************************yf*********************************/
94
; ;
;; ;;
int
/* root is a ptr to tree/subtree
/* currently working with
Elements (root)
**root;
NodeRec
/*
<QUALEXP>)
flag;
int
if ((flag = QualExp(root)
== ERROR_)
/* errors already reported
/* recursively look for next
/* qualexp
/* found a COMMA so fix tree
EatEm(COMMA_)
while (ByPass (COMMA_)
!=
TRUE)
/* note it, try & fix
/* fix tree so all QualExp's
(long)COMMA_)
if
/* end
return flag)
(
/*
end Elements
**********************************************************************
int
/* root is a ptr to tree/subtree
/* currently working with
Denotation (root)
NodeRec
**root;
<LITERAL>
<CONSTANT>
<DENOTATION> ::=
<FORMALS> -> <ACTUAL>
where LITERAL is quoted ('
string of zero or more chars and
where CONSTANT is an integer or decimal number
NOTE:
<FORMALS> -> <ACTUAL>
was already checked by Actual ()
/*
*/
*/
*
*
*
*/
long
ptr;
if (ptr = ByPass (LITERAL_)
*root = CreateNode(LITERAL_)
(*root) ->index = ptr;
return (TRUE)
{
/* end a LITERAL
if
{
(ByPass (EMPT_LIT_)
*root = CreateNode(LITERAL_)
(root) ->index = NULL;
return (TRUE)
/* end a LITERAL
if (ptr =ByPass
(
(CONSTANTJ
"root = CreateNode(CONSTANT_)
(*root) ->index = ptr;
return (TRUE)
/*
return (FALSE)
end
CONSTANT
/* default,
/* end Denotation
()
**********************************************************************
int
ArgBinding (root)
NodeRec
**root;
/*
/*
95
*/
/
)
;
;;
,_
<ARGBINDING>
;;
(<OPXQUALEXP>
i
r
['
<QUALEXPXOP>
<0P>)
']'
int
NodeRec
extern
specialcase;
'temp = NULL;
argbind;
int
/*
/*
if (ByPass (LTBRAKET_)
argbind = TRUE;
{
specialcase
IBall (ADD_,
1)
II
IBall (SUB_,
/
*/
*/
*/
*/
1 ))
DE3UG
tfifdef
print f "special case = %d argbind = %d\n", specialcase, argbind)
#endif
(
if
{
/*
(Op(root)
(ByPass (RTBRAKET_)
argbind = FALSE;
MakeNewRoot root ARGBINDOP, LEFT)
/*
/*
if
{
/*
/*
/*
/*
/*
return (TRUE)
1
if (IBall (ADD_,
specialcase
if
1)
II
IBall (SUB_,
= FALSE;
/*
/*
/*
if (ByPass (RTBRAKET_)
/*
had
<0p>
end if ByPass RTBRAKET_
don't have just an Op
might be +/- +/- QualExp
and don't want to accept
+/+/- QualExp Op later on
two cases where QualExp could
be TRUE
<Op><QualExp>
or + -<QualExp><Op>
reset global flag
could be +/- PRIMARY
(
/*
argbind = FALSE;
return (TRUE)
/*
else
if (specialcase && Op(Stemp)
SS ByPass (RTBRAKET_)
(*root) ->lptr) ->rptr= (*root) ->rpt r ;
/* now fix the tree
(root) ->rptr = temp;
(*root) ->lptr) ->name == ADD_) ?
(*root) ->lptr) ->name=POS_)
(*root) ->lptr) ->name = NEG_)
/* <0p> came last as a ","
(*root)-> name = ARGTRAILOP;
/* reset giobalflag
argbind = FALSE;
return (TRUE)
/* end else specialcase a Op
/* S& RTBRAKET_
/* end 2 cases where QualExp TRUE
/* reset giobalflag
argbind = FALSE;
/* report it, no fix
ErrorHandler (line_no, ERR_q, NULL)
return (ERROR_)
/* end Op comes first
/* found something
!= FALSE)
(QualExp(root)
MakeNewRoot (root ARGTRAILOP, LEFT)
/* reset global flag &
argbind = FALSE;
;
ByPass (RTBRAKET_)
return (TRUE)
ErrorHandler (line_no, ERR_q,NULL)
return (ERROR
&&
/*
/* report
it,
no fix
return (FALSE)
it*************************************** it****************************int
96
Op(root)
NodeRec
);
;
/*
/*
"root;
<OP> ::=
/*
<RELATOR>
<ADDOP>
<MULOP>
*/
*/
*/
flag;
int
return flag)
(
/* end Op
*/
/A********************************************************************/
int
/* root is a ptr to tree/subtree
/* currently working with
TypeExp root
NodeRec
"root;
(
<TYPEDOM>
<TYPEEXP> ::=
/*
-> <TYPEEXP>
*/
*/
*/
)*
NodeRec
*newroot;
int
flag;
/*
== TRUE)
if ((flag = TypeDom(root)
if (ByPass (RTARROW_)
newroot = CreateNode (RTARROW_)
newroot ->lptr = 'root;
*/
*/
*/
*/
*/
'root = newroot;
if (TypeExp (&( ('root) ->rptr)
{
!=
TRUE)
return (flag)
/* end
TypeExp
*/
/a*******************************************************************/
int
/* root is a ptr to tree/subtree
/* currently working with
TypeDom (root
NodeRec
"root;
<TYPEDOM> ::=
/*
<TYPETERM>(+ <TYPEDOM>)
*/
*/
*/
NodeRec
'newroot;
int
flag;
== TRUE)
if ((flag = TypeTerm(root)
if (ByPass (ADD_)
newroot = CreateNode (TYPEPLUS)
newroot ->lptr = 'root;
in the tree
*/
97
*/
*/
*/
;
;
;;
*root = newroot;
if
{
!= TRUE)
(TypeDomU (*root) ->rptr)
ErrorHandler (line no, ERR9, (long)ADDJ
)
return (ERROR_)
I
/*
*/
return (flag)
/* end
TypeDomO
*/
/it*******************************************************************/
mt
/* root is a ptr to tree/subtree
/* currently working with
TypeTerm (root)
NodeRec
**root;
<TYPEFAC>('*' <TYPETERM>)
<TYPETERM>
/'
NodeRec
*newroot;
int
flag;
if ((flag = TypeFac(root)
if (ByPass (MULT_)
*/
*/
*/
*/
*/
*/
== TRUE)
*/
return flag)
(
/* end TypeTerm
()
/************************************************************/
mt
TypeFac (root)
NodeRec
**root;
:=
<TYPEFAC>
<TYPEPRIMARY>@
<TYPEPRIMARY>
<ID> '' <TYPEEXP> (,<TYPEEXP>) * '' <ACTUAL>
Where TYPEEXP TYPEEXP,
and/or <ACTUAL>
need not be present
/*
/*
/*
/*
NodeRec
newroot
int
flag;
ptr;
long
if (ptr = ByPass
(
/*
IDENTIFIER^
4S ByPass (ST_SEQUENCE_)
ErrorHandler (lineno, ERR_r, NULL)
return (ERROR_)
if (ByPass (ST_SEQUENCE_)
{
/* end bypass
<<
goto CHECK;
/* end if
TypePrimary (root)
goto CHECK;
return flag)
if ((flag =
ID
== TRUE)
/* return either ERROR or FALSE
98
*/
*/
*/
*/
*/
*/
; ;
;;
)
)
)
;
)
;;
/*
}
end if STAR
'/
return (TRUE)
}
ail OK
*/
*/
/a***********************************************************/
int
/*
TypePrimary (root)
"root;
NodeRec
/*
'(' <TYPEEXP>
<TYPEPRIMARY> ::= <PRIMTYPE>
ID already checked in TYPEFACO
/*
/*
')'
*/
*/
*/
*/
NOTE:
if (ByPass (LTPARENJ
if (TypeExp(root)
!=
TRUE)
/* note
it,
no
f:
(long) LTPAREN_)
if (ByPass
(RTPARENJ
return (TRUE)
else
ErrorHandler (line_no, ERR_f,
(long)RTPAREN_)
return (ERROR_)
(
/* end ByPass
'
if (PrimType (root)
return (TRUE)
/* default
/* end TypePrimary
return (FALSE)
/a****************************************************************
int
PrimType (root)
NodeRec
**root;
<PRIMTYPE>
/*
:=
real
integer
natural
boolean
trivial
if (ByPass (REAL_)
{
if (ByPass
{
(INTEGERJ
if (ByPass (NATURALJ
Toot = CreateNode (NATURALJ
return (TRUE)
{
/*
if (ByPass
{
(BOOLEANJ
99
end if NATURAL
*/
*/
type */
;;
return (TRUE)
)
if (ByPass
{
(TRIVIALJ
/*
end if BOOLEAN
*/
/*
end if TRIVIAL
*/
TYPE_)
/* end if TYPE
return (FALSE)
/*
/*
*/
*/
*/
it********************************************************************/
100
/********** *************************************************************
PUBLIC DOMAIN SOFTWARE
* Name
Parser Ut ilities
* File
parsr_uti l.c
* Authors
Ma j E.J. COLE / Capt J.E. CONNELL
* Started
01/26/87
* Archived
03/03/87
*
* Modified
04/23/87 FillBufferO now calls GetTokenO direct.
*********** ************** ***********************************************
*
* This file contains the utility modules for the parser:
*
*
MakeNewRoot ()
ByPassO
CreateNode
*
*
IsFormaK)
IBallO
FillBuff ()
*
*
EnterNameO
FindNameO
NodeName
*********** *************************************************************
*
03/20/87 - Buffer Handling routines added - JC
Modified
*
*
FillBuferO calls GetTokenO direct vice
04/23/87
*
*
working with intermediate file of tokens
*
*
EnterNameO and FindNameO added to place
*
*
IDs, LITERALS, and CONSTANTS into the name
*
*
table.
JC
***********************************************************************
tinclude <stdio.h>
#include <parser.h>
extern
int
line_no;
extern
FILE
*pinfile;
/*
char
NameRec
/*
*/
/*
*/
1]
*/
*/
/**********************************************************************/
/*
*/
UTILITIES
NodeRec *
CreateNode (op)
NodeType op;
/* Creates a tree node and returns the pointer (temp) to this node.
/* Accepts node type (op), an integer, and inserts it into the node.
*/
*/
NodeRec
*temp;
/*
create
node
NULL;
/*
end CreateNode
()
*/
/A***************************************************************/
void
MakeNewRoot root type, side)
(
101
NodeRec
"root;
int
type,
/*
/*
side;
(type)
(side)
/*
/*
*/
*/
*/
*/
*/
*/
*newroot;
NodeRec
end MakeNewRoot
*/
/it*********************************************************************/
void
FillBuf (start)
long
*start;
*/
/
*/
*/
*/
*/
*/
*/
long tokenbuff[],
token_num;
*nptr;
extern
int
N'ameRec
*ptr;
/*
*/
*/
*/
/* ptr to
/*
ptr = start;
do
++ptr
switch (token_num)
case LITERAL_
case CONSTANT_
case IDENTIFIER_
token[0] = strlen (token)
if (nptr=EnterName (token)
*ptr = (long)nptr;
++ptr;
(
*/
/* address of token
*/
default:
)
while
ptr
(token_num != EOF)
&&
(ptr < Stokenbuff [BUFSIZE]
Stokenbuff
/*
*/
/* end case
/* do nothing
/* end switch
*/
*/
*/
*/
))
[Oj
/a*********************************************************************/
102
)
;
long
ByPass (tgt)
tgt;
int
Checks to see if the next token in the buffer matches the target.
If so, then returns the token no. and increments the buffer
pointer
/*
/*
/*
*/
*/
*/
long
extern
tokenbuff[],
*ptr;
*/
*/
/*
*/
increment counter
/* end
(*ptr
skip
if
while
*/
*/
*/
!= tgt)
return (FALSE)
/* otherwise,
++ptr;
if (ptr == Stokenbuf f [BUFSIZE]
FillBuff (itokenbuff
switch (tgt)
case LITERAL_
case IDENTIFIER
case CONSTANT_
return (* (ptr++)
[0])
it
was found
*/
/* if at end of buffer
/* refill buffer
*/
*/
*/
/*
*/
*/
default:
return (tgt)
/* end swithch
/* end ByPass
*/
*/
/a********************************************************************/
int
IsFormal (root
NodeRec
*root;
/*
/*
#ifdef
DEBUG
printf "isf ormal entered, root->name = %d\n", root->name)
if (root == NULL) printf ("root is null\n");
#endif
(
if (root == NULL)
return (TRUE)
if (root->name==COMMA_
II
I
root->name==IDENTIFIER_
root->name==ELLIST)
103
*/
*
*/
*/
*/
*/
*/
if
; ;
);
))
Is Formal (root->iptr)
ii
IsFormal (root->rptr
(
return (TRUE)
return (FALSE)
/* end
Isformal
*/
/*******************************************************************/
ir.t
/*
/*
/*
/*
/*
tokenbuff[],
long
*tptr;
extern
long
*/
*/
*/
*/
*/
*/
*/
*ptr;
DO_AGAIN:
tptr = ptr;
*/
*/
*/
*/
*/
increment tptr
++tptr;
/*
goto REFIL;
/* end while
/* only enter
/*
case IDENTIFIER_:
case CONSTANT_:
case LITERAL_:
tptr +=
/*
/*
2;
*/
/* increment counter
/*
/*
*/
*/
*/
refill buffer
end while
skip
start over
*/
*/
*/
++tptr;
/* end switch
/* check if will overflow buff
if (tptr
*/
*/
*/
*/
break;
case EOLN_:
while (*tptr == EOLN_)
++tptr;
if (ptr == Stokenbuf f [BUFSIZE]
goto REFIL;
default:
skip EOLNs
&
*/
*/
goto REFIL;
/*
*/
end for
REFIL:
pt r *+ tpt r + +
,
*/
/* refill buffer
/* posit to end
104
*/
*/
from current
*/
*/
/* refilled buffer,
/* over
goto DO_AGAIN;
/* end
IBall
so start
*/
*/
*/
()
/******************************************************************/
char *
NodeName (ptr)
NodeRec
*ptr;
/* Accepts a ptr to a structure of NodeRec.
Dereferences this node
/* to get a ptr to structure of NameRec which hold the string
/* containing the name of the value in NodeRec. Returns the name to
/* calling routine
*/
*/
*/
*/
NameRec
*temp;
*/
*/
NodeName
()
*/
/****************************************************************/
105
APPENDIX
ROCK COMPILER
ERROR HANDLER
/*********** ************************************************************
*
PUBLIC DOMAIN SOFTWARE
*
* Name
Error Handler
*
* File
errors
*
* Authors
Maj E.J. COLE / Capt J.E. CONNELL
*
* Started
01/20/87
*
* Archived
04/07/87
*
Modified
************ ************************************************************
* This file contains the execution modules for error recovery.
*
ErrorHandler ()
EatEmO
*
<
ErrorHandler
is called by other modules in the
compiler.
It insures the error count is updated and
*
the* error is written to the error file.
If required,
*
ErrorHandler
calls EatEmO to gobble tokens to get to
the parse.
a known point in
Used during error
*
After MAXERRORS number of errors simply
recovery.
*
returns to calling routine.
* NOTE
'errorfile' must have been initially created before
*
ErrorHandler
is first called - don't want to append
*
to last times errors!
************ ***********************************************************
* Modified
*
Algorithm
( )
***********************************************************************
^include
#include
#include
extern
<stdio.h>
<scanner.h>
<errors.h>
FILE
*errorfile;
int
nil
m errors =
errors
/*
working file
/*
/*
/*
incomplete '!->'",
RESERVED FOR FUTURE USE"
without following '/
logical OR is \\/
"$' without following 'R' 'N' 'Z' 'B',or 1'"/
> ",
'invalid numeric constant
- ",
'literal without ending
'unidentified char in input program ==> ",
'MEMORY OVERFLOW DURING COMPILATION",
'error in statement following ==> ",
'error in type definition following ==> ",
'unable to complete definition of blockbody after keyword
'missing or misplaced ';' after definition",
'valid qualexp/exp not found in the def/auxdef",
'
"W
106
/* d */
/* e */
/* f */
/* g */
/* h */
/*
*/
"
/* J
/* k */
/* 1 */
/* m */
/* n */
/* o */
/* p */
/* q */
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
*/
*/
*/
u */
v */
w */
s
x*/
y
*/
aa */
bb */
cc */
dd */
ee */
ff
*/
gg */
hh */
*/
*/
kk */
11 */
mm */
ii
jj
******** **************************************************************/
void
ErrorHandler (line_no,err_no, str_num)
int
line_no, err_no;
long
str_num;
/*
/*
{
DEBUG
fifdef
printf("eh entered, err#
#endif
if
(++num_errors
errorfiie
if
{
f open
>
= %d,
MAXERRORS)
return;
(err_no == ERR7)
fprintf (errorfiie, "%s\n", errors [err_no]
user err
(
107
/*
/*
/*
*/
*/
;
; ;
; ; ; ;
/*
%s
fprintf (errorf ile, "line %3d
line_no, errors [err_no]
",
switch (err_no)
case ERR4:
case ERR5:
case ERR6:
case ERR8:
switch (str
case LEQ_
case NEQ_
case GEQ_
case EQ_
case ADD_
case SUB_
case MULT
case IDIV
case RDIV_
case SUBSCRIPT
case ORLOG_
case ANDLOG
case NEGLOG
case COLON_
case CAT_
case LINERTARROW_:
case (KW_+GREATER_)
case (KW_+IN_)
case (KW_+LESS_)
case (KW_+NOTIN_
default
fprintf (errorfile,
(
*)
str_num)
break;
num)
fprintf
fprintf
fprintf
fprintf
fprintf
fprintf
fprintf
fprintf
fprintf
fprintf
fprintf
fprintf
fprintf
fprintf
fprintf
fprintf
fprintf
fprintf
fprintf
fprintf
(error file,
(error file,
(error file,
(error file,
(error file,
(error file,
(error file,
(error file,
(error file,
(error file,
(error file,
(error file,
(error file,
(error file,
(error file,
(error file,
(error file,
(error file,
(error file,
(error file.
<=\n'
*<>\n'
>=\n'
=\n")
+\n")
-\n")
*\n'
'%\n'
An'
!\n'
'\\/\:
AWn'
'~\n'
:\n")
"\n"]
'
->\n")
GREATER\n"
*IN\n")
LESS\n")
'NOTINXn")
break
break
break
break
break
break
break
break
break
break
break
break
break
break
break
break
break
break
break
break
UNDEFINED error\n")
/* end
break;
switch (str_num)
:RR9:
case ADD_
fprintf (errorf ile, "+\n")
case MULT_
fprintf (errorf ile, "*\n")
case RTARROW
fprintf (errorfile, "->\n")
case LTPAREN
fprintf (errorf ile, " (\n")
default:
fprintf (errorfile, "UNDEFINED error\n"
break;
break;
break;
break;
/* end
break;
switch str_num)
case KW_+AND_:
case KW_+WHERE_:
fprintf (errorfile, "==\n
break;
case RTPAREN_:
fprintf (errorfile, ") \n"
str_num=NULL; break;
case RTSQUIG_:
fprintf (errorfile, " }\n"
str_num=NULL; break;
case END_SEQUENCE_:
fprintf (errorfile, ">\n"
str num=NULL; break;
:ase ERR_f
/*
/*
/* don't want to go to
108
EatEm
case KW_+END_:
fprintf (errorfile, "KEYWORD END\n")
str_num += KW_; break;
case KW_+THEN_:
fprintf (errorfile, "KEYWORD THEN\n")
break;
/*
*/
/*
*/
/*
*/
/*
/*
*/
*/
/*
end switch
*/
/*
end ErrorHandler
*/
default
fprintf (errorfile, "UNDEFINED error\n")
break;
str_num += KW_;
break;
default:
fprintf (errorfile,
"
\n")
f close
if
(errorfile)
/*******************************************************
void
EatEm (tgt)
int tgt;
extern
extern
tokenbuf f
line_no;
long
int
#ifdef
DEBUG
print f "eatem entered, tgt
#endif
(
*ptr;
%d\n",tgt);
case SEMI_
if (*ptr==SEMI
break;
||
(*ptr==KW +LET
109
))
*/
*/
return;
break;
-Dtr;
switch
case EQUIV
case EQUIV_
case SEMI_
case KW_+AND_
case KW_+LET_
default
break;
(int) *ptr)
return;
++ptr;
case KW_+WHERE_
case KW_+WKERE_
case KW_+AND_
case KW_+LET_
case SEMI_
default
break;
switch
case KW +AND
case KW_+AND_
case KW_+LET
case SEMI_
default
break;
switch
case RTPAREN_
case RTPAREN_
case LTPAREN_
case COMMA_
case EQUIV_
case LINERTARROW
case KW_+LET_
case KW_+AND_
case SEMI_
default
break;
switch ((int)*ptr)
/*
/*
((int)*ptr)
return;
++ptr;
((int)*ptr)
return;
++ptr;
/* end switch case AND
return;
++ptr;
/* end
case KW
case KW
case KW
case KW
case
case
case
case
{
_+
IF_
ELSIF_
_+ ELSE_
_+ THEN_
KW_+ ELSIF
KW_+ ELSE_
KW_+ ENDIF
KW + THEN
_+
return;
/* end switch case THEN,
++ptr
break;
case COMMA_
case COMMA_
case LTPAREN_
case RTPAREN_
case LTSQUIG_
case RTSQUIG_
case ST_SEQUENCE_
case END_SEQUENCE_
case SEMI_
case KW_+LET_
case KW_+WHERE_
case KW_+ AND_
default
switch
(int) *ptr)
return;
++ptr;
110
*/
break;
case KW_+END_
case KW_+BEGIN_
case KW_+END_
case KW_+LET_
case KW_+WHERE_
case KW_^AND_
case COMMA_
case RTPAREN_
case RTSQUIG_
case END_SEQUENCE_
case SEMI_
default
break;
switch
/*
/*
(int) *ptr)
return;
++ptr;
default
return;
:
end swithch
end while
/* end EatEmO
/*
/*
'
* * *
*/
*/
*/
******************************** a*******************************/
111
APPENDIX
SEMANTIC CHECKER
ROCK COMPILER
/A*******************************************************************
*
PUBLIC DOMAIN SOFTWARE
Name
File
Authors
Started
Archived
Modified
This file contains the following modules for the PHI parser:
*
*
*
*
*
*
*
*
*
*
Hnumconvert
Numconvert
*
*
*
Algorithm
*
*
This module contains procedures for type conversion.
If the
* rt child of a node may be converted to the It type but the con*
* verse is not true,
*
"Hnumconvert" is called.
If either side may be
*
* converted,
"numberconvert" is called
A************************************************************
*
* Modified
a****************************************************************/
*
();
rtype,
(ltype,
ptr)
if
((ltype == BOOLEAN)
return (BOOLEAN);
switch (ltype)
case (REAL)
S&
switch (rtype)
case (REAL)
return
case (INTEGER)
case (NATURAL)
c_ztor
return (REAL)
default
:
*/
*/
*/
*/
*/
*/
*7
(rtype == BOOLEAN))
(REAL);
It*/
*/
/*
*/
/*
*/
112
terror
return
; ; ;
(ERR_aa,
(REAL)
;;
; ;;
ptr->ln)
switch (rtype)
case (INTEGER)
case (INTEGER)
return (rtype);
case (NATURAL)
default
terror (ERR_cc, ptr->in)
return (INTEGER);
:
/*
Matching types, no
cor.v
req
*/
case
(NATURAL)
(rtype == NATURAL)
return (rtype)
/* Can't
/* so sandbag the
if
else
terror
return
(ERR_bb, ptr->ln)
(NATURAL)
default
terror (ERR_aa, ptr->ln)
return (NATURAL)
:
nodal ptr;
{PHITYPE ltype, rtype;
extern PHITYPE semcheck
extern void c_ztor ();
ltype = semcheck
/*
(ptr->lptr);
/* Get
if
();
((ltype == BOOLEAN)
return (BOOLEAN)
ii
(rtype == BOOLEAN))
switch (ltype)
case (REAL)
switch (rtype)
case (REAL)
return (REAL)
case (INTEGER)
case (NATURAL)
c_ztor
return (REAL)
default
terror (ERR_aa, ptr->rptr->ln)
return (REAL)
{
left type
/* Special case of
/* Get
/* No
/*
"if" sequence
right type
conversion necessary
no action req
/*
/* to real
/* No
converison possible
case (NATURAL)
switch (rtype)
case (REAL)
c_ztor
return (REAL)
case (INTEGER)
return (INTEGER)
case (NATURAL)
return (NATURAL)
default
terror (ERR_aa, ptr->rptr->ln)
return (NATURAL)
:
/*
/* No
conversion necessary
/* No
conversion necessary
113
*/
case (INTEGER)
switch (rtype)
case (REAL)
c_ztor
return (REAL)
case (INTEGER)
case (NATURAL)
return (INTEGER);
default
terror (ERR_aa, ptr->rptr->ln)
return (NATURAL)
:
/* Convert
left side
/* No conversion necessary
default
terror
return
:
(ERR_aa, pt r->lptr->in)
(NATURAL) ;
114
numeric
;;
/**********************************************************************
*
PUBLIC DOMAIN SOFTWARE
Semcheck Module 1
Name
* File
Semi
* Authors
Maj
E.J. COLE / Capt J.E. CONNELL
* Started
01/02/87
* Archived
01/10/87
* Modified
***********************************************************************
* This file contains the following modules for the PHI parser:
*
*
Tletdef
Twhere
Tandcheck
Trtarrow
Tdataauxdef
Tauxand
Tkindef
Tauxand
Ttypetimes
*
*
*
*
*
Algorithm
*
*
*
:
*
*
*
***********************************************************************
*
* Modified
a*********************************************************************/
:
/* For "strcpy"
semcheck
semcheck
(ptr->lptr);
(ptr->rptr);
/*
(ptr->lptr->name == TYPETIMES)
(ptr->lptr->name == TYPEPLUS)
putform (ltype);
if
return
Returns type
/*
(rtype)
115
'*'
or
;;
;;
/* Adds
fhead
*/
*/
*/
/it***********************
it******************************/
t where
PHITYPE
twhere (ptr)
nodal ptr;
(PHITYPE type;
semchecker (ptr->lptr)
type = semchecker (ptr->rptr);
return (type)
*/
/* Check leftside
/* Check right side
*/
*/
c_jmp
*/
/* Temp holder
*/
();
type,
count = 0;
*/
*/
*/
*/
*/
*/
*/
(ptr->lptr->name == IDENTIFIER_)
if
typecheck */
variable
rtype,
putvar
ptr)
(type,
/* Convert
rt type
is
if
data def
feasible
*/
*/
ptr->lptr)
else
terror
/*
(ERR_dd,
ptr->lpt r->ln
116
;;
while ('(holder
count)
(ptr->lptr->label
++count;
c
store code
; ;
!= NULL)
=
[count!)
(*
(holder
count));
("ret\n");
c~store~code (nme)
c
store code
*/
*/
(":\n");
(ptr
!=
NULL)
(mark,
{
and_check
do
ptr->link, mark_and)
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
if (v_ptr->nptr->index==ptr->ptr->index)
buff_holder = buff_ptr;
buff_ptr = ptr->buf f ptr
c_call_proc (v_ptr->nptr->label)
buff_ptr = buf f_holder
(*mark_and == ptr)
*mark_and = ptr->link;
/*
if
Traverse list
*/
*/
*/
del_and (ptr)
break;
(v_ptr == mark)
if
break;
v_ptr = v_ptr->link;
while (TRUE)
reached
*/
*/
*/
save_and
/*
*/
*/
/* Holder for and flag
*/
/* Mark top entry in the varlist
/* Mark current head of and_stack */
and_flag;
/* Save current
/* Set and flag
ar.d_fiag = TRUE;
117
and_flag
*/
*/
; ;
/* Semantic Check
semcheck (ptr->lptr)
mark = varhead;
semcheck (ptr->rptr)
and check
and_flag
(mark,
=
and_head,
&mark_and)
/*
*/
data defs */
save_and;
*/
tptr = and_head;
/*
*/
if (mark_and != and_head)
terror (ERR_ee, ptr->ln)
/*
*/
/* Semantic check
/* for types
when used
*/
*/
() ;
'*'
(type = semcheck
(ptr->rptr)
*/
if 0,
*/
*/
putform (type)
return
/*
(NULL)
/* This
118
*/
*/
*
*
*
Semcheck Module 2
Name
*
* File
Sem2.c
* Authors
*
Maj E.J. COLE / Capt J.E. CONNELL
*
* Started
01/02/87
*
* Archived
04/10/87
*
* Modified
a****************************************************************
* This file contains the following modules for the PHI parser:
*
*
Tfunauxdef
Tid
Matchfor
Tactualist
Telist
*
*
*
Tfunid
Act_Walk
*
*
*
*
Algorithm
*
This module contains the procedures needed to define and call
functions. Tfunauxdef will set up the run-time structure of the fun-*
ction, tfunid will check the semantics of the function, & matchfor, *
called by tfunid, checks for the proper type & number of formal pa- *
*
rameters
Tactualist coordinates the checking of a function call.
It uses *
*
both telist and act_walk. Actwalk determines whether the number &
type of actuals is correct, and telist checks each element list and *
*
returns its type.
*
Tid performs semantic checking for program variables.
*
*
*
*
*
*
*
*
*
*
Modified
**********************************************************************/
/* For
"strcpy"
*/
();
*/
(nptr,
def)
nodal nptr;
defptr def;
{extern long curr_addr;
extern fnode *getfptr
extern FLAG form;
fnode *tptr = getfptr
/* Match formals
/* Called by tfunid () only
/* Ptr to rt side of funid node
/* Ptr to var table for fur.c name
*/
*/
*/
*/
*/
*/
();
(def)
form = TRUE;
tptr = def->fptr;
curr addr =0;
119
;;
;;
(nptr->name == IDENTIFIER_)
(nptr->type) = tptr->type;
nptr->addr = curr_addr;
putvar (tptr->type, nptr)
nptr = nptr->rptr;
tptr = tptr->link;
else
/*
do
Multiple formals
nptr->lptr->type = tptr->type;
nptr->lptr->addr = curr_addr;
curr_addr = curr_addr +
types [tptr->type] .bytes;
putvar (tptr->type, nptr->lptr)
nptr = nptr->rptr;
tptr = tptr->link;
while (nptr !=NULL) &S (tptr !=NULL)
(
reacned
form = FALSE;
if
(nptr
!=
return
NULL
tptr
!= NULL)
(FALSE)
else return
*/
*/
(TRUE)
ltype = semcheck
rtype = semcheck
/* Type check
funauxdef
();
());
*/
ptr->rptr =
hnumconvert (ltype,
c end proc (nme)
=
*/
(ptr->lptr)
(ptr->rptr)
curr_addr
*/
Convert if needed
rtype,
ptr->rptr)
/* Reset addresses
pres_addr;
120
;;
/a***************************
********************************/
T fun id
PHITYPE
tfunid (ptr)
nodal ptr;
{extern defptr finddef ();
extern long curr_addr;
extern char 'name ();
int count = 0;
defptr def;
char 'holder = malloc (8);
if
/*
terror
return
else
/* Semantic Check
(NOTFOUND)
for tfunid
found
*/
*/
*/
ptr->lptr->type = def->type;
ptr->type = def->type;
putvar (ptr->lptr->type, ptr->lptr, FALSE)
*/
Match formals
*/
/*
if
else
holder
strcpy
('(holder
while
(holder,
+
count)
(ptr->lptr->label
(
(holder + count)
++count;
ptr->iptr->addr
name
!=
());
0)
*/
*/
/* Gen code
*/
[count])
)
0;
c_start_proc (ptr->lptr->label)
return
(pt
r->type)
/* Semantic Check
if
(ptr->rptr
semcheck
semcheck
!= NULL)
*/
*/
(ptr->rptr)
(ptr->lptr)
/*
Generate code
*/
/* Recursive procedure to
/* sem check actual list
(ptr, fptr)
121
*/
*/
; ;
nodal ptr;
fnode *fptr;
{
if
(pt->rptr != NULL)
act_waik (ptr->rptr,
/*
*/
fptr->link)
semcheck (ptr->lptr)
if (ptr->iptr->name != ELLIST)
++actual_count;
/ *
/* on the stack
*/
*/
*/
*/
actual_count
if
(def)
if
/*
Evaluate actualists
*/
/* Defstack pointer
/* Varstack pointer
/* Buffer for
/* Conversion
*/
*/
variable
*/
0;
Definition found
*/
/* Legitimate cases
*/
/*
II
var)
fptr = def->fptr;
act_walk (ptr->rptr, fptr);
convert = actual_count
c_store_code ("mov bx, ");
/* Get
(and_flag)
&&
!var)
*/
*/
*/
*/
/*
add_and (ptr->lptr)
c_call_proc (name ());
/* Holder
*/
*/
else
c_call_proc var->nptr->label)
actual_count = count_hold;
return (def->type)
(
*/
*/
122
found
*/
;;
Cvar)
if
if
/* Typecheck
Id node
*/
/*
/*
found
else return
/* Get
(NOTFOUND)
/*
else
c
return
call proc
(getvtype
var->npt r->label
(var)
/* to assign value
/* Return variable type
123
/A******************************************************************
*
PUBLIC DOMAIN SOFTWARE
*
*
*
Semcheck Module #3
Name
*
* File
Sem3.c
* Authors
*
Maj E.J. COLE / Capt J.E. CONNELL
*
* Started
01/02/87
*
* Archived
04/02/87
*
* Modified
A********************************************************
* This file contains the following modules for the PHI parser:
*
*
Tidivide
*
Trdivide
Tarithop
*
*
Tconvert
Tprimary
Tconstant
*
*
Tand
Tor
Tnegation
Algorithm
*
*
*
*
*
*
*
*
it*********************************************
*
* Modified
* it******************************************************
/it*************************** Externals ******************************/
*
include <semcheck.h>
include <string.h>
extern void terror ();
extern void c_store_code
();
/* For "strcmpi"
*/
*/
*/
/* to a buffer
switch
case
case
case
semcheck
/*
(ptr->lptr
/* Check left
(ltype)
break;
(REAL)
(INTEGER)
(NATURAL)
{
*/
*/
*/
c_ztor
break;
default
terror
return;
(
(ERR_aa,
ptr->lptr->ln)
124
;;
rtype
semcheck
(ptr->rptr)
/*
switch (rtype)
case (REAL)
break;
case (INTEGER)
case (NATURAL)
c_ztor
break;
default
terror (ERR_aa, ptr->rptr->ln)
return;
/* Error,
acode
/*
REAL)
(ptr,
Generate code
*/
/* Semcheck
=
*/
NATURAL;
(ptr->lptr)
(ptr->rptr)
/*
*/
/*
*/
/*
If not
switch (ltype)
type = INTEGER;
case (INTEGER)
case (NATURAL) :break;
default
terror (ERR_cc, ptr->lptr->ln)
return (INTEGER);
(
Int or Nat,
error
*/
switch (rtype)
case (INTEGER)
type = INTEGER;
case (NATURAL)
break;
default
terror (ERR_cc, ptr->rptr->ln)
return (INTEGER)
/* Check rt
/* If not
Int or Nat,
error
*/
>
/*
Generate code
*/
(type)
switch
case
case
case
(ptr->name)
(ADD_)
(SUB_)
(MULT_)
*/
*/
();
/*
/*
*/
else
terror
return
<
(ERR_aa, ptr->ln)
(NATURAL)
>
125
trdivide
case (RDIV_)
ptr->type = type;
return (REAL)
tidivide
case (IDIV_)
ptr->type = type;
return (INTEGER);
case
(COLON_)
case
(CAT_)
(ptr)
(ptr);
break;
break;
semcheck
or "-"
(ptr->rptr)
else if
(ptr->name) == NEG_)
c_store_code ("call igetvalue\n")
c_store_code ("neg ax\n");
c_store_code ("call iputvalue\n")
/* Negate operation
/* Spew code
return (type)
is
req
stg string;
(FLAG e = FALSE,
period = FALSE;
int count = 0;
if
Si
/* If not boolean
if
(e)
else
return
(ERROR);
found
/*
"e" or "E"
/*
e = TRUE;
if
((string [count
(string [count
++count;
>
1]
1]
==
==
'+')
'-'))
126
II
*/
*/
else if
;; ;
;
[count] =='.'){
(period) return (ERROR)
else period = TRUE;
(string
if
/*
/*
*/
*/
if
(string
[0]
return
period)
if
== '-')
return
(NATURAL)
return
(BOOLEAN);
(REAL)
return
(INTEGER);
*/
*/
integer */
/*
natural */
/*
If
not a number,
boolean
*/
/*
*/
();
/* Constant type
/* Constant name
*/
*/
tptr = ptr->index;
if
1))
/*
Calculate type
/* Fill node
&
*/
increment address
*/
/* No legitimate constant
found
*/
/*******************************
Tand.
********************************/
PHITYPE
tand (ptr)
nodal ptr;
{PHITYPE ltype, rtype;
ltype = semcheck
rtype = semcheck
if
(!
(ptr->lptr)
(ptr->rptr)
/* Sem Check
*/
/*
*/
/*
Generate code
*/
terror
/* Sema Check
(ptr)
*/
nodal ptr;
{PHITYPE ltype, rtype;
ltype = semcheck
rtype = semcheck
if
(!
(ptr->lptr);
(ptr->rptr)
terror
127
*/
/*
Generate code
*/
(BOOLEAN);
/* Sema check
if
(!(semcheck
(ptr->rptr)
== BOOLEAN))
/* Rt
/* It
child must be
child is null
boolean;
*/
*/
return
/* Gen
(BOOLEAN)
128
*/
/a**********************************************************************
*
PUBLIC DOMAIN SOFTWARE
Semcheck Module #4
Name
*
Sem4.c
File
*
* Authors
J.E.
CONNELL
COLE
Capt
/
E.J.
Maj
*
* Started
01/29/87
*
* Archived
04/03/87
* Modified
a***********************************************************
* This file contains the following modules for the PHI compiler:
*
*
*
Telseif
Tthen
Tcomp
Tif
Telse
*
*
*
Algorithm
*
the
procedures
necessary
implement
This module contains
to
the
"if-then-elseif-else" series of commands. Tif coordinates the seman-*
tic checking by calling Tthen to check its left nodes, then calling *
Telse will be called until the right*
telse to check its right nodes.
*
subtree runs out of "elses" and "elseif s"
*
*
*
*
*
************************************************************************
*
* Modified
a**********************************************************************/
:
/*
For "strcpy"
();
();
(),
c_store_char
();
(ptr)
nodal ptr;
{extern PHITYPE numconvert
PHITYPE type;
if
();
/*
if label = malloc
name
0);
c_store_code (if_label);
(type)
129
/* Generate
label
/* Check 4 conv It and rt types
/*
return
*/
converter */
(8);
/*
c_store_code (":\n");
"if" node */
*/
*/
;;
strcpy
if
(ptr->lptr)
terror
pt r->ipt r->ln)
c_store_code
c_store_code
c_store_code
c_store_code
c_store_code
return
BOOLEAN)
!=
*/
/* Jump for
*/
asmlanguage code
*/
*/
(ltype=semcheck
(ERR_il,
*/
*/
*/
*/
*/
/* Generate code
*/
(ptr->rptr)
("jmp ") ;
(if_label);
("\n");
(label);
(":\n");
/* Right type
(rtype);
is
returned
*/
(numconvert
/*
/*
/*
/*
();
*/
*/
*/
*/
(ptr));
/* Sema checker
*/
return
(semcheck
(ptr->lptr)
*/
*/
/A*************************
^ c omp
******************************/
PHITYPE
tcomp (ptr)
nodal ptr;
{extern PHITYPE numconvert
PHITYPE type;
130
; ;
;;
type = numconvert
switch (ptr->name)
case
(EQ_)
(ptr)
break;
case
(NEQ_)
case
(KW_
LESS_)
break;
case
(KW_
IN_)
break;
(KW_ + NOTIN_)
break;
terror
break
:
(ERR_11,
ptr->ln)
return
(BOOLEAN)
131
/*
*/
/*
/*
/*
/*
'/
-/
/
*/
*/
/A****************************************************************
*
PUBLIC DOMAIN SOFTWARE
Name
Semcheck Utilities.
File
Sem_U. c
* Authors
Maj E.J. COLE / Capt J.E. CONNELL
* Started
01/02/87
* Archived
04/03/87
* Modified
jt********************************************************************
* This file contains the following modules for the PHI parser:
*
*
*
Putvar
Getfptr
Name
Putdef
*
*
*
*
Makef orm
Finddef
Form
Add And
Putf orm
Getvtype
Getdtype
And Alloc
Findvar
Put_addr
Makevar
Del And
A***************************************************************
*
* Modified
A******************************************************************/
:
include <stri.ng.h>
/*
/**************************** Globals
FLAG err_found = FALSE;
long curr_addr = START_ADDR;
long curr_scope
form = FALSE;
*/
START_ADDR;
for "stpcpy"
it*****************************/
*/
*/
*/
*/
/* True if
/* Ptr to last
/* Typetable
typetable insert
*/
*/
/*
*/
/* Head of
NULL;
*/
NULL;
*/
/*
()
Create
formal node
*/
return
((fnode*)
calloc
(1,
sizeof
(fnode)))
/* Put type
(),
tracer;
132
*/
*/
list
*/
ptr->type
if
= type;
/*
If
/*
tracer->link = ptr;
ptr->link = NULL;
/*
Insert Node
/*
If no list,
(fhead
tracer
!=
=
NULL)
fhead;
else
fhead = ptr;
ptr->link = NULL;
{
insert
/*
*/
/* Put variable in
vartable
*/
();
ptr->nptr = treenode;
ptr->type = type;
ptr->form = form;
/* Fill entry
formal flag
*/
ptr->link = varhead;
varhead = ptr;
*/
ptr = NULL;
free (ptr)
/* Free
/* Set
*/
pointer space
*/
/*
/*
Travel list,
/*
/*
*/
*/
/*
Increment link
*/
*/
while (ptr
if
!=
NULL)
(ptr->nptr->index == varname)
return (ptr);
ptr = ptr->link;
return
/* No tally on
(NULL)
133
variable
*/
*/
;
;
in var stack
*/
return
(ptr->type)
defptr ptr
ptr->nptr
ptr->type
=
=
/* Put var
1,
sizeof
in
definitions table
(struct defnode)
/* Fill entry
treeptr;
*/
*/
= type;
= defhead;
def he ad = ptr;
ptr = NULL;
free (ptr)
ptr->link
/* Set top of
/* Free
linked list
pointer space
*/
*/
while (ptr
if
!= NULL)
*/
(ptr->nptr->index == varname)
return (ptr)
ptr = ptr->link;
return
/*
*/
/* No tally on variable
*/
*/
(NULL);
/*
*/
return
(ptr->fptr)
in def table
*/
return
(ptr->type)
134
*/
*/
();
/*
*/
/* Set
a_ptr = NULL;
free (a_ptr)
/*
Dispose of a_ptr
*/
*/
*/
*/
/******************************
Alloc *****************************/
And.
and_ptr
and_alloc {)
/*
Create
*/
(1,
sizeof
(struct and_struct
/it**************************** Del
and.
void
del_and (ptr)
and_ptr ptr;
{extern and_ptr and_head;
and_ptr search = and_head;
if
(ptr
and_head)
!=
while (search->link
!=
ptr)
******************************/
/* Delete entry into the and list
*/
*/
*/
*/
*/
/* Set pointer
*/
search = search->link;
search->link
ptr->link;
/*
*/
ptr->link = NULL;
/*
'/
free
(ptr)
line_num)
*/
*/
*/
*/
int err_num,
iine_num;
{extern ErrorHandler ();
err_found
TRUE;
/*
&
*/
nodal ptr;
135
*/
*/
*/
*/
*/
;;
PHITYPE type;
/* Node type
*/
ptr->addr = curr_addr;
ptr->scope = curr_scope;
curr_addr = curr_addr + (types [type] .bytes
/* Set
*/
if
(curr_addr
terror
>
MAXADDR)
(ERR_mm,
node address
exceeds
*/
*/
*/
*/
ptr->ln)
*/
*/
*/
(7),
*/
String prefix
Insert string terminator
/* Convert long seed to string
/* Concatenate strings
/* Incr int to avoid duplication
*/
*/
/*
/*
/*
"string = 'a';
"(string + 1) = ENDSTRING;
stcl_d (stringl, seed);
string = strcat (string, stringl);
++seed;
return (string);
*/
*/
*/
varptr ptr;
{
if (ptr->form) return
else return (FALSE)
(TRUE)
136
*/
*/
APPENDIX K
ROCK COMPILER
/A******************************************************************
*
PUBLIC DOMAIN SOFTWARE
Name
Code Generation Module
* File
Code_Gen
* Authors
Maj E.J. COLE / Capt J.E. CONNELL
* Started
02/06/87
* Archived
04/10/87
* Modified
EC
04/13/87 Code output to vdisk
A***************************************************************
* This file contains the following modules for the PHI compiler
*
C_Store_Code
C Ending
Ac ode
C_I_Const
C_I_Op
C_Startup
C_Printcode
C_Jmp
C_I_Form
C Call Proc
C_Of f_Insert
C_Ztor
C_Start_Proc
C End Proc
*
Algorithm
*
This module contains the procedures necessary for code generation.
C_startup initializes the run_time file, & the semantic checker will*
*
call the procedures as necessary. Note that "c_store_code" is a
genaric generator which will spew any string given as an arg to the *
*
output file.
*
*
*
*
*
**********************************************************
* Modified
04/13/87 Code output to vdisk., drive "d:"
***************************************************
:
EC
/* For
/* Error flag
/* Current virtual address
level
I/O
*/
/*
/* Ptr to chars
*/
*/
137
*/
*/
*/
if (!err_found)
while ('(string + ptr) != NULL)
=
* (code_buf fer
+ buff_ptr)
/'
/*
-f
(string
*/
*/
ptr);
+ ptr;
+^buff_ptr;
jump command*/
of asm
'/
*/
char *name;
(
c_store_code (name);
c_store_code (":\n");
)
/*
/*
*/
/
char 'name;
{
c_store_code
c_store_code
c_store_code
c_store_code
("call del_scope\n")
("ret\n");
(name);
(":\n");
*/
'/
char 'name;
c_store_code ("call
c_store_code (name);
c_store_code ("\n");
")
/A************************* q
Form ** ***************************** /
void
c_i_form (num)
char *num;
{
c_store_code
c_store_code
c_store_code
c store code
("mov ex,");
(num);
("\n");
("call i formal\n");
138
'/
'/
;;
/a************************** q
c
void
const
; ;;
Const ******************************/
(name)
*/
*/
char *name;
{
store_code
c_store_code
c_store_code
c_store_code
("mov ax,");
(name)
("\n")
("call iputvalue\n"
/a*************************** q
void
c_i_op (op)
optype op;
{extern void terror
op *********************************/
arith ops
switch (op)
case (ADD)
c_call_proc ("iadd");
break;
case (SUB)
c_call_proc ("isub");
break;
case (DIVIDE)
c_call_proc ("idivn");
break;
c_call_proc ("imult")
case (MULT)
break;
return;
default
{
'
139
*/
*/
; ;
()
*/
*/
/* Output
*/
[];
/* set
/*
0_WRONLY, NULL)
file
up file name
save prefix
&
*/
*/
*/
/
file
Endincr ********************************
/A*********************** q
void
c_ending
/*
()
*/
err_f ound)
c_store_code ("call print_top\n")
*/
/* Print address pointed to by
if
CNTRL_Z;
();
ending
/* If no error, put asm language
/* delimiter to file
/* Output code to a file
*/
*/
*/
*/
*/
>
/it**************************
ztor ********************************/
void
c_ztor ()
{}
/A***************************
p^Q ode
void
acode (ptr, type)
*****************************/
/* NOTE
USES EMPTY STATEMENTS
/* FOR REAL OPERATIONS
*/
*/
*/
nodal ptr;
FLAG type;
(extern void terror
int name;
();
name = ptr->name;
switch (name)
case (ADD_)
if (type == REAL)
else c_i_op (ADD)
break;
case (SUB_)
if (type == REAL)
else c_i_op (SUB)
break;
case (MULT_)
if (type == REAL);
else c_i_op (MULT)
break;
case (RDIV_)
break;
{
/*
Addition
*/
/*
Subtraction
*/
/*
Multiplication
*/
/* Real Division
140
*/
case
(IDIV_)
c_i_op (DIVIDE);
break;
:
/*
141
Integer Dilvision
APPENDIX L
ROCK COMPILER
USER INTERFACE
**********************************************************************
User Interface
Name
* File
User .C
* Authors
Maj E.J. COLE / Capt J.E. CONNELL
* Started
04/01/87
* Archived
04/10/87
* Modified
***********************************************************************
* This file contains the following modules for the PHI compiler
*
/
User_err
Print header
Prog_name
User
Get name
P
Close
Algorithm
This module contains the procedures necessary for the user in- *
*
terface.
Prog_Name gets the user's choice of program by calling Get_Name *
*
Print header is called to print the initial screen display on console, & the User procedure is the overall coordinator of the inter- *
*
face.
User_Err and P_Close are both independent procedures. User_Err *
handles output in the event that an error or errors have been found.*
P_close is called by "Rock._Main" to ensure the input file has been *
*
closed.
*
*
*
*
*
*
*
*
:
********************************************************************
* Modified
*********************************************************************
/*
(),
mov_cursor
(),
c!r_window
for "getch
*/
()"
();
FILE "infile;
/* File handle of
source file
*/
*/
*/
/* Screen interface
();
142
; ;;
;; ;
c1rscr
*/
*/
*/
*/
/*
*/
*/
errors = fopen
numblocks
(ERRORFILE,
"r")
/*
/*
/*
/*
/*
PAUSE);
("%s",
input = getch
();
fclose
(errors)
c1rscr
*/
*/
*/
*/
*/
(input == ESCAPE)
if
exit
(I);
*/
*/
/*
/*
/*
/*
()
{int ch,
count =
do
0;
if
(ch = getch
if (count)
putchar
putchar
putchar
== BACKSPACE)
--count;
())
{
/*
/*
(ch)
('
');
*/
*/
ltr by Itr */
Backspace
Insert blank
/* Eat
(ch)
*/
*/
*/
*/
*/
*/
/* Escape pressed;
exit
*/
/*
putchar (ch)
u_name [count] = ch;
+ x count;
while ((count <= BUFFLENGTH)
*/
ch
!=
&&
EOLN)
143
*/
*/
;; ;;
u_name (count
; ;
;;
/*
= 0;
1]
*/
/* Get
()
*/
do
clr_window (9,1,21,79);
mov_cursor (10,2);
printf (GETPROGRAM)
getname
infile = fopen (u_name, "r")
(
if
(!
infile)
(getch
*/
== ESCAPE)
()
c1rscr
exit
sen
mov_cursor (20,33);
printf (FILE1_ERRCR)
mov_cursor (21, 16);
printf (FILE2_ERROR)
if
*/
*/
/* Exit
if ESCAPE
pressed
*/
(1)
}
while
(!
infile);
mov_cursor (13,28);
printf (WAIT)
}
()
for user
*/
c1rscr
mov_cursor (1,33);
printf (HEADER1);
mov_cursor (2,24);
printf (HEADER2)
}
/it**************************** p close
void
p_close
*^*** *************************
/*
()
*/
f close
infile)
print_header
prog_name
(
while
I
*/
*/
(u_name
==
[count]
'
*/
/* Copy root of input file name
*/
/* Loop until end of input name
/* reached OR until end of str is */
*/
/* reached, if no
extension
'
/* Insert end of
144
string value
*/
APPENDIX
ROCK COMPILER
RUNTIME UTILITIES
***********************************************************************
*
* Name
Phi Runtime Utilities
*
* File
U.a86
*
* Authors
Maj E.J. COLE / Capt J.E. CONNELL
*
* Started
01/26/87
*
* Archived
16 Feb 87
* Modified
*
16 Apr 87 Stack/Varspace Crash error check
EC
***********************************************************************
:
***********************************************************************
ALGORITHMS
1.
Input/Output:
access it.
3.
Stack:
The stack pointer is the si register, which is initialized to 3270C.
grows, the si register is reduced by two. Ppush and ppop will push ana pop two
registers. "Push_one" and "Pop_one" will push and pop single words to and from
4.
5.
Scoping:
Initially the scope is set to 0: the global scope.
The variable
space containing the outer scope, and the variable "S_Nest" contains the current
new scope is created, "S_Nest" is increased by one, and the three-tuple S =
(L = Static Link, pointing nesting level of the outer scope, N is the nesting
is the base address of display of variables for this scope.
When a scope is deleted, the top of the stack is saved, the top instantiation of
and S_Link and S_Nest are recalculated.
***********************************************************************
***********************************************************************
* Modified
*
EC
22 Feb 87 Add/del_scope changed to save TOS
*
16 Apr 87 Added check for stack/varspace crash, includes*
*
*
message to observer
***********************************************************************
:
145
.it********************************************************************
*
*
Public Procedures
.it*********************************************************************
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
i_mov
i_formal
igetvaiue
finis
iputvalue
find_addr
add_scope
del_scope
initial
finis
ppush
ppop
iassign
lor
land
iequ
ineq
ilt
igt
ilteq
igteq
negation
iadd
isub
imult
idivn
print_top
A******************************************************************
*
I/O Procedures
*******************************************************************
*********************** print char ********************************
Print a char to the screen
assumes letter to be printed is in dl register
print_char
push ax
mov ah, 06
int 21h
pop ax
/save registers
;put int vector
ret
mov dl, 10
eoln:
call print_char
mov dl, 13
call print_char
ret
Prints, as
146
print_num:
push ax
push bx
push ex
push dx
mov ex, 10000
emp bx,
jge small
mov dx,
call print_char
neg bx
'
small:
emp bx,
jl final
rtest
10
rlf not
xor dx,
10
jump
deer ex by factor of 10
bx
Divide
Move remainder to bx
Add for ascii
Print
up dx for division
Divide base value by 10
dx
ex
ax,
ex,
zero,
^Otherwise,
div ex
mov bx, dx
add ax, 4 8
mov dx, ax
call print char
mov
mov
div
mov
emp
if less than
Divide bx by ex
Set up dx register
mov ax, bx
div_loop:
xor dx, dx
div ex
emp ax,
jne P_l oop
mov ax, ex
mov ex, 10
xor dx, dx
div ex
mov ex, ax
jmp div_loop
mov ax,
p loop:
xor dx, dx
Negate
Set
10
ex
ex,
ax,
ax
If base value
Else continue
jne p loop
final
add bx, 4 8
mov dx, bx
call print char
call eoln
pop dx
pop ex
pop bx
pop ax
ret
1,
end loop
End of line
add
mov
add
mov
di,
dx,
mov di si
,
vars [di
vars [di
;Mov offset to ex
di,2
ex,
147
call find_addr
mov di, ex
mov bx, vars [di]
call print_num
call eoln
ret
push ax
mov ah,
int 21h
pop ax
/save register
9
ret
*******************************************************************
*
Stack Procedures
*******************************************************************
************************* ppush ***********************************
Pushes values from ex (offset) and di (nesting level)
ppush:
sub
mov
sub
emp
mov vars
si,
vars
si,
si,
[si],
offset in stack
stack pointer
Nest level into stack
stack pointer
;Check for stack/varspace crash
;If no crash, go to end
;Get string for error message
;Print it
;Hait execution
ex
;Put
Inc
;Put
; Inc
[si],
di
curr_addr
p_return
mov dx, offset crash
call print_s
call finis
jg
p_return:
ret
ret
add si,
mov di, vars
add si,
mov ex, vars
[si]
Set up ptr
;Get nesting level
[si]
;Recalc pointer
;Get offset
ret
add si, 2
pop_one:
mov ex, vars [si]
148
*******************************************************************
*
*
Varspace Management Procedures
*******************************************************************
*********************** i As s ign ***********************************
Assign an integer value to a variable space in current scope
Assumes value is in ax; offset is set to current max offset
mov di, s_link
iassign:
;get static link
sub di,2
mov di, varsfdi]
add di, max_offset
mov vars[di], ax
add max_offset,2
add curr_addr
ret
igetvalue:
call ppop;
mov dx, di
call find_addr
mov di, ex
mov ax, vars [di]
;Get addr of
(S_Nest, Max_Offset)
ret
(S_Nest,
Max_Offseti
(S_Nest, Max_Offset)
;Inc max offset and curr_addr
,-Store
ret
*******************************************************************
*
Scoping Procedures
*******************************************************************
********************* Find Addr ***********************************
Returns address of variable at nesting level dx, offset ex to ex reg
find_addr:
mov di,
s_link
j
dx
149
exit loop
add di,
mov di, es:vars[di]
jmp find_loop
f
ar.d
loco
sub di,2
add ex, es:vars[di]
out:
ret
ret
********************
Deletes a scope
dq]_
Scope ************************************
ret
*******************************************************************
*
Begin/End Procedures
*******************************************************************
************************ initial **********************************
initialize the stack, and variables
must initialize ex to base of stack heap before calling this
mov si,
initial:
mov di,
mov ex,
call ppush
ret
SPACE_TOP
150
;end procedure
mov ax,04c00h
int 21h
ret
*****************************************************************
*
*
Booleans
*****************************************************************
************************* Necrat ion ******************************
Negates a boolean value
;Get boolean
negation:
call igetvalue
cmp ax, 1
jne zero
mov ax,
jmp p
mov ax,
zero
call iputvalue
p:
ret
Jump to end
/Stuff boolean
&
lor:
reg
/save boolean
/get 2nd value using the stack ptr
/Perform or
/Put value into varspace & in stack
mov bx, ax
call igetvalue
or ax, bx
call iputvalue
ret
land:
/Perform and
/Push boolean address onto stack
ret
iequ:
/Jump if equal
/put false value into varspace
/Put value into varspace, addr on stack
ret
eql:
mov ax,
jmp cont
ret
TRUE
151
ineq:
;Jump if equal
;put false value into varspace
;Put value into varspace, addr on stack
ret
mov ax,
neql:
jmp fal
ret
TRUE
************************* Ht **********************************
Takes logical less than of two integers and stacks address of answer
Returns true if first value is less than the second value
call igetvalue
mov bx, ax
call igetvalue
cmp ax, bx
jge less
mov ax, TRUE
call iputvalue
con:
lit:
Compare
Jump if less
;put false value into varspace
;Put value into varspace, addr on stack
;
ret
less:
mov ax,
jmp con
ret
FALSE
call igetvalue
mov bx, ax
call igetvalue
cmp ax, bx
jle greater_than
mov ax, TRUE
call iputvalue
conl:
/Compare
/Jump if greater than
/put false value into varspace
/Put value into varspace, addr on stack
ret
greater_than
mov ax,
FALSE
jmp conl
ret
call igetvalue
mov bx, ax
call igetvalue
cmp ax, bx
jg lteq
Ilteq:
/Compare
/Jump if less to error
152
'put
ret
lteq:
jmp con2
ret
Igteq:
/Compare
Jump if greater than or equal to
;Pput false value into varspace
/Put value into varspace, addr on stack
;
ret
mov ax,
gteq:
jmp con3
ret
FALSE
*******************************************************************
*
*
Integer Operations
*******************************************************************
************************* i add ************************************
Adds two integer values
Assumes offset off second value is in SI register
Offset of first value is at the top of the stack
call igetvalue
mov bx, ax
call igetvalue
add ax, bx
jo err
ladd:
call iputvalue
ret
err:
mov dx,
call print_s
call eoln
call finis
ret
offset add_err
call igetvalue
mov bx, ax
call igetvalue
isub:
sub ax,
bx
153
errs
jo
/if overflow,
call iputvalue
ret
mcv dx,
errs:
call print_s
call eoin
call finis
ret
offset sub_err
call iputvalue
rec
errl:
mov dx,
call print_s
call eoln
call finis
offset mul_err
/print it
;end
ret
idivn
;Save Registers
push ex
push dx
call igetvalue
mov bx, ax
call igetvalue
xor
mov
mov
emp
dx,
cl,
ch,
bx,
;Get divisor
Mov divisor to bx
;Get dividend to ax
;
dx
Set dx to
;cl and ch are negative flags
;
test2
errd
jg
je
;bx
;bx
;bx
;bx
neg cl
neg bx
test2
is
is
is
is
;test dividend
emp ax,0
jge dloop
neg ch
neg ax
dloop:
sub ax,bx
emp ax,
dene
jl
inc dx
jmp dloop
/store result in dx
/continue loop
154
done
/Multiply ch and cl
mov al, cl
done:
mul ch
cmp al,
jge-dend
neg dx
mov ax,dx
dend:
pop dx
pop ex
call iputvalue
no action
;Put
ret
mov dx,
errd:
call print_s
call eoln
call finis
offset div_err
;end
ret
***********************************************************************
Function
Calling Procedures
***********************************************************************
******************************
mov **********************************
Movs integer or boolean actuals with addresses at the top of stack to
the lowest addresses within a scope
Assumes bx has number of actuals needed to be moved
j_
i_mov:
pep ret_addr
call add_scope
strt:
pop dx
pop ex
call find_addr
mov di, ex
;rnov
jne strt
push ret_addr
ret
ret
***********************************************************************
*
*
Variables
***********************************************************************
dseg
155
EQU
EQU
EQU
2,2100
max_offset
curr_addr
s_link
dw
S_nest
ret_addr
-32700
SPACE_T0P
dw
db
'
mul_err
db
db
add_err
db
'MULTIPLICATION OVERFLOW,
IDIOT!'
db
'ADDITION OVERFLOW,
DIMWIT!'
'S'
db
'
'
crash
db
FOOL!'
'$'
sub_err
db
'DIVISION BY ZERO,
$'
db
'$'
dw
156
APPENDIX N
TEST SUITE
c (20)
$Z
-> $Z;
where
c (n)
else 3
==
if
= 2 then
3 * n
+ n endif
let c
$Z -> $Z;
c (1 * 2) where c (n)
:
==
n * 3
let c
c (k
$Z
2)
c
-> $Z;
where k == 2 and
(n) == if n = 1 then n
* 3 else n
+ 4 endif
$Z
c (k * 2)
$Z
(n)
==
n * 3
-> $Z;
where
c (0)
c (n)
==
if
n =
then
* n endif
else c (n
1)
else c (n
1) *
let
$Z
-> $Z;
where c
c (5)
where k == 2 and c
let
-> $Z;
(n)
==
if
n =
then
let c
$Z
-> $Z;
157
n endif
where c
c (3)
--
==
if
n =
then
else n * c (n
1)
endif
else n * c (n
1)
endif
let
$Z
-> $Z;
where c
c (7)
--
(n)
(n)
==
if
then
==
n = 6
let
c(2
$Z
$Z
$Z
in
function
-> $Z;
where c(n,m,x) == n
1,3,4)
* x
letc:$Z->$B;
let d
$Z -> $Z;
:
c (1) where
c (n) ==
d(k)
= d(l) where
== k
let
let
lete
$Z -> $Z;
$Z -> $Z;
:$Z->$B;
c (3) where
c (n) ==
1 + d(n) where
d(k)==ife(l)
then k else k + 1 endif
where e (k) == k = 3
158
$Z -> $Z;
$Z -> $Z;
let d
$Z -> $B;
let e
let
c (3) * 10
where
==
1 + d(n) where
d(k)==ife(l)
then k else k + 1 endif
where e (k) == k = 3
c (n)
by constant
$Z -> $Z;
let d
$Z -> $Z;
let e
$Z -> $B;
let
c (3) * c(4)
c (n) ==
where
1 + d(n) where
d(k)==ife(l)
then k else k + 1 endif
where e (k) == k = 3
and b == 10
--
$Z -> $Z;
let d
$Z -> $Z;
lete:$B->$B;
let
c (3) * c(4)
c (n) ==
where
1 + d(n) where
d(k)==ife(2 = 3A4 =
then k else k + 1 endif
where e (k) == k
--
5)
c (3) *
b where b == 10 and
== n * d (n) where
c (n)
d(n)==3
~
159
let
let
$Z -> $Z;
$Z -> $Z;
c (3) * b
where b == 10 and
== n * d (n) where
d (n) == 3 * e where e == 10
c (n)
let
let
let
$Z -> $Z;
$Z -> $Z;
$Z -> $Z;
--
(g)
== g +
let
let
let
$Z -> $Z;
$Z -> $Z;
$Z -> $B;
c (3) where
c (n) ==
d(k)
+ d(n) where
if
where e
--
(b)
== b =
endif
$Z
let
let
d $Z;
-> $Z;
where c (n) == d
and d == 10 * 5
c(5)
--
let
let
let
$Z;
$Z;
$Z;
where c == (d + 10 + e where
==
10)
160
and d == 10
Test for Multiple ands
let
let
let
$Z;
$Z;
$Z;
where c == d + 10 +
and d == 10
and e == 10
let
let
let
$Z -> $Z;
$Z -> $Z;
$Z -> $Z;
c(5)
--
let
let
let
$Z -> $Z;
$Z -> $Z;
$Z -> $Z;
c(5)
--
let
let
let
== 100
nested wheres
$Z;
$Z;
$Z;
where c == d + 10 + e where
e == 10 and d == 10
-Test for Multiple ands
$Z -> $B;
let d
$Z -> $B;
let k
$Z -> $Z;
let
161
c(l)
c (n)
d(2) where
== n = 3 and
(n)
--
(1)
== (1 = k (n
== + 10)
1)
where
let c
let
let
$Z -> $Z;
$Z -> $Z;
$Z -> $Z;
c(5)
--
$Z -> $Z;
let d
$Z -> $Z;
let e
$Z -> $Z;
let
c(5)
--
let
let
let
$Z -> $Z;
$Z -> $Z;
$Z -> $Z;
c(5)
---
let
let
let
$Z * $Z -> $Z;
$Z * $Z -> $Z;
$Z * $Z -> $Z;
162
c(5,l)
--
$Z
-> $Z;
let
let
d $Z -> $Z;
let
$Z
-> $Z;
c(5)
--
let
let
let
$Z -> $Z;
$Z -> $Z;
$Z -> $Z;
and
--
e(r)
== 20 +
+k
let
let
let
$Z -> $Z;
$Z -> $Z;
$Z -> $Z;
and
--
e(r)
== 20 +
==
(r *
100 where
==
2)
+k
let
let
let
let f
$Z -> $Z;
$Z -> $Z;
$Z -> $Z;
$N ->
$Z;
and
e(r)
== 20 +
==
f (r)
163
(r *
100 where
==
2)
and
--
==
f(r)
let
let
let
let f
$Z -> $Z;
$Z -> $Z;
$Z -> $Z;
$N -> $Z;
and
and
--
e(r)
f(r)
== 20 +
== k
==
(r *
100 where
==
2)
f (r)
$Z -> $Z;
let d
$Z -> $Z;
let e
$Z -> $Z;
let
let f
$N -> $Z;
and
and
e(r)
f(r)
== 20 + r + f(r)
== if r = then 100
==
else f (r
(r *
1)
100 where
==
2)
endif
--
--
$Z -> $Z;
d $Z -> $Z;
let e
$Z -> $Z;
let
let
let f
let
$N ->
zebra
$Z;
$Z;
==
2)
---
let
let
let
$Z -> $Z;
$Z -> $Z;
$Z -> $Z;
164
c(5)
--Note the use of parenthesis here if they are removed, the program will
-bomb because t will be undefined
:
ERROR TESTING
let
:$z;
letj:$Z;
let i:$z;
where i ==x%j
and x ==5 and j ==0
- Gives
let
b:$b;
let i:$Z;
let j:$z;
let
n:$n;
let x: $z;
b then i
~(b A b) then j
else x endif
where
b == i=2 where
if
elsif
i==0
and where j
and where z == 69
Gives two parser errors
where following "and"
let fac
fac (5)
$N
line 13
and
14,
undefined and
-> $N;
where fac
- Check
(n)
==
fac (n
1)
1000
- Check
165
Check
--
for Subtraction
30000
Overflow
:$Z->$B;
letd:$Z->$B;
$Z -> $Z;
let k
let g
$Z -> $Z;
letc
c(l)
d(2) where
(n)
(1)
c
--
== ( 1 = k (n - 1 ) where
== + 10) and
(n) == n = 3
1
--be
MISCELLANEOUS TESTS
let
b:$b;
let i:$Z;
let j:$z;
let
n:$n;
let x: $z;
if(bV~b)theni
V ~b)
elsif (b
then
where
b == i=2 where
else x endif
i==0
and j ==2
and x == 69
let
b:$b;
let i:$Z;
let j:$z;
let
n:$n;
let x: $z;
if~(bV~b)theni
elsif
~(b
A ~b) then j
else x endif
where
== i=2 where
i==0
and j ==2
and x == 69
b
166
should give 2
Check and, or, notand, notor
--
---
Check
Especially, check
let
a:$Z;
let
b:$z;
let
y:$n;
let
else, elseif
all in
combination
$z;
let x:
let
if,
$n*$n->$n;
times $n*$n->$n;
f:
f(30,30)
where
== times(a,b) where
times(x,y) == x*y
f(a,b)
Multiargument Checking
Natural Type Checking
let
a:$Z;
let
b:$z;
let
y:$z;
$z;
let x:
let
let
$z*$z->$z;
times $n*$n->$z;
f:
f(30,4)
where
== times(a,b) where
times(x,y) ==
f(a,b)
if
= l)thenx%y
else 2 endif
end
c $Z -> $B;
letd:$Z->$B;
let k
$Z -> $Z;
let g
$Z -> $Z;
let
c(l)
d(2) where
(n)
==
c (n)
--
=k
(n - 1) where
+ 10) and
== n = 3
(1
k 0) ==
167
APPENDIX O
ROCK COMPILER
USER'S
MANUAL
Installation
I.
procedures:
1)
Change
floppy disk.
2) Type "INSTALL", followed by a space and the drive and
directory on which you want the program installed.
Note
that the
Rock compiler
operate:
II.
a.
Type
figure
in
"ROCK"
in
to appear.
ROCK COMPILER
Press Escape
Program
to
Key
to Exit
Compiler
Compile ->
Figure
168
If
a source
in a file
ROCK COMPILER
Press Escape
Program
to
Compile ->
Key
to Exit
Compiler
SQRT.PHI
Compiling: Please Wait
Figure 2
ROCK COMPILER
Key
to Exit
File not
Found
Press Escape
Program
to
Compile ->
Compiler
NOTFOUND
Press
ESCAPE
to exit,
Figure 3
Errors.Phi.
figure 4.
169
to continue
ROCKY ERRORS
formals list missing or error
misplaced or missing
number of errors = 2
line
line
PRESS
formals
in
list
If
d.
file
compilation
is
will be created.
occurs, neither
file will
WARNING
If
same
prefix,
and an
.obj
be created.
the
exit,
press
III.
Error Handling
COMPILER ERRORS
Message
incomplete
Explanation
Either an
'l->'
where
without following
logical
OR is
'/',
single backslash
where a
(V)
170
"I"
"l->"
was found
logical or construct
was expected.
'$'
without following
RVNVZVB'.or
invalid numeric
constant
literal
==>
An
illegal
in this
3.
constant
example,
was found;
"3."
An
without ending
A character with
unidentified char
in input
An
'1'
program ==> #
found
in the
no meaning was
source
MEMORY OVERFLOW
DURING COMPILATION
machine
file; '#',
in this
example.
too big
is
to compile.
error in statement
following
==>
An
illegal
statement follows
'*',
in the
example.
error in type
definition following
==>
An
An
unable to complete
definition of
after
keyword
after
LET
missing or misplaced
blockbody
A declaration, preceded by
';'
after definition
valid qualexp/exp
An
invalid expression
was found
An
expression defining a
type was either missing or incorrect.
def
misplaced or missing
')'
TYPE
found without an
in the
example.
identifier.
TYPE
Improper or no expression found
unable to complete
def/auxdef following
keyword
')'
following
AND
171
AND.
keyword
WHERE
WHERE
Formals found without closing
missing or misplaced
closing paren in formals
parenthesis.
list
error in processing
One
multiple Actuals
error
missing
after
literal
keyword FILE
IF statement
actual.
file-
missing or invalid
exp following
actual
KEYWORD
No ENDIF
w/o ENDIF
error in formals
preceding
list
l->
preceding
it
formals
contained an error.
missing or invalid
QualExp following
it.
COMMA operator
An
ArgBinding
check QualExp
improper expression in an
argument binding was found, or
the closing bracket on an argument binding
error in
-
or closing bracket
OZONE LEVEL
Unimplemented
I -
feature found,
implemented
in
1999
NATURAL EXPECTED
types or
improper
a single
UNDEFINED VARIABLE
IN AND SCOPE
An
in
172
in its scope.
FUNCTION WITHOUT
FUNCTION DEFINITION
declaration of
FORMALS MISMATCHED
Formals
function
No
An
its
function definition
in either type or
as those in the function's declaration.
in a
number
same
INVALID CONSTANT
EXPRESSION
An
incorrect type
a real
invalid constant
was found.
OUT OF RUN-TIME
was found.
MEMORY SPACE
the
RUN-TIME ERRORS
DIVISION BY ZERO
MULTIPLICATION OVERFLOW
ADDLTION OVERFLOW
An
SUBTRACTION OVERFLOW
in a
173
No. Copies
1.
Library,
Code 0142
Chairman, Code 52
Department of Computer Science
Naval Postgraduate School
Monterey, California 93943
3.
4.
5.
B.
J.
Capt.
J.
E. Connell,
USMC
Maj. E.
J.
Cole,
USMC
156HavilandRd
Ridgefield, Connecticut
8.
06877
Cameron
Station
Alexandria, Virginia
22304-6145
174
Thesis
C53169
c.l
Thesis
C53159
c.l
Cole
Implementation of a
compiler for the functional programming language PHI - (D.
Coie
Implementation of a
compiler for the functional programming language PHI - <D.