📄 cr.pas
字号:
(* CR Main Module of Coco/R
== =====================
This is a compiler generator that produces a scanner and a parser
from an attributed grammar, and optionally a complete small compiler.
Original code in Oberon by Hanspeter Moessenboeck, ETH Zurich
Ported at ETH to Apple Modula, and thence to JPI-2 Modula.
JPI version of 27 January 1991 was then modified to make more
portable by Pat Terry, January - October 1992
This is the IBM-PC MS-DOS Turbo Pascal version for generating Turbo Pascal
based on the port first done by Volker Pohlers, October 1995
Usage:
COCOR [-options] GrammarName[.atg] [$options]
Input:
attributed grammar input grammar
scanner.frm frame file
parser.frm frame file
compiler.frm frame file (optional)
(Frame files must be in the sme directory as the grammar, or may be
found on a path specified by DOS environment variable CRFRAMES).
Output:
<GrammarName>S.pas generated scanner
<GrammarName>P.pas generated parser
<GrammarName>.err error numbers and corresponding error messages
<GrammarName>.lst source listing with error messages and trace output
Optionally
<GrammarName>G.pas generated symbolic names
<GrammarName>.pas generated compiler main module
Implementation restrictions
1 too many nodes in graph (>1500) CRTable.NewNode
2 too many symbols (>500) CRTable.NewSym, MovePragmas
3 too many sets (>256 ANY-syms or SYNC syms) CRTable.NewSet,
4 too many character classes (>250) CRTable.NewClass
5 too many conditions in generated code (>100) CRX.NewCondSet
6 too many token names in "NAMES" (>100) CRTable.NewName
7 too many states in automata (>500) CRA.NewState
Trace output
(To activate a trace switch, write "${letter}" in the input grammar, or
invoke Coco with a second command line parameter)
A Prints states of automaton
C Generates complete compiler module
F Prints start symbols and followers of nonterminals.
G Prints the top-down graph.
I Trace of start symbol set computation.
L Forces a listing (otherwise a listing is only printed if errors are found).
N Uses default names for symbol value constants. This generates an
extra module <grammar name>G, and corresponding import statements
using constant names instead of numbers for symbols in parser and
scanner.
The constants are used unqualified and hence all needed constants
have to be imported; so a complete import list for these constants
is generated.
There is no decision whether a constant is actually needed.
The default conventions are (only terminals or pragmas can have names):
single character --> <ASCII name (lowercase)>Sym
eg. "+" --> plusSym
character string --> <string>Sym
eg. "PROGRAM" --> PROGRAMSym
scanner token --> <token name>Sym
eg. ident --> identSym
O Trace of follow set computation (not yet implemented).
P Generates parser only
S Prints the symbol list.
T Suppresses generation of units (grammar tests only).
X Prints a cross reference list.
==========================================================================*)
PROGRAM CR;
USES CRS, (* lst, src, errors, directory, Error, CharAt *)
CRP, (* Parse *)
CRC, CRTable, CRA, CRX, FileIO;
CONST
ATGExt = '.atg';
LSTExt = '.lst';
Version = '1.48 (for Pascal)';
ReleaseDate = '9 July 1999';
VAR
Options, GrammarName, ATGFileName, lstFileName : STRING;
ll1 : BOOLEAN; (* TRUE, if grammar is LL(1) *)
ok : BOOLEAN; (* TRUE, if grammar tests ok so far *)
P : INTEGER; (* ParamCount *)
(* ------------------- Source Listing and Error handler -------------- *)
TYPE
CHARSET = SET OF CHAR;
Err = ^ErrDesc;
ErrDesc = RECORD
nr, line, col: INTEGER;
next: Err
END;
CONST
TAB = #09;
_LF = #10;
_CR = #13;
_EF = #0;
LineEnds : CHARSET = [_CR, _LF, _EF];
VAR
firstErr, lastErr: Err;
Extra : INTEGER;
PROCEDURE StoreError (nr, line, col: INTEGER; pos: LONGINT); FAR;
(* Store an error message for later printing *)
VAR
nextErr: Err;
BEGIN
NEW(nextErr);
nextErr^.nr := nr; nextErr^.line := line; nextErr^.col := col;
nextErr^.next := NIL;
IF firstErr = NIL
THEN firstErr := nextErr
ELSE lastErr^.next := nextErr;
lastErr := nextErr;
INC(errors)
END;
PROCEDURE GetLine (VAR pos : LONGINT;
VAR line : STRING;
VAR eof : BOOLEAN);
(* Read a source line. Return empty line if eof *)
VAR
ch: CHAR;
i: INTEGER;
BEGIN
i := 1; eof := FALSE; ch := CharAt(pos); INC(pos);
WHILE NOT (ch IN LineEnds) DO BEGIN
line[i] := ch; INC(i); ch := CharAt(pos); INC(pos)
END;
line[0] := Chr(i-1);
eof := (i = 1) AND (ch = _EF);
IF ch = _CR THEN BEGIN (* check for MsDos *)
ch := CharAt(pos);
IF ch = _LF THEN BEGIN INC(pos); Extra := 0 END
END
END;
PROCEDURE PrintErr (line : STRING; nr, col: INTEGER);
(* Print an error message *)
PROCEDURE Msg (s: STRING);
BEGIN
Write(lst, s)
END;
PROCEDURE Pointer;
VAR
i : INTEGER;
BEGIN
Write(lst, '***** ');
i := 0;
WHILE i < col + Extra - 2 DO BEGIN
IF line[i] = TAB
THEN Write(lst, TAB)
ELSE Write(lst, ' ');
INC(i)
END;
Write(lst, '^ ')
END;
BEGIN
Pointer;
CASE nr OF
0 : Msg('EOF expected');
1 : Msg('ident expected');
2 : Msg('string expected');
3 : Msg('badstring expected');
4 : Msg('number expected');
5 : Msg('"COMPILER" expected');
6 : Msg('"USES" expected');
7 : Msg('"," expected');
8 : Msg('";" expected');
9 : Msg('"PRODUCTIONS" expected');
10 : Msg('"=" expected');
11 : Msg('"." expected');
12 : Msg('"END" expected');
13 : Msg('"CHARACTERS" expected');
14 : Msg('"TOKENS" expected');
15 : Msg('"NAMES" expected');
16 : Msg('"PRAGMAS" expected');
17 : Msg('"COMMENTS" expected');
18 : Msg('"FROM" expected');
19 : Msg('"TO" expected');
20 : Msg('"NESTED" expected');
21 : Msg('"IGNORE" expected');
22 : Msg('"CASE" expected');
23 : Msg('"+" expected');
24 : Msg('"-" expected');
25 : Msg('".." expected');
26 : Msg('"ANY" expected');
27 : Msg('"CHR" expected');
28 : Msg('"(" expected');
29 : Msg('")" expected');
30 : Msg('"|" expected');
31 : Msg('"WEAK" expected');
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -