mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 00:14:25 +00:00
1453 lines
40 KiB
Bash
1453 lines
40 KiB
Bash
#! /bin/sh
|
|
# This is a shell archive. Remove anything before this line, then unpack
|
|
# it by saving it into a file and typing "sh file". To overwrite existing
|
|
# files, type "sh file -c". You can also feed this as standard input via
|
|
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
|
|
# will see the following message at the end:
|
|
# "End of shell archive."
|
|
# Contents: README Makefile plm-lex.l plm-manifest.h plm-parse.y
|
|
# scope.c scope.h
|
|
# Wrapped by hays@hayshaus on Tue Apr 5 20:34:58 1994
|
|
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
|
|
if test -f 'README' -a "${1}" != "-c" ; then
|
|
echo shar: Will not clobber existing file \"'README'\"
|
|
else
|
|
echo shar: Extracting \"'README'\" \(7926 characters\)
|
|
sed "s/^X//" >'README' <<'END_OF_FILE'
|
|
X$Id: README,v 1.4 1994/04/05 20:33:58 hays Exp $
|
|
X
|
|
XAh, the wisdom of the ages...
|
|
X
|
|
XIntroduction
|
|
X------------
|
|
X
|
|
XWhat you are looking at is a basic (very basic) parser for a PL/M
|
|
Xlanguage.
|
|
X
|
|
XThe parser does nothing useful, and it isn't even a terribly wonderful
|
|
Xexample. On the other hand, it appears that no one else has bothered
|
|
Xto publish even this much, before.
|
|
X
|
|
XHowever, the parser does recognize a language very like PL/M-86,
|
|
XPL/M-286, or PL/M-386, as best we can determine.
|
|
X
|
|
XAll the information used to derive this parser comes from published
|
|
Xmanuals, sold to the public. No proprietary information, trade
|
|
Xsecrets, patented information, corporate assets, or skulduggery was
|
|
Xused to develop this parser. Neither of the authors has ever seen the
|
|
Xsource to a working PL/M compiler (or, for that matter, to a
|
|
Xnon-working PL/M compiler).
|
|
X
|
|
XImplementation Limits
|
|
X---------------------
|
|
X
|
|
XThis PL/M parser was developed and tested on a 486DX2/66 clone PC
|
|
Xrunning Linux. The C code is written for an ANSI-compliant C
|
|
Xcompiler; GCC was used in our testing. Also, flex and bison were
|
|
Xused, not lex and yacc. Paul Vixie's comp.sources.unix implementation
|
|
Xof AVL trees was used to implement symbol table lookups.
|
|
X
|
|
XYou should expect some problems if you plan on building this parser
|
|
Xwith a K&R style C compiler. Using yacc and/or lex may be
|
|
Xproblematic, as well.
|
|
X
|
|
XThis parser does not support any of the "dollar" directives of a
|
|
Xproper PL/M compiler. In fact, it will croak with the helpful message
|
|
X"parse error". Thus, implementing include files and compiler
|
|
Xdirectives is left as an exercise for the reader.
|
|
X
|
|
XThe macro facility (aka "literally" declarations) depends on the
|
|
Xlexical analysis skeleton allowing multiple characters of push-back on
|
|
Xthe input stream. This is a very, very poor assumption, but, with
|
|
Xflex, at least, workable for this example. A real PL/M compiler would
|
|
Xallow literals of unlimited length. To find the offending code, grep
|
|
Xfor the string "very weak" in the file "plm-lex.l".
|
|
X
|
|
XNo error recovery is implemented in the parser, at all.
|
|
X
|
|
XThere are no shift-reduce conflicts, nor reduce-reduce conflicts.
|
|
X
|
|
XThere are a couple of places in the parser where similar constructs
|
|
Xcannot be distinguished, except by semantic analysis. These are
|
|
Xmarked by appropriate comments in the parser source file.
|
|
X
|
|
XThe "scoped literal table" implementation depends on Paul Vixie's
|
|
X(paul@vix.com) public domain AVL tree code, available as
|
|
Xcomp.sources.unix Volume 27, Issue 34 (`avl-subs'), at a friendly ftp
|
|
Xsite near you. We use "gatekeeper.dec.com". The benefits of using
|
|
XAVL trees for a symbol table (versus, say, hashing) are not subject to
|
|
Xdiscussion. We used the avl-subs source code because it is reliable
|
|
Xand easy to use.
|
|
X
|
|
XThis grammar has been validated against about 10,000 lines of real and
|
|
Xartificial PL/M code.
|
|
X
|
|
XPL/M Quirks
|
|
X-----------
|
|
X
|
|
XPL/M has some very interesting quirks. For example, a value is
|
|
Xconsidered to be "true", for the purposes of an `if' test, if it is
|
|
Xodd (low bit set). Thus, the value 0x3 is true, whereas 0x4 is not.
|
|
XThe language itself, given a boolean expression, generates the value
|
|
X0xff for true. [This factoid doesn't affect the parser per se, but
|
|
Xdoes appear to be the main pitfall for those whose hubris leads them
|
|
Xto translate PL/M to C.]
|
|
X
|
|
XString constants can contain any ASCII value, excepting a single
|
|
Xapostrophe, a newline, or 0x81. The latter, presumably, has something
|
|
Xto do with Kanji support.
|
|
X
|
|
XTo embed a single apostrophe in a string constant, two apostrophes may
|
|
Xbe used. Thus, 'k''s' is a string consisting of a letter k, a single
|
|
Xapostrophe, and a letter s. Strings are not null terminated, so our
|
|
Xexample string, 'k''s', requires just three bytes of storage.
|
|
X
|
|
XPL/M supports a macro language, of sorts, that is integrated into the
|
|
Xlanguage's declaration syntax:
|
|
X
|
|
X declare Ford literally 'Edsel';
|
|
X declare Mercury literally 'Ford';
|
|
X
|
|
XAfter the above declarations, any instance of the identifier "Ford"
|
|
Xwill be replaced with the string "Edsel", and any occurrence of the
|
|
Xidentifier "Mercury" will be replaced by the string "Ford", which will
|
|
Xthen be replaced by the string "Edsel". The literal string can be
|
|
Xmore complicated, of course. Only identifiers are subject to
|
|
Xsubstitution - substitution does not occur inside string constants.
|
|
X
|
|
XLiteral macros are parameterless, and obey the scoping rules of the
|
|
Xlanguage. Thus, it is possible to have different values for the same
|
|
Xmacro in different, non-nested scopes. [Exercise: Why can't you have
|
|
Xdifferent values for literals in nested scopes?]
|
|
X
|
|
XKeywords, of course, cannot be macro names, because they are not
|
|
Xallowed as variable names.
|
|
X
|
|
XPL/M allows dollar signs ("$") to be used inside keywords,
|
|
Xidentifiers, and numerical constants. PL/M is also case insensitive.
|
|
XThus, the following two identifiers are the "same":
|
|
X
|
|
Xmy_very_own_variable_02346
|
|
X
|
|
Xm$Y_$$$VeRy_$$O$$$$$W$$$$$$N_varIABLE$$$$$$$$$$_$02$346
|
|
X
|
|
XLoverly, eh? Obfuscated C, stand to the side.
|
|
X
|
|
XCasting in PL/M (a relatively late addition to the language) is
|
|
Xprovided by a motley assortment of functions with the same names as
|
|
Xthe basic types to which they are casting, accepting a single argument
|
|
Xof some other (or even the same) type.
|
|
X
|
|
XNote that the EBNF grammar published in what must be considered the
|
|
Xdefinitive work, _PL/M Programmer's Guide_, Intel order number
|
|
X452161-003, Appendix C, is incorrect in several respects. If you're
|
|
Xinterested in the differences, we've preserved, as much as is
|
|
Xpossible, the production names of that EBNF in the YACCable grammar.
|
|
X
|
|
XSome known problems with the published, Appendix C, EBNF grammar:
|
|
X
|
|
X - One of the productions is an orphan, ("scoping_statements").
|
|
X
|
|
X - unary minus is shown as a prefix operator, and unary plus as a
|
|
X postfix operator ("secondary").
|
|
X
|
|
X - Casting does not appear in the published grammar.
|
|
X
|
|
X - Nested structures do not appear in the published grammar, and
|
|
X the reference syntax for selecting a nested structure member
|
|
X is also missing.
|
|
X
|
|
X - The WORD type is missing from the "basic_type" production.
|
|
X
|
|
X - The "initialization" production allows the initial value list
|
|
X only after the INITIAL keyword, when, in fact, the initial value
|
|
X list may follow the DATA keyword, as well.
|
|
X
|
|
XOn the other hand, the precedence of the expression operators is
|
|
Xcorrect as written in the EBNF grammar, the dangling else problem is
|
|
Xnon-existent, and there are no associativity problems, as all
|
|
Xoperators associate left-to-right.
|
|
X
|
|
XTo complicate matters, the above referenced manual may be out of
|
|
Xprint. A more recent version, which covers the PL/M-386 dialect only,
|
|
Xis _PL/M-386 Programmer's Guide_, Intel order number 611052-001.
|
|
X
|
|
XThe latter manual has some corrections, but has some introduced errors
|
|
Xin the EBNF, as well. The problems with the unary minus and the
|
|
X"initialization" production are repaired, but the definition for a
|
|
X"binary_number" is malformed, as are the definitions for the
|
|
X"fractional_part", "string_body_element", "variable_element", and
|
|
X"if_condition" productions.
|
|
X
|
|
XWe're right, they're wrong.
|
|
X
|
|
XThe Authors
|
|
X-----------
|
|
X
|
|
XGary Funck (gary@intrepid.com) was responsible for starting this
|
|
Xeffort. He authored the original grammar.
|
|
X
|
|
XKirk Hays (hays@ichips.intel.com) wrote the lexical analyzer and the
|
|
Xscoped literal table implementation. He also validated and corrected
|
|
Xthe grammar, and extended it to cover documented features not
|
|
Xappearing in the published EBNF.
|
|
X
|
|
XFuture Plans
|
|
X------------
|
|
X
|
|
XIf there is enough interest (or, even if there isn't), Kirk is
|
|
Xplanning on producing a PL/M front end for the GNU compiler. Contact
|
|
Xhim at the above Email address for further information. Donations of
|
|
XPL/M source code of any dialect (including PL/M-80, PL/M-51, and
|
|
XPL/M-96)(yes, we already have the Kermit implementations), or a
|
|
Xwillingness to be a pre-alpha tester with code you cannot donate, are
|
|
Xsufficient grounds to contact Kirk.
|
|
X
|
|
END_OF_FILE
|
|
if test 7926 -ne `wc -c <'README'`; then
|
|
echo shar: \"'README'\" unpacked with wrong size!
|
|
fi
|
|
# end of 'README'
|
|
fi
|
|
if test -f 'Makefile' -a "${1}" != "-c" ; then
|
|
echo shar: Will not clobber existing file \"'Makefile'\"
|
|
else
|
|
echo shar: Extracting \"'Makefile'\" \(871 characters\)
|
|
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
|
|
X# $Id: Makefile,v 1.3 1994/02/28 22:28:36 hays Exp $
|
|
X
|
|
XLEX=flex
|
|
XLEXFLAGS= -v
|
|
XYACC=bison
|
|
XYACCFLAGS= -y -v -d
|
|
XCFLAGS= -g
|
|
XDIST=README Makefile plm-lex.l plm-manifest.h plm-parse.y scope.c scope.h
|
|
XOBJS= plm-lex.o plm-parse.o scope.o tree.o
|
|
X#NOTE: tree.o and tree.h come from Paul Vixie's PD AVL Tree package,
|
|
X# comp.sources.unix Volume 27, Issue 34.
|
|
X
|
|
X.y.c:
|
|
X
|
|
Xplm: $(OBJS)
|
|
X $(CC) $(CFLAGS) -o $@ $(OBJS)
|
|
X
|
|
Xplm-parse.h: plm-parse.c
|
|
X
|
|
Xplm-lex.c: plm-lex.l
|
|
X $(LEX) $(LEXFLAGS) -t $< > $@
|
|
X
|
|
Xplm-parse.c: plm-parse.y
|
|
X $(YACC) $(YACCFLAGS) $< -o $@
|
|
X
|
|
Xplm-lex.o: plm-lex.c plm-manifest.h plm-parse.h scope.h
|
|
X
|
|
Xplm-parse.o: plm-parse.c plm-manifest.h scope.h
|
|
X
|
|
Xscope.o: scope.c tree.h scope.h
|
|
X
|
|
Xclean:
|
|
X rm -f plm-parse.c plm-parse.h plm-parse.output \
|
|
X plm-*.o scope.o lex.backtrack tmp *~ plm-lex.c core plm \
|
|
X plm.shar
|
|
X
|
|
Xsource:
|
|
X $(CO) $(DIST)
|
|
X
|
|
Xdist: source
|
|
X shar $(DIST) > plm.shar
|
|
X
|
|
X
|
|
X
|
|
END_OF_FILE
|
|
if test 871 -ne `wc -c <'Makefile'`; then
|
|
echo shar: \"'Makefile'\" unpacked with wrong size!
|
|
fi
|
|
# end of 'Makefile'
|
|
fi
|
|
if test -f 'plm-lex.l' -a "${1}" != "-c" ; then
|
|
echo shar: Will not clobber existing file \"'plm-lex.l'\"
|
|
else
|
|
echo shar: Extracting \"'plm-lex.l'\" \(8476 characters\)
|
|
sed "s/^X//" >'plm-lex.l' <<'END_OF_FILE'
|
|
X%{
|
|
X/* lexer for PL/M syntax.
|
|
X
|
|
X$Id: plm-lex.l,v 1.2 1994/02/28 22:24:34 hays Exp $
|
|
X
|
|
XCopyright 1994 by Kirk Hays (hays@ichips.intel.com) and Gary Funck
|
|
X(gary@intrepid.com)
|
|
X
|
|
XUSE AT YOUR OWN RISK. NO WARRANTY EXPRESSED OR IMPLIED.
|
|
XThis code is distributed in the hope that it will be useful,
|
|
Xbut without any warranty. Further, there is no implied warranty of
|
|
Xmerchantability or fitness for a particular purpose.
|
|
X
|
|
X*/
|
|
X
|
|
X/* This file defines the syntax of PL/M. */
|
|
X
|
|
X#include <ctype.h>
|
|
X#include <string.h>
|
|
X#include "plm-manifest.h"
|
|
X#include "plm-parse.h"
|
|
X#include "scope.h"
|
|
X
|
|
Xint lineno = 1;
|
|
X
|
|
X/* forward references */
|
|
Xchar * canonical_string (char *);
|
|
Xchar * canonical_identifier (char *);
|
|
Xstatic void error (char *);
|
|
X
|
|
X%}
|
|
X
|
|
XDIGIT_STRING [0-9][0-9$]*
|
|
XA [Aa]($)*
|
|
XB [Bb]($)*
|
|
XC [Cc]($)*
|
|
XD [Dd]($)*
|
|
XE [Ee]($)*
|
|
XF [Ff]($)*
|
|
XG [Gg]($)*
|
|
XH [Hh]($)*
|
|
XI [Ii]($)*
|
|
XL [Ll]($)*
|
|
XM [Mm]($)*
|
|
XN [Nn]($)*
|
|
XO [Oo]($)*
|
|
XP [Pp]($)*
|
|
XQ [Qq]($)*
|
|
XR [Rr]($)*
|
|
XS [Ss]($)*
|
|
XT [Tt]($)*
|
|
XU [Uu]($)*
|
|
XW [Ww]($)*
|
|
XX [Xx]($)*
|
|
XY [Yy]($)*
|
|
X
|
|
X%%
|
|
X
|
|
X{A}{D}{D}{R}{E}{S}{S} return ADDRESS;
|
|
X{A}{N}{D} return AND;
|
|
X{A}{T} return AT;
|
|
X{B}{A}{S}{E}{D} return BASED;
|
|
X{B}{Y} return BY;
|
|
X{B}{Y}{T}{E} return BYTE;
|
|
X{C}{A}{L}{L} return CALL;
|
|
X{C}{A}{S}{E} return CASE;
|
|
X{C}{A}{U}{S}{E}{I}{N}{T}{E}{R}{R}{U}{P}{T} return CAUSE_INTERRUPT;
|
|
X{C}{H}{A}{R}{I}{N}{T} return CHARINT;
|
|
X{D}{A}{T}{A} return DATA;
|
|
X{D}{E}{C}{L}{A}{R}{E} return DECLARE;
|
|
X{D}{I}{S}{A}{B}{L}{E} return DISABLE;
|
|
X{D}{O} return DO;
|
|
X{D}{W}{O}{R}{D} return DWORD;
|
|
X{E}{L}{S}{E} return ELSE;
|
|
X{E}{N}{A}{B}{L}{E} return ENABLE;
|
|
X{E}{N}{D} return END;
|
|
X{E}{O}{F} return EOF_KW;
|
|
X{E}{X}{T}{E}{R}{N}{A}{L} return EXTERNAL;
|
|
X{G}{O} return GO;
|
|
X{G}{O}{T}{O} return GOTO;
|
|
X{H}{A}{L}{T} return HALT;
|
|
X{H}{W}{O}{R}{D} return HWORD;
|
|
X{I}{F} return IF;
|
|
X{I}{N}{I}{T}{I}{A}{L} return INITIAL_KW;
|
|
X{I}{N}{T}{E}{G}{E}{R} return INTEGER;
|
|
X{I}{N}{T}{E}{R}{R}{U}{P}{T} return INTERRUPT;
|
|
X{L}{A}{B}{E}{L} return LABEL;
|
|
X{L}{I}{T}{E}{R}{A}{L}{L}{Y} return LITERALLY;
|
|
X{L}{O}{N}{G}{I}{N}{T} return LONGINT;
|
|
X{M}{I}{N}{U}{S} return MINUS;
|
|
X{M}{O}{D} return MOD;
|
|
X{N}{O}{T} return NOT;
|
|
X{O}{F}{F}{S}{E}{T} return OFFSET;
|
|
X{O}{R} return OR;
|
|
X{P}{L}{U}{S} return PLUS;
|
|
X{P}{O}{I}{N}{T}{E}{R} return POINTER;
|
|
X{P}{R}{O}{C}{E}{D}{U}{R}{E} return PROCEDURE;
|
|
X{P}{U}{B}{L}{I}{C} return PUBLIC;
|
|
X{Q}{W}{O}{R}{D} return QWORD;
|
|
X{R}{E}{A}{L} return REAL;
|
|
X{R}{E}{E}{N}{T}{R}{A}{N}{T} return REENTRANT;
|
|
X{R}{E}{T}{U}{R}{N} return RETURN;
|
|
X{S}{E}{L}{E}{C}{T}{O}{R} return SELECTOR;
|
|
X{S}{H}{O}{R}{T}{I}{N}{T} return SHORTINT;
|
|
X{S}{T}{R}{U}{C}{T}{U}{R}{E} return STRUCTURE;
|
|
X{T}{H}{E}{N} return THEN;
|
|
X{T}{O} return TO;
|
|
X{W}{H}{I}{L}{E} return WHILE;
|
|
X{W}{O}{R}{D} return WORD;
|
|
X{X}{O}{R} return XOR;
|
|
X
|
|
X[_A-Za-z][_$0-9A-Za-z]* {
|
|
X char * string;
|
|
X int i;
|
|
X yylval = canonical_identifier(yytext);
|
|
X string = lookup_literal(yylval);
|
|
X if (!string)
|
|
X {
|
|
X return IDENTIFIER;
|
|
X }
|
|
X free(yylval);
|
|
X yylval=0; /*excessive neatness*/
|
|
X /* push the string back onto the input
|
|
X stream - it is necessary to push
|
|
X from right to left */
|
|
X for (i = strlen (string);
|
|
X i >= 0;
|
|
X i--)
|
|
X {
|
|
X /* very weak - depends on lexical
|
|
X generator allowing sufficient
|
|
X push-back */
|
|
X unput (string[i]);
|
|
X }
|
|
X }
|
|
X
|
|
X[0-9][0-9$]*(d)? return DECIMAL_NUMBER;
|
|
X
|
|
X{DIGIT_STRING}\.({DIGIT_STRING})?([E|e][+|-]?{DIGIT_STRING})? return FLOATING_POINT_NUMBER;
|
|
X
|
|
X[01][01$]*[bB] return BINARY_NUMBER;
|
|
X
|
|
X[0-9][0-9a-fA-F$]*[hH] return HEX_NUMBER;
|
|
X
|
|
X[0-7][0-7$]*[OoQq] return OCTAL_NUMBER;
|
|
X
|
|
X'([^'\n\201]|(''))+' {
|
|
X yylval = canonical_string(yytext);
|
|
X return STRING;
|
|
X }
|
|
X
|
|
X:= return ASSIGN_OP;
|
|
X
|
|
X[\@] return AT_SIGN;
|
|
X
|
|
X: return COLON;
|
|
X
|
|
X, return COMMA;
|
|
X
|
|
X[\.] return DOT;
|
|
X
|
|
X= return EQ;
|
|
X
|
|
X>= return GE;
|
|
X
|
|
X> return GT;
|
|
X
|
|
X"<=" return LE;
|
|
X
|
|
X\( return LPAREN;
|
|
X
|
|
X"<" return LT;
|
|
X
|
|
X- return MINUS_SIGN;
|
|
X
|
|
X"<>" return NE;
|
|
X
|
|
X"+" return PLUS_SIGN;
|
|
X
|
|
X\) return RPAREN;
|
|
X
|
|
X; return SEMI;
|
|
X
|
|
X"/" return SLASH;
|
|
X
|
|
X\* return STAR;
|
|
X
|
|
X\f
|
|
X
|
|
X\n lineno++;
|
|
X
|
|
X[\t ]*
|
|
X
|
|
X"/*" {
|
|
X register int c;
|
|
X
|
|
X for ( ; ; )
|
|
X {
|
|
X while ( (c = input()) != '*' &&
|
|
X c != EOF )
|
|
X if (c == '\n') lineno++;
|
|
X /* eat up text of comment */
|
|
X
|
|
X if ( c == '*' )
|
|
X {
|
|
X while ( (c = input()) == '*' )
|
|
X ;
|
|
X if ( c == '/' )
|
|
X break; /* found the end */
|
|
X }
|
|
X
|
|
X if (c == '\n') lineno++;
|
|
X
|
|
X if ( c == EOF )
|
|
X {
|
|
X error( "EOF in comment" );
|
|
X break;
|
|
X }
|
|
X }
|
|
X }
|
|
X
|
|
X.
|
|
X
|
|
X%%
|
|
X
|
|
Xstatic void error (char * x) {printf (x);}
|
|
X
|
|
X/* Strip the single quotes from a pl/m string, and
|
|
X compress any single quote pairs to one quote.
|
|
X
|
|
X Allocates new storage for the string.
|
|
X*/
|
|
Xchar *
|
|
Xcanonical_string (char * s)
|
|
X{
|
|
X int i, i_ret;
|
|
X char * ret;
|
|
X int len = strlen (s);
|
|
X
|
|
X ret = malloc (len+1);
|
|
X if (!ret)
|
|
X return 0;
|
|
X
|
|
X for (i = 1, i_ret = 0; i < (len-1); i++)
|
|
X {
|
|
X ret[i_ret++] = s[i];
|
|
X if (s[i] == '\'')
|
|
X {
|
|
X i++;
|
|
X }
|
|
X }
|
|
X
|
|
X ret[i_ret] = 0;
|
|
X
|
|
X return ret;
|
|
X
|
|
X}
|
|
X
|
|
X/* Strip the dollar signs from a pl/m identifier or
|
|
X numeric constant, and force all alphabetic characters
|
|
X to lower case.
|
|
X
|
|
X Allocates new storage for the identifier string.
|
|
X
|
|
X*/
|
|
Xchar *
|
|
Xcanonical_identifier (char * s)
|
|
X{
|
|
X int i, i_ret;
|
|
X char * ret;
|
|
X int len = strlen (s);
|
|
X
|
|
X ret = malloc (len+1);
|
|
X if (!ret)
|
|
X return 0;
|
|
X
|
|
X for (i = 0, i_ret = 0; i < len; i++)
|
|
X {
|
|
X if (s[i] == '$')
|
|
X {
|
|
X continue;
|
|
X }
|
|
X ret[i_ret++] = tolower (s[i]);
|
|
X }
|
|
X
|
|
X ret[i_ret] = 0;
|
|
X
|
|
X return ret;
|
|
X
|
|
X}
|
|
X
|
|
X#ifdef LEX_ONLY
|
|
X
|
|
Xmain() {
|
|
X
|
|
X for (;;)
|
|
X yylex();
|
|
X
|
|
X}
|
|
X
|
|
X#endif
|
|
END_OF_FILE
|
|
if test 8476 -ne `wc -c <'plm-lex.l'`; then
|
|
echo shar: \"'plm-lex.l'\" unpacked with wrong size!
|
|
fi
|
|
# end of 'plm-lex.l'
|
|
fi
|
|
if test -f 'plm-manifest.h' -a "${1}" != "-c" ; then
|
|
echo shar: Will not clobber existing file \"'plm-manifest.h'\"
|
|
else
|
|
echo shar: Extracting \"'plm-manifest.h'\" \(605 characters\)
|
|
sed "s/^X//" >'plm-manifest.h' <<'END_OF_FILE'
|
|
X/* manifest constants/types for PL/M lexer/parser.
|
|
X
|
|
X$Id: plm-manifest.h,v 1.1 1994/02/28 20:54:26 hays Exp $
|
|
X
|
|
XCopyright 1994 by Kirk Hays (hays@ichips.intel.com)
|
|
X
|
|
XUSE AT YOUR OWN RISK. NO WARRANTY EXPRESSED OR IMPLIED.
|
|
XThis code is distributed in the hope that it will be useful,
|
|
Xbut without any warranty. Further, there is no implied warranty of
|
|
Xmerchantability or fitness for a particular purpose.
|
|
X
|
|
X*/
|
|
X
|
|
Xextern int lineno;
|
|
X
|
|
X/* brute force type the value stack - this would not be appropriate in
|
|
X a real compiler, but suits our purposes just fine */
|
|
X
|
|
Xtypedef char * CHAR_PTR;
|
|
X#define YYSTYPE CHAR_PTR
|
|
X
|
|
END_OF_FILE
|
|
if test 605 -ne `wc -c <'plm-manifest.h'`; then
|
|
echo shar: \"'plm-manifest.h'\" unpacked with wrong size!
|
|
fi
|
|
# end of 'plm-manifest.h'
|
|
fi
|
|
if test -f 'plm-parse.y' -a "${1}" != "-c" ; then
|
|
echo shar: Will not clobber existing file \"'plm-parse.y'\"
|
|
else
|
|
echo shar: Extracting \"'plm-parse.y'\" \(14574 characters\)
|
|
sed "s/^X//" >'plm-parse.y' <<'END_OF_FILE'
|
|
X/* YACC parser for PL/M syntax.
|
|
X
|
|
X$Id: plm-parse.y,v 1.1 1994/02/28 20:54:56 hays Exp $
|
|
X
|
|
XCopyright 1994 by Kirk Hays (hays@ichips.intel.com) and Gary Funck
|
|
X(gary@intrepid.com)
|
|
X
|
|
XUSE AT YOUR OWN RISK. NO WARRANTY EXPRESSED OR IMPLIED.
|
|
XThis code is distributed in the hope that it will be useful,
|
|
Xbut without any warranty. Further, there is no implied warranty of
|
|
Xmerchantability or fitness for a particular purpose.
|
|
X
|
|
X*/
|
|
X
|
|
X/* This file defines the grammar of PL/M. */
|
|
X
|
|
X%{
|
|
X
|
|
X/*
|
|
X * YACC grammar of PL/M
|
|
X */
|
|
X#include <stdio.h>
|
|
X#include <stdlib.h>
|
|
X#include "plm-manifest.h"
|
|
X#include "scope.h"
|
|
X
|
|
Xvoid yyerror ();
|
|
X
|
|
X/* Cause the `yydebug' variable to be defined. */
|
|
X#define YYDEBUG (1)
|
|
X
|
|
X%}
|
|
X
|
|
X%token ADDRESS AND ASSIGN_OP AT AT_SIGN BASED
|
|
X%token BINARY_NUMBER BY BYTE CALL CASE
|
|
X%token CAUSE_INTERRUPT CHARINT COLON COMMA DATA
|
|
X%token DECIMAL_NUMBER DECLARE DISABLE DO DOT
|
|
X%token DWORD ELSE ENABLE END EOF_KW EQ
|
|
X%token EXTERNAL FLOATING_POINT_NUMBER GE GO
|
|
X%token GOTO GT HALT HEX_NUMBER HWORD
|
|
X%token IDENTIFIER
|
|
X%token IF INITIAL_KW INTEGER INTERRUPT
|
|
X%token LABEL LE LITERALLY LONGINT LPAREN LT
|
|
X%token MINUS MINUS_SIGN MOD NE NOT
|
|
X%token OCTAL_NUMBER OFFSET OR PLUS PLUS_SIGN
|
|
X%token POINTER PROCEDURE PUBLIC QWORD
|
|
X%token REAL REENTRANT RETURN RPAREN SELECTOR
|
|
X%token SEMI SHORTINT SLASH STAR STRING
|
|
X%token STRUCTURE THEN TO WHILE WORD XOR
|
|
X
|
|
X
|
|
X%start compilation
|
|
X
|
|
X%%
|
|
Xactual_parameters:
|
|
X LPAREN expression_list RPAREN
|
|
X ;
|
|
Xadding_operator:
|
|
X MINUS
|
|
X | MINUS_SIGN
|
|
X | PLUS
|
|
X | PLUS_SIGN
|
|
X ;
|
|
Xand_operator:
|
|
X AND
|
|
X ;
|
|
Xarithmetic_expression:
|
|
X term
|
|
X | arithmetic_expression adding_operator term
|
|
X ;
|
|
Xarray_specifier:
|
|
X explicit_dimension
|
|
X | implicit_dimension
|
|
X ;
|
|
Xassignment_statement:
|
|
X left_part EQ expression SEMI
|
|
X ;
|
|
Xbase_specifier:
|
|
X IDENTIFIER
|
|
X | IDENTIFIER DOT IDENTIFIER
|
|
X ;
|
|
Xbasic_statement:
|
|
X assignment_statement
|
|
X | call_statement
|
|
X | goto_statement
|
|
X | microprocessor_dependent_statement
|
|
X | null_statement
|
|
X | return_statement
|
|
X ;
|
|
Xbasic_type:
|
|
X ADDRESS
|
|
X | BYTE
|
|
X | CHARINT
|
|
X | DWORD
|
|
X | HWORD
|
|
X | INTEGER
|
|
X | LONGINT
|
|
X | OFFSET
|
|
X | POINTER
|
|
X | QWORD
|
|
X | REAL
|
|
X | SELECTOR
|
|
X | SHORTINT
|
|
X | WORD
|
|
X ;
|
|
Xbound_expression:
|
|
X expression
|
|
X ;
|
|
Xby_part:
|
|
X BY step_expression
|
|
X ;
|
|
Xcall_statement:
|
|
X CALL simple_variable SEMI
|
|
X | CALL simple_variable actual_parameters SEMI
|
|
X ;
|
|
Xcast_type:
|
|
X basic_type
|
|
X ;
|
|
Xcause_interrupt_statement:
|
|
X CAUSE_INTERRUPT LPAREN integer_constant RPAREN SEMI
|
|
X ;
|
|
Xcompilation:
|
|
X module
|
|
X | module EOF_KW
|
|
X ;
|
|
Xconditional_clause:
|
|
X if_condition true_unit
|
|
X | if_condition true_element ELSE false_element
|
|
X ;
|
|
Xconstant:
|
|
X STRING
|
|
X | numeric_constant
|
|
X ;
|
|
Xconstant_attribute:
|
|
X DATA
|
|
X ;
|
|
Xconstant_list:
|
|
X constant
|
|
X | constant_list COMMA constant
|
|
X ;
|
|
Xdeclaration:
|
|
X declare_statement
|
|
X | procedure_definition
|
|
X ;
|
|
Xdeclaration_sequence:
|
|
X declaration
|
|
X | declaration_sequence declaration
|
|
X ;
|
|
Xdeclare_element:
|
|
X factored_element
|
|
X | unfactored_element
|
|
X ;
|
|
Xdeclare_element_list:
|
|
X declare_element
|
|
X | declare_element_list COMMA declare_element
|
|
X ;
|
|
Xdeclare_statement:
|
|
X DECLARE declare_element_list SEMI
|
|
X ;
|
|
Xdisable_statement:
|
|
X DISABLE SEMI
|
|
X ;
|
|
Xdo_block:
|
|
X do_case_block
|
|
X | do_while_block
|
|
X | iterative_do_block
|
|
X | simple_do_block
|
|
X ;
|
|
Xdo_case_block:
|
|
X do_case_statement ending
|
|
X | do_case_statement unit_sequence ending
|
|
X ;
|
|
Xdo_case_statement:
|
|
X DO CASE expression SEMI {
|
|
X push_scope();
|
|
X }
|
|
X ;
|
|
Xdo_while_block:
|
|
X do_while_statement ending
|
|
X | do_while_statement unit_sequence ending
|
|
X ;
|
|
Xdo_while_statement:
|
|
X DO WHILE expression SEMI {
|
|
X push_scope();
|
|
X }
|
|
X ;
|
|
Xembedded_assignment:
|
|
X variable_reference ASSIGN_OP logical_expression
|
|
X ;
|
|
Xenable_statement:
|
|
X ENABLE SEMI
|
|
X ;
|
|
Xend_statement:
|
|
X END opt_identifier SEMI {
|
|
X pop_scope();
|
|
X }
|
|
X ;
|
|
Xending:
|
|
X end_statement
|
|
X | label_definition_sequence end_statement
|
|
X ;
|
|
Xexplicit_dimension:
|
|
X LPAREN numeric_constant RPAREN
|
|
X ;
|
|
Xexpression:
|
|
X embedded_assignment
|
|
X | logical_expression
|
|
X ;
|
|
Xexpression_list:
|
|
X expression
|
|
X | expression_list COMMA expression
|
|
X ;
|
|
Xfactored_element:
|
|
X factored_label_element
|
|
X | factored_variable_element
|
|
X ;
|
|
X/*
|
|
X * factored_label_element doesn't permit based variables,
|
|
X * yet factored_variable_element does. This can't be disambiguated
|
|
X * syntactically. Thus, the factored_label element will have to
|
|
X * make the proper semantic checks to make the sure that the
|
|
X * variable_name_specifier_list is in fact an identifier_list.
|
|
X */
|
|
Xfactored_label_element:
|
|
X LPAREN variable_name_specifier_list RPAREN LABEL opt_public_or_external
|
|
X ;
|
|
Xfactored_member:
|
|
X LPAREN member_name_list RPAREN opt_explicit_dimension variable_type
|
|
X ;
|
|
Xfactored_variable_element:
|
|
X LPAREN variable_name_specifier_list RPAREN opt_explicit_dimension variable_type opt_variable_attributes
|
|
X ;
|
|
Xfalse_element:
|
|
X unit
|
|
X ;
|
|
Xformal_parameter:
|
|
X IDENTIFIER
|
|
X ;
|
|
Xformal_parameter_list:
|
|
X formal_parameter
|
|
X | formal_parameter_list COMMA formal_parameter
|
|
X ;
|
|
Xformal_parameter_specifier:
|
|
X LPAREN formal_parameter_list RPAREN
|
|
X ;
|
|
Xgo_to:
|
|
X GOTO
|
|
X | GO TO
|
|
X ;
|
|
Xgoto_statement:
|
|
X go_to IDENTIFIER SEMI
|
|
X ;
|
|
Xhalt_statement:
|
|
X HALT SEMI
|
|
X ;
|
|
Xid_colon:
|
|
X IDENTIFIER COLON
|
|
X ;
|
|
Xif_condition:
|
|
X IF expression THEN
|
|
X ;
|
|
Ximplicit_dimension:
|
|
X LPAREN STAR RPAREN
|
|
X ;
|
|
Xindex_part:
|
|
X index_variable EQ start_expression
|
|
X ;
|
|
Xindex_variable:
|
|
X simple_variable
|
|
X ;
|
|
Xinitial_value:
|
|
X expression
|
|
X ;
|
|
Xinitial_value_list:
|
|
X initial_value
|
|
X | initial_value_list COMMA initial_value
|
|
X ;
|
|
Xinitialization:
|
|
X DATA LPAREN initial_value_list RPAREN
|
|
X | INITIAL_KW LPAREN initial_value_list RPAREN
|
|
X ;
|
|
Xinteger_constant:
|
|
X BINARY_NUMBER
|
|
X | DECIMAL_NUMBER
|
|
X | HEX_NUMBER
|
|
X | OCTAL_NUMBER
|
|
X ;
|
|
Xinterrupt:
|
|
X INTERRUPT opt_interrupt_number
|
|
X ;
|
|
Xinterrupt_number:
|
|
X integer_constant
|
|
X ;
|
|
Xiterative_do_block:
|
|
X iterative_do_statement ending
|
|
X | iterative_do_statement unit_sequence ending
|
|
X ;
|
|
Xiterative_do_statement:
|
|
X DO index_part to_part opt_by_part SEMI {
|
|
X push_scope();
|
|
X }
|
|
X ;
|
|
Xlabel_definition:
|
|
X id_colon
|
|
X ;
|
|
Xlabel_definition_sequence:
|
|
X label_definition
|
|
X | label_definition_sequence label_definition
|
|
X ;
|
|
Xlabel_element:
|
|
X IDENTIFIER LABEL opt_public_or_external
|
|
X ;
|
|
Xleft_part:
|
|
X variable_reference_list
|
|
X ;
|
|
Xliteral_element:
|
|
X IDENTIFIER LITERALLY STRING {
|
|
X enter_literal ($1, $3);
|
|
X }
|
|
X ;
|
|
Xlocation_reference:
|
|
X AT_SIGN variable_reference
|
|
X | AT_SIGN LPAREN constant_list RPAREN
|
|
X | DOT variable_reference
|
|
X | DOT LPAREN constant_list RPAREN
|
|
X ;
|
|
Xlocator:
|
|
X AT LPAREN expression RPAREN
|
|
X ;
|
|
Xlocator_initialization:
|
|
X locator
|
|
X | initialization
|
|
X | locator initialization
|
|
X ;
|
|
Xlogical_expression:
|
|
X logical_factor
|
|
X | logical_expression or_operator logical_factor
|
|
X ;
|
|
Xlogical_factor:
|
|
X logical_secondary
|
|
X | logical_factor and_operator logical_secondary
|
|
X ;
|
|
Xlogical_primary:
|
|
X arithmetic_expression
|
|
X | arithmetic_expression relation_operator arithmetic_expression
|
|
X ;
|
|
Xlogical_secondary:
|
|
X logical_primary
|
|
X | NOT logical_primary
|
|
X ;
|
|
Xmember_element:
|
|
X structure_type
|
|
X | factored_member
|
|
X | unfactored_member
|
|
X ;
|
|
Xmember_element_list:
|
|
X member_element
|
|
X | member_element_list COMMA member_element
|
|
X ;
|
|
Xmember_name:
|
|
X IDENTIFIER
|
|
X ;
|
|
Xmember_name_list:
|
|
X member_name
|
|
X | member_name_list COMMA member_name
|
|
X ;
|
|
Xmember_specifier:
|
|
X DOT member_name
|
|
X | DOT member_name subscript
|
|
X ;
|
|
Xmember_specifier_sequence:
|
|
X member_specifier_sequence member_specifier
|
|
X | member_specifier
|
|
X ;
|
|
Xmicroprocessor_dependent_statement:
|
|
X cause_interrupt_statement
|
|
X | disable_statement
|
|
X | enable_statement
|
|
X | halt_statement
|
|
X ;
|
|
Xmodule:
|
|
X module_name COLON simple_do_block
|
|
X ;
|
|
Xmodule_name:
|
|
X IDENTIFIER
|
|
X ;
|
|
Xmultiplying_operator:
|
|
X MOD
|
|
X | SLASH
|
|
X | STAR
|
|
X ;
|
|
Xnull_statement:
|
|
X SEMI
|
|
X ;
|
|
Xnumeric_constant:
|
|
X FLOATING_POINT_NUMBER
|
|
X | integer_constant
|
|
X ;
|
|
Xopt_array_specifier:
|
|
X /* empty */
|
|
X | array_specifier
|
|
X ;
|
|
Xopt_by_part:
|
|
X /* empty */
|
|
X | by_part
|
|
X ;
|
|
Xopt_explicit_dimension:
|
|
X /* empty */
|
|
X | explicit_dimension
|
|
X ;
|
|
Xopt_formal_parameter_specifier:
|
|
X /* empty */
|
|
X | formal_parameter_specifier
|
|
X ;
|
|
Xopt_identifier:
|
|
X /* empty */
|
|
X | IDENTIFIER
|
|
X ;
|
|
Xopt_interrupt_number:
|
|
X /* empty */
|
|
X | interrupt_number
|
|
X ;
|
|
Xopt_procedure_attribute_sequence:
|
|
X /* empty */
|
|
X | procedure_attribute_sequence
|
|
X ;
|
|
Xopt_procedure_type:
|
|
X /* empty */
|
|
X | procedure_type
|
|
X ;
|
|
Xopt_public_or_external:
|
|
X /* empty */
|
|
X | EXTERNAL
|
|
X | PUBLIC
|
|
X ;
|
|
Xopt_variable_attributes:
|
|
X /* empty */
|
|
X | variable_attributes
|
|
X ;
|
|
Xor_operator:
|
|
X OR
|
|
X | XOR
|
|
X ;
|
|
Xprimary:
|
|
X constant
|
|
X | location_reference
|
|
X | subexpression
|
|
X | variable_reference
|
|
X ;
|
|
Xprocedure_attribute:
|
|
X EXTERNAL
|
|
X | PUBLIC
|
|
X | REENTRANT
|
|
X | interrupt PUBLIC
|
|
X | interrupt EXTERNAL
|
|
X ;
|
|
Xprocedure_attribute_sequence:
|
|
X procedure_attribute
|
|
X | procedure_attribute_sequence procedure_attribute
|
|
X ;
|
|
Xprocedure_definition:
|
|
X procedure_statement ending
|
|
X | procedure_statement declaration_sequence ending
|
|
X | procedure_statement unit_sequence ending
|
|
X | procedure_statement declaration_sequence unit_sequence ending
|
|
X ;
|
|
Xprocedure_statement:
|
|
X id_colon PROCEDURE opt_formal_parameter_specifier opt_procedure_type opt_procedure_attribute_sequence SEMI
|
|
X {
|
|
X push_scope();
|
|
X }
|
|
X ;
|
|
Xprocedure_type:
|
|
X basic_type
|
|
X ;
|
|
Xrelation_operator:
|
|
X EQ
|
|
X | GE
|
|
X | GT
|
|
X | LE
|
|
X | LT
|
|
X | NE
|
|
X ;
|
|
Xreturn_statement:
|
|
X typed_return
|
|
X | untyped_return
|
|
X ;
|
|
Xsecondary:
|
|
X primary
|
|
X | unary_sign primary
|
|
X ;
|
|
Xsimple_do_block:
|
|
X simple_do_statement ending
|
|
X | simple_do_statement unit_sequence ending
|
|
X | simple_do_statement declaration_sequence ending
|
|
X | simple_do_statement declaration_sequence unit_sequence ending
|
|
X ;
|
|
Xsimple_do_statement:
|
|
X DO SEMI {
|
|
X push_scope();
|
|
X }
|
|
X ;
|
|
Xsimple_variable:
|
|
X IDENTIFIER
|
|
X | IDENTIFIER DOT IDENTIFIER
|
|
X ;
|
|
Xstart_expression:
|
|
X expression
|
|
X ;
|
|
Xstep_expression:
|
|
X expression
|
|
X ;
|
|
Xstructure_type:
|
|
X STRUCTURE LPAREN member_element_list RPAREN
|
|
X ;
|
|
Xsubexpression:
|
|
X LPAREN expression RPAREN
|
|
X ;
|
|
Xsubscript:
|
|
X LPAREN expression RPAREN
|
|
X ;
|
|
Xsubscript_or_actual_parameters:
|
|
X LPAREN expression_list RPAREN
|
|
X ;
|
|
Xterm:
|
|
X secondary
|
|
X | term multiplying_operator secondary
|
|
X ;
|
|
Xto_part:
|
|
X TO bound_expression
|
|
X ;
|
|
Xtrue_element:
|
|
X true_statement
|
|
X | label_definition_sequence true_statement
|
|
X ;
|
|
Xtrue_statement:
|
|
X do_block
|
|
X | basic_statement
|
|
X ;
|
|
Xtrue_unit:
|
|
X unit
|
|
X ;
|
|
Xtyped_return:
|
|
X RETURN expression SEMI
|
|
X ;
|
|
Xunary_minus:
|
|
X MINUS_SIGN
|
|
X ;
|
|
Xunary_plus:
|
|
X PLUS_SIGN
|
|
X ;
|
|
Xunary_sign:
|
|
X unary_minus
|
|
X | unary_plus
|
|
X ;
|
|
Xunfactored_element:
|
|
X label_element
|
|
X | literal_element
|
|
X | variable_element
|
|
X ;
|
|
Xunfactored_member:
|
|
X member_name opt_explicit_dimension variable_type
|
|
X ;
|
|
Xunit:
|
|
X unit_element
|
|
X | label_definition_sequence unit_element
|
|
X ;
|
|
Xunit_element:
|
|
X basic_statement
|
|
X | conditional_clause
|
|
X | do_block
|
|
X ;
|
|
Xunit_sequence:
|
|
X unit
|
|
X | unit_sequence unit
|
|
X ;
|
|
Xuntyped_return:
|
|
X RETURN SEMI
|
|
X ;
|
|
Xvariable_attributes:
|
|
X EXTERNAL constant_attribute
|
|
X | EXTERNAL
|
|
X | PUBLIC locator_initialization
|
|
X | PUBLIC
|
|
X | locator_initialization
|
|
X ;
|
|
Xvariable_element:
|
|
X variable_name_specifier opt_array_specifier variable_type opt_variable_attributes
|
|
X ;
|
|
Xvariable_name_specifier:
|
|
X IDENTIFIER
|
|
X | IDENTIFIER BASED base_specifier
|
|
X ;
|
|
Xvariable_name_specifier_list:
|
|
X variable_name_specifier
|
|
X | variable_name_specifier_list COMMA variable_name_specifier
|
|
X ;
|
|
X/*
|
|
X * Variable references may be either data references or function
|
|
X * references. Syntactically, they appear to be the same, each
|
|
X * is followed by a parenthesized comma separated list of expressions.
|
|
X *
|
|
X * A function reference, of course, cannot have the trailing list of
|
|
X * member specifiers - semantic checking will catch this.
|
|
X */
|
|
Xvariable_reference:
|
|
X IDENTIFIER
|
|
X | IDENTIFIER member_specifier_sequence
|
|
X | cast_type subscript
|
|
X | IDENTIFIER subscript_or_actual_parameters
|
|
X | IDENTIFIER subscript_or_actual_parameters member_specifier_sequence
|
|
X ;
|
|
Xvariable_reference_list:
|
|
X variable_reference
|
|
X | variable_reference_list COMMA variable_reference
|
|
X ;
|
|
Xvariable_type:
|
|
X basic_type
|
|
X | structure_type
|
|
X ;
|
|
X
|
|
X%%
|
|
X
|
|
Xvoid
|
|
Xyyerror(char * s)
|
|
X{
|
|
X fprintf (stderr, "error at line %d: %s\n", lineno, s);
|
|
X}
|
|
X
|
|
Xmain()
|
|
X{
|
|
X init_scope();
|
|
X return yyparse();
|
|
X}
|
|
END_OF_FILE
|
|
if test 14574 -ne `wc -c <'plm-parse.y'`; then
|
|
echo shar: \"'plm-parse.y'\" unpacked with wrong size!
|
|
fi
|
|
# end of 'plm-parse.y'
|
|
fi
|
|
if test -f 'scope.c' -a "${1}" != "-c" ; then
|
|
echo shar: Will not clobber existing file \"'scope.c'\"
|
|
else
|
|
echo shar: Extracting \"'scope.c'\" \(3455 characters\)
|
|
sed "s/^X//" >'scope.c' <<'END_OF_FILE'
|
|
X/* literal symbol table for PL/M.
|
|
X
|
|
X$Id: scope.c,v 1.1 1994/02/28 20:55:56 hays Exp $
|
|
X
|
|
XCopyright 1994 by Kirk Hays (hays@ichips.intel.com)
|
|
X
|
|
XUSE AT YOUR OWN RISK. NO WARRANTY EXPRESSED OR IMPLIED.
|
|
XThis code is distributed in the hope that it will be useful,
|
|
Xbut without any warranty. Further, there is no implied warranty of
|
|
Xmerchantability or fitness for a particular purpose.
|
|
X
|
|
XThis code implements a scoped symbol table. It depends on Paul
|
|
XVixie's PD AVL Tree code, distributed in comp.sources.unix, Volume 27,
|
|
XIssue 34.
|
|
X
|
|
X*/
|
|
X
|
|
X#include <stdlib.h>
|
|
X#include <stdio.h>
|
|
X#include "tree.h"
|
|
X#include "scope.h"
|
|
X
|
|
Xtypedef struct lit_table_stack_t_elem {
|
|
X struct lit_table_stack_t_elem *next;
|
|
X tree * literal_table;
|
|
X} lit_table_stack_t;
|
|
X
|
|
X/* innermost scope for scope list */
|
|
Xstatic lit_table_stack_t *lit_table_stack;
|
|
X
|
|
Xtypedef struct {
|
|
X char * identifier;
|
|
X char * string;
|
|
X} literal_t;
|
|
X
|
|
X/* static forward references */
|
|
Xstatic void new_scope (lit_table_stack_t *);
|
|
Xstatic int literal_compar (literal_t *, literal_t *);
|
|
Xstatic void literal_error (literal_t *);
|
|
Xstatic void literal_t_delete (literal_t *);
|
|
X
|
|
X/* lookup an identifier in the scoped symbol table */
|
|
Xchar *
|
|
Xlookup_literal (char * identifier)
|
|
X{
|
|
X literal_t * datum;
|
|
X literal_t * node;
|
|
X lit_table_stack_t * scope;
|
|
X
|
|
X node = alloca (sizeof (literal_t));
|
|
X node->identifier = identifier;
|
|
X
|
|
X for (scope = lit_table_stack; scope; scope=scope->next)
|
|
X {
|
|
X datum = tree_srch(&(scope->literal_table), literal_compar, node);
|
|
X if (datum)
|
|
X {
|
|
X return datum->string;
|
|
X }
|
|
X }
|
|
X
|
|
X return 0;
|
|
X
|
|
X}
|
|
X
|
|
X/* enter an identifier in the current scoping level */
|
|
Xvoid
|
|
Xenter_literal (char * identifier, char * string)
|
|
X{
|
|
X literal_t * datum;
|
|
X
|
|
X datum = malloc (sizeof (literal_t));
|
|
X datum->identifier = identifier;
|
|
X datum->string = string;
|
|
X tree_add (&(lit_table_stack->literal_table),
|
|
X literal_compar,
|
|
X datum,
|
|
X literal_error);
|
|
X}
|
|
X
|
|
X/* increase scope depth by one level - creates a new symbol table
|
|
X for the current scope */
|
|
Xvoid
|
|
Xpush_scope (void)
|
|
X{
|
|
X new_scope (lit_table_stack);
|
|
X}
|
|
X
|
|
X/* remove the innermost scope of the symbol table - releases all
|
|
X allocated storage for that scope */
|
|
Xvoid
|
|
Xpop_scope (void)
|
|
X{
|
|
X lit_table_stack_t * p;
|
|
X
|
|
X p = lit_table_stack;
|
|
X lit_table_stack = lit_table_stack->next;
|
|
X tree_mung (&(p->literal_table), literal_t_delete);
|
|
X if (p->literal_table)
|
|
X {
|
|
X free(p->literal_table);
|
|
X }
|
|
X free(p);
|
|
X}
|
|
X
|
|
X/* initialize this module, creating the outermost scope */
|
|
Xvoid
|
|
Xinit_scope (void)
|
|
X{
|
|
X new_scope (0);
|
|
X}
|
|
X
|
|
X/* work procedure to create a new scope */
|
|
Xstatic void
|
|
Xnew_scope (lit_table_stack_t * next)
|
|
X{
|
|
X lit_table_stack = malloc (sizeof (lit_table_stack_t));
|
|
X lit_table_stack->next = next;
|
|
X tree_init (&(lit_table_stack->literal_table));
|
|
X}
|
|
X
|
|
X/* internal procedure to free storage when a symbol table entry is
|
|
X deleted */
|
|
Xstatic
|
|
Xvoid literal_t_delete (literal_t * datum)
|
|
X{
|
|
X free (datum->string);
|
|
X free (datum->identifier);
|
|
X}
|
|
X
|
|
X/* internal procedure to determine the match order for two symbol
|
|
X table entries */
|
|
X
|
|
Xstatic int
|
|
Xliteral_compar (literal_t * left, literal_t * right)
|
|
X{
|
|
X return strcmp (left->identifier, right->identifier);
|
|
X}
|
|
X
|
|
X/* assertion procedure to assure that duplicate literals are never
|
|
X added at a single scoping level */
|
|
X
|
|
Xstatic void
|
|
Xliteral_error (literal_t * in_error)
|
|
X{
|
|
X fprintf (stderr,
|
|
X "literal table error - attempt to enter same identifier twice\n");
|
|
X exit (255);
|
|
X}
|
|
X
|
|
X
|
|
END_OF_FILE
|
|
if test 3455 -ne `wc -c <'scope.c'`; then
|
|
echo shar: \"'scope.c'\" unpacked with wrong size!
|
|
fi
|
|
# end of 'scope.c'
|
|
fi
|
|
if test -f 'scope.h' -a "${1}" != "-c" ; then
|
|
echo shar: Will not clobber existing file \"'scope.h'\"
|
|
else
|
|
echo shar: Extracting \"'scope.h'\" \(690 characters\)
|
|
sed "s/^X//" >'scope.h' <<'END_OF_FILE'
|
|
X/* public interfaces for literal symbol table for PL/M.
|
|
X
|
|
X$Id: scope.h,v 1.1 1994/02/28 20:56:13 hays Exp $
|
|
X
|
|
XCopyright 1994 by Kirk Hays (hays@ichips.intel.com)
|
|
X
|
|
XUSE AT YOUR OWN RISK. NO WARRANTY EXPRESSED OR IMPLIED.
|
|
XThis code is distributed in the hope that it will be useful,
|
|
Xbut without any warranty. Further, there is no implied warranty of
|
|
Xmerchantability or fitness for a particular purpose.
|
|
X
|
|
XThis code implements a scoped symbol table. It depends on Paul
|
|
XVixie's PD AVL Tree code, distributed in comp.sources.unix, Volume 27,
|
|
XIssue 34.
|
|
X
|
|
X*/
|
|
X
|
|
Xchar * lookup_literal (char *);
|
|
Xvoid enter_literal (char *, char *);
|
|
Xvoid push_scope (void);
|
|
Xvoid pop_scope (void);
|
|
Xvoid init_scope (void);
|
|
END_OF_FILE
|
|
if test 690 -ne `wc -c <'scope.h'`; then
|
|
echo shar: \"'scope.h'\" unpacked with wrong size!
|
|
fi
|
|
# end of 'scope.h'
|
|
fi
|
|
echo shar: End of shell archive.
|
|
exit 0
|