coco.use
来自「一个Modula-2语言分析器」· USE 代码 · 共 719 行 · 第 1/3 页
USE
719 行
TOKENS X AND Y CANNOT BE DISTINGUISHED
The terminal symbols X and Y are declared to have the same structure,
e.g.
integer = digit { digit } .
real = digit { digit } ["." { digit } ].
In this example, a digit string appears ambiguously to be recognized as
an integer or as a real.
The following messages are warnings. They may indicate an error but they may
also describe desired effects. The generated compiler parts may still be
valid. If an LL(1) error is reported for a construct X, one must be aware
that the generated parser will choose the first of several possible
alternatives for X.
X DELETABLE
X can be derived to the empty string, e.g. X = { Y } .
LL(1) ERROR IN X:Y IS START OF MORE THAN ONE ALTERNATIVE
Several alternatives in the production of X start with the terminal Y
e.g.
Statement = ident ":=" Expression | ident [ ActualParameters ] .
LL(1) ERROR IN X:Y IS START AND SUCCESSOR OF DELETABLE STRUCTURE
Deletable structures are [ ... ] and { ... }
e.g.
qualident = [ ident "." ] ident .
Statement = "IF" Expression "THEN" Statement [ "ELSE" Statement ] .
The ELSE at the start of the else part may also be a successor of a
statement. This LL(1) conflict is known under the name "dangling else".
The Parser Interface
====================
A parser generated by Coco/R for Modula-2 has the following simple interface:
DEFINITION MODULE grammarP;
(* Parser generated by Coco/R *)
PROCEDURE Parse;
(* Parse the source *)
PROCEDURE Successful(): BOOLEAN;
(* Returns TRUE if no errors have been recorded while parsing *)
PROCEDURE SynError (errNo: INTEGER);
(* Report syntax error with specified errNo *)
PROCEDURE SemError (errNo: INTEGER);
(* Report semantic error with specified errNo *)
PROCEDURE LexString (VAR Lex: ARRAY OF CHAR);
(* Retrieves Lex as exact spelling of current token *)
PROCEDURE LexName (VAR Lex: ARRAY OF CHAR);
(* Retrieves Lex as name of current token (capitalized if IGNORE CASE) *)
PROCEDURE LookAheadString (VAR Lex: ARRAY OF CHAR);
(* Retrieves Lex as exact spelling of lookahead token *)
PROCEDURE LookAheadName (VAR Lex: ARRAY OF CHAR);
(* Retrieves Lex as name of lookahead token (capitalized if IGNORE CASE) *)
END grammarP.
The functionality provides for the parser to
- initiate the parse for the goal symbol by calling Parse().
- investigate whether the parse succeeded by calling Successful().
- report on the presence of syntactic and semantic errors by calling SynError
and SemError.
- obtain the lexeme value of a particular token in one of four ways
(LexString, LexName, LookAheadString and LookAheadName). Calls to
LexString are most common; the others are used for special variations.
The main program simply has to open the source file and call Parse to start
the compilation. A simple main program would thus embroider on the idea:
FileIO.Open(<Grammar>S.src, sourceName, FALSE);
IF FileIO.Okay THEN
(* install error handler if required *)
<Grammar>S.Error := SomeHandler;
(* parse source and check result *)
<Grammar>P.Parse;
IF <Grammar>S.errors = 0 THEN (* parsed okay *) END
END
Note, however, that a tailored frame file can be supplied, from which Coco/R
can generate a main program if the $C pragma/option is used. Examples of this
can be found in the kit as well.
The Scanner Interface
=====================
The scanner generated by Coco/R has the following interface (for FileIO usage;
the ISO usage is trivially different in the declaration of the file types):
DEFINITION MODULE grammarS;
(* Scanner generated by Coco/R *)
IMPORT FileIO;
TYPE
INT32 = FileIO.INT32;
VAR
src, (* source/list files *)
lst: FileIO.File; (* to be opened by the main program *)
directory: ARRAY [0 .. 63] OF CHAR; (* of source file *)
line, col: INTEGER; (* line and column of current symbol *)
len: CARDINAL; (* length of current symbol *)
pos: INT32; (* file position of current symbol *)
nextLine: INTEGER; (* line of lookahead symbol *)
nextCol: INTEGER; (* column of lookahead symbol *)
nextLen: CARDINAL; (* length of lookahead symbol *)
nextPos: INT32; (* file position of lookahead symbol *)
errors: INTEGER; (* number of detected errors *)
Error: PROCEDURE ((* nr *) INTEGER, (* line *) INTEGER,
(* col *) INTEGER, (* pos *) INT32);
PROCEDURE Get (VAR sym: CARDINAL);
(* Gets next symbol from source file *)
PROCEDURE GetString (pos: INT32; len: CARDINAL; VAR s: ARRAY OF CHAR);
(* Retrieves exact string of max length len from position pos in source
file *)
PROCEDURE GetName (pos: INT32; len: CARDINAL; VAR s: ARRAY OF CHAR);
(* Retrieves name of symbol of max length len from position pos in source
file. Capitalized if IGNORE CASE was specified *)
PROCEDURE CharAt (pos: INT32): CHAR;
(* Returns character at position pos in source file *)
PROCEDURE Reset;
(* Reads and stores source file internally *)
END grammarS.
Notes
-----
It is rarely necessary to make use of any of this interface directly. The
parser interface discussed above exports most of the functionality that is
required when actions are required to retrieve token information.
The variables src, lst and directory are exported from this module simply for
convenience. src is assumed to be opened before parsing begins.
The variables line, col, pos, len are apposite for the most recently parsed
token.
The variables nextLine, nextCol, nextPos, nextLen are apposite for the most
recently scanned token (the look-ahead token retrieved by the most recent call
to Get).
PROCEDURE Reset is called by the parser to initialize the scanner. Note that
the main module is responsible for opening the source file src prior to
calling the parser. Reset reads the entire source into a large internal
buffer, thus improving the efficiency of the scanner very markedly.
PROCEDURE Get is called repeatedly from the parser, to get the next token from
the source text.
PROCEDURE CharAt can be used to retrieve a single character from the source
text at a known position.
PROCEDURE GetName can be used to obtain the text of the token at position pos
with length len. PROCEDURE GetString does the same thing, but returns the
exact string as found in the source. (GetName returns the string converted to
uppercase if the scanner was generated so as to IGNORE CASE).
Procedure variable Error is called by the parser for every syntax error
detected, with an appropriate error number and an error position as
parameters. The user can install any procedure that prints a message, or that
saves the error information for later output, subject to the restraint that
after parsing is completed, variable grammarS.errors should contain a
count of the total number of errors detected.
Procedure variable Error can also be used to report semantic errors. If you
use it for this purpose, make sure that you use semantic error numbers that do
not clash with automatically generated syntax error numbers (i.e. start
semantic error numbers at a high number like 200.)
The error numbers together with an explanatory text are written to a file
grammar.ERR by Coco/R in the following form:
0: Msg("EOF expected")
| 1: Msg("ident expected")
| 2: Msg("string expected")
| 3: Msg("number expected")
...
This text can then be merged into a CASE statement within a procedure that
prints textual error messages. This is done automatically if the $C pragma
(/C command line option) is used.
Bootstrapping Coco
==================
The parser and scanner used by Coco/R were themselves generated by a bootstrap
process; if Coco/R is given the grammar CR.atg as input, it will reproduce the
files CRS.DEF and MOD and CRP.DEF and MOD. It can also regenerate its own
main program from the file SOURCES\CR.FRM and CR.ATG if the $C pragma is used.
This means that Coco/R can be extended and corrected by changing its grammar
and recompiling itself. If you feel tempted to do this, please make sure that
you have kept copies of the original system in case you destroy or corrupt the
scanner and parser! GPM-PC is unable to bootstrap Coco/R, due to memory
limitations.
To bootstrap Coco/R itself you will need to install the FileIO library as
detailed earlier.
Table size limitations
======================
The symbol tables used internally by Coco/R make use of fixed length arrays
- always a rather dangerous thing to do. The dimensions of these arrays
have been chosen to ensure that the data segments for the modules will
remain within the limits imposed by MS-DOS system compilers that typically
impose a 64K limit on structures. The limits can be extended for compilers
that allow this (such as 32 bit compilers) by editing CRT.DEF and CRT.MOD
appropriately, and recompiling Coco/R. This may have to be done if a user
wishes to handle large grammars with many productions, for example.
Trademarks
==========
Any and all trademarks mentioned above are duly acknowledged.
=END=
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?